Oct 16, 2014

Migrating a JSF-Based Web Application from Spring 3 to Java EE 7 and CDI

This is a detailed case study about the migration of a JSF-based web application from Spring 3 to Java EE 7 and CDI. I presented this talk at the JavaOne 2014 conference.

At first sight this didn’t seem to be too difficult. Both technologies are based on similar concepts and provide similar mechanisms for dependency injection (DI). So migrating pure annotation based bean wiring from Spring to CDI was obvious and straight forward.


But the deeper we looked into the source code the more Spring specific code we found with no direct and easy mapping in neither of JEE7, EJB3 or CDI available. Some of the problems and challenges we were confronted with were:

  • How to migrate XML based bean wirings? 
  • How to migrate FactoryBeans? 
  • How to migrate AspectJ based AOP proxies? 
  • How to implement Spring profiles for environment based wiring? 
  • How to implement custom bean scopes? 
  • How to implement custom Spring XML schema notations and wiring? 
  • How to migrate code that is built against Spring APIs? 
  • How to migrate unit test based on Spring Test?

To answer these questions the talk will present the patterns and strategies used to map, transform and migrate the different concepts from Spring 3 to JEE7with CDI. The talk will discuss the changes and implications of the migration on the system’s architecture.
You can find more details abou the talk in the JavaOne content catalog. The final slides are also available at Speaker Deck and SlideShare.

Using CDI annotations from Spring

A question from the audience was, if it is possible to do the migration and still be able to implement upcoming features in parallel. The answer was: yes, this is technically possible.

First of all, my advice would be to perform the migration as quickly as possible. Also try to keep the change set of the newly developed features as small as possible to reduce the merge efforts to an absolute minimum. Use a separate SVN or Git branch for further development and perform the migration directly in your trunk or master branch.

The Spring Framework uses a ScopeMetadataResolver to resolve the Spring based scopes of any bean definition. Since Spring 3 there already is a JSR330 supporting implementation: Jsr330ScopeMetadataResolver. But, this implementation only supports the @Singleton annotation per default, so we need to extend it a little.
/**
 * A custom CDI scope metadata resolver implementation. 
 */
public class CdiScopeMetadataResolver 
                           extends Jsr330ScopeMetadataResolver {
    /**
     * Register additional CDI scope annotations with their Spring 
     * scope equivalent.
     */
    public CdiScopeMetadataResolver() {
       registerScope("javax.enterprise.context.ApplicationScoped", 
               BeanDefinition.SCOPE_SINGLETON);
       registerScope("javax.enterprise.context.Dependent", 
               BeanDefinition.SCOPE_PROTOTYPE);
       registerScope("javax.enterprise.context.SessionScoped", 
               "session");
       registerScope("javax.enterprise.context.RequestScoped", 
               "request");
    }

    @Override
    public ScopeMetadata resolveScopeMetadata(BeanDefinition bean) {
       ScopeMetadata metadata = super.resolveScopeMetadata(bean);
       String scopeName = metadata.getScopeName();

       // CDI always uses scoped proxies except for @Dependent
       if (!BeanDefinition.SCOPE_PROTOTYPE.equals(scopeName)) {
          metadata.setScopedProxyMode(ScopedProxyMode.TARGET_CLASS);
       }

       return metadata;
    }
}
Basically, what this implementation does it to translate the CDI scope annotations to their Spring scope equivalent. Your newly developed components can now be annotated with CDI scope annotations instead, but under the hood you are still using Spring. That is the trick. Once you are done with the migration, these components should work without any further migration efforts. All that is left to do in your Spring code is to activate the scope resolver in your component scan definition:
<context:component-scan base-package="your.package.here"
    scope-resolver="...CdiScopeMetadataResolver"/>

Using Arquillian with Spock and the Shrinkwrap Groovy DSL

In my talk I described the migration of Spring Testing Framework based integration tests towards Arquillian as quite painful and cumbersome. At the end of my session Reza Rahman asked me what my experiences with Arqillian were.

Don't get me wrong now: Arquillian is a great framework for in-container testing of your CDI enabled artifacts and is by far the best I found. But: the shrink wrap process to build a testable and isolated CDI archive is very elaborate. Shrinkwrap might have a nice fluent API to do this but still you have to write a lot of Java code. So how can we improve this?

Testing Java code using Groovy, and especially using the Spock Framework, is in my opinion the way how tests should be written nowadays. Your tests are more expressive, you need less code and it is more fun writing Spock specifications than it is writing plain old JUnit tests.

So after searching the WWW for a few minutes I discovered that there is an offical Arquillian Spock Testrunner. This already felt a lot better, but still not 100% perfect. After a few more minutes I then discovered that there is a Shrinkwrap Groovy DSL that enables you to describe Shrinkwrap archives using Groovy closures. Now have a look at this:
@RunWith(ArquillianSputnik.class)
class TestableCdiArchiveSpec extends Specification {
    @Deployment
    def static JavaArchive "Create testable CDI archive"() {
        ShrinkWrap.jar {
            packages true, "your.package.here"
            asManifestResource EmptyAsset.INSTANCE, "beans.xml"
        }.build()
    }
}

Awesome and Groovy!

Oct 1, 2014

Simplifying JavaScript/HTML5 Rich Clients with Java EE

Simplifying JavaScript/HTML5 Rich Clients with Java EE 

JEE7 Angular CRUD Demo
JavaOne 2014 - CON6170
Johannes Weigend

This year at the JavaOne 2014 in San Francisco I did a session together with Geertjan Wielenga. The session was about combining JavaScript/HTML5 Clients with JavaEE. I developed live a JEE7 based CRUD application with an AngularJS frontend. In the linked video you can see every step of the live programming demo: 
JavaOne2014-JEE7-Angular-CRUD

The source is available on Github: https://github.com/jweigend/JEEAngularCRUD.
It contains the customer list, detail, update and delete functionality.
Customer List
It is a simple CRUD Singlepage HTML5 Application developed with NetBeans 8, Glassfish 4.1 and AngularJS. We use a JEE REST Server Backend and a HTML/JS Frontend. The HTML Frontend communicates with REST Services. The Server is stateless. 

In the first step I developed a  REST Backend for JavaDB by using NetBeans, Maven and Glassfish. In the second step I developed a HTML5 Frontend with the Yeoman Angular Generator and showed debugging and development of a Angular Single Page Application
Finally everything was put together in a single Deployment Unit by adding the HTML5 Application as a Maven Resource using the Maven WAR-Plugin.

If you want to repeat the demo by yourself follow these steps:


Step 1: Customer JEE7 REST Server

  • Create a new Maven based Web Application in NetBeans: 
    • Project->New->Maven->Web Application 
  • Use the „Create REST Services from Database“ Wizard to create REST Services direct by connecting to the sample database and choose the Customer table to generate your services.
  • Test the „Count“ Service by clicking the method in the Projects/Webservices Section
  • Create a „Cross Origin Resource Sharing Filter (CORS)“ in NetBeans to make sure the external HTML5 app can access our Webservice (After step 3 - the filter could be later removed for production).
Thats all. Amazing. Thats a perfect starting point for rapid prototyping. Since most enterprises have JEE Application Servers this Application will also meet enterprise requirements. Now we are ready to develop the HTML5 Client.


Step 2: Customer HTML5 AngularJS Client

Use the yo angular generator to generate a Angular HTML5 application. 

yo angular

Prerequisite: Make sure Yeoman is installed. 

$> grunt serve  #opens the browser and shows the generated page


After successful generation you can use grunt to show the generated sources in your browser. „grunt serve“ starts a simple NodeJS server which is a good first test.
We are ready to open the generated project in NetBeans. We use the „HTML Project from existing sources“ type of project.
The NetBeans project has some errors because the generated structure is not direct supported. The problem here is that the downloaded bower dependencies are one directory lower than the index.html file. This is currently not supported by the Netbeans toolchain.
We can fix this easily be changing the directory in the .bowerrc file from bower-components to app/bower-components.
After successful editing of the bower component file we kann download the bower libraries by clicking „bower install“ direct to the app directory in the project tree.
Now we have professional template for our project. The template uses Grunt as build automation tool. It uses bower as library download tool. It has the standard angular structure with unit tests and integration tests.
We now want to have two views. A list view to display the list of customers. A detail view to update or create a single customer. With the Yeoman generator we can create the two views inclusive the corresponding controllers. The reference to the controller code is automatically added to the index.html page.

yo angular:route customer-list
yo angular:route customer-detail

To make a first test we edit customer-list.html to loop over the generated array in the controller.
<div ng-repeat="thing in awesomeThings">
    {{ thing }}    
</div>

We change the awesomeThings array of string to an array of customer objects which contains a name and an email property. 

// customer-list.js
$scope.customers = [{
                    name: "Johannes Weigend",
                    email: "johannes.weigend@weigend.de"
                }, {
                    name: "Jonathan Weigend",
                    email: "jonathan.weigend@weigend.de"
                }];

// customer-list.html 
<tr ng-repeat="customer in customers">
                <td>{{ customer.name }}</td>
                <td>{{ customer.email }}</td>


The complete HTML Code for the customer-list view looks like this:

// customer-list.html
<div class="col-xs-12">
    <h1>Customers</h1>
    <table class="table table-striped table-condensed">
        <thead>
            <tr>
                <th style="min-width: 80px;">First name</th>
                <th style="min-width: 80px;">Last name</th>
                <th style="width:20px;">&nbsp;</th>
                <th style="width:20px;">&nbsp;</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="customer in customers">
                <td>{{ customer.name }}</td>
                <td>{{ customer.email }}</td>
                <td><a class="btn btn-small btn-primary">edit</a></td>
                <td><a class="btn btn-small btn-danger">delete</a></td>
            </tr>
        </tbody>
    </table>
    <a class="btn btn-default">create new customer</a>
</div>

Now we are ready to connect the UI with our REST service. 

First create a customer-svc factory. 

$ yo angular:factory customer-svc

We have to change the generated customer-svc.js file to return a angular resource object to access our webservice. 

// customer-svc.js
angular.module('customerServices', ['ngResource'])
        .factory('customerSvc', ['$resource',
            function ($resource) {
                return $resource(
                        'http://localhost:8080/customerserver/webresources/com.javaone.customerserver.customer/:customerId:id',
                        {},
                        {}
                        });
            }]);

We also have to add the new module „customerServices“ to our list of module dependencies of our application. Otherwise the module will not be accessible in our controller.

// app.js
angular
  .module('demoClientApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngSanitize',
    'ngTouch', 
    'customerServices'
  ])

We change now the customer list controller to use the Customer Service instead of an hard coded array.

// customer-list.js

$scope.customers = customerSvc.query();


Step 3: Putting HTML5 Client direct into the WAR Webapplication Archive

To include the HTML Project in our JEE Webapp we use the Maven WAR Plugin:

// pom.xml
<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.3</version>
     <configuration>
         <failOnMissingWebXml>false</failOnMissingWebXml>
         <webResources>
            <resource>
                <!-- this is relative to the pom.xml directory -->
                <directory>../CustomerClient/app</directory>
            </resource>
         </webResources>
     </configuration>
</plugin>

After new Maven build and deployment the page shows up when you start the Glassfish

Customer List View
To create the Update/Create dialog nothing special is needed. If you have this running it should be easy to extend the example as you wish.

Customer Create View
Customer Update View

Johannes Weigend