Over a million developers have joined DZone.

The Recipe for Angular 2 in a Java EE Environment: Rest Service

In the second post to our Recipe for Angular 2 in a Java EE Environment series, we're provided detailed examples of how to connect the backend our Angular2AndJavaEE Project to Java EE APIs.

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

This is the second article in our "The Recipe for Angular 2 in a Java EE Environment" series with a more detailed description of the Backend of the Angular2AndJavaEE Project. It follows my first article about Angular 2 and Java EE that gave an overview of the project, its goals, and motivation. 

The backend uses Java EE APIs because they are a widely used stack of technologies and free implementations are available. The APIs are:

The Rest Interface

The rest service uses the JAX-RS annotations and uses the EJBs for the business logic. It switches off Cors for requests from localhost and disables caching. 

To set up the rest service this class is used. It is in the configuration of JAX-RS.

@ApplicationPath("rest")
public class CrApplication extends Application {

@Override
public Set<Class<?>> getClasses() {
  Set<Class<?>> classes = new HashSet<Class<?>>();
  classes.add(CrPortfolio.class);
  classes.add(CrDetail.class);
  classes.add(CrMessage.class);
  classes.add(CrPeriod.class);
  classes.add(CrTableRow.class);
  classes.add(CrTableResource.class);
  classes.add(CrDetailResource.class);
  return classes;
}

}

In Line 1 the path of the rest interface is set. It follows the context path of the application. 

In Line 2 CrApplication is extended with application to inherit the getClasses() method and set the required classes.

In Line 5 and following, a Set is created with the classes JAX-RS uses to serialize/deserialize the data for the rest service. These are the DTO classes and the resource classes that define the rest calls that are supported.

To define the CrTable rest call, this class is used.

@Path("/model/crTable/mietNr/{mietNr}")
@Produces({ "application/json" })
public class CrTableResource {
@Inject
private CrTableService service;

@GET
@DisableCaching
public Response getAll(@PathParam("mietNr") final String mietNr, @HeaderParam("Origin") final String origin) {
  if (origin != null && origin.contains("http://localhost")) {
    return Response.ok(service.readCrRowsByMiete(mietNr)).header("Access-Control-Allow-Origin", "*")
      .header("Access-Control-Allow-Headers", "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept")
      .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS").allow("OPTIONS")
      .build();
  } else {
    return Response.ok(service.readCrRowsByMiete(mietNr)).build();
  }
}

@OPTIONS
@DisableCaching
public Response getOptions(@HeaderParam("Origin") final String origin) {
  if (origin != null && origin.contains("http://localhost")) {
    return Response.ok().header("Access-Control-Allow-Origin", "*")
      .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
      .header("Access-Control-Allow-Headers","X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept")
      .allow("OPTIONS")
      .build();
  } else {
    return Response.ok().build();
  }
}
}

In Line 1 the path of the CrTableService is defined. It comes after the context path and the rest path. 

In Line 2 the serialization/deserialization format is defined. JSON is used here, but XML would be possible too. 

In the Lines 4-5 the EJB CrTableService is injected to access the data with the EJB Layer.

In Line 7 the supported HTTP command is defined.

In Line 8 an Interceptor is added, to set the noCache option in the Http Header. 

In Line 9 the method getAll is defined. This method returns a collection of CrTableRow Objects. It gets the "mietNr" with the @PathParam Annotation of the URL defined in Line 1. It gets the "origin" Parameter with the @HeaderParam("Origin") to check if the request came from localhost. 

In Line 10 the origin parameter is checked and if the request came from localhost. For development, the project uses Angular CLI to serve the UI and Java EE Server for the Rest Service. For the browser, these are different servers due to different port numbers. To enable the browser to access the rest service, Cors needs to be switched off. That is done in the lines 11-14. Switching off Cors is only acceptable for development. 

In Line 21-33 the HTTP options call is supported. It is used to switch off Cors. The browser first sends an options request to the server and needs to get the Headerparams, and after that, it sends the get request. That makes support for the HTTP options call necessary.

The DTOs

The DTOs are the objects that JAXB serializes/deserializes. The same Annotations are used as for XML. The DTOs are a tree and can have 1 to 1 and 1 to many relations. I show this DTO class as an example.

@XmlRootElement(name="CrPeriod")
@XmlAccessorType(XmlAccessType.FIELD)
public class CrPeriod {
@XmlElement(required=true)
private String id;
@XmlElement(required=false)
private Date from;
@XmlElement(required=false)
private Date to;
@XmlElement(required=false)
private List<CrPortfolio> crPortfolios = new ArrayList<>();

public CrPeriod() {

}
  ...
}

Line 1 defines the name of element. It can be different from the object name.

Line 2 defines the AccessorType. Field means that the annotations on the fields of the class are used.

Line 10-11 defines a one to many relationship between the CrPeriod class and the CrPortfolio class. In JSON, there will be an array of CrPortfolios created.

The Entities

The entities are used to read and later store the data in the DB with JPA. I show this entity class as example.

@Entity
@Table(name = "CrPeriod")
public class CrPeriodDB {
@Id
@GeneratedValue
private Long id;
private Date periodFrom;
private Date periodTo;
@OneToMany(mappedBy="crPeriod",fetch=FetchType.EAGER,cascade=CascadeType.REMOVE, orphanRemoval=true)
private List<CrPortfolioDB> crPortfolios = new ArrayList<>();
@ManyToOne
private CrDetailDB crDetail;

...
}

In Line 1-2 the entity is defined, and a different table name in the DB is set. 

In Line 4-6 the primary key in the DB table is defined. For new entities, the DB will generate unique keys.

In Line 9-10 the one-to-many relationship to the PortfolioDB entities is defined. The annotation has "mappedBy", that sets the mapping to the crPeriod Field in CrPortfolio. FetchType.Eager reads the related entities immediately, CascadeType.Remove removes all related objects if the parent is removed, OrphanRemoval deletes entities without parent object.

In Line 11-12 many-to-one relationship to the CrDetailDB Entity is defined. In the @OneToMany annotation of CrDetailDB this field is referenced in the "mappedBy" value. 

The bidirectional mapping of entities is not required, but that way you get a nice mapping of the foreign keys in the DB tables.

The EJBs

The EJBs should have the business logic and the data access. In my example class there is no business logic.

The DTOs and entities are separate objects because this project will become a full CRUD application. The process of converting and persisting the data will be an explicit step that needs to be executed. That gives me more confidence in the data, but that is a personal choice that everybody has to make for themselves.

@Local
@Stateless
public class CrTableServiceSLB implements CrTableService {

@EJB
private CrServerSIB server;
@PersistenceContext
private EntityManager em;
private Converter conv = new Converter();

@AutoLogging
@Override
public List<CrTableRow> readCrRowsByMiete(String mietNr) {
  if (Utils.checkForWildfly()) {
    List<CrDetailDB> resultList = em
      .createQuery("select c from CrDetailDB c where c.mietNr=:mietNr", CrDetailDB.class)
      .setParameter("mietNr", mietNr).getResultList();
    List<CrTableRow> rows = new ArrayList<CrTableRow>();
    resultList.forEach(d -> d.getCrPeriods().forEach(per -> per.getCrPortfolios()
      .forEach(port -> rows.add(conv.convertTableRow(port, d.getJahr(), d.getMietNr())))));
    return rows;
  }
  return server.readCrRowsByMiete(mietNr);
}
}

Line 1-3 define the SLB.

Line 5-6 inject a singleton bean that is used if the project is deployed on an app server other than Wildfly. 

Line 7-9 inject the EntityManager and create the DTO<->Entity Converter.

Line 11 is the annotation of a logging interceptor. It logs the method call, the parameters, and the time the method needed.

Line 14 checks for Wildfly.

If it does find Wildfly, then it uses H2 that has been supplied with values during startup. The JPA Query is sendt to H2 and the entities are returned. The entities are then converted to DTOs. 

If it does not find Wildfly, then a Singleton Bean is used to provide the values. The bean will work on any Appserver. 

Summary

Java EE 6 provides all you need for a Backend of an Angular 2 UI. The APIs are standardized and well documented. The existing investment in such an environment can be reused. That makes Angular 2 UIs an easy addition to existing Java EE Environments.

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

Topics:
java ,java ee ,angular 2 ,maven ,web dev

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}