spring boot
, , ,

This is the fifth part of my tutorial series on building a Spring Boot Web Application. We started off in the first part looking at using the Spring Initializr to start our Spring Boot project. In part 2, we configured Spring MVC and ThymeLeaf templates to display a basic web page. This was followed by part 3 where we setup the H2 database and Spring Data JPA and used them to persist data of our application to the database. In part 4, we consolidated everything to provide a working Spring Boot MVC Web Application capable of performing CRUD operations. We now have an application which displays data from the database, allows you to create new records, update existing records, and delete selected records too.

In part 5, we will use Spring Security to set up authentication and authorization in our application.

Spring Security, one of the most commonly used project in the Spring family of projects, provides a powerful and highly customizable authentication and authorization framework designed specifically to secure Java applications. In this part, I’ll show you how to setup Spring Security to secure our Spring Boot Web Application using the basic in-memory authentication provider.

Security Requirements

Our Spring Boot Web application in the current state is accessible to all users. Any user can create and view products, and also edit or delete them. Before we setup Spring Security to secure our application, let’s set few security requirements:

  • An anonymous user (user who doesn’t sign in) should be able to view the home page and product listing.
  • An authenticated user, in addition to the home page and product listing, should be able to view the details of a product.
  • An authenticated admin user, in addition to the above, should be able to create, update, and delete products.

Maven Dependencies

Spring Security is already listed as a dependency of our application in the Maven POM.

In the Maven Projects pane of IntelliJ we can see the additional dependencies of  Spring Security.

spring security dependencies in Maven

As we can see the Spring Security starter has brought in Spring AOP, Spring Security web, and Spring Security config, which in turn bring in Spring Security core.

Authentication and Authorization

Before we go deep, we need to understand what authentication and authorization means in Spring Security. Although both sound similar and it’s very easy to confuse them..

Authentication means ascertaining that somebody really is who they claim to be. Authentication is performed using different mechanisms. One simple and common mechanism is through user credentials in the form of user name and password. These are stored in some type back end data store, such as a SQL database. Others include LDAP, Single Sign-On (SSO), OpenID, and OAuth 2.0.

Authorization, on the other hand, defines what you are allowed to do. For example, an authenticated user may be authorized to view products but not to add or delete them.

Remember that authentication is “Who I am?” as a user to the system. While authorization is “You are either allowed or not to do this” from the system.

Securing URLs

In part 1, where we added Spring Security into our build, Spring Boot configured Spring Security to require Basic authentication for all endpoints. In part 2, we configured Spring Security to allow all requests access to the root path. We did this by creating a SecurityConfiguration class that extends the WebSecurityConfigurerAdapater class and overridden the configure() method. We will now update the same configure() method to define which URL paths should be secured and which should not.

Here is the the updated configure() method:

This security configuration will:

  • Allows all requests to the /, /products, /product/show/*, /console/** paths (Line 5)
  • Secures all other paths of the application to require authentication (Line 6)
  • Allows everyone to view a custom /login page specified by loginPage()(Line 8)
  • Permits all to make logout calls (Line 10)
  • Disables CSRF protection (Line 12)
  • Disables X-Frame-Options in Spring Security (Line 13) for access to H2 database console. By default, Spring Security will protect against CRSF attacks.

Note: Although this is not a production-level configuration, it should get us started with the basic in-memory authentication. I’ll revisit this part, when I discuss more advanced security configuration in my upcoming posts.

In the same SecurityConfiguration class, we will also autowire a configureGlobal() overridden method of WebSecurityConfigurerAdapter. At runtime, Spring will inject an AuthenticationManagerBuilder that we will use to configure the simplest, default in-memory authentication with two users. The complete code of the
SecurityConfiguration class is this.

SecurityConfiguration.java

In this code, Line 27 – Line 30 configures in-memory authentication with two users. The first user with the username user and a password user is assigned a role of USER. The second user with the username admin and a password admin is assigned a role of ADMIN.

The Login Page

Our application will have a login page to capture user credentials in the form of user name and password. The login page, a Thymeleaf template will be served whenever a request to /login is received. We will configure the request mapping in ProductController like this.

The code of the login template is this.

login.html

This is a standard Thymeleaf template that presents a form to capture a username and password and post them to /login. Spring Security provides a filter that intercepts that request and authenticates the user with our configured in-memory authentication provider. If authentication succeeds, the application displays the requested page. If authentication fails, the request is redirected to /login?error and the login page displays the appropriate error message (Line 10 – Line 12). Upon successfully signing out, our application is sent to /login?logout and the login page displays a sign out message (Line 13 – Line 17).

This is how the login page displays an error message on authentication failure.
Spring Security Login Error Message

Spring Security Integration in Thymeleaf

To integrate Spring Security in our Thymeleaf templates, we will use the Thymeleaf “extras” integration module for Spring Security. For this, we need to add a JAR dependency in our Maven POM like this.

The Thymeleaf “extras” module is not a part of the Thymeleaf core but fully supported by the Thymeleaf team. This module follows its own schema, and therefore we need to include its XML namespace in those templates that will use security features, like this.

Showing Content based on Role

One of our application requirement states that only authenticated users with the ADMIN role can create products. To address this, we will configure authorization in the header.html Thymeleaf fragment to display the Create Product link only to users with the ADMIN role. In this template, we will also display a welcome message with the user name to an authenticated user. The code of the header.html template file is this:

header.html

The Thymeleaf security extension provides the sec:authorize attribute that renders its content when the corresponding Spring Security expression evaluates to true.

In Line 16 we used the sec:authorize attribute to display the Create Product link only if the authenticated user has the ADMIN role. Observe that we are checking against ROLE_ADMIN instead of the ADMIN role. This is because of Spring Security’s internal feature of mapping a configured role to the role name prefixed with ROLE_. In Line 23 we again used the sec:authorize attribute to check whether the user is authenticated, and if so, displayed the name using the sec:authenticate attribute.

This is how the home page appears to authenticated users with USER and ADMIN roles.

Home Page View for USER Role
Home Page View for ADMIN Role

Our current Product Listing page rendered by the products.html template displays the View, Edit, and Delete links to all users. In this template, we will configure authorization:

  • To show the View, Edit, and Delete links to a user with ADMIN role
  • To show only the View link to a user with USER role
  • Not to show any links to an anonymous user who hasn’t signed in

The code of the products.html page is this.

products.html

In Line 16 the “Sign Out” form submits a POST to /logout. Upon successfully logging out it will redirect the user to /login?logout. The remaining authorization is performed using the sec:authorize attribute. The hasAnyRole('ROLE_USER','ROLE_ADMIN') expression on Line 30 and Line 39 evaluates to true if the user has either the ROLE_USER or ROLE_ADMIN.

With this configuration, the product listing page will appear to different roles like this.

Home Page View for Anonymous
Home Page View for USER Role
Home Page View for ADMIN Role
If you are wondering why the Sign Out Submit button is getting displayed as a link, it’s due to this CSS code I added to the guru.css stylesheet.

guru.css

The code of productshow.html and productform.html templates, except for the addition of the “Sign Out” form, remains the same.

productshow.html

productform.html

Finally, if any signed in user clicks on Sign Out in any one of the secured pages, the user is redirected to the login page with a message, like this.
Spring Security Log Out Message

free spring framework tutorialSummary

Spring Security is a very popular project in the Spring Framework family of projects. When you need to secure content in a Spring Boot web application, Spring Security is a natural ‘go to’ tool to use.

In this post, I’ve only scratched the surface of the capabilities of Spring Security. For example, I used the in-memory authentication provider for Spring Security. This a great tool to demonstrate how to configure Spring Security. But, you probably would not use an in-memory authentication provider in production. It’s actually fairly common to store user credentials in a database. In the next post of this series, I’ll explain how to setup a DAO authentication provider for Spring Security.

1
Share
,

In case you’ve been living under a rock for the last couple years, Spring Boot Actuator is an awesome set of tools for monitoring and managing your Spring Boot applications. Spring Boot Actuator exposes information via ‘endpoints’. One of the Spring Boot Actuator endpoints is an information endpoint, which is available at the ‘/info’ url from the root of your application.

The information URL is intended to give you basic information about your application.

Typical uses of the information end point from Spring Boot Actuator is to provide git check-in information or build information. I go in-depth on setting these up in my on-line course on Spring Boot Actuator.

Spring Boot Information Contributors

Another feature in Spring Boot Actuator is to provide custom information contributors. The implementation of a custom information provider is fairly simple. Just provide a Spring Bean which implements the InformationContributor interface. Once your custom Spring Bean is wired into your Spring Context, Spring Boot will automatically include its output on the info endpoint.

I’m sure the Spring team had visions of the info endpoint being used to emit information about the OS version, build information, or other application information.

You know – serious stuff!

How boring!

As part of my Spring Boot Actuator course, I have my students implement a custom information contributor. In building the course, I wanted to use something fun for my students to implement. The enterprise stuff can get stuffy and boring.

Introducing Chuck Norris for Spring Boot Actuator

Shamelessly inspired by the Chuck Norris plugin for Jenkins, I thought why not write a Chuck Norris information contributor for Spring Boot Actuator?

Chuck Norris Approves Spring Boot

Chuck Norris for Spring Boot Actuator is a simple implementation of a custom information contributor. The initial release has roughly 125 Chuck Norris sayings. Every time the information endpoint is accessed, a Chuck Norris saying is randomly selected from the list.

Installation & Usage

Dependencies

Maven

Gradle

Spring Configuration

To configure Spring Boot Actuator to use the Chuck Norris Information Contributor, you will need to add the ChuckNorrisInfoContributor to your Spring Context. Below is an example Java configuration bean, you can add to your Spring Boot project.

Usage

Once configured, simply start your Spring Boot Application and navigate to the info endpoint (http://localhost:8080/info). You should see a Chuck Norris message.

Spring Boot Actuator Course

Do you want to learn more about Spring Boot Actuator? Use this link to take 30% off the regular course price!

Just use the code 30OFFACTUATOR at checkout.

Spring Boot ActuatorSource Code

The source code is open source and available here on Github.

Contribute

Got a favorite Chuck Norris quote you want to add?

Fork my project on Github, add it and send me a pull request!

I’ll periodically make new releases to include more Chuck Norris quotes.

Chuck Norris Doesn't Write Code for Spring Boot Actuator

0
Share
spring boot
, ,

In my earlier Integration Testing with Spring and JUnit post, I discussed how to test a service bean facade with JUnit. I also posted a video, titled Testing Spring with JUnit on YouTube. In post, Spring Boot Web Application – Part 3 – Spring Data JPA, I showed how to test a Spring Data JPA repository of a Spring MVC application.

It has been more than a year now since I wrote these posts and posted the video. Since then, there’s been an exciting overhaul of testing support for Spring Boot MVC applications. The Spring Boot 1.4 release includes a number of exciting new testing features for our use.

In this post, I will look the new Spring MVC testing features. And I’ll show you how to put them to use.

Spring Boot 1.4 Testing Enhancements

In Spring Boot 1.3, there’s a lot of choices to write tests for a Spring MVC application. One option to set Spring MVC is shown in my earlier post here. In this post on Spring Boot 1.3, the @RunWith annotation with @ContextConfiguration is used to test for a business service façade, like this:

Another method I used in the post here is a combination of the @RunWith annotation with @SpringApplicationConfiguration to test a Spring Data JPA repository, like this:

There are several other approaches you can check in the official Spring blog here.

The testing approaches I used above are actually integration tests.  A pure unit test shouldn’t create and load Spring Context.

Spring Boot 1.4 replaces these various testing approaches that via a single @SpringBootTest annotation for regular integration tests.

Prior to Spring Boot 1.4, I found Spring was lacking a simplified unit testing approach. This is really no surprise. The Spring team is always creating. Spring and Spring Boot offers a number of testing options. Due to innvotation, the testing options have evolved over time. In Spring Boot 1.4, the Spring committers took some time to clean testing up. They gave us much simpler options to use for testing Spring Boot applications. For example, a simple approach to unit test a controller having @Autowired external services without having to load Spring Context was lacking. With Spring Boot 1.4, it’s now possible.

Another missing piece that Spring Boot 1.4 tackels, is the ability to test portions (slices) of code. This can be done without the need to fire up a server. And with out the need to load up the entire Spring Context. Spring Boot 1.4 does this through the new Test Slicing feature that is designed to set-up a narrow slice of the Spring Context. This makes testing single ‘slices’ much easier. You can now focus on testing specific slices of your application. For example:

For example:

  • MVC slice: Controller code through the @WebMvcTest annotation
  • JPA slice: Spring Data JPA repository code through the @DataJpaTest annotation
  • JSON slice: JSON serialization code through the @JsonTest annotation

This may not seem like much at first glance. But when you have a large application starting the Spring context in testing, it is time consuming. Context loads can really increase your build time.

Let’s start putting the new test features to use.

The Application Under Test

I wrote a series of posts on Spring MVC starting off from Spring Boot Web Application – Part 1 – Spring Initializer. In the last post of the series, Spring Boot Web Application – Part 4 – Spring MVC, I completed creating a Spring MVC application to perform Create, Read, Update, and Delete (CRUD) operations.

In this post, I’ll show you how to write tests for the controllers of the same Spring MVC application.

If you are new to Spring MVC, you should go through my series on Spring MVC starting here.

You can also download the source code of the application available on GitHub here to follow along this post.

It’s a pretty simple example of a Spring Boot MVC application consisting of the following primary components:

  • Product: The domain object, which is a JPA entity
  • IndexController: Returns the index.html Thymeleaf template for a GET request to the application root
  • ProductController: Contains number of actions methods that use ProductService to perform CRUD operations via the repository model
  • ProductRepository: A Spring Data JPA repository
  • ProductService: A business service façade interface
  • ProductServiceImpl: A business service façade implementation annotated with @Service

With the Spring Boot MVC application that will be under test in place, lets start by writing few tests for the controllers.

Maven Dependencies

The testing features we’re looking at were introduced in Spring Boot 1.4. The version of Spring Boot we’ll be using is 1.4.0.RELEASE.

Here is the complete Maven POM that we’ll use.

pom.xml

Unit Testing Spring MVC Controllers

MockMvc has been around since Spring 3.2. This providing a powerful way to mock Spring MVC for testing MVC web applications. Through MockMvc, you can send mock HTTP requests to a controller and test how the controller behaves without running the controller within a server. You can obtain a MockMvc instance through the following two methods of MockMvcBuilders:

  • standaloneSetup(): Registers one or more @Controller instances and allows programmatically configuring the Spring MVC infrastructure to build a MockMvc instance. This is similar to plain unit tests while also making it possible to focus tests around a single controller at a time.
  • webAppContextSetup(): Uses the fully initialized (refreshed) WebApplicationContext to build a MockMvc instance. This lets Spring load your controllers as well as their dependencies for a full-blown integration test.

Pro Tip: Whenever possible, I will try to use standaloneSetup() for my SpringMVC tests. Your tests will remain true unit tests and stay blazing fast!

This is the IndexController that we are going to test:

IndexController.java

For our purpose, we’re starting with standaloneSetup() to test this IndexController.

The test class is this.

IndexControllerTest.java

The test class above is a JUnit test. If you are new to JUnit, you should go through my series on unit testing with JUnit, starting from here. In the test class above, observe the new Spring Boot 1.4 test runner, named SpringRunner that we specified for @RunWith in Line 20. Under the hood, both SpringRunner and its predecessor SpringJUnit4ClassRunner are the same. SpringRunner is only the new name for SpringJUnit4ClassRunner – to just make it easy on the eyes.
In the @Before annotated method that runs before all @Test method, we programmatically constructed a MockMvc instance after registering the IndexController instance.

In the @Test method, we used the MockMvc instance to verify the following behavior of IndexController:

  • HTTP status code 200 is returned
  • The name of the returned view is index

Finally, by using andDo(print()), we get the following output on the console

Spring MockMvc IndexController Test Output

Testing the Spring MVC Slice

The unit test we wrote were for some basic expectations of the controller. Let’s write some more specific tests, this time to test ProductController. This time we’re going to use webAppContextSetup() to build MockMvc.

For a quick recap, the ProductController class is this.

ProductController.java

We will start by testing the behavior of ProductController.list() method. For a GET request to /product, we will perform the following verification:

  • The ProductService mock is not null
  • The HTTP status code 200 is returned
  • The returned content type is text/html;charset=UTF-8
  • The name of the returned view is products
  • The view contains the Spring Framework Guru string

Here is the test class.

ProductControllerTest.java

As we are testing the MVC slice of the application (testing whether the ProductController is working as expected), we used the @WebMvcTest annotation combined with @RunWith(SpringRunner.class).

As we planned to use webAppContextSetup() to build MockMvc, we @autowired WebApplicationContext in Line 6 – Line 7 to bring it into our test. Then in line 13, we passed WebApplicationContext as an argument to webAppContextSetup() to build the MockMvc instance.

Going back to the ProductController class under test, note that the controller class is @Autowired with ProductService. Therefore, we used the @MockBean annotation to define a Mockito mock for ProductService (Line 8 -Line 9) that will be passed to the controller. If you are new to mocking in unit tests, checkout my Mocking in Unit Tests with Mockito post.

Coming back to the test, in Line 17 we used the AssertJ library to assert that the ProductService mock is not null.

Note: Starting with Spring Boot 1.4, AssertJ comes out-of-the-box with Spring Boot to provide a fluent assertion API with a plan to replace JUnit’s  org.junit.Assert class.

From Line 19 – Line 23, it’s all about verifying our expectations. As you can see, a lot of static methods are being used in this test method, including static methods of MockMvcRequestBuilders ( get()), MockMvcResultMatchers ( status(), content(), and view()), MockMvcResultMatchers ( match()), and Hamcrest Matcher’s ( match()). The last two match() are similar and performs the same functions in our test. They exist together only to demonstrate the different approaches that can be used.

Our test method reads naturally. First it performs a

First it performs a GET request against /products. Then it expects that the request is successful ( isOk() asserts an HTTP 200 response code) and that the content type and name of the view is text/html;charset=UTF-8 and products respectively. Finally, it asserts that the view contains the Spring Framework Guru string.

When all the expectations pass, Line 24 prints the result out to the console.

The important thing to note here is that at no time is the application gets deployed to a server. The Tomcat container is not use. Instead the application runs within a mocked out Spring MVC to handle the HTTP request that we provided through the

Instead the application runs within a mocked out Spring MVC to handle the HTTP request that we provided through the MockMvc instance.

Here is the test result in the console.
Test output of ProductController.list()

The complete output of the test sent to console is this.

Testing Spring MVC Slice with @Autowired MockMvc

Now let’s test the behavior of showProduct() of ProductController. Instead of manually building MockMvc, we’ll use a @Autowired MockMvc in the test and let Spring create, configure, and provide a MockMvc for us.

This is how the test class now looks minus any @Test method implementations.

In the test class above, notice that we used the @Autowired annotation on MockMvc in Line 5 – Line 6 instead of building it manually.

An @Autowired MockMvc combined with @WebMvcTest(controllers = ProductController.class) gives us a fully configured MockMvc instance with Spring security configured to set up BASIC authentication.

At this point, if we run the ProductControllerTest.testList() test again, we’ll encounter an authentication error, like this.

We’re getting the 401 response because Spring Boot is auto-configuring Spring Security for us.

To disable the Spring Security auto-configuration, we can the MockMvc instance to disable security with @AutoConfigureMockMvc(secure=false) in Line 3.

Note, in the @Before method, we created and initialized a Product domain object that we will use in the @Test method.

The @Test method is this:

In the @Test method above:

  • Line 4: Performs an AssertJ assertion to test that the ProductService mock is not null.
  • Line 5: Uses Mockito to stub the getProductById() method on the ProductService mock to return the initialized Product instance
  • Line 8 to Line 15: Performs the following verifications for a GET request to product/{id}:
    • The HTTP status code 200 is returned
    • The name of the returned view is productshow
    • The view model contains a product attribute
    • The various properties of the product attribute matches against the values we used to initialize Product
  • Line 16: Returns the result as MvcResult
  • Line 19- Line 20: Uses AssertJ to assert that the content type of the response is
    text/html;charset=UTF-8
  • Line 22- Line 27: Uses JUnit assertions to assert that:
    • The response header that MvcResult returns as MockHttpServletResponse is not null
    • There is only one response header
    • The response header name is Content-Type
    • The response contains the Spring Framework Guru string
  • Line 29 -Line 30: Uses Mockito to verify that the getProductById() is called only once on the ProductService mock, and that no other methods of the ProductService mock are called during the test.

The complete test class is this:

ProductControllerTest.java

The complete output of the test sent to console is this:

Summary

The new @WebMVC used with MockBean allows creating powerful yet simple tests for your Spring MVC apps. Unlike the @SpringBootTest annotation, the @WebMvcTest annotation disables full auto-configuration. @WebMvcTest only auto-configures the Spring MVC infrastructure and limits scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Filter, WebMvcConfigurer, and HandlerMethodArgumentResolver beans.

When you use @WebMvcTest, regular @Component, @Service, or @Repository beans will not be scanned – an important point to differentiate @WebMvcTest from a full-blown @SpringBootTest.

If you’re looking to load your full application configuration and use MockMVC, you should consider @SpringBootTest combined with @AutoConfigureMockMvc rather than @WebMvcTest. I will cover it in an upcoming post of this Spring MVC testing series. I will also help you to explore more about mocking services and JPA repositories with @MockBean combined with @DataJpaTest and @WebMvcTest, and also how to unit test RESTful controller’s GETs and POSTs using MockMvc and @JsonTest.

4
Share
spring boot
,

Containers based deployments are rapidly gaining popularity in the enterprise. One of the more popular container solutions is Docker.

Many view containers as virtual machines. They’re not. Well kind of not. A container is a virtual walled environment for your application. It’s literally a ‘container’ inside the host OS. Thus your application works like it is in it’s own self contained environment, but it’s actually sharing operating system resources of the host computer.  Because of this, containers are more resource efficient than full blown virtual machines. You get more bang for your buck running a bare metal machine with a bunch of containers, than you do running a bare metal machine with a bunch of VMs. This is why massive cloud computing companies running 10’s of thousands of servers are running containers. Google, Facebook, Netflix, Amazon are all big advocates of containers.

Introducing  Docker Containers

To help you visualize the difference, here are a couple images provided by Docker. Here is the bloated architecture of a traditional virtual machine environment. A popular solution you can try is Oracle’s Virtual Box which allows you run a variety of operating systems on your personal machine. I personally use VMWare Fusion to run Windows on my MBP (and I still feel a little dirty every time I do). If you’ve never used either these, I recommend you give them a try.

In this graphic, note how each stack has its own Guest OS.

what-is-docker-diagram

Now for comparison, here is the same stack containerized by Docker. Here you can see how each application does not get its own operating system. This is key to why Docker containers are so efficient. You’re not providing a virtual layer mimic the hardware, for the the guest OS to use. And you’re not running n+1 guest hosts either.

Docker What is a VM

Clearly this is more efficient computing. I’ve seen estimates in the 10-25% range of improved performance. But like with everything else when it comes to computing performance – your mileage may vary. I’d expect lightweight linux VMs to be closer to the 10% side of the scale, and Windows VMs probably closer to the 25% end of the scale – just because the Windows OS is so bloated in comparison.

This leads me to an important distinction about Docker – Linux only. Yes, you can “run” Docker on Windows and OSX – but at this time, you can only do so using a VM running in Virtual Box to run – a Linux VM.

Running Spring Boot in a Docker Container

Introduction

When I first heard about running Spring Boot in a Docker container, I personally thought – “now why would you want to run a JVM in a VM, on a VM?” At first glance, it just seemed like a absolutely terrible idea from a performance standpoint. I doubt if any of these solutions will ever match the performance of a JVM running on a bare metal installation of Linux. But, I’ve shown above, running a Spring Boot application in a Docker container should have minimal performance impact. Certainly less of an impact than running in a VM. Which is exactly what you’re doing running applications in any cloud provider (see image one above).

Installing Docker

I’m not going to get into installing Docker on your OS. There is ample documentation about installing Docker in the internet. Going forward, I’m going to assume you have Docker installed. Since Docker is Linux based, my focus will be on Linux (RHEL / CentOS).

Spring Boot Example Application

For the purposes of this tutorial, let’s start with a simple Spring Boot Application. I’m going to use the completed application from my Mastering Thymeleaf course. This is a simple Spring Boot web application which is perfect for our needs.

If you want to follow this tutorial along step by step, head over to GitHub and checkout this Spring Boot project. Be sure to change to the branch “spring-boot-docker-start”.

Free Spring TutorialBuilding a Spring Boot Docker Image

For us to run Spring Boot in a Docker container, we need to define a Docker image for it. Building Docker images is done through the use of “Dockerfile”s. Dockerfiles are basically a manifest of commands we will use to build and configure our docker container. To configure our Docker image to run our Spring Boot application, we will want to:

  • Start with the latest CentOS image from Docker Hub.
  • Install and configure Oracle Java.
  • Install the Spring Boot artifact – our executable JAR file.
  • Run the Spring Boot application.

I’m using CentOS for its compatibility with RHEL, which is probably the most popular linux distribution used by enterprises. And Oracle’s Java, mainly for the same reason.

Create Our Dockerfile

In our Maven project, we need to create our Dockerfile. In /src/main/docker  create the file Dockerfile .

NOTE: As a Java developer you may be tempted to create the file as DockerFile. Don’t do this. The Maven Plugin we cover later won’t see your file if it’s CamelCase. I learned this lesson the hard way.

CentOS

We’ll start our Docker image off by using the CentOS image from Docker hub.

Dockerfile

Installing Oracle Java

The following lines in our dockerfile will install wget into the image using the yum package installer, download the Oracle Java JDK from Oracle using wget, then configure Java on the machine.

Dockerfile

Installing the Spring Boot Executable Jar

In this section of the Dockerfile, we are:

  • Adding a /tmp volume. Docker will map this to to /var/lib/docker on the host system. This is the directory Spring Boot will configure Tomcat to use as its working directory.
  • The ADD  command adds the Spring Boot executable Jar into our Docker image.
  • The RUN  command is to ‘touch’ the JAR and give it a modified date.
  • The ENTRY  point is what will run the jar file when the container is started.

I learned about these configuration settings from a post from the Pivotal team here.

Dockerfile

Complete Dockerfile

Here is the complete Dockerfile.

Dockerfile

Building the Docker Image Using Maven

Naturally, we could build our Docker image using docker itself. But this is not a typical use case for Spring developers. A typical use case for us would be to use Jenkins to generate the Docker image as part of a CI build. For this use case, we can use Maven to package the Spring Boot executable JAR, then have that build artifact copied into the Docker image.

There’s actually several competing Maven plugins for Docker support. The guys at Spotify have a nice Maven / Docker plugin. In this example, I’m going to show you how to use the Fabric8 Docker plugin for Maven.

Fabric8

Of the Maven plugins for Docker, at the time of writing, Fabric8 seems to be the most robust. For this post, I’m only interested in building a Docker Image for our Spring Boot artifact. This is just scratching the surface of the capabilities of the Fabric8 Maven plugin. This plugin can be used to spool up Docker Images to use for your integration tests for CI builds. How cool is that!?!? But let’s learn to walk before we run!

Here is a typical configuration for the Fabric8 Maven plugin for Docker.

Fabric8 Maven Docker Plugin Configuration

If you’re following along in tutorial, the complete Maven POM now is:

pom.xml

Building the Docker Image

To build the Docker image with our Spring Boot artifact run this command:

The ‘clean’ tells Maven to delete the target directory. While this step is technically optional, if you don’t use it, sooner or later you’re going to get bit in the ass by some weird issue. Maven will always compile your classes with the package command. If you’ve done some refactoring and changed class names or packages, without the ‘clean’ the old class files are left on the disk. And in the words of IBM – “Unpredictable results may occur”.

It is very important to run the package command with the docker:build command. You’ll encounter errors if you try to run these in two separate steps.

While the Docker image is building, you will see the following output in the console:

Docker images are built in layers. The CentOS image from Docker Hub is our first layer. Each command in our Dockfile is another ‘layer’. Docker works by ‘caching’ these layers locally. I think of it as being somewhat like your local Maven repository under ~/.m2. Where Maven will bring down Java artifacts once then cache them for future use.

The first time you build this Docker image, will take longer since all the layers are being downloaded / built. The next time we build this, the only layers that change are the one which adds the new Spring Boot artifact, all commands after this. The layers before the Spring Boot artifact aren’t changing, so the cached version will be used in the Docker build.

Running the Spring Boot Docker Image

Docker Run Command

So far, we have not said anything about port mapping. This is actually done at run time. When we start the Docker container, in the run command, we will tell Docker how to map the ports. In our example we want to map port 8080 of the host machine to port 8080 of the container. This is done with the ‘-p’ parameter, followed with <host port>:<container port>. We also want to use the ‘-d’ parameter. This tells Docker to start the container in the background.

Here is the complete command to run our docker container:

This command will start the Docker container and echo the id of the started container.

Congratulations, your Spring Boot application is up and running!

You should now be able to access the application on port 8080 of your machine.

Working with Running Docker Containers

Viewing Running Docker Containers

To see all the containers running on your machine, use the following command:

View Log Output

Our running Docker containers are far from little black boxes. There’s a lot we can do with them. One common thing we want to do is see the log output. Easy enough. Use this command:

Access a Running Docker Container

Need to ssh into a Docker container? Okay, technically this really isn’t SSH, but this command will give you a bash:

Stopping the Docker Container

Shutting down our Docker container is easy. Just run this command:

Ending Source Code

Just incase you’ve run into trouble, like always, I have a branch in GitHub with the complete working example. You can get the ending source code for this tutorial here on GitHub.

Conclusion

The default executable Jar artifact of Spring Boot is ideal for deploying Spring Boot applications in Docker. As I’ve shown here launching a Spring Boot application in a Docker container is easy to do.

In terms of technology, Docker is still fairly young. At the time of writing, Docker is only about three years old. Yet, it is rapidly catching on. While Docker is widely used by the web giants, it is just starting to trickle down to Fortune 500 enterprises. At the time of writing, Docker is not available natively on OSX or Windows. Yet. Microsoft has committed to releasing native version of Docker for Windows. Which is interesting. A lot things going on around Docker at Red Hat and Pivotal too.

Docker is a fundamental paradigm shift in the way we do things as Spring developers. I assure you, if you’re developing applications in the enterprise using the Spring Framework and have not used Docker, it’s not a matter of if, it is a when.

As a developer Docker brings up some very cool opportunities. Need a Mongo database to work against? No problem, spool up a local Docker container. Need a virtual environment for your Jenkins CI builds. No problem.

I personally have only been working with Docker a short time. I am honestly excited about it. My thoughts on Docker – Now we’re cooking with gas!

3
Share
spring boot
,

Recently while working with Jackson within a Spring Boot project, I encountered an issue I’d like to share with you.

Jackson is currently the leading option for parsing JSON in Java. The Jackson library is composed of three components: Jackson Databind, Core, and Annotation. Jackson Databind has internal dependencies on Jackson Core and Annotation. Therefore, adding Jackson Databind to your Maven POM dependency list will include the other dependencies as well. To use the latest Jackson library, you need to add the following dependency in the Maven POM.

The above dependency works well in other Java projects, but unfortunately in a Spring Boot 1.3.x application, you may stumble upon this error.

Jackson Dependency Conflict Error in Spring Boot

You may see several different errors. Here are some additional examples.

This error occurs due to Jackson dependency conflict. We are working on a Spring Boot project and it’s inheriting from the Spring Boot parent POM that includes Jackson. Without any Jackson dependency in the project POM, let’s print the Maven dependency tree to view the in-built Jackson dependencies.

The output is this.

As you can see above, the Spring Boot parent POM uses an older version of Jackson (2.6.5).

Now, if we add the Jackson dependency to our Maven POM using the version like this:

Maven will pulling in older versions of Jackson-annotation and Jackson-core and overriding the newer ones. We can see this by running the dependency:tree command again.

I did not expect Maven to behave this way in dependency resolution. The POM for the primary Jackson artifact does call for the proper version. However, this seems to be getting overridden by the versions specified explicitly in the Spring Boot parent POM.

Ideally, when working with Spring Boot, is to leverage the curated dependencies in the Spring Boot parent POM. In this case, we drop the version for the Jackson dependency so it will get inherited from the Spring Boot Parent POM.

Now, the version will be inherited from the parent POM, and the issue will be resolved.

But what if we want to use a newer version of Jackson? The proper way is to exclude the inherent dependencies, and explicitly add their new versions, like this.

This POM configuration will override the Jackson dependencies set in the Spring Boot parent POM.

This post is specific to Spring Boot version 1.3.3. Naturally, the Spring Boot team will be evolving the version of Jackson used in future releases.

For developers accustomed to working with Maven dependendencies, it’s a very easy mistake to include the version in the dependency declaration. This can cause some unintended issues due to version conflicts. It is a little bit of a paradigm shift for experienced developers to depend on the Spring Boot parent POM. Some won’t want to relinquish control, but in the long run I expect you will be better of leveraging the Spring Boot curated dependencies.

3
Share
spring boot
, ,

When it comes to logging in enterprise applications, logback makes an excellent choice – it’s simple and fast, has powerful configuration options, and comes with a small memory footprint. I have introduced logback in my introductory post, Logback Introduction: An Enterprise Logging Framework. YAML is just one option you can use for Spring Boot configuration. In a series of posts on logback, I’ve also discussed how to configure Logback using XML and Groovy and how to use Logback in Spring Boot applications. The posts are available as:

In my earlier post on Using Logback with Spring Boot, I used a properties file to configure logback. In this post, I’ll discuss how to configure Logback using Spring Boot’s YAML configuration file. If you’re a seasoned user of the Spring Framework, you’ll find YAML a relatively new configuration option available to you when using Spring Boot.

Creating a Logger

We’ll use a simple Spring Boot web application and configure logback with YAML in that application. Please refer my previous post, where I wrote about creating a web application using Spring Boot. This post expands upon concepts from the previous post, but is focused on the use of YAML configuration with Spring Boot.

The application from the previous post contains a controller, IndexController to which we’ll add logging code, like this.

IndexController.java

Since Logback is the default logger under Spring Boot, you do not need to include any additional dependencies for Logback or SLF4J.

Run the SpringBootWebApplication main class. When the application starts, access it from your browser with the URL, http://localhost:8080

The logging output on the IntelliJ console is this.

Default Logging Output

In the output above, the logging messages from IndexController are sent to the console by the logback root logger. Notice that the debug message of IndexController is not getting logged. Logback by default will log debug level messages. However, the Spring Boot team provides us a default configuration for Logback in the Spring Boot default logback configuration file, base.xml. In addition, Spring Boot provides provide two preconfigured appenders through the console-appender.xml and file-appender.xml files. The base.xml file references both of them.

The code of the base.xml file from the spring-boot github repo is this.

Here you can see that Spring Boot has overridden the default logging level of logback by setting the root logger to INFO, which is the reason we did not see the debug messages in the example above. As we’ll see in the next section, changing log levels in Spring Boot is very simple.

YAML Configuration via Spring Boot’s application.yml File

In a Spring Boot application, you can externalize configuration to work with the same application code in different environments. The application.yml file is one of the many ways to externalize configuration. Let’s use it to externalize logging configuration.

If you wish to use YAML for your Spring configuration, you simply need to create a YAML file. Spring Boot will look for a  application.yml file on the classpath. In the default structure of a Spring Boot web application, you can place the file under the Resources directory. To parse YAML files, you need a YAML parser. Out of the box, Spring Boot uses SankeYAML, an YAML parser. There is nothing you need to do to enable YAML support in Spring Boot. By default under Spring Boot, YAML is ready to go.

Here is an example of an application.yml file with basic configurations of logging levels.

In the configuration code above, we set the log levels of the Spring framework, any application logger of the guru.springframework.controllers package and its sub-packages, and hibernate to DEBUG. Although, we are not using Hibernate in our example application, I have added the Hibernate logging configuration for demonstration purposes so you can see how to configure logging for various Java packages.

When you run the application, you’ll notice DEBUG messages of the Spring frameworks’ startup on the console. When you access the application, notice the log messages of the IndexController now include the debug message.

Logging Level Configuration in YAML with Spring Boot
At this point, log messages are only being sent to the console. You can configure Spring Boot to additionally log messages to log files. You can also set the patterns of log messages both for console and file separately, like this.

With the updated YAML configuration, here is an example of the logging output.

Logging to File and Console with updated YAML configuration

Spring Active Profile Properties in YAML

Spring Profiles are commonly used to configure Spring for different deployment environments. For example, while developing in your local machine, it is common to set the log level to DEBUG. This will give you detailed log messages for your development use. While on production, its typical set the log level to WARN or above. This is to avoid filling your logs with excessive debug information and incurring the overhead of excessive logging.

You can segregate a YAML configuration into separate profiles with a spring.profiles key for each profile. Then, add the required logging configuration code to each profile and ensure that the profile lists are separated by the --- lines. In the same file, you can use the spring.profiles.active key to set the active profile. However, this is not mandatory. You can also set the active profile to use programmatically or passing it as a system property or JVM argument while running the application.

The complete application.yml file with logging configuration based on Spring profiles is this.

In the configuration code above, we defined two profiles: dev and production with different logging configurations. We also set the active profile to dev.

When you run and access the application, the logging configuration of the dev profile will be used and the logging outputs will be similar to this.
Logging Output of dev Profile

Now let’s make production the active profile by passing the -Dspring.profiles.active=production JVM argument.

In IntelliJ, select Run-> Edit Configurations, and set the JVM argument in the Run/Debug Configurations dialog box that appears, like this.
Run Debug Configurations Dialog Box

The logging output on accessing the application with production as the active profile is this.

Logging Output of production Profile

Separating Profiles in YAML Configuration Files

A Spring Boot configuration file is not limited to logging configurations only. Typically, several different types of configurations go into the different profiles of an enterprise application. Configurations can be of bean registrations, database connection settings, SMTP settings, etc. spread across development, testing, staging, production, and other profiles.

It’s both tedious and error prone to maintain a single file with multiple profiles with each profile containing different types of configuration settings. Remember, much more time is spent reading code and configuration files than is spent writing it. At some point in the future, yourself, or someone else, will be reading or updating the configuration files. And for monolithic configuration files with low readability, the chances of errors creeping in is high. Spring addresses such challenges by allowing separate configuration files – one for each profile. With separate configuration files, you improve the long term maintainability of your application.

Each of such configuration file must follow the application-.yml naming convention. For example, for the dev and production profiles, you need the application-dev.yml and application-production.yml files in the classpath. You should also add a application-default.yml file containing default configurations. When no active profile is set, Spring Boot falls back to the default configurations in application-default.yml.

It’s important to note that if you have a application.yml  file (with no suffix) on your path, that it will always be included by Spring, regardless of what profiles are or not active.

The project structure of the Spring Boot web application with different profile-specific configuration files is this.
Profile-specific YAML Configuration Files for Spring Boot

Following are the code for each of the configuration files.

application-default.yml

application-dev.yml

application-production.yml

Test the application by first starting it without any profile, then with the dev profile, and finally the production profile. Ensure that the expected configurations are being used for the different environments.

Conclusion

YAML configuration file in Spring Boot provides a very convenient syntax for storing logging configurations in a hierarchical format. YAML configuration, similar to Properties configuration cannot handle some advanced features, such as different types of appender configurations, and also encoders and layout configurations.

Functionally, YAML is nearly the same as using a traditional properties file. Personally, I find YAML fun to write in. It feels more expressive than the old school properties files and it has a nice clean syntax. Often you don’t need many of the more advanced logging features of logback. So you’re fine using the simplicity of the YAML file configuration. For advanced logging configurations using XML and Groovy, explore my earlier posts on them available here, and here.

I have encountered one issue with using YAML files for Spring Boot configuration. When setting up a JUnit test outside of Spring Boot, it was problematic to read the YAML properties file with just Spring. Remember, YAML support is specific to Spring Boot. I suspect at some point it will get included into the core functionality of Spring (If it has not already been).

1
Share
spring boot