Codementor Events

Full-stack Tutorial: Angular 2+ and Java EE

Published Sep 07, 2018

This post was inspired by an article of Pablo Albella on Toptal blog Angular 5 and ASP.NET Core. Indeed, Angular 2+ is one of the hottest, modern and powerful frameworks for the front end development. And integrating it with enterprise back-end sometimes might become quite a challenge. Pablo perfectly described how to do it for .NET back-end.

But since Java remains the world's most popular programming language with over 12 million developers and more than 15 billion installed devices, it would be a good idea to make a similar tutorial for integrating Angular 2+ front-end with Java EE back-end.

If you search the topic in Google, you will find hundreds of posts how to integrate Spring Framework with Angular. Spring is indeed a very useful and powerful tool for Enterprise applications. It is de facto standard for enterprise development on Java. I have developed many projects on this framework and I actually love working with it.


But what if your company already has Java EE back-end without Spring and reassembling it with Spring is not an option? Should you forget about Angular, Vue, Node or any other Javascript frameworks? I've got good news for you! You still can integrate Javascript front-end to standard Java EE. So let's make a full-stack app with Angular 2+ front-end and Java EE backend.

I won't repeat the steps for developing Angular part. Pablo described it in detail in his article, I couldn't done it any better. So I just refer you to his post.

So let's go straight to the integration part. For integrating any Javascript front-end framework with Java EE we can use JAX-RS technology. JAX-RS is a standard library in Java EE, introduced in Java SE 5 and developed to provide API for RESTfulweb-services. JAX-RS provides annotations for mapping a resource class (a POJO) as a web resource. Let's create these POJO classes with JPA annotations. One more thing: to enable the serialization of our data and the ability to expose it using REST web services we need to add Jersey and supporting libraries to our project:

org.glassfish.jersey.core/jersey-client
org.glassfish.jersey.core/jersey-server
org.glassfish.jersey.containers/jersey-container-servlet
org.glassfish.jersey.media/jersey-media-moxy

In order to to declare a Jersey servlet and a corresponding URL mapping, as well as a CORS filter let's modify the web.xml file:

1: <servlet> 
2: 	<servlet-name>JAX-RS Servlet</servlet-name> 
3: 	<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
4: 	<init-param> 
5: 		<param-name>jersey.config.server.provider.packages</param-name> 
6: 		<param-value>com.example.angular-java-integration</param-value> 
7: 	</init-param> 
8: 	<load-on-startup>1</load-on-startup> 
9: </servlet> 
10: <servlet-mapping> 
11: 	<servlet-name>JAX-RS Servlet</servlet-name> 
12: 	<url-pattern>/jaxrs/*</url-pattern> 
13: </servlet-mapping> 
14: <filter> 
15: 	<filter-name>CorsFilter</filter-name> 
16: 	<filter-class>org.apache.catalina.filters.CorsFilter</filter-class> 
17: 	<init-param> 
18: 		<param-name>cors.allowed.origins</param-name> 
19: 		<param-value>*</param-value> 
20: 	</init-param> 
21: 	<init-param> 
22: 		<param-name>cors.allowed.methods</param-name> 
23: 		<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value> 
24: 	</init-param> 
25: </filter> 
26: <filter-mapping> 
27: 	<filter-name>CorsFilter</filter-name> 
28: 	<url-pattern>/*</url-pattern> 
29: </filter-mapping>

Why CORS filter you would say? Depending on how and where you deploy your back-end application, and what server you use, you will most likely need a variation of these settings to allow your front-end Angular application to access the services exposed by the back end. Essentially, if your client application is running on a different domain, modern browsers will restrict the call made to the domain running your back end, unless the headers in the back end indicate that this call is permitted. Next we create entity (JPA) classes. In our example it will be just a simple class User with username and password:

1: import javax.persistence.Column;
2: import javax.persistence.Entity; 
3: import javax.persistence.Id; 
4: import javax.persistence.Table; 
5: import javax.xml.bind.annotation.XmlRootElement; 
6:
7: @XmlRootElement 
8: @Entity 
9: @Table(name = "USER", schema = "TOPTAL") 
10: public class User implements java.io.Serializable { 
11: 	private static final long serialVersionUID = 1L; 
12: 	private Integer id; 
13: 	private String username; 
14: 	private String password; 
15:
16: 	public User() { 
17: 	} 
18:
19: 	@Id 
20: 	@Column(name = "ID") 
21: 	public Integer getId() { 
22: 		return this.id; 
23: 	} 
24: 
25: 	public void setId(Integer id) { 
26: 		this.id = id; 
27: 	} 
28:
29: 	@Column(name = "NAME", length = 50) 
30: 	public String getUsername() { 
31: 		return this.username; 
32: 	} 
33:
34: 	public void setUsername(String username) { 
35: 		this.username = username; 
36: 	} 
37:
38: 	@Column(name = "PASSWORD", length = 30) 
39: 	public String getPassword() { 
40: 		return this.password; 
41: 	} 
42:
43: 	public void setPassword(String password) { 
44: 		this.password = password; 
45: 	} 
46: }

Finally, we come to making our user class accessible via REST services. Here’s the class that exposes the REST services via JAX-RS.

1: import java.util.List; 
2: 
3: import javax.persistence.EntityManager; 
4: import javax.ws.rs.Consumes; 
5: import javax.ws.rs.DELETE; 
6: import javax.ws.rs.GET; 
7: import javax.ws.rs.PUT; 
8: import javax.ws.rs.Path; 
9: import javax.ws.rs.PathParam; 
10: import javax.ws.rs.Produces; 
11: import javax.ws.rs.core.MediaType; 
12: import javax.ws.rs.core.Response; 
13: import javax.ws.rs.core.Response.Status; 
14: 
15: @javax.inject.Singleton 
16: @Path("User") 
17: public class UserFacade extends AbstractFacade<User> { 
18: 
19: 	private EntityManager em; 
20: 
21: 	public UserFacade() { 
22: 		super(User.class); 
23: 	} 
24: 
25: 	@PUT 
26: 	@Override 
27: 	@Consumes({ "application/xml", "application/json" }) 
28: 	public Response edit(User entity) { 
29: 		if (entity.getName().length() <= 3) { 
30: 			return Response.status(Status.CONFLICT).entity("Username is too short").type(MediaType.TEXT_PLAIN).build(); 
31: 		} 
32: 	return super.edit(entity); 
33: 	} 
34: 
35: 	@DELETE 
36: 	@Path("remove/{id}") 
37: 	public Response remove(@PathParam("id") Integer id) { 
38: 		return super.remove(super.find(id)); 
39: 	} 
40: 
41: 	@GET 
42: 	@Path("{id}") 
43: 	@Produces({ "application/json" }) 
44: 	public User find(@PathParam("id") Integer id) { 
45: 		return super.find(id); 
46: 	} 
47: 
48: 	@GET 
49: 	@Override 
50: 	@Produces({ "application/json" }) 
51: 	public List<User> findAll() { 
52: 		return super.findAll(); 
53: 	} 
54: 
55: 	@GET 
56: 	@Path("count") 
57: 	@Produces("text/plain") 
58: 	public String countREST() { 
59: 		return String.valueOf(super.count()); 
60: 	} 
61: 
62: 	@Override 
63: 	protected EntityManager getEntityManager() { 
64: 		em = EntityManagerHelper.getEntityManager(); 
65: 		return em; 
66: 	} 
67: }

And that's basically it. Ensure that your back-end application is deployed and running first. You can test that back-end returns JSON data by url http://localhost:8080/AngularJavaIntegration/jaxrs/User/1. And then run your Angular front-end. Here we are! A full-stack app with Angular 2+ at the front-end and Java EE at the back-end.

Discover and read more posts from Maria Yapryntseva
get started