Boot your application with Spring Boot

February 25, 2014 by Michael

This is the first Post in my series Developing a web application with Spring Boot, AngularJS and Java 8 and has been featured in This Week in Spring – April 15, 2014.

Spring Boot makes it very easy to get you up and running with the Spring ecosystem without the need for XML configuration and the like. The nice thing about Boot is: It doesn’t add aspects and doesn’t generate code. Instead it uses several conditional beans to configure sensible defaults that disappear as soon as you add your own beans. This document helps a lot to discover the defaults and properties to customize everything you need: How Do I Do That With Spring Boot?.

So we want to create a simple MVC app with a hand full of (REST) controllers. Therefor i use the “spring-boot-starter-parent” as my parent pom:

and then use “spring-boot-starter-web” as the dependencies that include everything that is needed for Spring MVC to work:

Another goodie i wanted to use is Spring Boots ability to create executable jar files with an embedded web container, Tomcat 7 by default, so i need the spring-boot-maven-plugin as well:

Given my Application.java as the “start-class” (defined in the properties of my pom), i can run this application via “mvn spring-boot:run” or create an executable jar file with mvn package.

So what is this Application class? It looks like this:

You’ll see that it is a Spring @Configuration class that tells Spring Boot to enable automatic configuration (@EnableAutoConfiguration) as well as scheduling (@EnableScheduling) and finally tells Spring to look for more components in this and all child packages (@ComponentScan). The main method initializes an application context via a factory method inside SpringApplication. The configure method inherited from SpringBootServletInitializer does essentially the same but only when deployed as a war file. The one additional bean “home” just didn’t fit anywhere else, but you see a nice @Value annotation around the two parameters that reads “take the required value ‘biking2.home.longitude’ from the environment and used id as a parameter”. Methods annotated with @Bean are subject to dependency injection for their parameters, either beans or values. The values here are taken from application.properties at the root of the classpath.

With just a bunch of code you’ll have a fully configured application including scheduled jobs.

I want to keep track of my milage so i need some kind of persistence. I opted for H2 and added com.h2database:h2 as a dependency. Without any version number as a lot of possible dependencies are already versioned and managed by the parent pom. As i added org.springframework:orm and org.springframework.data:spring-data-jpa i could stop here. Spring Boot would automatically create a data source for me. I want some control so i added the following to the application properties:

This is also a nice example of using SpEL and nested properties inside property files managed by spring. The colon inside spring.datasource.username means “take the value of biking2.database-username if exists, otherwise use biking2”. Nice detail. Given this data source, i wanted a little more control over JPA, see PersistenceConfig.java. For example, i wanted the Spring Data repository inside a given package (@EnableJpaRepositories(basePackages = “ac.simons.biking2.persistence.repositories”)) (otherwise they would have been initialized as well, but only in the default level), have some control over sql statements and adding the hibernateExceptionTranslator.

So, data source and repositories are ready? Nearly. I have an additional application-test.properties. This properties file is only evaluated with profile test being active. I’m configuring a test in-memory db. This would happen automatically as well but with the added DB_CLOSE_DELAY=-1 parameter to the database url which means: “Keep the content of this db inside memory until the VM closes, not only until the last connection closes.” I had problems with my tests. The builder automatically adds schema.sql and data.sql and that fails if a new tests forks and the database is reused. I’m not sure wether it’s a problem with my configuration or with the Spring test runner.

So i’ve created a bunch of entities together with a repository if needed. The basic idea behind the bike –< milage entities is to record the milage of my trip recorder each month and to be done. All calculations happens inside the app. JpaRepositories are just great. The following interface

will be instantiated at runtime and together with basic CRUD functionality, it maps two named queriers (“Bike.findActive” as #findActive(final @Param(“cutoffDate”) Calendar cutoffDate) and “Bike.getDateOfFirstRecord” as #getDateOfFirstRecord() both defined inside Bike and a dynamic query build by parsing “findByDecommissionedOnIsNull”.

So we have an application context, a data source including entities and repositories, we could throw in some services, but just keep it simple, i use the repository inside the following @RestController:

@RestControllers assume an implicit @ResponseBody at all methods annotated with @RequestMapping.

What do we see? First, an auto wired constructor. I opted for all dependency injection through constructors as i’m currently observing in another project when getter/setter injection get’s out of hands. People usually start to feel uncomfortable having a constructor more than 15 parameters (at least i hope). As an added benefits, most objects are immutable.

The repository is than used, depending on a request parameter, to retrieve a list of all bikes or of all active bikes and this list is returned. As jackson-core is on the class path, this list is automatically converted to a valid JSON representation. Given ” @RequestMapping(value = “/api/bikes”, method = GET)”, the method is exposed at the given endpoint.

Testing this method is an easy task. Just instantiate the controller with a mock repository, run your tests directly on the instance and be done. You can alternatively boot an application context or parts of a context to test methods with MockMvc, have a look at BikesControllerTest.java (More on that topic in a later post).

This method is actually used here for the list of bikes at the bottom of the page.

With a minimum effort, i’ve developed an API without nearly zero maintenance cost. I like this a lot.

Here is a short list of hints, that maybe help you:

Running behind a proxy

The app runs behind a proxy and needs to generate some links and therefore must know the proxy name.

Apart from seeing a Java 8 lambda, you’ll find a static Condition that checks the presence of a given property in the environment of the application context.

The following @Bean “embeddedServletContainerCustomizer” is only instantiated when the @Conditional matches and the property is present. The parameter proxyName uses this property name, the parameter proxyPort has a default of 80. The following just sets those two values on a TomcatEmbeddedServletContainerFactory.

Uploading files

To enable the Servlet 3.0 Multipart support, the Spring Boot Guides show here a bean of type MultipartConfigElement is enough. That’s true and works very well. But as many people just copy & paste code, the note the default configuration imposes no limits on the file size for an upload should really be a warning if you ever plan to run this in public. An authentication doesn’t protect you from big uploads. Those are send first, than the authentication is processed. So be sure the bean reads something like

This restricts uploads to 5Mb.

Multipart/form-data and UTF-8

To support UTF-8 in Multipart/form-data, add the following bean to your config:

The ServletContextInitializer is a special form of ServletContainerInitializer that works with Spring and Spring Boot. Here it’s used to add the CharacterEncodingFilter before all other filters. The before all other part is important, otherwise it doesn’t work for Multipart/form-data.

Customizing RequestMappingHandlerMapping

At the moment it is not possible to get hold of the default RequestMappingHandlerMapping and customize things like “useRegisteredSuffixPatternMatch” and the like. It’s not a conditional bean and adding your own will lead to double mappings.

So i’m using a classic beanPostProcessor to achieve this with Spring Boot 1.0.0.RC3:

Summary

At this point we have a working API, that can be used immediately in a JavaScript framework like Knockout.js or AngularJS.

Next post will be about Java 8 in the context of this application.

The whole source code at the point of writing this post is available at GitHub, the application is live right there biking.michael-simons.eu.

11 comments

  1. Anonymous wrote:

    It’s ironic that you start by saying that “Spring Boot makes it very easy to get you up and running with the Spring ecosystem without the need for XML configuration and the like” and then the first thing you discuss is how to set up the XML configuration file.

    Posted on April 20, 2014 at 7:27 PM | Permalink
  2. Michael wrote:

    Yeah, you’re probably right… I could have used Gradle for managing dependencies, but Maven is – at least for me and i guess several other developers – that much a standard, that it was much easier to setup.

    What does Maven do here? Primary dependency management and build the executable jar file. That’s ok for me. Nothing regarding the application itself here is tied to XML.

    But anyway, thanks for pointing out.

    Posted on April 20, 2014 at 7:41 PM | Permalink
  3. Mark wrote:

    Hi Michael,

    I am using Spring Boot and am working on the tests using MockMvc. I have logic within my main() method to handle arguments. One of the steps is to load data from a file into a collection.

    When I run my integration tests using MockMvc, the main method doesn’t appear to be executed. The collection that is supposed to be populated in main is instead null. Any of the tests that don’t involve the collection work. But any tests which involve the collection give a null pointer exception.

    Do you know if the main() method gets executed when using MockMvc?

    Thanks!

    Posted on October 2, 2014 at 12:16 AM | Permalink
  4. Michael wrote:

    Hi Mark

    thanks for your feedback.

    Why would a main Method somewhere be automatically executed? This won’t be the case.

    You mock services, controllers and the like… And that’s all you get, a mock. The application isn’t started that way.

    Cheers,
    Michael.

    Posted on October 5, 2014 at 6:51 PM | Permalink
  5. Write Code wrote:

    Nice tutorial but but far too complex and time consuming for this day and age. I use the Jigy Generator to create my Spring projects. Jigy Generator completely configures Spring for me it will reverse engineer your database to create all your DAO’s, domain objects and validators for you. Plus you have certain things that just work out of the box like login, authentication, file upload etc. It’s a really great too and can be downloaded at www .getjigy .com

    Posted on October 20, 2014 at 6:38 AM | Permalink
  6. Michael wrote:

    Hello “Write Code”

    Nice tutorial but but far too complex and time consuming for this day and age

    Yeah, sure, but no.

    Also, i don’t think i was clear enough about what Boot is all about: There is no code generation involved and that is one of the best things in my opinion.

    Take care and have a nice day.

    Posted on October 20, 2014 at 8:58 AM | Permalink
  7. Nice write up.. Spring Boot is pretty awesome man… love working with it.

    Posted on February 22, 2015 at 1:12 PM | Permalink
  8. Shreyas wrote:

    I am getting this exception:

    Exception in thread “main” java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.boot.SpringApplicationRunListener : org.springframework.boot.context.event.EventPublishingRunListener
    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:369)
    at org.springframework.boot.SpringApplication.getRunListeners(SpringApplication.java:340)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:265)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at test.Application.main(Application.java:15)
    Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:365)
    … 5 more
    Caused by: java.lang.NoSuchFieldError: INSTANCE
    at org.springframework.boot.SpringApplication.asUnmodifiableOrderedSet(SpringApplication.java:988)
    at org.springframework.boot.SpringApplication.getListeners(SpringApplication.java:887)
    at org.springframework.boot.context.event.EventPublishingRunListener.(EventPublishingRunListener.java:46)
    … 10 more

    Code:
    public class Application {

    public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run(Application.class, args);

    WeatherClient weatherClient = ctx.getBean(WeatherClient.class);

    String zipCode = “94304”;
    if (args.length > 0) {
    zipCode = args[0];
    }
    GetCityForecastByZIPResponse response = weatherClient.getCityForecastByZip(zipCode);
    weatherClient.printResponse(response);

    }
    }

    Posted on May 13, 2015 at 3:34 PM | Permalink
  9. Michael wrote:

    Sorry, Shreyas, what are you expecting from me? Fixing that without knowing anything? Theres a code fragment and nothing else… What are you trying to accomplish?

    Posted on May 13, 2015 at 5:50 PM | Permalink
  10. Shreyas wrote:

    I am incorporating the Spring-WS framework from ‘http://spring.io/guides/gs/consuming-web-service/’.

    In the above code mentioned, I am getting the exception as mentioned above in the line,

    ApplicationContext ctx = SpringApplication.run(Application.class, args);

    Posted on May 14, 2015 at 7:52 AM | Permalink
  11. Michael wrote:

    Sorry, Shreyas, i think i’m not able to help without having the whole project.
    The getting started guide doesn’t work without any modification?

    Posted on May 22, 2015 at 6:37 AM | Permalink
3 Trackbacks/Pingbacks
  1. […] Part 1: Boot your application with Spring Boot […]

  2. […] Boot your application with Spring Boot […]

  3. […] Boot your application with Spring Boot | info.michael-simons.eu. […]

Post a Comment

Your email is never published nor shared. Required fields are marked *