Java as RESTful backend of Angular.js
1. Introduction
In my last series of posts about real-time applications, I set up a little Java web application with Spring and Angular.js. I did not go in details about the architectural choices and the way I made Angular and Spring talk to each other. I thought a quick tutorial could be interesting.
2. Maven dependencies
The first thing we need is to setup Spring. For that, you need to add the Spring WebMVC dependency to your pom.xml
. Under the hood, Maven will fetch the Spring MVC’s dependencies like Spring Core and Spring Context.
pom.xml
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.1.RELEASE</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.6.2</version> </dependency> </dependencies>
AngularJS Programming Cookbook
In this ebook, we provide a compilation of AngularJS based examples that will help you kick-start your own web projects. We cover a wide range of topics, from Single Page Apps and Routing, to Data Binding and JSON Fetching. With our straightforward tutorials, you will be able to get your own projects up and running in minimum time. Download the cookbook by joining the Web Code Geeks Newsletter.
3. Setup Spring
3.1. Configuration with annotations
In order to have Spring configured, we need 2 things. The first one is the application initializer which has to be a subclass of AbstractAnnotationConfigDispatcherServletInitializer
. Quick side note here regarding the name of that class. It’s long… Personally, I prefer seeing a name that long that having something like AbstractAnnConfDispServletInit
like I did myself here with my AppInitializer
and my AppConfig
(!), or worse, AACDServletInit
. That aside, this implementation will force you to override 3 functions. The main one that is interesting is getRootConfigClasses()
which tells Spring which class is the configuration class. Those two classes replaces the configuration XML.
AppInitializer.java
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { AppConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
Here, I refer to a class named AppConfig
. This class will have the @Configuration
annotation and will define the component package for Spring to look in. The getServletMappings()
function binds the URI path "/"
to Spring’s request dispatcher, so in order to have static resources returned when queried, such as images, CSS and JS files, we also have to define a resource handler. This is done in the AppConfig
file.
AppInitializer.java
@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.javacodegeeks.examples.restfulbackend") public class AppConfig extends WebMvcConfigurerAdapter { public static final String REST_API_ROOT = "/api/"; @Override public void addResourceHandlers(final ResourceHandlerRegistry reg) { reg.addResourceHandler("/**").addResourceLocations("/"); } }
You can see here that Spring will search for components in com.javacodegeeks.examples.restfulbackend
.
3.2. The Web Service
If you go back to the pom.xml
above, you will see that there is Jackson DataBind in the dependencies. This will automatically convert all objects returned from the web service to the browser into Json ready to be processed by Angular. To create that web service, we will simply create a class with the @RestController
annotation and implement the different mapping.
SpringContactCRUDRestController.java
@RestController public class SpringContactCRUDRestController implements ContactCRUDController { @Autowired private ContactService contactService; @Override @RequestMapping(path = "/api/contact", method = RequestMethod.PUT) public void create(@RequestBody Contact contactToCreate) { this.contactService.create(contactToCreate); } @Override @RequestMapping(path = "/api/contact", method = RequestMethod.GET) public @ResponseBody List<Contact> get() { return this.contactService.get(); } @Override @RequestMapping(path = "/api/contact/{id}", method = RequestMethod.GET) public @ResponseBody Contact getById(@PathVariable("id") Integer id) { return this.contactService.getById(id); } }
All the business tier and the data storage is the same as in my previous article. It’s simply a repository I like to have to make proofs of concept. It allows to have a pseudo data store which is simply a Map
holding a key and the object. Another thing I like to use in POC for data storage is the embedded database of Java called Apache Derby. This way you can use a JPA implementation and change to a real database later on. If you are interested in the repository I just described, please see my article on real-time applications.
4. The Angular Module and Controllers
As we have pretty much no business logic, all the layers I put in place might seem overkill, but I really think that even a POC or an example like this one should have a proper basic architecture with separations like this. Of course, in Angular, you should be using services for any business logic and reusable code.
contactApp.js
contactApp = angular.module("ContactApp", []); contactApp.controller("ContactController", function($scope, $http) { $scope.contact = {}; $scope.getAll = function() { $http.get('api/contact') .success(function(data) { $scope.contacts = data; }); }; $scope.create = function() { $http.put('api/contact', $scope.contact) .success(function() { $scope.contact = {}; $scope.getAll(); }); }; $scope.get = function(id) { $http.get('api/contact/' + id) .success(function(data) { $scope.contact = data; }); }; $scope.getAll(); });
Here, we use Angular’s $http
service to create an XMLHttpRequest
to our CRUD controller which accepts PUT
and GET
. The PUT
method is used to create a new instance of the contact, and the GET
method is used in two different ways. Either we query the controller for a specific contact by adding the id as a request parameter, or we retrieve all contacts using no parameters.
5. Conclusion
So, in this article, we learnt how we can make Angular speak directly to a Spring service using the $http
service of the front-end framework. Using Jackson Databind along with Spring, we are able to have a web service that automatically converts our POJO to JSON and vice-versa. I think it’s important to notice also the way I implemented Spring’s configuration. I have absolutely no XML configuration files as it is done through Spring Java based configuration. This example could be interpreted as a simple startup project. I have done many tests to keep this as small as possible.
If you have any question, feel free to tweet at me (@syl20TOS) or send me a message on LinkedIn.
6. Download the Eclipse project
You can download the full source code of this example here: Java as a Restful Back-end for AngularJS