A seed-project for starting new REST-API Camel/Spring Boot projects
This project can be used to kick-start Spring-Boot-wrapped-Camel projects which expose a REST API. The core use case for this is a microservice. When used in conjunction with camel-boot-cxf-soap (which does the same thing but exposes a SOAP API) you have a good starter for ten for most synchronous microservices architectures you may want to create.
So what do I get by seeding my project in this way? Well, you'll get a set of code, tests (unit and integration) and config, plus Gradle build, which bootstraps an Apache Camel app that exposes a REST API. All this is handily packaged as a executable Spring Boot fat jar.
You also get:
- Camel endpoint exposure via Jetty
- integration tests via RESTassured which run under the integrationTest Gradle target and which start up your Spring Boot app locally in order to run them against it
- logging via SLF4J/Logback (with a sample config files for STDOUT and Jetty Access logging)
- REST api docs via Swagger
- circuit breaking on downstream calls via Hystrix
- metrics collection and publishing via CodaHale Metrics for JVM, Jetty, and Hystrix as well as your app code (we also had Camel metrics, but we never used them)
- an embedded Jetty servlet container which exposes the Hystrix metrics-event-stream servlet and the Codahale Metrics servlets
To use this seed project, fork this repository, and rename it as desired. Then run the following gradle tasks:
gradle clean test
- runs the example unit testsgradle clean integrationTest
- runs the example unit testsgradle bootRun
- starts the Spring-Boot appgradle clean test integrationtest install
- runs all tests (unit and integration, packages the spring boot fat jar and installs it in your local repo
We have a design goal to reduce the amount of code which distracts form your business logic. To this end, we've focussed on removing XML-config, kept the dependencies clean and lean, and provided a structure which should give clear indication where to put your code. It can however result in things looking a little magical. Here are how the various elements are set up:
Environment-dependent config information is read from a set of .properties
files which will be located external to your resulting JAR file. The ones for developent are located in the gradle config
directory. These are split up so as to prevent any one file from getting too dense. They are loaded and shared with Spring, Camel, and Hystrix via the archaius-spring-adapter which is configured as a Spring @Bean
in the MyAppConfig class. The idea is to build a JAR which will work in all environments, and then configure it with env-specific properties files deployed alongside it.
TBC
The core of the Spring Boot app is the Application
class. This has the @SpringBootApplication
annotation and gets us most of the way towards the fat-jar goodness we desire. Note that the @EnableAutoConfiguration
annotation is NOT used. We prefer to do things a little more explicitly which we find helps us avoid many of the Spring-magic problems most people encounter at some point or other.
This aside, you may notice that there seems to be little Spring Boot (or indeed Spring-anything) in evidence. This is intentional. If you want to see what is there in the seed, build.gradle
is a good place to start. Note that we have excluded the Tomcat starter (so we get Jetty instead) as well as web-mvc. We don't need them in our projects.
We ended up doing this because Spring Boot loves to look at your classpath and do clever things based on what it finds. While this is definitely a boon in most situations, it is possible that this can give you major headaches. We have found that it is best therefore to add single dependencies to your project and then, before you add any code or config, run your tests and check that gradle bootRun
still works. It's amazing the havoc that a stray servlet-api, buried down in your dependency graph can wreak.
We have added a banner.txt file which gives us the ASCII-goodness you see when you run your app. If you change the contents of this file, the contents of your app's Spring Boot banner will change also.
Finally note that we've managed to do away with all that nasty XML Spring config. As mentioned in the Properties section above, when we do need to create a bean, we do by creating a @Bean
method it in the @Configuration
annotated MyAppConfig
class, or we explicitly import is with an explicit @Import
at the top of the Application
class.
Taking the MyAppConfig
class first, you can see there is some boiler-plate which illustrates how to get access to the Spring context (should you need it) and also a Spring bean instance of ArchaiusBridgePropertyPlaceholderConfigurer
which loads the properties (into Spring-, Camel- and Netflix-scopes) from the files listed in the Properties section above. See github for more info on the Archaius-Spring-Adapter (which provides this class).
With the @Import
, we're using Spring here to explicitly bring into config-scope another class which is again annotated @Configuration
. One of these beans comes from one of our dependencies - springboot-camel-metrics-publisher in this case - and simply starts up and registers the servlets which publish the Hystrix metrics stream, the Codahale metrics, and allows thread dumps. (For more information on all of these, see the relevant sections below.) The other configuration beans are local to your project - look in the config package to see them. Note: we'll probably move these to dependencies too in the future.
Also note that this indicates a convention. If we want to add more configuration @Bean
s for our app alone, we add them to MyAppConfig
. If we are bringing them in from a dependency, explicitly declare them in Application
via an @Import
.
Finally note that we are starting up a Jetty container which is used to register all our monitoring servlets, as well as the camel "servlet" provider which provides HTTP access to your REST routes and Swagger API docs.
TBC
The first thing to note with the Camel elements are the dependencies. There should be very few surprises here if you've used Camel before.
The Second thing to look at again is src/main/java/...Application.java
. This extends Camel's FatJarRouter
, and as already mentioned is annotated @SpringBootApplication
thereby removing the need for us to have any Camel XML config at all. This tiny piece of typing means that when we do gradle bootRun
(or java -jar YourApp.jar
) you will see your Camel context starting up inside a Spring context with next to no effort on your part.
The rest (no pun intended) is up to you. We typically create our Camel routes in the route
package. There is an example REST one in there for you already. We have also added an example RESTassured integration test which runs when you run gradle integrationTest
.
As mentioned above, the Camel REST DSL routes map to the Jetty Servlet container provided by Spring Boot. TBC - where is this configured?
TBC
The example REST DSL route class generates and publishes Swagger files at http://localhost:xx/xxxxxxxxx. To view these in the Swagger broswer you need to ..... TBC.
We use SLF4J and Logback for our logging. In addition to the expected STDOUT logging which goes by default to file and console, there is also HTTP access logging (also to file).
TBC
Its always nice to have an idea what your app is doing. We make heavy use of CodaHale Metrics to give us this information. As already mentioned, instrumented aspects of the seed project are:
- JVM
- Jetty
- Hystrix
- Apache HTTPClient (via the separate circuit-broken-camel-rest-client library)
- App Code Camel is also instrumented, but we never made use of this data so its not included in this at this time.
TBC
TBC
TBC
TBC
The idea for these projects was pretty much stolen from Netflix's Karyon. It then evolved as we built more and more Microservice-based solutions at Capgemini.
There is little original thought in all that has been pulled together here - we're just sharing our glue code, and the build files, and some examples which illustrate some nice ways to do things. The core is based on:
- Apache Camel
- Spring-Boot
- Netflix's Archaius and Hystrix
- CodaHale's Metrics
- Swagger
- Logback
- Jetty
If you submit a PR, please add your name to this list.