Saturday, 29 December 2012

JAX-RS as JSON provider for AngularJS

Introduction

In this blog text, I'll discuss the steps for using JAX-RS restful services as JSON data provider of a AngularJS application.
With JAX-RS it is quit easy to return some data when a certain URL is called.  By annotating a POJO class and his methods, you can write a flexible gateway in no time.
In the specification, there is explicitly mentioned that multiple mediaTypes are supported.  And although JAX-RS implementations use JAXB to produce and consume XML content, they all support JSON.
So my second goal was to create an AngularJS application that uses JAX-RS to retrieve and store his data.

The annotations

As already mentioned, a few annotations on a POJO are enough to create your JAX-RS restful service.
I'll explain the annotations based on the example.

@Path("person")
public class PersonDataController {
    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Path("list")
    public List<Person> getList() {
        ...
    }
}

The @Path on the class defines the part of the URL on which this restful resource will respond. The one on the method defines the next part of the URL.  So the above class will respond to calls of the following format <host><rootWebApp><restRoot>/person/list
<host> is quite obvious and <rootWebApp> is the context root of the deployed web application. The <restRoot> will be discussed later in the text.
With the @Get, we specify that the method getList() will be called when the application receives a HTTP GET request on the URL.  Other methods can be called in the case we issue other HTTP command like POST or DELETE.
And the last annotation defines the format of the data the URL will return. Since we are producing data (with a POST you need to Consume data), we use the @Produces annotation.  Here we specified both XML and JSON.  That way we can easily test the outcome of our methods in a browser.

The method to receive the post data when a new Person needs to be added is

    @POST
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Path("item")
    public Person save(Person person) {
        ...
    }

The annotations are self explaining now that you know the principles behind them.
Also the PUT method is supported.  So for those that want to make a strict distinction between PUT and POST operation, they can make it.

With JAX-RS you can also create a system that responds on more dynamical URL's.  Let's have a look at the delete person method:

    @DELETE
    @Path("item/{id}")
    public void deleteById(@PathParam("id") Long id) {
        personService.removePerson(id);
    }

In the Path annotation, we define here a variable part and the actual value will be used as the parameter of the method due the @PathParam annotation.
Besides the interception of parts of the URL, you can also have access to Query parameters, Header values, Cookies, form parameters and so on. 

Configuration


The only configuration we need to make before all of this works, is the setting of the <restRoot> part of the URL.  There is a default, but I guess that in most real world applications you like to define it yourself.
You can define it in the web.xml with a parameter but I prefer to do it with an annotation on the Application class.

@ApplicationPath("/rest")
public class NamesApplication extends Application {
}

The <restRoot> part of the URL is defined by the ApplicationPath annotation. For our simple use case, we don't need any other configuration, so the class can be empty.

Injections


At the moment, the JAX-RS resource classes, those annotated with @Path, are islands.  So in non hello world situations, they need to retrieve and store the data somewhere.

Since the specification, currently JAX-RS 1.1 is the latest, dates from before the CDI era, the most important injectable resource is the EJB.
Within the specification, there is an explicit mentioning of support for @EJB. One of the other possibilities is using @PersistenceContext to communicate directly with a database.

With the new specification JAX-RS 2.0, JSR-339, targeted for Java EE 7, CDI will be supported of course.  But until then the best option is using EJB's.  CDI is supported for instance in Glassfish (Jersey) and JBoss (RestEasy) but needs some additional jars (RestEasy) or has some issues in certain versions (Glassfish)

By converting our POJO into a stateless EJB (just the @Stateless annotation on the class level) we can inject other EJB's, like services, into the JAX-RS resource class.

@Path("person")
@Stateless
public class PersonDataController {
    @EJB
    private PersonService personService;
...    
}

Servers


Glassfish 3.1.2/wls 12c


Both have the Jersey implementation which is the default implementation for the JAX-RS 1.1 specification.
If you try to show a list of persons, let say a list of 2 persons, it isn't working.
The problem lies in the 'formatting' of the JSON data.

If you inspect the http calls in for instance FireBug, you see the following return value for the call to the restful service.

{"person":[{"firstName":"a","id":"0","lastName":"b"},{"firstName":"x","id":"1","lastName":"y"}]}

And it is not difficult to see that the returned value is not an array of objects, but is an object that contains the list of persons.

Jersey uses the Jettison framework for this JSON support. And looking in the documentation, I found the option to change the ‘formatting’

@Provider
public class JSONContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext context;

    private Class[] types = {Person.class};

    public JSONContextResolver() throws Exception {
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), types);
    }

    public JAXBContext getContext(Class<?> objectType) {
        for (Class type : types) {
            if (type == objectType) {
                return context;
            }
        }
        return null;
    }
}

With this class, see it as an extension to the JAX-RS system; we define our version of the ContextResolver. Classes annotated with @Provider which implement certain classes, look in the specification text for the complete list, are used to customize the way the system works.

Here we define that we use the ‘natural’ convention when the class Person is used.

With this class on the class path, the result of the URL call looks likes this


[{"id":0,"firstName":"a","lastName":"b"},{"id":0,"firstName":"x","lastName":"y"}]
Now we returned an array as top level object which makes AngularJS recognize it correctlyand shows the data.
Another option would be that you use JSONArray (and JSONObject) as the return type of the methods. 

But these classes are jettison specific so that reduces your portability even more. Even this solution is not perfect.  It doesn’t work on all the servers and you need to specify each class

JBoss AS 7.1


This application servers has RestEasy as JAX-RS implementation.  It also supports JSON data and by default, it formats the JSON data in a way which is directly understood by AngularJS

TomEE 1.5.1


The Apache TomEE is based on a Apache Tomcat servlet server which has been enriched with all the required frameworks to make it a Java EE 6 Web profile compliant server.  You can download a version that contains JAX-RS, provided by the Apache CXF framework.

Here we also have support for JSON data but have the same problem when we supply AngularJS with a List of Objects.
However Apache CXF is based on the Spring Framework and I couldn’t find a way to configure the JSON formatting without using Spring.

Since I decided already to go for the universal way, so nesting arrays in a root object, I didn’t try to fix this problem.

Conclusion


Since there are some minor differences in the JAX-RS implementations you should try to keep your code server agnostic.  This means that returning a List of objects as top level should be avoided.

On the other side, with JAX-RS, part of the Java EE 5 and 6 versions, we are able to supply the AngularJS framework with JSON data in a very easy way.

You can find the version for Glassfish and JBoss in the GitHub code repository.

Friday, 14 December 2012

Goal1: Integrate PrimeUI with AngularJS

Introduction

My first goal is to integrate the widgets from PrimeUI into AngularJS.  If you are fairly new to AngularJS, you should first grasp the concepts of the framework by reading the documentation.
There are also some good blog posts out there, for instance these of Sébastien Letélié.
As he also mentions, the ability to create custom directives is a perfect match for those who are working with reusable custom components, like I do with JavaServer Faces.
So, one of the first things I tried, after playing around with the framework and followed some demos, was to create a directive for the PrimeUI Panel widget.

Names applications

As a demo application, I tried to create a very simple application in AngularJS.  It is based on the Todo application created for comparing the different JavaScript frameworks which you can find on GitHub. In my version, you can just keep a list of names.
My controller has just an array to keep the names, a field for entering a new name and 2 methods for adding and removing to and from the list.
 
namesmvc.controller('NamesCtrl', function TodoCtrl($scope) { 
    $scope.names = [];
    $scope.newName = '';
    $scope.addName = function () {
        if (!$scope.newName.length) {
            return;
        }
        $scope.names.push({
              value: $scope.newName
            });
        $scope.newName = '';
    };
    $scope.removeName = function(name) {
        $scope.names.splice($scope.names.indexOf(name), 1);
    }
});


Also the html page is very simple, an input field, a button and the list of names, as an unordered list.
 
<section id="namesapp">
    <header id="header">
        <form id="name-form">
            <div ng-controller="NamesCtrl">
                <input id="default" ng-model="newName" type="text"/>
                <br/>
                <button ng-click="addName()" type="button">Save</button>
                <ul id="names-list">
                    <li ng-repeat="name in names">
                        <div class="view">
                            <label>{{name.value}}</label>
                            <button class="destroy" ng-click="removeName(name)"></button>
                        </div>
                    </li>
                </ul>
            </div>
        </form>
   </header>
</section>


pui-panel directive


When I had a working AngularJS application, I wanted to add some PrimeUI widgets, starting with the panel.
Since PrimeUI uses JQuery and JQuery-ui, that was the first thing that I did.  Adding the scripts to the head section of the html page together with the PrimeUI script.
The PrimeUI panel can be used as follows:
 
<div id="panelTitle" pui-panel title="Names list">
   ... PanelContent
</div>

The attribute pui-panel is what I need to configure next in the AngularJS system.
The most difficult thing here was to understand what every configuration option meant and what function that I should implement.  After a bit of trial and error, reading the docs and looking at other examples, I came up with this which seemed to work.
 
namesmvc.directive('puiPanel', function () {
    return {
        restrict: 'A',
        replace: true,
        compile: function (element, attrs, transclude) {
            $(function () {
                element.puipanel();
            });
        }
    };
});


Some words of explanation,
  • Restrict 'A' means that the new directive is only recognized as attribute on a html tag.  Other options are E (element/tag), C (style Class) and M (comment).  But the attribute version seems to be the most compliant way between all browsers.

  • Replace indicates that the element that contains the directive will be replaced by the outcome of the action.

  • Compile is the function that will transform the element with the directive to the end result. Here it just calls the PrimeUI method puipanel().

My first tries were using the link function, template property and transclude parameters. Because most of the examples are constructed that way and the documentation states that compile function should only be used in rare cases.  Well, integration of PrimeUI is one of those rare case but if you look at the code, simple case.

Growl integration


The second thing I tried was integrating the growl component.  I wanted to show a message on the screen when the name was removed from the list.  So basicly the removeName function in the controller should become something like

    $scope.removeName = function(name) {
        $scope.showMessage('Removed', name.value);
        $scope.names.splice($scope.names.indexOf(name), 1);
    }


On the HTML side of the things (look at the PrimeUI documentation), I need a div like this for the growl component.
 
<div id="growl" />


AngularJS allows you to define methods in the rootScope so that it will be available to all scopes in the controllers as used in the above snippet.
This is quit well documented so I added the following code:
 
namesmvc.run(function ($rootScope) {
    $rootScope.showMessage = function (title, msg) {
       // implementation
    }
});


So before I can show a message ( .puigrowl('show', [{severity: 'info', summary: title, detail: msg}]); ), it needs to be initialized ( .puigrowl();)
The solution I came up with is
 
namesmvc.run(function ($rootScope) {
    var growl;
    $rootScope.showMessage = function (title, msg) {
        if ($rootScope.growl == undefined ) {
            $(function () {
                $rootScope.growl = $('#growl');
                $rootScope.growl.puigrowl();
            });
        }
        $rootScope.growl.puigrowl('show', [
            {severity: 'info', summary: title, detail: msg}
        ]);
    }
});

Using PrimeFaces style


A third thing that I tried was to add a PrimeFaces theme to the application.  Since PrimeUI is based on the PrimeFaces widgets, they are using the same style classes.  So adding the CSS and images from a PrimeFaces theme jar was enough to have the panel and growl styled according the theme.
The theme has also nice styling for input fields and buttons.  Therefor I needed to PrimeUI-ize them.  This can simply be achieved by putting the following lines in the run method

    $(function () {
        $('[type="text"]').puiinputtext();
        $('[type="button"]').puibutton();
    });


Issues


There is one issue that I was unable to resolve.  When you use a ng-controller directive within a PrimeUI panel (the div with the pui-panel directive), the data isn’t no longer shown on the page. I haven’t found a reason or a solution for this problem.  So you should be aware of this when you reuse my code.

Integration script


Due to the modular design of AngularJS, I was able to put all the PrimeUI related stuff in one javaScript file.  So .run and .directive methods that I showed above were placed in a single file and I used the var angularPrime to access them.  So now I can ‘activate’ the PrimeUI integration if I define the following javascript for creating the application.
 
var namesmvc = angular.module('namesmvc', []);

var angularPrime = namesmvc;


By reassigning the AngularJS module to the angularPrime variable the integration script can dos his work.

Conclusion


The integration of PrimeUI and AngularJS resulted in quit simple code.  It took me some time to figure out the things but that is because I’m new to the AngularJS framework.  You can find the names application on github.
As I mentioned already in my opening post, feed is welcome about the proposed solution.

Monday, 10 December 2012

StatelessPrime announcement

Introduction

For many years now, I'm developing web applications with JavaServer Faces.  And although I'm extremely satisfied with the framework, I realized during the last few years that the technology has his limits.
Some state is kept in the session memory for the user and this limits the usability in high volume websites.  However, other features makes it the best choice for administrative applications.
Over the years, I followed the trends within JSF to reduce the memory consumption.  There was a big effort done with the release of JSF 2.0 where there was the introduction of partial state saving mechanism. And for Apache MyFaces and the Mojarra implementations, you have a 'stateless' version.
But for those that still think that JSF is not an option (because of his bad history) I had an idea of using JavaScript and PrimeUI on the client side and JAX RS that provides the JSON data.
How this idea emerged can be read in this blog post.

Forming the stack

But after one day I realized that I will never create something useful with JavaScript on the client side. My knowledge of the language is so minimal and I don't want to start with DOM manipulation.  If you have done so many years of declarative definitions in JSF, it feels like the stone age.
I searched a bit on the internet about JavaScript libraries.  I heard already that there where many of time but the search returned an overwhelming list. By accident I stumbled on AngularJS, and for me, it resembles the way of working with JSF.
You start with some kind of template, HTML with some additional attributes on the tags or even new tags.  The 'link' with the model data is made by some kind of EL and the DOM manipulation is done automatically based on the model data.  With this data linking, it create a list with the data in a tabular form by just some specifying some html and giving it a collection of data.
And even with my limited skills in JavaScript, I could made an example very easily that shows data which were produced by a JAX-RS method returning JSON data.
Another interesting features is the ability to define some directives yourself.  That allows me to create an integration for the PrimeUI widgets.
And although I didn't do any comparison between AngularJS and the other MV* JavaScript frameworks or other frameworks to create 'stateless' Web applications, my choice was made.

JSF back in the picture

After that I played a bit more with the combination AngularJS and JAX-RS, the resemblance between the JSF way of working and AngularJS became stronger and stronger. So I decided to create a component library and JSF renderers that can generate the files for the AngularJS way of working based on the JSF views.
This will become of course a tremendous amount of work to support everything and implement all options, but a first prototype was ready after a few weeks.
So at that time, I found it useful enough for me, as a kind of side project to learn more about the Stateless web development, to start the StatelessPrime project and blog.

StatelessPrime project goals

So this is the, non restrictive, list of goals that I want to tackle the next months with the StatelessPrime project.
  • Learn some JavaScript
        At least, I should come at a point where I no longer 'fear' using it.  However, I don't need to become an expert.
  • Know and use the features of AngularJS
  • Integrate PrimeUI with AngularJS
        By creating directives specific for PrimUI using PrimeUI can become as easy as additng the StatelessPrime AngularJS javaScript file.
  • Integrate AngularJS with JAX-RS functionality
        There are a few config that you need to make
  • Generate AngularJS/PrimeUI/JAX-RS application based on 'standard' JavaServer faces applications
        You need a specific component library to have this trick.  With renderers you can run this kind of application as any other JSF application.  With the 'Compiler' you can create the HTML5 (with AngularJS tags and directives), JavaScript and Java files containing the JAX-RS part files.
  • Create Maven plugin
  • Keep a blog
        Write down my adventures, lessons learned etc in a blog

Deliverables

As you can see in the list of goals, there are 2 groups of things that I like to cover.  Therefor, the project is also divided in 2 parts.
  • StatelessPrime AngularJS
        Here I will explore the combination AngularJS and PrimeUI with JAX-RS on the backend.
  • StatelessPrime JSF
        Here you can find the thnings related to the component library, renderers, Maven plugin and the compiler to generate an AngularJS/PrimeUI/JAX-RS application from JSF/CDI
On each blog post I will mention the part which wioll be covered.  This allows the people to decide if they are really interested in it or not.

Disclaimer

As I already said before, this project became a kind of hobby of someone who is not very familiar with JavaScript.  So don't expect production quality code, perfect architecture, etc... But constructive criticism and comments are of course very appreciated because I want to learn something.