AngularJS $http service is used for asynchronous server communication. This post explains $http
service in great details, specially $q
& promise
, with a complete CRUD application example, using AngularJS front-end client, communicating asynchronously with Spring REST API based back-end. You can plug-in your own server with this client to play with.
$resource
service instead. If you want to learn $resource, a complete post with CRUD example is available at Angularjs Server Communcation using ngResource-CRUD application example. To learn more about Spring REST API in general, don’t forget to visit Spring REST API Tutorial
AngularJS $http service allows us to communicate asynchronously with server endpoints using XHR [browser’s XMLHttpRequest Object] API. $http is designed for general purpose AJAX calls that can deal with both RESTful & Non-RESTful API on your server. For anyone coming from jQuery background, $http can be treated somewhat equivalent to jQuery.ajax. The $http API is based on the deferred/promise APIs exposed by the $q service which is an implementation of Promise interface
, based on Kris Kowal’s Q approach, which is a standardized way of dealing with asynchronous calls in JavaScript.
The Promise API comes with following flow:
Let’s take a simple example to understand $http.
// Simple GET request example : $http.get('/someUrl'). then(function(response) { // this callback will be called asynchronously when the response is available }, function(response) { // this callback will be called asynchronously if an error occurs or server returns response with an error status. });
In above example, then function takes two callbacks as parameter. First parameter gets called if the response is success. In case of failure, second parameter gets called. Both of callback parameters takes response as input.
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Our Server is Spring Based REST API, taken from this post. Basically, This is what our REST API does:
GET request to /api/user/ returns a list of users
GET request to /api/user/1 returns the user with ID 1
POST request to /api/user/ with a user object as JSON creates a new user
PUT request to /api/user/3 with a user object as JSON updates the user with ID 3
DELETE request to /api/user/4 deletes the user with ID 4
DELETE request to /api/user/ deletes all the users
For this post we will reuse the Server from mentioned post. We will just tweak the properties in User model object to meet the client from this example.
Declare Module [app.js
]
'use strict'; var App = angular.module('myApp',[]);
Create Service [user_service.js
]
Let’s create the service (using module.factory as discussed in AngularJs Service Post). This service will then be injected in controller.
'use strict'; App.factory('UserService', ['$http', '$q', function($http, $q){ return { fetchAllUsers: function() { return $http.get('http://localhost:8080/SpringMVC4RestAPI/user/') .then( function(response){ return response.data; }, function(errResponse){ console.error('Error while fetching users'); return $q.reject(errResponse); } ); }, createUser: function(user){ return $http.post('http://localhost:8080/SpringMVC4RestAPI/user/', user) .then( function(response){ return response.data; }, function(errResponse){ console.error('Error while creating user'); return $q.reject(errResponse); } ); }, updateUser: function(user, id){ return $http.put('http://localhost:8080/SpringMVC4RestAPI/user/'+id, user) .then( function(response){ return response.data; }, function(errResponse){ console.error('Error while updating user'); return $q.reject(errResponse); } ); }, deleteUser: function(id){ return $http.delete('http://localhost:8080/SpringMVC4RestAPI/user/'+id) .then( function(response){ return response.data; }, function(errResponse){ console.error('Error while deleting user'); return $q.reject(errResponse); } ); } }; }]);
Create Controller [app_controller.js
]
Controllwe will have our service injected, which it will then use from inside it’s functions exposed to User interface.
'use strict'; App.controller('AppController', ['$scope', 'UserService', function($scope, UserService) { var self = this; self.user={id:null,username:'',address:'',email:''}; self.users=[]; self.fetchAllUsers = function(){ UserService.fetchAllUsers() .then( function(d) { self.users = d; }, function(errResponse){ console.error('Error while fetching Currencies'); } ); }; self.createUser = function(user){ UserService.createUser(user) .then( self.fetchAllUsers, function(errResponse){ console.error('Error while creating User.'); } ); }; self.updateUser = function(user, id){ UserService.updateUser(user, id) .then( self.fetchAllUsers, function(errResponse){ console.error('Error while updating User.'); } ); }; self.deleteUser = function(id){ UserService.deleteUser(id) .then( self.fetchAllUsers, function(errResponse){ console.error('Error while deleting User.'); } ); }; self.fetchAllUsers(); self.submit = function() { if(self.user.id===null){ console.log('Saving New User', self.user); self.createUser(self.user); }else{ self.updateUser(self.user, self.user.id); console.log('User updated with id ', self.user.id); } self.reset(); }; self.edit = function(id){ console.log('id to be edited', id); for(var i = 0; i < self.users.length; i++){ if(self.users[i].id === id) { self.user = angular.copy(self.users[i]); break; } } } self.remove = function(id){ console.log('id to be deleted', id); if(self.user.id === id) {//clean the form if the user to be deleted is shown there. self.reset(); } self.deleteUser(id); } self.reset = function(){ self.user={id:null,username:'',address:'',email:''}; $scope.myForm.$setPristine(); //reset Form } }]);
Create FE Application [ServiceExample.html]
It’s a trivial user management CRUD application with AngulasrJS, using bootstrap for styling. We have modularized it a bit, by keeping module,controller & service in different files.
<html> <head> <title>AngularJS $http Example</title> <style> .username.ng-valid { background-color: lightgreen; } .username.ng-dirty.ng-invalid-required { background-color: red; } .username.ng-dirty.ng-invalid-minlength { background-color: yellow; } .email.ng-valid { background-color: lightgreen; } .email.ng-dirty.ng-invalid-required { background-color: red; } .email.ng-dirty.ng-invalid-email { background-color: yellow; } </style> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="app.css"> </head> <body ng-app="myApp" class="ng-cloak"> <div class="generic-container" ng-controller="AppController as ctrl"> <div class="panel panel-default"> <div class="panel-heading"><span class="lead">User Registration Form </span></div> <div class="formcontainer"> <form ng-submit="ctrl.submit()" name="myForm" class="form-horizontal"> <input type="hidden" ng-model="ctrl.user.id" /> <div class="row"> <div class="form-group col-md-12"> <label class="col-md-2 control-lable" ><u>2. Server Part</u></h4> As mentioned before, we can create a <strong>Spring REST API</strong> using <a href="http://websystique.com/springmvc/spring-mvc-4-restful-web-services-crud-example-resttemplate/">this post</a>. We need to adapt User properties based on User Interface in this example. Complete Server is shown below. <strong>Spring REST API controller</strong>: This Controller returns JSON response [thanks to Jackson library in classpath]. <strong>Service Interface</strong> <strong>Service Implementation.</strong> <strong>User Model class.</strong> <strong>Spring Configuration Class.</strong> <strong>Spring Initializer class.</strong> <strong>CORS filter class</strong> : To handle <strong>Same Origin policy</strong> related issues. <strong> Declare dependencies in pom.xml</strong> <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.websystique.springmvc</groupId> <artifactId>SpringMVC4RestAPI</artifactId> <packaging>war</packaging> <version>1.0.0</version> <name>SpringMVC4RestAPI Maven Webapp</name> <properties> <springframework.version>4.2.0.RELEASE</springframework.version> <jackson.version>2.5.3</jackson.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warSourceDirectory>src/main/webapp</warSourceDirectory> <warName>SpringMVC4RestAPI</warName> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </pluginManagement> <finalName>SpringMVC4RestAPI</finalName> </build> </project>
Project Structure
Build and Deploy Server to any Servlet 3 environment. I am using Tomcat 8 here. Then run the server using bin/startup.bat in Tomcat.
Open the FE (ServerExample.html) created above. You will see list of users.
Play with create/edit/delete users to see them in action. Open Developer Tools in your browser to see how client and server is communicating using JSON.
Please note that this live demo is showing only UI of your application, backed with static user data.There is no live JVM attached with this live demo. Refresh the page to repopulate with initial data.
That’s it. Complete source code for this post can be downloaded from Spring 4 MVC+AngularJS Example.
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
how to upload file using angularjs and spring boot thanks advance
You gotta have a look at ng-file-upload.
Thanks and i want ask How to make server api for upload file using spring boot plis help me thanks advance
Ng-file-upload just client side server side what to use
Ng-file-upload just client side
Hi Chandra, Did you look at File Upload/download section on Spring MVC Tutorials series?
Oh very good example. Thanks a lot. I expect an example to integrate app with social media like facebook..
Example is good but there should be some explanation for new users.
Hi Savita, i understood your concern. Thanks for pointing it out loud. In the beginning of post, i have just added the reference to specific posts over AngularJS Services and Spring REST API which can provide great detail for anyone.
Did find the solution myself, for welcome.jsp
@RestController
@RequestMapping(method = RequestMethod.GET)
public ModelAndView sayHello(ModelMap model) {
ModelAndView mav = new ModelAndView("welcome");
return mav;
}
Hi Mark,
Under the hood, @RestController is similar to @Controller+@ResponseBody. You might find this & this post useful.
Dear websystique,
Is it possible to combine the usual @Controller with @RestController.
If i put the contents of ServiceExample.html in a welcome.jsp, i just get the text welcome.jsp in the browser.
Mark
First of all thanks for the post. It's nice and useful. I've got one question. What is the difference between the following two snippets:
...then(self.fetchAllUsers, function(errResponse)...);
and
...then(self.fetchAllUsers(), function(errResponse)...);
The second one has additional braces. I mean why do you use the first one, and why does the second one give wrong behavior?
Thanks in advance!
Hi Stepan,
In first case, we are passing the function 'fetchAllUsers' as callback, without executing it immediately. It will be executed at some point in time when certain condition met [successful response from server, which will eventually carry some data from server we can play with].
In second case, we are executing it immediately. But this is not our goal, we want to execute it as a callback function only.
Note that in first case, you could have written the complete body as well, but since 'fetchAllUsers' is used on several places, i preferred to put only the function name, and defined it somewhere else. Hope it's clear for you
Congratulations again, great post.The source code is available for download ?
Hi Cleison,
This post consist of separate FE application & BE applications. It is deliberately done. FE application consist of just plain HTML with AngularJS, which is fully shown in this post. BE application is taken from from this post, also shown here with full code.
If you prefer one single application consisting both parts (with download), please look at SpringMVC+AngularJS Example post.