,

@RequestMapping is one of the most common annotation used in Spring Web applications. This annotation maps HTTP requests to handler methods of MVC and REST controllers.

In this post, you’ll see how versatile the @RequestMapping annotation is when used to map Spring MVC controller methods.

Request Mapping Basics

In Spring MVC applications, the RequestDispatcher (Front Controller Below) servlet is responsible for routing incoming HTTP requests to handler methods of controllers.

When configuring Spring MVC, you need to specify the mappings between the requests and handler methods.

Spring MVC Dispatcher Servlet and @RequestMappingTo configure the mapping of web requests, you use the @RequestMapping annotation.

The @RequestMapping annotation can be applied to class-level and/or method-level in a controller.

The class-level annotation maps a specific request path or pattern onto a controller. You can then apply additional method-level annotations to make mappings more specific to handler methods.

Here is an example of the @RequestMapping annotation applied to both class and methods.

With the preceding code, requests to /home will be handled by get() while request to /home/index will be handled by index().

@RequestMapping with Multiple URIs

You can have multiple request mappings for a method. For that add one @RequestMapping annotation with a list of values.

As you can see in this code, @RequestMapping supports wildcards and ant-style paths. For the preceding code, all these URLs will be handled by indexMultipleMapping().

  • localhost:8080/home
  • localhost:8080/home/
  • localhost:8080/home/page
  • localhost:8080/home/pageabc
  • localhost:8080/home/view/
  • localhost:8080/home/view/view

@RequestMapping with @RequestParam

The @RequestParam annotation is used with @RequestMapping to bind a web request parameter to the parameter of the handler method.

The @RequestParam annotation can be used with or without a value. The value specifies the request param that needs to be mapped to the handler method parameter, as shown in this code snippet.

In Line 6 of this code, the request param id will be mapped to the personId parameter personId of the getIdByValue() handler method.

An example URL is this:
localhost:8090/home/id?id=5

The value element of @RequestParam can be omitted if the request param and handler method parameter names are same, as shown in Line 11.

An example URL is this:
localhost:8090/home/personId?personId=5

The required element of @RequestParam defines whether the parameter value is required or not.

In this code snippet, as the required element is specified as false, the getName() handler method will be called for both of these URLs:

  • /home/name?person=xyz
  • /home/name

The default value of the @RequestParam is used to provide a default value when the request param is not provided or is empty.

In this code, if the person request param is empty in a request, the getName() handler method will receive the default value John as its parameter.

Using @RequestMapping with HTTP Method

The Spring MVC  @RequestMapping annotation is capable of handling HTTP request methods, such as GET, PUT, POST, DELETE, and PATCH.

By default all requests are assumed to be of HTTP GET type.

In order to define a request mapping with a specific HTTP method, you need to declare the HTTP method in @RequestMapping using the method element as follows.

In the code snippet above, the method element of the @RequestMapping annotations indicates the HTTP method type of the HTTP request.

All the handler methods will handle requests coming to the same URL ( /home), but will depend on the HTTP method being used.

For example, a POST request to /home will be handled by the post() method. While a DELETE request to /home will be handled by the delete() method.

You can see how Spring MVC will map the other methods using this same logic.

Using @RequestMapping with Producible and Consumable

The request mapping types can be narrowed down using the produces and consumes elements of the @RequestMapping annotation.

In order to produce the object in the requested media type, you use the produces element of @RequestMapping in combination with the @ResponseBody annotation.

You can also consume the object with the requested media type using the consumes element of @RequestMapping in combination with the @RequestBody annotation.

The code to use producible and consumable with @RequestMapping is this.

In this code, the getProduces() handler method produces a JSON response. The getConsumes() handler method consumes JSON as well as XML present in requests.

@RequestMapping with Headers

The @RequestMapping annotation provides a header element to narrow down the request mapping based on headers present in the request.

You can specify the header element as myHeader = myValue.

In the above code snippet, the headers attribute of the @RequestMapping annotation narrows down the mapping to the post() method. With this, the post() method will handle requests to /home/head whose content-type header specifies plain text as the value.

You can also indicate multiple header values like this:

Here it implies that both text/plain as well as text/html are accepted by the post() handler method.

@RequestMapping with Request Parameters

The params element of the @RequestMapping annotation further helps to narrow down request mapping. Using the params element, you can have multiple handler methods handling requests to the same URL, but with different parameters.

You can define params as myParams = myValue. You can also use the negation operator to specify that a particular parameter value is not supported in the request.

In this code snippet, both the getParams() and getParamsDifferent() methods will handle requests coming to the same URL ( /home/fetch) but will execute depending on the params element.

For example, when the URL is /home/fetch?id=10 the getParams() handler method will be executed with the id value 10.. For the URL, localhost:8080/home/fetch?personId=20, the getParamsDifferent() handler method gets executed with the id value 20.

Using @RequestMapping with Dynamic URIs

The @RequestMapping annotation is used in combination with the @PathVaraible annotation to handle dynamic URIs. In this use case, the URI values can act as the parameter of the handler methods in the controller. You can also use regular expressions to only accept the dynamic URI values that match the regular expression.

In this code, the method getDynamicUriValue() will execute for a request to localhost:8080/home/fetch/10. Also, the id parameter of the getDynamicUriValue() handler method will be populated with the value 10 dynamically.

The method getDynamicUriValueRegex() will execute for a request to localhost:8080/home/fetch/category/shirt. However, an exception will be thrown for a request to /home/fetch/10/shirt as it does not match the regular expression.

@PathVariable works differently from @RequestParam. You use @RequestParam to obtain the values of the query parameters from the URI. On the other hand, you use @PathVariable to obtain the parameter values from the URI template.

The @RequestMapping Default Handler Method

In the controller class you can have default handler method that gets executed when there is a request for a default URI.

Here is an example of a default handler method.

In this code, A request to /home will be handled by the default() method as the annotation does not specify any value.

@RequestMapping Shortcuts

Spring 4.3 introduced method-level variants, also known as composed annotations of @RequestMapping. The composed annotations better express the semantics of the annotated methods. They act as wrapper to @RequestMapping and have become the standard ways of defining the endpoints.

For example, @GetMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.GET).
The method level variants are:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

The following code shows using the composed annotations.

In this code, each of the handler methods are annotated with the composed variants of @RequestMapping. Although, each variant can be interchangeably used with @RequestMapping with the method attribute, it’s considered a best practice to use the composed variant. Primarily because the composed annotations reduce the configuration metadata on the application side and the code is more readable.

@RequestMapping Conclusion

As you can see in this post, the @RequestMapping  annotation is very versatile. You can use this annotation to configure Spring MVC to handle a variety of use cases. It can be used to configure traditional web page requests, and well as RESTFul web services in Spring MVC.

 

3
Share
, ,

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.

7
Share

In the 1.3.0 release of Spring Boot and new module is available called Spring Boot Developer Tools. This new Spring Boot module is aimed at improving developer productivity in building Spring Web Applications.

When you’re developing a web application in Java, or really any programming language, a common workflow is to code, compile, deploy, and then test in the browser. In scripting languages, such as PHP, there is no compile / deploy phase. The script is evaluated by the server at run time, thus negating the need for a compile / deploy phase.

In the world of Java web development, we don’t have this luxury. Our Java code is compiled down to Java byte code, then deployed to an application server such as Tomcat. The compile, deploy, test phase is a common step in the process of writing software. The longer it takes, the greater the impact it has on your productivity. I’ve seen this cycle take just a few seconds, to 30 minutes. Yes, 30 minutes! (It was a highly coupled legacy application from the early 90s – one of the most effing awful developer experiences I’ve ever encountered!)

For a long time, the Grails community has enjoyed the benefits of automatic class reloading. It’s such a pleasure coding a Java application, and only needing to save your file to have the code automatically reload in the Tomcat container – nearly instantly. This is one of the features that drew me to web development with Grails.

This feature has been missing from web development with Spring MVC for a long time. You could use a 3rd party tool such as jRebel, but at $475 annually for a license, it’s an expensive option for those coding outside the enterprise.

In the world of web development with just Spring MVC, this new feature available in Spring Boot Developer Tools has been long overdue. Way way overdue!

Reloading vs Restarting

The reloading agent from Grails is now its own project, called Spring Loaded. This takes a slightly different, but important approach than the one used in Spring Boot Developer Tools. In reloading, the agent reloads the Java class in the JVM. This avoids the need to start the Tomcat container and Spring context. But has some drawbacks. Works great for coding changes in the class itself. But change the package, or add a new class / Spring bean, and you still need to restart.

Spring Boot Developer Tools takes a different approach, it does a restart, not a reload. BUT – under the covers, it is using two class loaders. One for all jar classes in your project, and one for your project classes. Thus on a ‘restart’, only the project classes are reloaded. The 10’s of thousands of classes contained in jar files in your typical Java Spring project are not reloaded. By doing this, restarting Tomcat and the Spring context become VERY fast. Since the Spring context is being restarted, it addresses issues found with the approach used in Spring Loaded.

Use with Build Tools

The automatic restart is triggered when changes on the classpath are detected. Thus if you build with Maven or Gradle class files in the target directory will change and an automatic build will be triggered.

Use with IDEs

IntelliJ and Eclipse are the two most popular IDEs for Java development. There are some notable differences in use between the two IDEs.

Eclipse is the foundation for the Spring Tool Suite (aka STS). Development of the Spring Boot Developer Tools seems biased towards STS. Which is to be expected. Both are Pivotal products. An automatic restart in Eclipse is triggered with the save action. In Eclipse, this triggers a recompile of the change classes, which triggers the automatic restart.

With IntelliJ the process is slightly different. IntelliJ does not recompile on save, but unlike Eclipse, it does perform automatic file saves for you. IntelliJ can be configured to compile on save, but this gets disabled when an application is running. Thus in IntelliJ, you need to trigger the build manually, which will in turn fire off the automatic restart. So with the extra step, the developer experience in IntelliJ is not quite as smooth.

I prefer the developer experience with Spring Loaded, where the changes made to your *.java files will trigger the automatic restart/reload. If the Spring Boot Developer Tools had been developed the same way, the developer experience in both IDEs would be the same. Maybe the team developing the Developer Tools had a technical reason for this. Or maybe it was a choice by Pivotal to promote STS on the Eclipse platform.

This is inconvenient, but I’m not changing IDEs. The last time I tried STS, it was awful. Randomly hanging, or crashing. You just get what you pay for IMHO.

Live Reload

Another cool feature of the Spring Boot Developer Tools is the Live Reload integration. Live Reload is a browser plugin, which will trigger a page reload upon changes to the source. Thus when you change web content, the page in the browser will automatically refresh. Small improvement. But it is nice not clicking refresh in the browser all the time.

Live Reload is advertised to work for Firefox, Chrome, and Safari. I was unable to get the plugin working in Firefox – it may be currently broken with Firefox. I did get Live Reload working fine with Chrome. I did not try using it with Safari.

Free Introduction to Spring Tutorial

Are you new to the Spring Framework? Checkout my Free Introduction to Spring Online Tutorial.

Remote Development and Debug

The Spring Boot Developer Tools includes support of doing remote development and debugging. You can configure automatic restarts and debugging to a remote server. Kind of a cool thing to do. But I’m not sure where I would personally ever use this feature. The folks from Pivotal have a little demonstration of this towards the end of this video.

Demonstration of Spring Boot Developer Tools

I’ve described how Spring Boot Developer Tools can improve the development workflow and improve your productivity. But a seeing a demonstration is far more effective. I recorded this video to show you the Developer Tools in action.

Conclusion

The Spring Boot Developer Tools module brings some great (and long overdue) features to developing applications with Spring. The automatic restart feature will have a positive impact on your productivity in developing web applications. Use of Developer Tools will change how you develop applications, in a good way. This is the initial release, and the time I’ve spent using the Developer Tools has been short. I saw one quirky thing, but not a show stopper. My impression is the developer tools module is ready for production use. If you’re using Spring Boot to develop web applications, it’s time to upgrade to the 1.3.0 release.

2
Share
, , ,

This is the 4th part of my tutorial series on building a web application using Spring Boot.  In the the last part of the series, we looked at setting up Spring Data JPA for database persistence. In the second part of the series we looked at using Thymeleaf for building the web pages. And we started off in the first part looking at using the Spring Initializr to start our Spring Boot project.

In this part of the series, we tie everything together to provide a working Spring Boot web application. An application which will display data from the database, and allow you to create new records, update existing records, and delete selected records too.

Spring MVC

In this part of my tutorial series for Spring Boot, we’re going to look at setting up a Spring MVC controller to support CRUD operations against the database.

MVC stands for Model, View, Controller. The MVC design pattern is probably the most popular design pattern used when writing code to generate dynamic web content. This design pattern is not limited to Java nor Spring. The MVC design pattern has been applied in Javascript, PHP, .NET, Python, and many other programming languages. The MVC pattern is popular because it does a great job of separating concerns, and leads you to a clean, maintainable, and easy to understand code base.

MVC Overview

Model

Model refers to a data model, or some type of data structure. For example a web page showing a list of products, the ‘model’ would contain a list of product data.

View

The view layer, in Java frequently a JSP. This will take data from the Model and render the view.

Controller

I like to describe the controller as a traffic cop. It will take an incoming request, decide what to do with it, then direct the resulting action. For example, the controller could get a view product request. It will direct a service to get the product data, then direct to the product view and provide the ‘model’ (product data) to the view.

Single Responsibility Principle Applied to MVC

Frequently when dealing with legacy code, I see a lot of leakage between the layers. JSP pages making database calls. Controllers building database connection pools. On one legacy application I recently worked with the JSP pages and controllers were littered with static method calls, which ultimately made a call to an Oracle database. Because of this, the application was impossible to run outside of the application server. The code was so tightly coupled, there were no unit tests in what is a very large code case. Why? You can’t run any of the code under JUnit because of all the embedded static method calls.

In an MVC application each component has a specific function in life. You should be able to unit test your controllers. Using Mocks, you should be able to unit test that your controller returns the proper model, and makes the proper decisions.

CRUD Operations with Spring MVC

CRUD is a common acronym for Create, Read, Update, and Delete. In the last part of the series, we looked at creating a CRUD repository using Spring Data JPA. In this post, we’ll look at setting up the Spring MVC controller for the corresponding CRUD operations. We’ll continue using the Product class we previously used.

Create

The Create operation is a two step operation. The first step needs to display the create form, the second needs to do the save of the form post.

Here is the controller code for displaying the create product form.

The @RequestMapping  annotation maps the url ‘product/new’ to this controller action. Our controller method is taking in the model attribute. This is the ‘model’ being returned to the view layer.

You can see in the code, we are returning an empty product class to the view. This is more of a trick to re-use the view code for both the Create and Update form. By providing a empty Product object, we reduce the likelihood of null pointer errors when rendering the view. You can either provide an empty object to the model, or do a lot of null checking in the view. From experience, I’ve found this simpler.

Our create view is going to have a form post. We need a controller action to handle this.

In this controller method, we’re handing the form post. The @RequestMapping annotation says to take the ‘url’ ‘product’ and the HTTP request method of POST to map it to this controller method. You can see how we’re asking for a Product object as input to the controller method. One of the cool things about Spring MVC is that it will take your form parameters and automatically bind them to a Product object. The object is automatically created and passed into your controller method. The Spring Framework saves you from the mundane work of parsing out HTTP request parameters.

You can see how we’re using a product service to handle the persistence. This is just a facade to the Spring Data JPA repository we created in the last post. I’m going to skip over the persistence code here. You’ll be able to find it in github. I want you to notice how I’m writing to an interface. The controller doesn’t know about persistence. It does not need to. Storing data is not the job of the controller. Maybe that method is using JDBC. Maybe it is calling a web service. Maybe it’s using JMS. Might be using AQMP. The controller does not care. The controller code does not need to care. This is a great example of decoupling code. Too often I see legacy code where the controllers are doing way too much.

On the last line of the saveProduct method, you can see I’m returning a string with “redirect”. This tells Spring after the save action to redirect to the view to show the created item. This example just show the ‘happy path’ – where everything happens as it should. In a more robust controller you’d have logic not only for the happy path, but to redirect to the create form if validations were to fail.

Read

In Read operations, the client is going to tell you what it wants. In our case, the client will give us an Id value, and we’ll return the corresponding Product.

Read by Id

You can see in our controller method, the Request Mapping is using ‘product’ with a id value in squigglies. This identifies that portion of the url path as an ‘id; value.

Now, we’re using a new annotation @Pathvariable to inject the id value from the url path into our controller as the ID variable. Again, we’re accepting the model variable into our controller. We’re asking the product service to get the product, and the result is appended to the model object, which is returned to the view. The controller method returns a string to indicate which view to render.

List All

A common method is also to provide a list view. Normally, you’re going to want to add paging or some type of filter. However, in this example, we just want to show a simple example of listing products from the database.

We’ve mapped this controller method to the URL ‘/products’. We ask the product service for a list of all products and append it to the model attribute “products”. The controller method returns the string ‘products’ to tell Spring MVC to render the products view.

Update

Updates are actions against existing entities. Updates are similar to create actions, where we have two controller actions involved. With a create, we’re showing a form for a new item, while an update is going to be populated with data from an existing item. While this is very similar to the create action, we typically will want a separate controller action to show the edit form to capture the data for the update.

The good news, functionally the save and view of the saved item is the same as the create action.

Here is our save method once more:

You can see we’re using Spring to bind the form post parameters to a Product object, then calling the product service to save the item. Then just like in the save method of the create process, we want to view the saved product, so we redirect to the show product view.

Delete

There’s a few different ways to implement a delete action. One of the easiest is to use a url with the ID for the delete action. This can then be implemented on the web forms as a simple URL to click on. Below is the controller action for the delete action.

This method will take in the id value from the URL and pass it to the delete method of the product service. Since we’re not creating or updating a product, a typical course of action is to return to the list view. In this example, we redirect to the products view to show the user a list of products.

Summary of CRUD Operations

At this point we’ve covered the necessary controller actions to support CRUD operations on an entity. You can see these operations work in conjunction with the Spring Data JPA methods we looked at in the previous post on Spring Data JPA. I’m using a Facade Service to mask the Spring Data JPA implementation. We’ll take a look at the Facade in the next section.

Free Spring Tutorial

Spring Facade Service

You can see in the controller methods above, there is no dependency on the persistence layer. The controller is completely unaware of how data is being persisted. This is exactly as it should be. Too often I see legacy code where the controller is interacting with the database directly. This is a very poor coding practice. It makes your code tightly coupled and hard to maintain.

Code to an Interface

When using Spring to develop applications it is always best to develop to an interface, especially when leveraging the benefits of dependency injection.  To support our controller actions, I wrote the following interface.

ProductService.java

Notice how this interface is rather generic? Can you tell how data is being persisted? JDBC? Spring Data JPA? Web Service? JMS? This is what decoupling is about. At this point, the answer is all of the above. We just need to provide the appropriate implementation.

Spring Data JPA Product Service Implementation

In the last post of this series, we looked at using Spring Data JPA. Now we need an implementation of the Product Service which will use the Spring Data JPA repositories.

Spring Data JPA Repository

We’ll need to inject an instance of the Spring Data JPA repository into the implementation of our product service. You can do so by declaring a property for the repository and annotating the setter method with the @Autowired  annotation.

List Products

Using Spring Data JPA, it becomes trivial to list all the products for our application. While we did not actually create a findAll()  method on the repository we defined, we inherited by extending the CrudRepository  in Spring Data JPA. This is one of many handy features of Spring Data JPA. It’s going to provide us an implementation of the findAll()  method, which we do not need to write code for.

Get Product (Read)

To fetch a product by its id value, again, we can leverage a method implemented for us by Spring Data JPA.

Save Product (Create / Update)

Spring Data JPA also provides us an implementation of a save method for saving entities. We use this method in creating and updating products in our web application.

Delete Product (Delete)

Finally, in our CRUD operations, Spring Data JPA provides us an implementation of a delete method. Spring Data JPA overloads the delete method, accepting just the ID value, or the entity itself. For our purposes, we are using the ID value to delete the desired entity.

Summary of Spring Data JPA Usage

In this example, we implemented the CRUD operations using a CrudRepository supplied by Spring Data JPA. If you look at the code you will see all we did was extend the Spring Data JPA CrudRepository to create our Product Repository. We did not define, nor implement an additional methods. We’re not declaring transactions. We’re not writing any SQL. I hope you can see the simplicity and time saving using tools like Spring Data JPA can bring you.

Thymeleaf

Thymeleaf Fragments

Thymeleaf fragments are a very powerful feature of Thymeleaf. They allow you to define repeatable chunks of code for your website. Once you define a Thymeleaf fragment, you can reuse it in other Thymeleaf templates. This works great for components you wish to reuse across your web pages.

In developing the Spring Boot Web Application, I found two uses for Thymeleaf templates. The first was common includes of the CSS, Javascript. The second was for a common menu I wanted to display at the top of each web page.

Includes

Below is the Thymeleaf Fragment I’m using for the HTML header includes. You can see its a normal HTML document, using Thymeleaf tags to define the resources for a page.

headerinc.html

Menu

For our Spring Boot Web Application, I chose to use the Bootstrap CSS framework. I’m big fan of Bootstrap. It’s easy to use, and its components look great. Bootstrap CSS has a menu component which I chose to use for the menu system.

In this Thymeleaf fragment, I’m providing the Bootstrap CSS menu I want to place at the top of all my pages. I also have a section to show my Spring Boot logo on each page.

header.html

Including Thymeleaf Fragments

Example

Previously, we defined an index page for our Spring Boot web application. You can apply Thymeleaf templates through the use of HTML comments. By doing this, you preserve the ability of the document to be viewed in the browser. You will be able to see the document okay in your browser, but the fragment portions will be omitted. The fragments are only included when the Thymeleaf template is rendered by Spring.

Remember, Spring will be reading the Thymeleaf templates, then producing output based upon the Thymeleaf directives.

index.html

You can see how our index page is very simple now. While this is a very lean HTML document, when Spring renders it at run time, you will see HTML looking like this:

Actual HTML Rendered to Browser

Notice how Thymeleaf and Spring have merged the contents of the index.html document and the two Thymeleaf fragment documents? Now you have pure HTML, and Thymeleaf tags are not rendered to the HTML content sent to the browser.

The index.html Thymeleaf template will show this page in your browser.

Thymeleaf Index page

Thymeleaf Views for CRUD Application

Show Product

Showing a product is one of the simpler operations under Spring MVC and Thymeleaf. Our controller returned a product object to the model and bound it to the property ‘product’.  Now we can use the typical name-dot-property syntax to access properties of the product object.

This Thymeleaf tag:

Will get text from the description property of the product object and replace the ‘description’ text in the paragraph HTML tag.

Here is the full Thymeleaf template for showing a product:

productshow.html

The show product Thymeleaf template will show this page:

Thymeleaf Show Product Page

List Products

The list view is a little trickier because now we have a list of products to iterate over. Luckily, Thymeleaf makes this very easy to do.

Here is a snippet showing how to iterate over a list of products.

You can see the syntax of this Thymeleaf tag is similar to a for-each loop in Java.

Our controller added a list of products to the ‘products’ property to the model, which we pass to the Thymeleaf tag. The variable name we are assigning to the iterator is ‘product’.

The body of the each tag will be rendered once for each product in the list of products.

Here is the complete Thymeleaf template used for showing a list of products.

products.html

Here is the Thymeleaf list products page:

Thymeleaf List Products

Create / Update Product

We can use the same HTML form for creating and updating products. A little trick is to have your controller method return an empty object to the view for the create option, and the existing object for the update option. By doing this you don’t need to worry about null objects on the view layer. For a new object, the null properties show up blank. For existing objects, non-null properties will get populated into the form fields.

The following line sets up the form in Thymeleaf.

The “th:object” tag binds the product object to the form. Thus, you only use the property names on the form fields. No need to qualify the object name too.

The “th:action” tag maps the form action to the ‘/product’ url. And we specify to use the HTML post action for the form.

Here is the controller action this maps back to:

Notice how we’ve assigned the url ‘product’ and method POST in the request mapping.

This next step is critical for your updates to work properly. All entities have an ID value. This is not accessible for the user to edit, but it still needs to be included to the post back to the server, so Spring / Hibernate can find the correct entity to update. If this is missing, there is no way to distinguish between and update and a create. If the ID property is missing from the form post, Spring Data JPA will think it’s a new item and create a new entity.

The way to handle this is through the use of hidden form fields. In this snippet, we’re assigning hidden fields for the Id and version values. (A best practice in Hibernate is to use a version property to detect conflicting updates.)

Here is the complete product form.

productform.html

Here is the Thymeleaf product form.

Thymeleaf Product Form

Thymeleaf Spring Course
Want to learn more about Thymeleaf, check out my Thymeleaf Spring Course!

Conclusion

In this post we built upon the previous posts in this series on building a web application using Spring Boot to have a functional web application which performs CRUD operations against a single entity. At this point, you can checkout the project from Github and build it using Maven. Spring Boot will create an executable JAR, which you can run to demo the application. Spring Boot will run the application in an embedded Apache Tomcat instance and you will be able to see the application running at http://localhost:8080.

In the next part of this series, I’ll show you how to secure content using Spring Security.
&nbsp:

Free Introduction to Spring Tutorial

Are you new to the Spring Framework? Enroll in my free Introduction to Spring Course!

Get The Source!

Like all of my tutorials, the source code for this post is available on GitHub here.

Save

47
Share

Spring Boot – Making Spring Fun Again

I’ve been playing around with Spring Boot again and really like what The Spring Team has been doing. Spring Boot is making Spring fun again. I haven’t had this much pleasure developing Spring Applications since I started learning Grails.

One of the things I loved about the Grails framework was its common sense approach to building web applications. Sure, Spring was under the covers of Grails. But the Grails team wired Spring up with a lot of defaults. For example, if you were using Hibernate to write to a database of course you’re going to want a Spring Transaction Manager.

Grails came out of the box with a transaction manager configured for you. If you were writing a Spring MVC application, you’d need to add a transaction manager into your configuration. The Spring Framework gives you all these pre-built components, but it was left up to you to wire them up into your application. You as the developer are responsible for everything. All the components are there, but some ‘assembly’ is required.

The cool part about Spring Boot is it makes a lot of common sense guesses for you. Like if you add Hibernate to your build, it guesses you’re going to want a transaction manager. The transaction manager is just one example of a common no-brainer Spring component you’d normally need to wire up that Spring Boot will automatically do for you. Spring Boot actually has over 200 default choices which it makes for you.

Spring Boot takes a lot of the mundane pain out of building Spring Applications. It really is making Spring Fun again. Spring Boot is still a newcomer in the family of Spring Projects. Even though Spring Boot is new, I think its the future of Spring application development.

Building a Spring Boot Web Application

Think about building a simple web application using Spring. You’re probably going to want to:

  • Use Spring of course!
  • Spring MVC for the web part.
  • Thymeleaf for the template engine, because you’re just plain tired of using JSPs.
  • Good ol’ Hibernate for your ORM.
  • An H2 database as your development database.
  • Spring Data to take the pain out of using Good Ol’ Hibernate.
  • Spring Security to secure your web application.
  • Tomcat as your application server.

In this Spring Boot tutorial I’m going to walk you through step by step in developing a web application using Spring Boot and the technologies I listed above.

Free Spring Tutorial
New to Spring? Checkout my free Introduction to Spring online course.

Getting Started with Spring Boot

I already created one ‘Getting Started with Spring Boot‘ post, but I’m going to walk through another example here. I want you to be able to follow through this Spring Boot tutorial step by step.

Creating the Spring Boot Project Using IntelliJ

The folks over at JetBrains have added some awesome support for Spring Boot in IntelliJ. This makes it very easy to create a Spring Boot based project using the IntelliJ IDE.

In the following video, I show you how to initialize a Spring Boot project with IntelliJ.

If you don’t have access to IntelliJ, you can always use the Spring Initializr to download a preconfigured Spring Boot project. Be sure to check the following options:

  • Security
  • Thymeleaf
  • Web
  • JPA
  • H2

Reviewing the Spring Initializr Artifacts

The project created by the Spring Initializer is a Maven project and follows the standard Maven directory layout. Below is a screen print from my IntelliJ IDE. There is one application class created for us, an empty properties file, a stub for a JUnit integration test, and the Maven POM file.
spring boot project structure

SpringBootWebApplication.java

The Spring Initializer create us a very basic Spring Boot application class. Technically, this is a Spring Configuration class. The annotation @SpringBootApplication enables the Spring Context and all the startup magic of Spring Boot.

SpringBootWebApplicationTests.java

We’re also give a stub of a JUnit Integration test. Checkout this post if you’d like to learn more about Integration Testing with Spring and JUnit.

pom.xml

Here is the Maven POM file that the Spring Initializer created for us. This was customized for us based on the options we selected in the Spring Initializer. The presence of these dependencies is important because Spring Boot will make decisions on what to create automatically when certain things are found on the classpath. For example, you can see the dependency for the H2 database. Because this exists on the classpath when the application is run, Spring Boot will automatically create a data connection and an embedded H2 database.

Spring Boot Dependencies

What I found interesting about Spring Boot is how it manages dependencies. In the early days of Java development, you as the developer were required to manage all the dependencies. It was a very time consuming task. And led to a lot of errors. If you were using an open source library in your project, it was very easy to forget one of its dependencies, which could lead to runtime errors. In modern Java development this task of dependency management has been delegated to tools such as Maven.

Now when you define a dependency in Maven, Maven checks that artifacts dependencies, each of which can have its own set of dependencies, and so on. You can read more about dependency management in Maven here.

I’m impressed with how the Spring Boot team has leveraged the dependency management features of Maven (and Gradle) for Spring Boot. Prior to Spring Boot, when setting up a Spring Project, you needed to compose the Spring jars needed for your project. This was not always as straight forward as it sounds. The Spring Boot team has basically created Spring Boot POMs with bundled Spring dependencies.

You can use the Maven command of mvn dependency:tree to generate a report on the dependency tree. Running the command on this project produces the following dependency tree.

Here you can see how the top level Spring Boot starter dependencies listed in the Maven POM file call in their respective Spring components. Its a very simple idea, but very useful too. In days past, I can remember whenever starting a new Spring project spending a morning or so mucking around setting up the Maven Dependencies for the Spring components I was using.

Free Introduction to Spring Tutorial

Are you new to the Spring Framework? Checkout my Free Introduction to Spring Online Tutorial.

Conclusion

In this post we’ve taken a look at using the Spring Initializer via IntelliJ to create a Spring Boot Project and examined the project files created by the Spring Initializer.

If you watched the video of me trying to run the Spring Boot application in IntelliJ, you saw the application fail because there were not Thymeleaf templates. In the next post of this tutorial series on Spring Boot, I’ll show you how to setup the Web Assets.

Get The Code

I’ve committed the source code for this post to github. It is a Maven project which you can download and build. If you wish to learn more about the Spring Framework, I have a free introduction to Spring tutorial. You can sign up for this tutorial in the section below.

The source code for this post is available on github. You can download it here.

Save

0
Share