Building modern web applications using Java and Spring
Creating Java web applications using Spring Framework has never been easier. If you’re already familiar with Java and have little to no experience creating web applications, or if you’re worried that all the cool kids abandoned Java in favor of Ruby and Node.js, you want to read this.
My intention is to provide here a practical guide to get up and running quickly on creating modern web applications using Java and Spring.
We’ll be using the latest versions of Java, Spring Framework (4.x), Spring Boot (v1.2.x), Spring Security, Spring Data JPA, Thymeleaf and Maven 3 frameworks.
Why using Spring framework
Spring is one of the most wildely adopted open-source Java frameworks.
- Spring is a mature yet still innovative open-source framework
- Spring has a very active community
- Spring is light-weight – can be run from the command line using an embedded container
- Spring and especially Spring Boot makes you productive – no requirement for XML configuration
Spring is more than a framework…
… it’s a platform that can get you covered on most technologies needed to build web applications:
- Creating MVC applications
- Providing authentication and authorization
- Connecting to RDBMS databases using JDBC, Hibernate and JPA
- Connecting to NoSQL databases (MongoDB, Neo4J, Redis, Solr, Hadoop, etc.)
- Handling messages (JMS, AMQP)
- Caching
- etc.
Time to Create Some Code
In this tutorial we’ll be creating a sample url-shortener application (the source code is available here) and while this post doesn’t cover all aspects of building a web application, hopefully you’ll find enough useful information to be able to get started and to want to learn more.
The application consist of a single HTML page and it can create a short-url from any url and as you can probably guess, it can also redirect from the short-url to the original url.
To run it execute below command in the command line (assuming you already have Maven v3 installed):
$ mvn spring-boot:run
Components
YourlApplication.java
This is the main class of the application that initializes the Spring context including all the Spring components in this project and starts the web application inside an embedded Apache Tomcat (http://tomcat.apache.org) web container.
@SpringBootApplication public class YourlApplication { public static void main(String[] args) { SpringApplication.run(YourlApplication.class, args); } }
It’s basically the @SpringBootApplication and the SpringApplication.run() method that does the magic here.
UrlController.java
@Controller public class UrlController { @Autowired private IUrlStoreService urlStoreService; // ... }
Following the MVC paradigm, this class serves as the Controller (note the @Controller annotation) that processes HTTP requests. Each method in this class annotated with @RequestMapping maps to a specific HTTP endpoint:
- showForm(): displays the home screen where users can enter url to be shortened
@RequestMapping(value="/", method=RequestMethod.GET) public String showForm(ShortenUrlRequest request) { return "shortener"; }
- redirectToUrl(): redirects from shortened url to the original one
@RequestMapping(value = "/{id}", method = RequestMethod.GET) public void redirectToUrl(@PathVariable String id, HttpServletResponse resp) throws Exception { final String url = urlStoreService.findUrlById(id); if (url != null) { resp.addHeader("Location", url); resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); } else { resp.sendError(HttpServletResponse.SC_NOT_FOUND); } }
- shortenUrl(): as the name suggests it creates a shortened version of the provided url and passes it to the shortener.html to be displayed
@RequestMapping(value="/", method = RequestMethod.POST) public ModelAndView shortenUrl(HttpServletRequest httpRequest, @Valid ShortenUrlRequest request, BindingResult bindingResult) { String url = request.getUrl(); if (!isUrlValid(url)) { bindingResult.addError(new ObjectError("url", "Invalid url format: " + url)); } ModelAndView modelAndView = new ModelAndView("shortener"); if (!bindingResult.hasErrors()) { final String id = Hashing.murmur3_32() .hashString(url, StandardCharsets.UTF_8).toString(); urlStoreService.storeUrl(id, url); String requestUrl = httpRequest.getRequestURL().toString(); String prefix = requestUrl.substring(0, requestUrl.indexOf(httpRequest.getRequestURI(), "http://".length())); modelAndView.addObject("shortenedUrl", prefix + "/" + id); } return modelAndView; }
As you can see, the @RequestMapping annotation takes care of mapping a single url to a Java method. The method can have multiple params:
- a @PathVariable (ie: id) which comes from the dynamic part of the url (/{id}), or
- a @RequestParam, or
- a POJO (Plain Old Java Object) where the fields correspond to request parameters, or
- a @RequestBody in the case of POST requests, or
- other predefined beans Spring makes available (for example, HttpServletResponse)
ShortenUrlRequest.java
The shorten url request is mapped into this POJO (Plain Old Java Object) by Spring. Spring also takes care of validating the request, see the the annotations on the url field.
public class ShortenUrlRequest { @NotNull @Size(min = 5, max = 1024) private String url; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
shortener.html
This is a Thymeleaf-based (http://www.thymeleaf.org/) template that uses Twitter Bootstrap (http://getbootstrap.com/) to render the home screen’s HTML code. It renders the data (Model) provided by the request mappings in the UrlController class.
... <div class="jumbotron"> <div class="container"> <h1>Shorten your url</h1> <p> <div class="alert alert-success" role="alert" th:if="${shortenedUrl}" th:utext="'Link created: <a href=\'' + ${shortenedUrl} + '\'>' + ${shortenedUrl} + '</a>'"> </div> <form class="form-inline" th:action="@{/}" th:object="${shortenUrlRequest}" method="POST"> <div class="alert alert-danger" role="alert" th:if="${#fields.hasErrors('*')}" th:errors="*{url}">Input is incorrect</div> <div class="form-group"> <input type="text" class="form-control" id="url" name="url" placeholder="http://www.example.com" th:field="*{url}" th:class="${#fields.hasErrors('url')}? fieldError"/> </div> <button type="submit" class="btn btn-primary">Shorten</button> </form> </p> </div> </div> ...
InMemoryUrlStoreService.java
The application currently only persists shortened urls into an in-memory persistence layer implemented in this minimalist class. Later on we can improve this by implementating the IUrlStoreService interface to persist data to a database.
@Service public class InMemoryUrlStoreService implements IUrlStoreService{ private Map<String, String> urlByIdMap = new ConcurrentHashMap<>(); @Override public String findUrlById(String id) { return urlByIdMap.get(id); } @Override public void storeUrl(String id, String url) { urlByIdMap.put(id, url); } }
Note the @Service method that tells Spring this is a bean from the Service layer that can be injected to other beans, like the UrlController.
Conclusion
That’s it in a nutshell. We covered all the pieces of this web application. I hope you agree now that building web applications using Java and Spring can be fun. No more boilerplate code and XML configurations, the latest version of Spring takes care all of that for us.
If you’re interested to learn more about Spring framework and Spring Boot, don’t forget to subsribe to my newsletter to get latest updates on Spring. Feel free to leave a comment below, if you have any questions or suggestions.
Reference: | Building modern web applications using Java and Spring from our JCG partner David Kiss at the Building scalable enterprise applications blog. |
Thanks for an amazing post. Just had one query though! configured the whole project as is into my system but it is not responding to localhost:8080/yourl/ and sending me to 404 page! Am I missing something here? Please help!
You don’t need /yourl in the context path as the application is using in the root context. This should work: http://localhost:8080.
May I get the source code? I’m starting with Spring and Thymeleaf and it can helps me.
Thanks
Dayan, you’ll find it here on github: https://github.com/davidkiss/yourl. Best of luck with learning Spring and Thymeleaf!