Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

The Recipe for Angular in a Java EE Environment: Aot Build

DZone's Guide to

The Recipe for Angular in a Java EE Environment: Aot Build

In the final part of this series, we go over the XML you need to implement URL rewriting, and the Java you need to incorporate Swagger into your REST API.

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

In this additional part of the series "The Recipe for Angular 2 in a Java EE Environment" I want to show how to implement an Aot Build for the UI. The Angular2AndJavaEE project uses the Ahead of Time compilation feature of Angular to minimize size and maximize speed. Aot needs URL rewriting and to access the right application for the selected language. For that, the tuckey urlrewriter is used. Then I show how to add Swagger to the REST API for easy testing of the REST Interface. 

Web Module Build

The Web Module Build has been explained in the article about the Maven build. Here I will explain steps 4 and 6 that have been enhanced to support the Aot Build.

Step 4

The Aot build compiles in the translations and templates into one optimized package. That means you get one package per supported language. These packages need to be put in different directories. In this case, the directories en/ and de/. To build the two packages, Angular-CLI needs to be executed twice.

<plugin>
   <artifactId>exec-maven-plugin</artifactId>
   <groupId>org.codehaus.mojo</groupId>
   <version>1.4.0</version>
   <executions>
      <execution>
         <id>angular-cli build de</id>
         <goals>
            <goal>exec</goal>
         </goals>
         <phase>generate-resources</phase>
         <configuration>
            <executable>node_modules/@angular/cli/bin/ng</executable>
            <arguments>
               <argument>build</argument>
               <argument>--prod</argument>
               <argument>--aot</argument>
               <argument>--bh</argument>
               <argument>/carrental-web/de/</argument>
               <argument>--output-path</argument>
               <argument>dist/de</argument>
               <argument>--locale</argument>
               <argument>de</argument>
               <argument>--i18nFile=./src/locale/messages.xlf</argument>
            </arguments>
            <workingDirectory>${basedir}/target/angular2/carrental</workingDirectory>
         </configuration>
      </execution>
      <execution>
         <id>angular-cli build en</id>
         <goals>
            <goal>exec</goal>
         </goals>
         <phase>generate-resources</phase>
         <configuration>
            <executable>node_modules/@angular/cli/bin/ng</executable>
            <arguments>
               <argument>build</argument>
               <argument>--prod</argument>
               <argument>--aot</argument>
               <argument>--bh</argument>
               <argument>/carrental-web/en/</argument>
               <argument>--output-path</argument>
               <argument>dist/en</argument>
               <argument>--locale</argument>
               <argument>en</argument>
               <argument>--i18nFile=./src/locale/messages.en.xlf</argument>
            </arguments>
            <workingDirectory>${basedir}/target/angular2/carrental</workingDirectory>
         </configuration>
      </execution>
   </executions>
</plugin>

In line 30, we have the unique id for the execution.

In line 36, the Angular-CLI executable is provided.

In line 38, Angular-CLI gets the build parameter.

In lines 39 and 40,  the --prod --aot parameters are set to switch on the ahead of time compilation.

In lines 41 and 42, the base-href is set to make the routing work. It needs to be set to the right package directory.

In lines 43 and 44, the output-path is set to build the packages into different directories.

In lines 45 and 46, the locale of the package is set for translation.

In line 47, the i18nFile is provided to enable the translations to be compiled.

Step 6

In Step 6, the war is built and the directories en/ and de/ with the packages need to be included.

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
   <artifactId>maven-war-plugin</artifactId>
   <version>${version.war.plugin}</version>
   <configuration>      
      <failOnMissingWebXml>false</failOnMissingWebXml>      
      <webResources>
         <resource>
            <directory>${basedir}/target/angular2/carrental/dist</directory>
            <includes>
               <include>en/*.*</include>
               <include>de/*.*</include>
            </includes>
         </resource>
      </webResources>
   </configuration>
</plugin>

In line 10, the working directory is set where Angular-CLI has built the packages.

In lines 12 and 13, the English and German packages are included in the war.

The Swagger directory is included because it is inside the web app directory.

URL Rewriting

To make the reload functionality and links within the application work, URL rewriting is required. With URL rewriting, the requests are sent to the right Angular application for the language. To include the URL rewrite filter, this web.xml is needed:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
   <filter>
      <filter-name>UrlRewriteFilter</filter-name>
      <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
      <init-param>
         <param-name>logLevel</param-name>
         <param-value>DEBUG</param-value>
      </init-param>
      <init-param>
         <param-name>confPath</param-name>
         <param-value>/WEB-INF/urlrewrite.xml</param-value>
      </init-param>
      <init-param>
         <param-name>statusEnabledOnHosts</param-name>
         <param-value>localhost</param-value>
      </init-param>
   </filter>
   <filter-mapping>
      <filter-name>UrlRewriteFilter</filter-name>
      <url-pattern>/*</url-pattern>
      <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
</web-app>

In lines 3 and 4, the filter is included.

In lines 10 and 11, the path to the config file of the urlrewriter is set.

In lines 14 and 15, the access to the status page is set. The status page is found at http://localhost:8080/carrental-web/rewrite-status  

In linse 18-22, the filter mapping that processes all requests is set.

To configure the URL filter, this urlrewrite.xml is needed:

<urlrewrite>
   <rule>
      <from>^\/de\/[a-zA-Z_0-9\/]+$</from>
      <to>/de/index.html</to>
   </rule>
   <rule>
      <from>^\/en\/[a-zA-Z_0-9\/]+$</from>
      <to>/en/index.html</to>
   </rule>
</urlrewrite>

In line 3, the regular expression matches requests with /de/ in the URL that does not include a ".". This forwards Paths but not Files.

In line 4, the request is forwarded to the German Angular application.

In lines 7 and 8, the same is done for English.

The regular expressions work for the application but they deserve some work to make them more robust and reusable.

Swagger

Swagger is a UI interface to test REST services. Swagger for Jax-Rs uses additional annotations to generate a JSON file that specifies the Swagger UI. The JSON file can be found at http://localhost:8080/carrental-web/rest/swagger.json. To add Swagger, the Swagger directory is included in the in the war and Swagger is added to the application class:

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

public CrApplication() {
   BeanConfig beanConfig = new BeanConfig();
   beanConfig.setVersion("1.5.10");
   beanConfig.setSchemes(new String[]{"http"});
   beanConfig.setHost("localhost:8080");
   beanConfig.setBasePath("/rest");
   beanConfig.setResourcePackage("ch.xxx.carrental.ui.rest.model");
   beanConfig.setScan(true);
}

@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);
   classes.add(io.swagger.jaxrs.listing.ApiListingResource.class);
   classes.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
   return classes;
}

}

In line 5, a new beanConfig is made.

In line 6, the swagger jax-rs version is set.

In line 7, the scheme is set to HTTP.

In line 8, the host is set to the port. Currently, Swagger only works on app servers with the HTTP port 8080. If you need a different port, it needs to be changed here.

In line 9, the base path for the REST calls is set. 

In line 10, the package with the resource classes is set. This Swagger package searches for the annotations in the classes.

Inl ine 11, the parameter scan is set to 'true' to make Swagger scan its annotations.

In lines 24-25, the Swagger classes for Jax-Rs are added.

To add Swagger support to a resource class the annotations @Api and @ApiOperation have to be added:

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

   @GET
   @Path("/mietNr/{mietNr}")
   @DisableCaching
   @ApiOperation(value="gets the rows for the table", response=CrTableRow.class, responseContainer="List")
   public Response getAll(@PathParam("mietNr") final String mietNr, @HeaderParam("Origin") final String origin,
      @HeaderParam("Accept-Language") final String acceptLang) {
      String[] langs = acceptLang.split(",");
      Locale locale = Locale.forLanguageTag(langs[0]);
      if (origin != null && origin.contains("http://localhost")) {
         return Response.ok(service.readCrRowsByMiete(mietNr, locale)).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, locale)).build();
      }
   }
}

In line 4, the annotation @Api is added with the title of the resource.

In line 12, the annotation @ApiOperation is added with title and response metadata.

Conclusion

The GitHub project Angular2AndJavaEE now has all the features that were planned. The Aot build is included and Swagger is available. The project shows some important features of Angular and Java EE and demonstrates that Angular can fit in a corporate environment. Angular provides an easy to use and powerful UI framework that can be integrated with Java EE. That makes it a good fit for future UI development in the Java EE world. The project will continue to be maintained. The news of the project can be found in the Project Diary.

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:
java ee ,angular 4 ,angular cli ,swagger ,web dev

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}