In this post, we will learn how to integrate AngularJS with Spring MVC and perform CRUD operation using $http service. We will be building a REST Web service using Spring MVC Controller (@RESTController) and AngularJS will act as the front-end, through $http service we will perform Create, Read, Update, Delete operations.
Folder Structure:
- Create a simple Maven Project “Spring-Angularjs-Tutorial” and create a package for our source files “com.javainterviewpoint” under src/main/java
- Now add the following dependency in the POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javainterviewpoint</groupId> <artifactId>Spring-Angularjs-Tutorial</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Spring-Angularjs-Tutorial Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.3.3</version> </dependency> </dependencies> <build> <finalName>Spring-Angularjs-Tutorial</finalName> </build> </project>
- Create the Java classes UserController.java and UserDetails.java under com.javainterviewpoint folder.
- Place the UserManagement.jsp under /webapp directory.
- Place the web.xml and SpringAngular-servlet.xml under the /WEB-INF directory
AngularJS Spring MVC CRUD Example using $http Service
We will be building the User Management system where in which you will be able to Create a User, Get all the user details, Modify an existing user and Delete the user. The final Screen looks like below
UserController
package com.javainterviewpoint; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { public List<UserDetails> userDetailsList = new ArrayList<UserDetails>(); public UserController() { userDetailsList.add(new UserDetails("User1", "Mechanical")); userDetailsList.add(new UserDetails("User2", "Electrical")); } @RequestMapping(value="/userdetails",method=RequestMethod.GET,produces="application/json") public List<UserDetails> GetUserdetails() { return userDetailsList; } @RequestMapping(value="/user",consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST) public ResponseEntity ProcessUser(@RequestBody UserDetails userDetails) { boolean nameExist = false; for(UserDetails ud : userDetailsList) { if(ud.getName().equals(userDetails.getName())) { nameExist = true; ud.setDepartment(userDetails.getDepartment()); break; } } if(!nameExist) { userDetailsList.add(userDetails); } return new ResponseEntity(HttpStatus.OK); } @RequestMapping(value="/deleteuser",consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.DELETE) public ResponseEntity DeleteUser(@RequestBody UserDetails userDetails) { Iterator<UserDetails> it = userDetailsList.iterator(); while(it.hasNext()) { UserDetails ud = (UserDetails) it.next(); if(ud.getName().equals(userDetails.getName())) it.remove(); } return new ResponseEntity(HttpStatus.OK); } }
Our UserController will be acting as the RESTFul Webservice, it has the below methods.
- UserController() constructor – This constructor will be creating two UserDetails objects and it will be added into the userDetailsList since we are not using any database in this AngularJS Spring MVC CRUD Example this step is necessary.
- GetUserDetails() – This method simply returns the userDetailsList which we have already built in our constructor.
- ProcessUser() – This method takes the JSON input and either creates a new User or modify the existing user. If the username which is sent in the request is already present in our userDetailsList then it will perform the “Edit” operation. If not it will “Create” the user and add it to the userDetailsList and Finally returns the “OK” Status message.
- DeleteUser() – This method deletes the UserDetails object which is sent in our request from the userDetails List.
UserDetails
package com.javainterviewpoint; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class UserDetails { @XmlAttribute private String name; @XmlAttribute private String department; public UserDetails() { super(); } public UserDetails(String name, String department) { super(); this.name = name; this.department = department; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } @Override public String toString() { return "UserDetails [name=" + name + ", department=" + department + "]"; } }
UserDetails class is a simple POJO class consisting the details of the user such name and department.
UserManagement.jsp
<!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>User Management</title> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> <script type="text/javascript"> var app = angular.module('myapp', []); app.controller('myappcontroller', function($scope, $http) { $scope.users = [] $scope.userform = { name : "", department : "" }; getUserDetails(); function getUserDetails() { $http({ method : 'GET', url : 'userdetails' }).then(function successCallback(response) { $scope.users = response.data; }, function errorCallback(response) { console.log(response.statusText); }); } $scope.processUser = function() { $http({ method : 'POST', url : 'user', data : angular.toJson($scope.userform), headers : { 'Content-Type' : 'application/json' } }).then( getUserDetails(),clearForm()) .success(function(data){ $scope.users= data }); } $scope.editUser = function(user) { $scope.userform.name = user.name; $scope.userform.department = user.department; disableName(); } $scope.deleteUser = function(user) { $http({ method : 'DELETE', url : 'deleteuser', data : angular.toJson(user), headers : { 'Content-Type' : 'application/json' } }).then( getUserDetails()); } function clearForm() { $scope.userform.name = ""; $scope.userform.department = ""; document.getElementById("name").disabled = false; }; function disableName() { document.getElementById("name").disabled = true; } }); </script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body ng-app="myapp" ng-controller="myappcontroller"> <h3>User Registration Form</h3> <form ng-submit="processUserDetails()"> <div class="table-responsive"> <table class="table table-bordered" style="width: 600px"> <tr> <td>Name</td> <td><input type="text" id="name" ng-model="userform.name" size="30" /></td> </tr> <tr> <td>Department</td> <td><input type="text" id="department" ng-model="userform.department" size="30" /></td> </tr> <tr> <td colspan="2"><input type="submit" class="btn btn-primary btn-sm" ng-click="processUser()" value="Create / Update User" /></td> </tr> </table> </div> </form> <h3>Registered Users</h3> <div class="table-responsive"> <table class="table table-bordered" style="width: 600px"> <tr> <th>Name</th> <th>Department</th> <th>Actions</th> </tr> <tr ng-repeat="user in users"> <td>{{ user.name}}</td> <td>{{ user.department }}</td> <td><a ng-click="editUser(user)" class="btn btn-primary btn-sm">Edit</a> | <a ng-click="deleteUser(user)" class="btn btn-danger btn-sm">Delete</a></td> </tr> </table> </div> </body> </html>
- First of all, we have created our angular app
var app = angular.module('myapp', []);
- Then we have created our controller “myappcontroller” and have injected the dependencies $scope and $http service. $scope interacts with the data in the screen and $http is used to make the REST service calls.
app.controller('myappcontroller', function($scope, $http)
- We have defined two scope variables $scope.users and $scope.userform. The $scope.users is a collection of users registered and whereas $scope.userform is used in the form fields.
$scope.users = [] $scope.userform = { name : "", department : "" };
- On the page load, we need to populate the users who are already registerd using the getUserDetails() method we will performing this. This method retrieves the list of all the registered users from the server through REST Service call. Once the JSON response is received it is mapped to $scope.users array.
getUserDetails(); function getUserDetails() { $http({ method : 'GET', url : 'userdetails' }).then(function successCallback(response) { $scope.users = response.data; }, function errorCallback(response) { console.log(response.statusText); }); }
- Once the user enters the form data and clicks on the “Create / Update User” button the processUser() method will be called this method send the user-entered form data to the server using REST call POST method. The user will be added newly if the userDetails list doesn’t contain the username, if the username is already present then the existing values will be edited.
$scope.saveUser = function() { $http({ method : 'POST', url : 'user', data : angular.toJson($scope.userform), headers : { 'Content-Type' : 'application/json' } }).then( getUserDetails(),clearForm()).success(function(data){ $scope.users= data }); }
- When the user clicks on the “Edit” button, the user object will be assigned to $scope.userform so that we will have the User Registration Form populated for edit. We will be disabling the Name field during edit in order to prevent duplicate users added.
$scope.editUser = function(user) { $scope.userform.name = user.name; $scope.userform.department = user.department; disableName(); }
- Delete button calls the deleteUser() method, the method removes the particular user in the server by placing the DELETE request.
$scope.deleteUser = function(user) { $http({ method : 'DELETE', url : 'deleteuser', data : angular.toJson(user), headers : { 'Content-Type' : 'application/json' } }).then( getUserDetails()); }
- clearForm() method resets the $scope.userform data and keeps the Name field enabled.
function clearForm() { $scope.userform.name = ""; $scope.userform.department = ""; document.getElementById("name").disabled = false; };
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Spring AngularJS Tutorial</display-name> <servlet> <servlet-name>SpringAngular</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SpringAngular</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>UserManagement.jsp</welcome-file> </welcome-file-list> </web-app>
- The web.xml has everything about the application that a server needs to know, which is placed under the WEB-INF directory. It contains the name of the SpringConfiguration file, when the DispatcherServlet is initialized the framework will try to load a configuration file “[servlet-name]-servlet.xml” under the WEB-INF directory.
SpringAngular-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.javainterviewpoint" /> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/Jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
- The SpringConfig-servlet.xml is also placed under the WEB-INF directory.
- <context:component-scan> will let the Spring Container to search for all the annotation under the package “com.javainteriviewpoint”.
- <mvc:annotation-driven/> annotation will activate the @Controller, @RequestMapping, @Valid etc annotations.
- The view is resolved through “org.springframework.web.servlet.view.InternalResourceViewResolver” which searches for the jsp files under the /WEB-INF/Jsp/ directory.
Output:
Santosh DJ says
thanx buddy.. very helpfull
Mido says
Thank you for the explanation
but the project is still unfinished and doesn’t work as it is with a Tomcat Server.
Thank you
javainterviewpoint says
I have uploaded the source code, check again
Mido says
That’s great thank you
KetanRay says
Thanks Brother.
This demo is very helpful , simple and clean code without explanation easy understand.
Thanks again brother
KetanRay says
NICE DEMO
THANKS BROTHER
satyanarayana says
clear example and easy understand…thank you sir
Flyff says
Thank you!!!
daren says
Thank you, sir. can I know whether this sample app is considered as RESTful application?
javainterviewpoint says
Yes, it can be as we are typically hitting the web service to get the desired response