AngularJS is the current MVV-Whatever JavaScript framework by Google. Among other things, it provides bidirectional data binding.
we choose the following scenario for my ‘Hello-World’ example:
Java backend provides a RESTful web service.
AngularJS consumes the web service.
That’s it.
Project structure
We intentionally put the backend and frontend code in the same project to simplify the example. In a real project you probably want to have seperate projects for front- and backend.
1
2
3
4
5
6
7
8
+---------------------------------------------------+
| demo project |
| |
| +----------------+ +---------------+ |
| | backend ( Java) | < -( REST) - > | frontend ( JS) | |
| +----------------+ +---------------+ |
| |
+---------------------------------------------------+
Since the backend is Java based, we used a Maven default structure (maven-archetype-site-simple
):
project structure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
├── _documentation
│ └── readme.txt
├── ngdemo.iml
├── pom.xml
└── src
└── main
├── java
│ └── ngdemo
│ ├── domain
│ │ └── User.java
│ ├── rest
│ │ └── UserRestService.java
│ └── service
│ └── UserService.java
└── webapp
├── css
│ └── app.css
├── img
├── index-async.html
├── index.html
├── index.jsp
├── js
│ ├── app.js
│ ├── controllers.js
│ ├── directives.js
│ ├── filters.js
│ └── services.js
├── lib
│ └── angular
│ ├── angular-cookies.js
│ ├── angular-cookies.min.js
│ ├── angular.js
│ ├── angular-loader.js
│ ├── angular-loader.min.js
│ ├── angular.min.js
│ ├── angular-resource.js
│ ├── angular-resource.min.js
│ ├── angular-sanitize.js
│ ├── angular-sanitize.min.js
│ └── version.txt
├── partials
│ └── partial1.html
└── WEB-INF
└── web.xml
src/main/java
is the backend.
src/main/webapp/js
is the frontend.
src/main/webapp/
also includes a copy of angular-seed.
RESTful web service (backend)
Jersey is the Java reference implementation for providing REST.
Install the following dependencies in your pom.xml
:
pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- .. -->
<!-- RESTful web service: Jersey -->
<dependency>
<groupId> com.sun.jersey</groupId>
<artifactId> jersey-server</artifactId>
<version> 1.17.1</version>
</dependency>
<dependency>
<groupId> com.sun.jersey</groupId>
<artifactId> jersey-servlet</artifactId>
<version> 1.17.1</version>
</dependency>
<dependency>
<groupId> com.sun.jersey</groupId>
<artifactId> jersey-json</artifactId>
<version> 1.17.1</version>
</dependency>
<!-- .. -->
Add the following servlet snippet to your web.xml
:
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- .. -->
<servlet>
<servlet -name > jersey-serlvet< /servlet-name>
<servlet -class >
com.sun.jersey.spi.container.servlet.ServletContainer
< /servlet-class>
<init -param >
<param -name > com.sun.jersey.config.property.packages< /param-name>
<param -value > ngdemo.rest< /param-value>
< /init-param>
<init -param >
<param -name > com.sun.jersey.api.json.POJOMappingFeature< /param-name>
<param -value > true< /param-value>
< /init-param>
<load -on-startup > 1< /load-on-startup>
</servlet>
<servlet -mapping >
<servlet -name > jersey-serlvet< /servlet-name>
<url -pattern > /rest/*< /url-pattern>
< /servlet-mapping>
<!-- .. -->
Enough configuration for now: Create a simple User
object…
User.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package ngdemo . domain ;
import javax.xml.bind.annotation.XmlRootElement ;
@XmlRootElement
public class User {
private String firstName ;
private String lastName ;
public String getFirstName () {
return firstName ;
}
public void setFirstName ( String firstName ) {
this . firstName = firstName ;
}
public String getLastName () {
return lastName ;
}
public void setLastName ( String lastName ) {
this . lastName = lastName ;
}
}
…and a service class…
UserService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
package ngdemo . service ;
import ngdemo.domain.User ;
public class UserService {
public User getDefaultUser () {
User user = new User ();
user . setFirstName ( "JonFromREST" );
user . setLastName ( "DoeFromREST" );
return user ;
}
}
…and finally the RESTful Service… (Update 2015-08-07 small fix, thanks Jason):
UserRestService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package ngdemo . rest ;
import ngdemo.domain.User ;
import ngdemo.service.UserService ;
import javax.ws.rs.GET ;
import javax.ws.rs.Path ;
import javax.ws.rs.Produces ;
import javax.ws.rs.core.MediaType ;
@Path ( "/users" )
public class UserRestService {
@GET
@Produces ( MediaType . APPLICATION_JSON )
public User getDefaultUserInJSON () {
UserService userService = new UserService ();
return userService . getDefaultUser ();
}
}
Converting the User
object to JSON via @Produces(MediaType.APPLICATION_JSON)
requires jersey-json in web.xml
(POJOMappingFeature
).
Consuming web service from AngularJS (frontend)
Don’t forget to add angular-resources.js
to your index.html
…
Consuming the web service:
services.js
1
2
3
4
5
6
7
8
9
10
11
var services = angular . module ( 'ngdemo.services' , [ 'ngResource' ]);
services . factory ( 'UserFactory' , function ( $resource ) {
return $resource ( '/ngdemo/rest/users' , {}, {
query : {
method : 'GET' ,
params : {},
isArray : false
}
})
});
Usage in controller:
controller.js
1
2
3
4
5
6
7
var app = angular . module ( 'ngdemo.controllers' , []);
app . controller ( 'MyCtrl1' , [ '$scope' , 'UserFactory' , function ( $scope , UserFactory ) {
UserFactory . get ({}, function ( userFactory ) {
$scope . firstname = userFactory . firstName ;
})
}]);
Usage in view:
1
2
3
4
5
<div>
<p>
Result from RESTful service is: {{ firstname }}
</p>
</div>
Output: