May 31, 2015

AngularJS + MongoDB: Goodbye middle tier? (part 2 of 2)


With the advent of client side JavaScript frameworks, it seems like the middle tier has become Java’s last resort. But as a Java developer myself, I have to admit there are compelling alternatives to a full-blown enterprise server. For this blog post, I want to push this thought to the limit and try out whether we really need the middle tier at all… Please read part 1 here first.

Working with AngularJS

I didn’t implement any fancy functionality in this example application; I didn’t have to.

In order to implement the payments “popup” windows, I used ngDialog as a small helper framework.

Working with Restangular

After proper setup, working with Restangular on a RESTHeart backend really is a joy as one fits the other like a glove:
  • Restangular provides CRUD actions (HTTP verbs) on a route provided which happen to match a RESTHeart / MongoDB collection.
  • Restangular works with attached (“restangularized”) objects as entities which directly implement CRUD functionality.
  • Restangular functions are implementes as promises for a very clean, non-blocking asynchronous programming model.
Let’s see this in action.

GET without parameter

In the CustomerListCtrl, when we request all customers, we do
angular.module('restangularOnMongoDbApp')
    .controller("CustomerListCtrl", function ($scope, Restangular) {
        Restangular.all("customers").getList().then(function(entities) {
          $scope.entities = entities;
        });
    });
Restangular is the dependency-injected Restangular service.

Restangular.all("customers").getList() starts the asynchronous GET request to fetch all entities in the customers collection, then() takes the callback which here sets the $scope model.

The same principles apply to every CRUD operation.

GET with parameter

Here’s how CustomerEditCtrl is implemented:
angular.module('restangularOnMongoDbApp')
    .controller('CustomerEditCtrl', function ($scope, $routeParams, $location, Restangular) {
        $scope.save = function () {
            ...
        };

        if ($routeParams.id === "new") {
            $scope.entity = Restangular.one("customers");
        }
        else {
            Restangular.one("customers", $routeParams.id).get().then(function (entity) {
                $scope.entity = entity;
            }, function (response) {
                $location.path("/customers").search({errorNotFound: $routeParams.id});
            });
        }
    });
In addition to the Restangular service, we also inject $routeParams to retrieve “#” URL parameters and $location to trigger page redirect in the AngularJS way. Please refer to the AngularJS documentation for details.

The edit page which is backed by this controller should behave like so:
  • With id = “new”, a new entity is created.
  • With any other id, the requested entity is fetched.
  • If the entity is not found, the user is redirected to the list view and an error message is shown.
Here, a couple of interesting operations are implemented:
  • Retrieving the one entity with the id provided happens through Restangular.one("customers", id).
  • Initializing a new entity is accomplished with Restangular.one("customers"). The returned object is “restangularized” and thus can be used in the save() function later.
  • Restangular operations optionally take a second function as an additional parameters for error handling. In this listing, this is used for the “redirect on error” functionality.

Write operations

Here’s the save() function of CustomerEditCtrl:
$scope.save = function() {
    $scope.entity.save().then(function() {
        $location.path("/customers");
    });
};
As mentioned earlier, “restangularized” objects come with a bunch of useful additional functions. Most prominently, they feature CRUD functions for HTTP verbs, plus an additional save() which would either trigger PUT (no id set yet) or POST (when an id is present). Note however that RESTHeart accepts PUT as an alias for POST anyway.

It’s important to remember that all Restangular functions work asynchronously and their outcome is processed in the promise callback function. Thus, subsequent actions must be implemented in the callback function.

For instance, if the redirect in above function would just be another procedural call after $scope.entity.save(), then, as the save() function returns immediately, redirect would possibly happen before save() has been committed. The outcome would then render outdated information.

With these few principles in mind, really any CRUD operation can be implemented with a simple Restangular function call.

Working with RESTHeart

RESTHeart’s API is really simple and straightforward if you get your head around the idea of RESTful CRUD. There’s actually no magic I could teach you here.

The documentation is also OK. Search for error codes and missed HTTP headers if you run into trouble.

Working with MongoDB

Thanks to RESTHeart, you will barely get in touch with MongoDB’s internals. However, you will have to adopt your thinking to the MongoDB way and to the world of document-oriented databases; this is especially true if you come from the relational DB world.

No schema – no constraints

MongoDB doesn't support the notion of a schema, hence there are no constraints, not even “not null” constraints nor data types. Without a middle-tier, you can literally put any kind of trash in your database.

For instance, in the example application, the only way really to mark the customer’s “name” field as “requried” is by applying the respective UI component attribute:
<input id="form:name" type="text" name="form:name" ng-model="entity.name" title="Name" required/>
However, UI layer constraints are completely unsafe as the user can easily disable them by manipulating HTML /JavaScript code.

In the same way, the user can put a value of any kind into the account’s “date” field; even an arbitrary String.

Transaction boundaries: Don’t think relational!

A document-based data store such as MongoDB relies on embedded documents rather than relations established with foreign keys; hence, there is also no normalization, and the smallest transactional entity is the whole document, possibly consisting of layers upon layers of embedded documents! This has a huge impact on the overall system architecture and user experience.

In the example application for instance, a customer holds its payments as embedded documents:
{
    "_id": ObjectID("5568e53e11c14fee4e39d469"),
    "name": "Max",
    "address": "First Street",
    "city": "Los Angeles",
    "payments": [
        {
            "amount": "100",
            "date": "05/31/2015"
        },
        {
            "amount": "200"
        }
    ],
    "_etag": ObjectID("5568e53e11c14fee4e39d46a")
}
Thus, the transaction comprises the entire customer, not individual payments. For the user experience, this has two consequences:
  • A payment always has to exist as a child of a customer.
  • A payment cannot be manipulated independently of its customer. The customer and all its associated payments must be persisted as a whole.
In the example application, this is reflected by the navigation behavior: CRUD operations on a payment don’t open in a separate page; rather, they open a popup and are executed within the page of a customer. This helps making the user aware that in order to commit his changes, he has to save the entire customer at the end.

This makes the view truly stateful, which is the opposite of a stateless view, as suggested for a RESTful navigation. Yes, even though the backend API is RESTful, the UI navigation is not.

This design is not bad per se; otherwise, MongoDB wouldn’t be that successful. However, it’s very important to judge whether this design is appropriate for your use case. The span of transactional boundaries is a business decision. If you need per-entity-boundaries, MongoDB is not the right choice.

Also, you shouldn’t try to trick the system, e.g. by introducing pseudo-foreign key properties into documents. You still wouldn’t be able to guarantee ACID transactions, and even less so in a distributed environment where MongoDB is supposed to shine.

Conclusion

Of course, due to security concerns, real world applicability of direct access to the backend from client-side GUI approaches zero, but that is not what this article aims to show. Rather, it’s an interesting thought experiment showing that the more simplified and lightweight a service interface is, the more ease of development is increased, and that this is especially true for a RESTful API.

Indeed, the whole tech stack is really optimized for rapid application development:
  • AngularJS provides a mature ecosystem for powerful abstractions, such as Restangular.
  • RESTHeart makes working with MongoDB really easy.
  • MongoDB works great as a simplistic data store for junks of data.
As for the individual components used in this application:
  • Setting up Restangular for use with RESTHeart is not trivial, but after that, its straightforward programming model really shines. I’d recommend this for any REST API access with AngularJS.
  • RESTHeart works really well with MongoDB. It also covers more sophisticated needs such as concurrency control and security. As of May 2015, its homepage still suffers from partially incomplete documentation though.
  • MongoDB really is the show-stopper in this example tech stack, even beyond the obvious security concerns. Its conceptual differences to relational DBs will be a huge impediment as soon as you need constraints or more fine-grained transaction control which I assert is true for typical enterprise projects. There are quite a few articles out there discussing the pros and cons of MongoDB for certain scenarios, e.g. here. Don’t take a rash decision on the DB you want to use.
The example application proved nonetheless that building an application without middle tier, based on AngularJS + MongoDB, is possible and very straightforward. Despite not being production ready, this tech-stack could still be interesting to quickly build an internal document store UI or to rapidly prototype an AngularJS application. As the interface to the backend is pure REST, you could later introduce a thin “proxy” middle tier serving the same RESTful API. I think it would also be very interesting to re-implement the application with a “RESTified” relational database so as to avoid the restrictions added by MongoDB.

At least it proved that keeping the middle tier thin is a very good means to increase ease of development. For server side developers, e.g. Java EE developers, this is especially impressive. We should really embrace the changes initiated by more sophisticated client-side UIs and more powerful clients and aim for lightweight middle tier implementations. This includes, in my opinion, to balance a full-blown Java EE server against e.g. a very lightweight Node.js Express server. There’s just no more “one size fits all” solution.

Do you agree with any of my assertions? Did you find this article interesting? Please let me know your opinion in the comments section below.

Feel free to view the demo project’s complete source code on its GitHub repository.


Pages: 1 2

AngularJS + MongoDB: Goodbye middle tier? (part 1 of 2)




With the advent of client side JavaScript frameworks, it seems like the middle tier has become Java’s last resort. But as a Java developer myself, I have to admit there are compelling alternatives to a full-blown enterprise server. For this blog post, I want to push this thought to the limit and try out whether we really need the middle tier at all…

The tool set

For the build environment:
  • I use the Yeoman generator for project scaffolding which is built on top of Node.js + npm and which sets up the JavaScript build system based on Grunt and dependency management based on Bower.
  • During development, the application is loaded into Grunt’s static server which provides live reload on source change. It runs on default port 9000.
  • I use NetBeans as file editor / IDE.
For the application stack:
  • I use MongoDB 3.1.3 as the database. It runs on default port 27017.
    • I use Mongo Express 0.21.0 as a simple web-based UI frontend for MongoDB. It runs on default port 8081.
  • I use RESTHeart 0.10.2 as the MongoDB REST frontend. It runs on default port 8080.
    • RESTHeart includes the HAL browser as a simple web-based UI frontend for RESTHeart. It is accessible through RESTHeart’s port.
    • For convenience, I use the httpie 0.9.2 tool parallel to the HAL browser to test RESTHeart queries through RESTful HTTP requests (it’s basically a more user-friendly version of curl).
  • I use Restangular 1.5.1 as an AngularJS abstraction layer to do RESTful HTTP requests which offers a far more sophisticated although more concise API than AngularJS’s built-in $http and $resource.
  • Finally, the GUI is developed with AngularJS 1.3.0.

A RESTful stack

Thus, the tech stack looks like this:
You can clearly see that something is lacking here – there’s no such thing as a middle tier. As MongoDB has been extended with a REST interface through RESTHeart and AngularJS has been extended with a REST interface through Restangular, these two tiers can communicate directly with each other.

The beauty of a RESTful API which is taken advantage of here is that
  • REST is CRUD. As the example application will do CRUD only, this is a perfect fit. A “middle tier” would apparently not add any value.
  • REST is de-facto-standardized. Even without any formal service descriptor, the API can be used really intuitively and concisely. There’s no need for further abstraction; a “middle tier” would just be an empty delegate.

Technology choice

Please skip this section unless you’re interested in why I chose the technologies mentioned for my stack.
  • I chose MongoDB because it’s considered by far the most widespread “NoSQL” databases at the moment. I didn’t go for a “proper” SQL database because the application’s requirements should be covered by a simple document store. The fact that MongoDB doesn’t provide a RESTful HTTP interface out of the box (in contrast to e.g. CouchDB) doesn’t really matter; I wouldn’t choose a DB based on the interfaces it provides, as long as it’s extensible.
  • After choosing MongoDB though I needed a RESTful interface for that. Of all available options, RESTHeart seemed the most mature one.
  • AngularJS, as well, was chosen based on its popularity as well as on its functionality.
  • With some experience from plain AngularJS HTTP handling, I wanted to try a more high-level API, as provided by Restangular. I will explain throughout the text why I quickly became very happy with my choice.

The example application

Based on above tech stack, I created a simple web application with CRUD functionality for these two business entities:

Each entity is uniquely identified by its id which is auto-generated on persist.

A customer can have one or more payments, and one payment is associated with exactly one customer. A customer of employment type unemployed must not have a company name.

There will be a master view (list of all entities) and a detail view (edit page for current entity) for the customer entity. The payments master view will be integrated in the detail view of the parent customer entity which provides editing options for its payments though popup windows.

Note that the complete source code of the example project is available on its GitHub repository.

This is actually a recreation of the very same example application I created just two weeks ago with the server-side JSF stack which, for me, added to the fun of creating a middle-tier-less application. (In fact, I even reused the HTML markup generated by the JSF application for this one.)

Setup

Setting up the whole stack really is just a matter of following the tutorials provided with each tool.

However, setting up Restangular for use with RESTHeart deserves some more explanation.

Restangular + RESTHeart

RESTHeart’s HAL+JSON document format doesn’t quite match Restangular’s default expectations, but luckily, Restangular provides a clever API to tweak its configuration.

Having Restangular included into the AngularJS application (script included, dependencies declared), one can configure Restangular like so:
angular.config(function (RestangularProvider) {
    RestangularProvider.setBaseUrl('http://localhost:8080/restangularOnMongoDb/');

    // we are mapping the id of each element to the _id field.
    RestangularProvider.setRestangularFields({
      id: "_id.$oid",
    });

    RestangularProvider.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
        var extractedData;
        // look for getList operations
        if (operation === "getList") {
            // the actual entities are in the _embedded section
            extractedData = data._embedded['rh:doc'];
        } else {
            extractedData = data;
        }
        return extractedData;
    });
    
    RestangularProvider.addFullRequestInterceptor(function (data, operation, what, url) {
        if (operation !== "getList") {
            if (typeof data._etag !== 'undefined') {
                return {headers: {"If-Match": data._etag.$oid}};
            }
            if (typeof data._id.$oid === 'undefined') {
                data._id = null;
            }
        }
        return {};
    });
});
  • RestangularProvider is the dependency-injected Restangular config service.
  • First of all, we set the base URL to the server / port of RESTHeart and point to the database which contains all document collections.
  • We have to tell Restangular that the “id” of a JSON document is not stored in the property named id, but in _id.$oid, as defined by MongoDB.
  • We have to tell Restangular that when querying for a list of documents, the actual payload (the list) is stored in the _embedded.rh:doc property.
  • Finally, we have to tell Restangular where to find the ETag property of a JSON document which must be included in a “write” request in the “If-Match” HTTP header. ETag is an HTTP concept which is used by RESTHeart to implicitly provide optimistic locking. Similar to the “id” problem described above, we must tell Restangular that this information is not stored in etag, but in _etag.$oid.

Pages: 1 2

May 24, 2015

Java EE 7 Bean scopes compared (part 2 of 2)


In this article, I take a closer look at the various lifecycle “scopes” specified by Java EE 7’s Bean definitions. I created a simple demo web application which provides a  comparison of JSF, CDI, EJB and “Dependency Injection for Java” Bean scopes, which you should check out here first. Here come my conclusions.

Lessons learnt!

In this section, I will present you my findings as I played with the demo application myself, and their consequences for proper usage of specific bean scopes and types.

For comparison purposes, I grouped cross-framework “similar” scope definitions in rows in the demo application. I will now go through these rows and explain my findings. I highly encourage you to try this out yourself and draw your own conclusions as well.

No scope / dependant scope

Similar scope definitions are provided by:
  • JSF’s @javax.faces.bean.NoneScoped
  • CDI’s @javax.enterprise.context.Dependent
  • EJB’s @javax.ejb.Stateful
Although conceptually different, these three scope types behave quite similar; their lifespan is typically “less than request scoped”, or it is bound to the lifespan of a referencing “parent” bean, if present. When used directly in the JSF EL, a new bean is created for every reference in an EL expression.

Note than of these three scopes, CDI’s @Dependent is the only one which is destroyed as soon as the parent is, e.g. after usage in a JSF EL expression.

EJB @Stateful beans, on the other hand, are individual, long-living instances of an EJB eligible for holding state. They must be explicitly destroyed.

JSF’s @NoneScope really is just a helper scope, making the bean eligible for dependency injection into any other JSF bean independent of that bean’s type.

Request scope

Equivalent scope definitions are provided by:
  • JSF’s @javax.faces.bean.RequestScoped
  • CDI’s @javax.enterprise.context.RequestScoped
The lifespan of these beans is bound to the HTTP request’s lifespan. Regardless of whether a new request is invoked with GET or POST, a request scoped bean will be destroyed / recreated with every new HTTP request.

These two scopes thus provide a means for truly stateless JSF navigation, as e.g. used in a RESTful architecture. There are however some known pitfalls when used with JSF as this framework is optimized for at least some state being held on the server side.

Flash scope

This scope is exclusively provided by:
  • JSF’s javax.faces.context.Flash
Flash scope works quite differently from all the other scopes discussed here. It doesn’t work by annotating bean classes; rather, it provides a Map-like structure which you can access from JSF EL (flash) or by dependency injection (Flash), in order to explicitly store and retrieve objects.

Flash is literally the next higher scope after request as any object put into flash scope will have a lifespan of not one, but two HTTP requests. This actually closes a gap coming up quite frequently in everyday JSF development, and to quickly put an object in flow scope should really be seen as a practical workaround.

It is however bad practice to abuse this facility for use cases where higher scopes would be appropriate. Also note that flash scope has been notorious for buggy behavior in earlier Oracle Mojarra 2.1 and 2.2 releases. Make sure to upgrade to the latest version in order to avoid trouble!

View scope

(Theoretically) equivalent scope definitions are provided by:
JSF 2.2 has here introduced some serious confusion: Prior to that version, the only view scope available in the Java EE 7 stack was JSF’s own @javax.faces.bean.ViewScoped annotation, available for JSF @ManagedBean beans only.

But with JSF 2.2, a new scope has been introduced, namely @javax.faces.view.ViewScoped (mind the package name!) which is actually a port of the original view scope for use not in JSF beans, but in CDI beans. Yes, that’s right. The JSF specification defines a CDI scope type for exclusive use with CDI beans. This is perfectly reasonable as CDI exposes a means to implement custom scopes with the @NormalScope base annotation; this is what JSF 2.2 did. The real world motivation behind this is that JSF’s @ManagedBeans are thought to become @Deprecated in the near future and to eventually get removed altogether from the Java EE stack in favor of CDI beans. With that upgrade, the view scope, formerly not available for CDI beans, would still be preserved. I thus placed the “new” view scope in the list of CDI scopes.

The view scope’s lifespan essentially lies between request scope and session scope: It will survive postbacks, e.g. POST requests to the origin page.

It will though never outlive the session as it is bound to it: If the session is destroyed, so are all view scopes bound to it.

However, with any GET request as well as with POST requests with navigation to a different page, a new view scope will be opened. This scope thus is really built for dealing with AJAX calls.

As the demo application shows, the situation is actually even quite worse: With a POST to a different page, at least the previous view scope is destroyed. But with GET, this is not the case, which is a conceptual problem: The server cannot know whether e.g. a new browser tab has been opened for the GET request or whether the origin page has been changed to a new URL. It must assume that the former may be the case, and if so, it will by design try to retain parallel scopes rather than destroying them. Thus, with each GET request, a new view scope will be created, but the previous one will not be destroyed. This is potentially a huge memory leak.

Empirical tests with the demo application however show a peculiar behavior: Sending GET requests will show the described leaky behavior, but only up to 25 times! After 25 view scopes have been opened with one session, with every new GET request, an active view scope will be destroyed, stabilizing the number of active view scopes per session to 25. What’s even more curious, this only appplies to JSF’s original @javax.faces.bean.ViewScoped implementation, not to CDI’s @javax.faces.view.ViewScoped. I don’t understand where the magical number of 25 comes from. I don’t know whether this behavior is a bug or not; I have no explanation for it.

For the moment, I must assume that both @ViewScoped implementations are either leaky or buggy, or both. I’d recommend not to use either of them and use one of the cleaner higher scopes instead.

As per styrand’s comment, I later tried out the @org.omnifaces.cdi.ViewScoped implementation provided by the OmniFaces JSF util library, which is meant to be used as a backport for the ViewScoped CDI extension for use with JSF 2.0 / 2.1. Curiously, this implementation shows yet another behavior: It seems to be the only one which actually respects the com.sun.faces.numberOfLogicalViews web.xml context parameter, but only when set explicitly; instead of taking the officially documented default number of 15, it seems to default to 20. I am still inclined to consider this this only proper ViewScoped implementation, and to recommend using it with a numberOfLogicalViews parameter set as small as possible.

As view scope is bound to the session, the same restrictions and memory leak possibilities apply. Unlike the session, a view does not span over multiple browser windows or tabs.

Conversation scope

This scope is exclusively provided by:
  • CDI’s @javax.enterprise.context.ConversationScoped
Conversation scope is a flexible scope with a lifespan lying between request scope and session scope. A conversation can be programmatically opened and closed. The scope will be opened at the beginning of the conversation, and is destroyed as soon as it ends. However, as long as no conversation is opened, conversation scope’s lifespan is bound to an HTTP requests, and the scope is destroyed and recreated on each request (as a so-called “transient conversation scope”).

As long as the conversation is open, no request (GET or POST) can end the conversation.

However, as the conversation is bound to the session, it is destroyed as soon as the session is.

You can open multiple conversations per session; however, you cannot open a new conversation while being in a conversation.

You need to keep the conversion id as a request parameter for every subsequent HTTP request to keep track of the current conversation. If you loose the parameter, the old conversation will still be kept open, but for the new request, a new (transient) conversation is opened.

Empirical tests with the demo application confirm that this is a potential memory leak. By simple “forgetting” the conversation id with an HTTP request (thus opening a new transient conversation) and subsequent opening of a new long-running conversation, and repeating these steps over and over again, a possibly infinite number of conversations can be opened. Luckily, you as the developer can, and must, make sure that this cannot be exploited by adding appropriate checks on any method which spawns a new long-running conversation.

As conversation scope is bound to the session, the same restrictions and memory leak possibilities apply. Unlike the session, a conversation does not span over multiple browser windows or tabs.

Flow scope

This scope is exclusively provided by:
  • JSF’s / CDI’s @javax.faces.flow.FlowScoped
Now, the confusion is perfect! Yes, just as @javax.faces.view.ViewScoped, this is another CDI bean scope provided by JSF 2.2. And of course, it is completely unrelated to the somewhat similar sounding “Flash scope”, which is a rather recent addition to JSF as well. In the demo application, I placed this flow scope in the list of CDI scopes as well.

Flow scope works quite different from any other scopes discussed here as it comes with very strict requirements for its application. Flow scope can only be applied to XHTML pages which adhere to an explicitly provided XML- or Java-based configuration, enforcing e.g. placing the XHTML pages in a dedicated folder.

Thus, the typical use case of flow scope really is confined to true “page flows” and “multi-page wizards”. Even though the flow accepts logic for dynamic page navigation, it is clearly not as dynamic as are other scopes discussed here.

Also, at its core, the flow facility isn’t actually a CDI scope; the scope really is just an addition. A flow primarily consists of a Flow instance marked as a @FlowDefinition and which defines page navigation which can then be invoked from the UI by using implicit navigation outcomes. Depending on the complexity of the flow’s logic, you may or may not define a number of beans annotated with the respective @FlowScoped("myFlow") directive; for more simple cases, the implicit JSF EL object flowScope, which is backed by a Map, may suffice.

Note that as with the conversation scope, the user can leave the flow scope by manipulating the URL, potentially leaving back “lost” flow scoped beans. This, in my opinion, is a potential memory leak.

If you consider using flow scope, note that the flow facility as such is tightly bound to JSF, further increasing dependency on that UI framework for your application.

A flow does not span over multiple browser windows, but it does span over multiple tabs.

Session scope

Equivalent scope definitions are provided by:
  • JSF’s @javax.faces.bean.SessionScoped
  • CDI’s @javax.enterprise.context.SessionScoped
The session scope is the classic solution for any scope lifespan higher than request. And it typically is a bad solution as its lifespan is really too long for most use cases. There isn’t much more explanation left. The scope’s lifespan is bound to the session which can be either explicitly destroyed on the server side by calling ExternalContext#invalidateSession() or which will be destroyed after user idle time defined by web.xml’s <session-config><session-timeout> parameter. A session spans over multiple browser tabs and windows.

However, recognizing a user’s session on the server side relies on the HTTP request sending the JSESSIONID cookie. After deletion of this cookie on the client side, any new HTTP request will spawn a new session whereas the previous session will stay alive until session timeout is reached. This is a potential memory leak! (And there is basically nothing you can do against it in your app, and you have to find other ways to secure your server-side infrastructure.)

Misusage, including over-usage of the session to hold information longer than for one request is considered poor practice anyways. It typically leads to cluttered state information held by a multitude of beans, proving the central wisdom of functional programming, that maintaining mutable state is hard and error-prone. Actually, you should really perceive the session scope as your last resort. In most cases you can even go away with plain request scope, transferring state information through request parameters. When applied in perfection, this is what a true RESTful page navigation amounts to, as I just described it in the previous blog post series.

For other cases, you may want to consider using flash scope, conversation scope or flow scope.

Stateless scope

This scope is exclusively provided by:
  • EJB’s @javax.ejb.Stateless
Although in the demo application, EJB’s @Stateless and @Singleton show the same behavior, their implementation and their use case is actually very different when it comes to concurrent access:

When accessed concurrently, the server may decide whether to re-use an existing, pooled instance of the bean or whether to create and yield a new instance and add it to the pool.

This has important consequences when dealing with state as you just cannot rely on any state held by a stateless bean: upon the next invocation, the bean (and thus its state) may be completely different. Thus, a @Stateless bean should, as its name suggests, really be used exclusively if its doesn’t hold any state at all. This is typically the case for a service-oriented implementation.

If you instead search for an EJB holding a global state, go for @Singleton.

Global / singleton scope

Equivalent scope definitions are provided by:
  • JSF’s @javax.faces.bean.ApplicationScoped
  • CDI’s @javax.enterprise.context.ApplicationScoped
  • EJB’s @javax.ejb.Singleton
  • Dependency Injection for Java’s @javax.inject.Singleton
As their names suggest, all these bean scopes / bean types exist as singleton instances exactly once during application lifetime. Their lifespan begins when the application starts up, and ends when the application or the application server is shut down.

As such, they can be used to hold global state or as stateless implementations. If your use case requires the latter, and going for an EJB bean is an option, you should however consider creating a @Stateless EJB bean.

It’s very important to realize that you, as the developer, are in charge of dealing with concurrent access to that singleton instance. You must pay close attention to access synchronization in order to prevent race conditions.

You will typically use singleton beans for solutions to rather technical problems only, and use much more restricted scopes in everyday programming. On the other hand, singleton scoped beans are a great replacement for any statically implemented functionality (e.g. factories). As they can be easily mocked, they greatly reduce component interdependency and increase testability.

Conclusion

Creating this demo application and playing around with bean scopes revealed some interesting, and even some fairly shocking properties of various Java EE 7 Bean scope definitions.

As a final conclusion, I am now even more certain that one should stick with the shortest-living scope lifespan in order to avoid memory leaks:
  • Use “no scope” only where it technically makes sense.
  • Use request scoped beans whenever possible.
  • Use the flash scope if you just need to carry over information from one request to the next.
  • The view scope is leaky by design, and potentially buggy as well. I would thus advice against using it. I don’t have enough experience with the OmniFaces implementation yet, but maybe it’s a true alternative. However, you then have to be aware that you’re leaving the Java EE standard.
  • For page flows, I would go for the @ConversationScoped solution, and make sure that beginning / ending a conversation is well controlled, destroying orphan conversations prior to adding new ones. Note that this solution still suffers from the underlying potential leaky session concept.
  • As I didn’t found a way to recover “lost” flow scoped objects / beans, I wouldn’t use that scope and use @ConversationScoped instead.
  • The session is potentially leaky, and so are all the scopes built on top of it. As you cannot prevent deletion of the JSESSIONID cookie, you have to apply other methods to save your server-side infrastructure from session flooding. Keeping the session as short-living as possible certainly helps as well.
  • Use singleton beans when it technically makes sense.
Please let me know in the comments section below whether you found this demo application useful and if you came to the same conclusion as I did. Please alert me as well if you found an error in this blog post or the demo application.

Updated June 21, 2015: Included OmniFaces' @ViewScoped implementation


Pages: 1 2

Java EE 7 Bean scopes compared (part 1 of 2)



Having dissected the five standards of “Bean” definitions which are part of Java EE 7 in a previous blog post, I will in this article take a closer look at the various lifecycle “scopes” specified by these Bean definitions. Again, I created a simple demo web application which provides a comparison of JSF, CDI, EJB and “Dependency Injection for Java” Bean Scopes.

TL;DR? Jump into the demo immediately!

Java EE 7: More scopes, more confusion

Java EE 7 defines five notions of “JavaBeans” with partially overlapping, related or just plain incompatible definitions. I went more into the details in my blog post where I made a basic comparison of these five bean types. I judged the current situation as “modularity overkill” when looking at the bean types alone.

Things get even more confusing when looking at one of the most important properties of a Bean type – its lifecycle definition, as provided by its scope type. Three of the five aforementioned bean definitions come with their own scope definitions:
  • JSR-330: Dependency Injection for Java
  • JSR-346 (formerly JSR-299): Contexts and Dependency Injection for Java EE (CDI)
  • JSR-344 (formerly JSR-314): JavaServer Faces (JSF)
Also, the EJB specification distinguishes its individual bean types by their lifecycle properties, thus we can add this framework to the list for providing these “implicit scopes”:
  • JSR-345 (formerly JSR-318): Enterprise JavaBeans (EJB) Lite
…in total, there are 17 scopes available through bean class annotations! It is however important to know that one can use a scope for bean classes of its corresponding bean type only. In fact, the reasoning about which bean type to use in a certain situation is predominantly defined by the scoping requirements: First you decide which scope you need, then you decide the most suitable bean type which provides that scope.

This decision is not made easy as the scope definitions, very much like bean definitions, include ambiguity both in meaning and artifact naming, and clear walk-though documentation is apparently rare. I would assert that the latter is especially true to the latest addition of the “scopes family”: JSF’s flash scope and JSF’s / CDI’s flow scope.

Therefore, I created yet another JSF demo web application which compares the available bean scope definitions of Java EE 7 Web Profile. Feel free to download the source code, play with the live demo, or read on for more information and conclusions.

Exploring bean scope definitions: how the demo works

The demo web application I created is not based on JUnit tests; rather, it runs in the browser which allows you to interact with the server and observe page navigation consequences for the different bean scope definitions.

Within the demo application, for each scope definition under test, one bean class has been created and annotated appropriately. Their @PostConstruct / @PreDestroy methods are used to increase / decrease a counter on an @ApplicationScoped (global, infinite lifespan) bean (Counter) in order to observe the number of currently active beans, the number of previously created beans, and the number of previously destroyed beans of the given type. These numbers are then displayed in a comparison table on a JSF page.

Through eleven actions, the user can interact with the server and thus influence the lifecycle of the beans with immediate visual feedback to his actions:
  • GET to same page: Sends a GET request to the origin URL. This is as if the user refreshes the page in his browser or if he follows an <a> link to the same page.
  • GET with navigation: Sends a GET request to a different URL. This is as if the user navigates to a different URL, e.g. through an <a> link pointing to a different page.
  • POST to same page: Sends a POST request to the origin URL. This is like a <form>’s <h:commandButton> / <h:commandLink> submit action with void navigation outcome (a “postback”).
  • POST with navigation: Sends a POST request to the a different URL. This is like a <form>’s <h:commandButton> / <h:commandLink> submit action with String navigation outcome.
  • Begin CDI Conversation: Invokes the CDI @ConversionScoped bean’s Conversation#begin() method in order to start a conversation.
  • Forget CDI Conversation: Removes the cid HTTP request parameter which holds information about the current Conversation.
  • End CDI Conversation: Invokes the CDI @ConversionScoped bean’s Conversation#end() method in order to end a conversation.
  • Begin CDI Flow: Sets the navigation outcome to the id of a configured CDI flow in order to start a flow.
  • End CDI Flow: Sets the navigation outcome to the id of the return node of the current CDI flow in order to end the flow.
  • Invalidate session: Invokes ExternalContext#invalidateSession() in order to destroy the current session.
  • Reset: Resets the counter. Note that this will not reset the server’s state (as e.g. held in the session).
Additionally, the user may want to:
  • Destroy the session cookie on the client side: Remove the JSESSIONID cookie so the web application won’t recognize the user as being associated with a session already.
For this demo application, session timeout has been set to 5 minutes.

Some more “behind the scenes”

EJB's @MessageDriven

Omitted, because it doesn’t really represent a “scope”, but a special use case.

EJB's @Stateful

Because EJB @Stateful beans are not eligible for @Named to enable EL injection, I used a static helper method to retrieve the bean via CDI’s BeanManager.

Flash Scope

In order to keep track of the lifespan of objects put in flash scope in the same way as the application keeps track of beans in other scopes, I created an additional @RequestScoped JSF @ManagedBean,  but instead of referring to it directly in the EL, I pointed to a helper method which either retrieved the bean from the flash scope, or, if it is not present there, injects a new instance of the bean and puts it into flash scope (in JsfFlashLoader):
@ManagedProperty("#{flash}")
private Flash flash;

public JsfBeanRequestFlash loadBean() {
    JsfBeanRequestFlash instance = (JsfBeanRequestFlash) flash.get("jsfBeanFlash");
    if (instance == null) {
        instance = Faces.evaluateExpressionGet("#{jsfBeanRequestFlash}");
        flash.put("jsfBeanFlash", instance);
    }
    return instance;
}
At runtime, the application thus shows the expected behavior of switching between new bean creation and flash scoped bean retrieval.

Flow Scope

In order to use the same XHTML pages for flow scope tests which are used for all the other tests, I had to put them in the directory structure expected for flow pages.

The Flow is produced by a method in an @ApplicationScoped CDI bean (CdiFlowBuilder).

Run it!

This is an interactive demo application; its true value is perceived only if you go ahead and click yourself through it, playing with different actions and observing their consequences.

LIVE on WildFly

Click here to see a LIVE demo of the application running on WildFly 8.2.0 (hosted on OpenShift).

Note that for the live demo version, the Counter bean which takes track of the bean count has been switched from @ApplicationScoped to @SessionScoped so that each user gets his individual counter.

Watch on YouTube

If the live demo server is down and you don’t like installing the demo on your own server, you can here watch a simple click-through screen recording I uploaded to YouTube:

On your own server

Please feel free to download this demo application from GitHub and deploy it to your own server instance.

I encourage you to try out the demo application on your own, and draw your own conclusions before reading my own findings on the next page!


Pages: 1 2

May 17, 2015

RESTful JSF with POST-redirect-GET (part 5 of 5)


Pages: 1 2 3 4 5

What about optimistic locking?

As I briefly mentioned earlier, our application is implicitly ready for optimistic locking. There’s really not much left to do:

In the edit view, make sure to include an <h:inputHidden> field which is backed by the entity’s @Version annotated property, and handle OptimisticLockException accordingly.

Because the example implementation uses a mocked backend instead, I neglected this topic in the implementation.

True RESTful URLs with PrettyFaces

Our application now supports RESTful URLs, but they are still not truly RESTful as they work with GET request parameters rather than nested resource paths. For example, a URL such as myapp/faces/pages/customers/edit.xhtml?id=1 should really be written as myapp/customers/1. Good news is that with the PrettyFaces library in your path, you get this almost for free.

As the climax of our work, we will thus use PrettyFaces to get true RESTful URLs according to the Microformats definition. This will change the application’s URLs as follows:

Customers Payments
List /customers/ /customers/1/payments/


Edit /customers/1 /customers/1/payments/1


Create /customers/new /customers/1/payments/new



Here’s a little walkthough, based on the official documentation.

First of all, add PrettyFaces dependencies to your pom.xml.

Then, create a WEB-INF/pretty-config.xml page.

For the demo application, this is its complete content:
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
                      http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
    
    <url-mapping>
        <pattern value="/customers/" />
        <view-id value="/faces/pages/customers/list.xhtml" />
    </url-mapping>
    <url-mapping>
        <pattern value="/customers/#{/[0-9]+/ id}" />
        <view-id value="/faces/pages/customers/edit.xhtml" />
    </url-mapping>
    <url-mapping>
        <pattern value="/customers/new" />
        <view-id value="/faces/pages/customers/edit.xhtml" />
    </url-mapping>
    
    <url-mapping>
        <pattern value="/customers/#{customer}/payments/" />
        <view-id value="/faces/pages/payments/list.xhtml" />
    </url-mapping>
    <url-mapping>
        <pattern value="/customers/#{customer}/payments/#{/[0-9]+/ id}" />
        <view-id value="/faces/pages/payments/edit.xhtml" />
    </url-mapping>
    <url-mapping>
        <pattern value="/customers/#{customer}/payments/new" />
        <view-id value="/faces/pages/payments/edit.xhtml" />
    </url-mapping>

</pretty-config>
After redeployment, really everything will work. In fact, not only will you be able to enter the new URL and still access the expected site, but thanks to what PrettyFaces calls “outbound-rewrite”, even link URLs generated by the application (<a href> values) will be rewritten (sort of reverse-engineered) to match the new URL patterns.

Here are a few lessons learnt:
  • The <url-mapping>s are checked in order and the first match wins. You should thus start with the most specialized pattern and then get more general.
  • However, you may find unexpected behavior if the first match is too specific. For example, if the two <url-mapping>s pointing to /faces/pages/customers/edit.xhtml were swapped, a link which should map to /customers/1 would map to /customers/new?id=1. I do not fully understand this behavior, but by swapping the definition, the problem disappeared. Note that instead I had to use regex matching for the parameter in order to overcome ambiguity.
  • Note that even trailing slashes in the URL matter! For example, /customers/1 works fine, but /customers/1/ would lead to a 404 Not Found error. This is actually in accord to the RESTful URL definitions mentioned earlier.
  • Rewriting <h:button> and <h:link> outcomes only works if every pattern path-parameter is matched by a non-disabled <f:param>. In the example application, this is especially true for the link in the Id column of the payments dataTable in /customers/list.xhtml and for the Reset button in payments/edit.xhtml. Note how I used the rendered attribute to create two versions of that button just to make sure that its params match the respective mapping:
<h:button value="Reset" outcome="edit.xhtml" rendered="#{empty paymentController.currentEntity.id}">
    <f:param name="customer" value="#{paymentController.currentEntity.customer.id}"/>
</h:button>
<h:button value="Reset" outcome="edit.xhtml" rendered="#{not empty paymentController.currentEntity.id}">
    <f:param name="id" value="#{paymentController.currentEntity.id}"/>
    <f:param name="customer" value="#{paymentController.currentEntity.customer.id}"/>
</h:button>
  • Finally, I found out that PretttyFaces does not support <a> anchor navigation (“#”). While this is perfectly valid for a true REST framework, it may nevertheless be a nice feature for integration with JavaScript actions or the like. Luckily, there’s a workaround:
In the example application, I’ve made it so that /customers/1/payments/ should redirect to /customers/1#payments. Currently, #payments is just an anchor on the page, but you could imagine it triggering e.g. a tab change on a JavaScript-controlled tab element.

The trick is to create a separate XHTML page (/payments/list.xhtml) which is then used in the respective <url-mapping> just like any other page URL. The page, however, consists of a single JavaScript function call which redirects to /customers/1#payments:
<h:head>
    <title>Payments</title>
    <h:outputScript library="js" name="purl.js" />
    <script type="text/javascript">
        var Navigation = {
            navigate : function() {
                var customer = purl().param("customer");
                if (typeof customer === 'undefined') {
                    customer = purl().segment(3);
                }
                window.location = '/' + purl().segment(1) + '/customers/' + customer + '#payments';
            }
        };
    </script>
</h:head>
<h:body>
    <o:onloadScript>Navigation.navigate();</o:onloadScript>
</h:body>
Here, I’m using the Purl helper library to parse the request URL. Note that I have to parse it for either the request parameter (that’s the case for an outbound-rewritten URL) or for a segment in the URL (that’s the case for a manually typed URL) to find the id of the customer to the edit.xhtml of which I have to redirect.

Conclusion

Building a true RESTful application in JSF is not trivial. Yes, there are a few pitfalls, and there’s no complete out-of-the-box recipe out there. But once the base has been built, your application will stand on a solid best-practices foundation. I think the most important part really is to think about the concepts behind REST, and then reason which parts of it will be useful for the application’s requirements. Adhering to the concepts of REST helps building a web application in a robust and clean way, and you should have very good reasons not to do so. Lack of JSF knowledge should not be one of those reasons.

I encourage you to check out the example application and adapt the techniques I presented here for your own application, as needed. If you run the application on your own server, remember that as the mocked backend services are just @SessionScoped CDI beans, you just have to invalidate the session in order to reset the entities. Please let me know whether this article has been helpful for you or if it lacks any important information. Also feel free to share your experience with “JSF on REST” in the comments section below. Than you for your interest in this blog post!

Updated June 21, 2015: part 3 / 4 restructured (“Restoring invalid null input”); included a link to the @ViewScoped source code on GitHub.


Pages: 1 2 3 4 5

RESTful JSF with POST-redirect-GET (part 4 of 5)


Pages: 1 2 3 4 5

Going @RequestScoped

So far, we’ve built our application with @ViewScoped / @SessionScoped controllers. But wait, you say, as page navigation is stateless, can’t we go for stateless controllers as well... @RequestScoped controllers?

Yes, we can, and we will, although we’ll have to overcome some technical difficulties.

Concept

For your own RESTful web application, you’ll have to decide whether to go for @RequestScoped controllers or not by comparing the advantages:
  • Server-side memory consumption minimized: there is just no state.
  • “Open session in view” problem is prevented.
  • Memory leaks through session pollution are prevented: there are just no non-empty sessions.
  • Session timeouts are prevented: ditto.
to the disadvantages:
  • Data access rate maximized: On every request, the data of the current view needs to be fetched from the backend.
  • You cannot use AJAX. (We’ll discuss later how to address this issue.)
Thus in an application where the bottleneck is memory consumption on the (view layer) JVM, and not data retrieval rate at the backend, I would suggest opting for @RequestScoped controllers.

Implementation

In order to change to @RequestScoped controllers, we have to adjust some parts of the application, and watch out for some pitfalls.

GET

For GET, nothing changes. Everything still works, with or without parameters.

POST-redirect-GET: Reload on PreValidate

There is however a problem with POSTing a form with applies e.g. to the Save action on /customers/edit.xhtml.

With a @RequestScoped controller, the current implementation would immediately throw an exception:
javax.faces.FacesException: /pages/customers/edit.xhtml @48,123 
    value="#{customerController.currentEntity.name}": 
    Target Unreachable, 'null' returned null
Note that the error does not happen in a <f:viewAction>. Actually, its execution is never reached as the error happens in the PROCESS_VALIDATIONS phase in the first lifecycle run already:

As the backing bean is request scoped, it is rebuilt from scratch with the “Save” request. As the action does not set immediate="true", the full life cycle is invoked including phase 3, PROCESS_VALIDATIONS. However, as the backing bean has just been recreated, customerController.currentEntity is now null.

To prevent the exception, we must initialize customerController.currentEntity prior to validation. We do so by refetching the entity from the backend. Why not just create a new entity e.g. with the default constructor? After all, the entity’s values will be overridden during UPDATE_MODEL_VALUES anyways. Yes, but due to lazy loading, only those values would be set which actually have a corresponding input component in the form. We cannot rely on that and thus we have to refetch the entire thing.

Technically, we could use @PostConstruct, but as I mentioned previously, I don’t like mixing up concepts.

Instead, we use an additional <f:event>:
<f:metadata>
    <f:viewParam name="id" value="#{customerController.currentEntityId}"/>
    <f:event type="preValidate" listener="#{customerController.initCurrentEntity}"/>
    <f:viewAction action="#{customerController.initCurrentEntity}"/>
</f:metadata>
The event reuses the method bound to the viewAction which now includes a bit more logic:
public String initCurrentEntity() {
    if (currentEntityLoadedOutcome != null) {
        String ret = currentEntityLoadedOutcome;
        currentEntityLoadedOutcome = null;
        return ret;
    }
    
    // load param during preValidate phase (if @RequestScoped)
    String idParam = Faces.getRequestParameterMap().get("id");
    if (!Strings.isEmpty(idParam)) {
        currentEntityId = Long.parseLong(idParam);
    }
    
    // without id param: CREATE
    if (currentEntityId == null) {
        currentEntity = createNewEntity();
    }
    else {
        // with id param: READ
        currentEntity = getService().findById(currentEntityId);
        if (currentEntity == null) {
            Messages.addGlobalError("Entity with id " + currentEntityId + " not found!");
            currentEntityLoadedOutcome = "list.xhtml";
            return currentEntityLoadedOutcome;
        }
    }
    currentEntityLoadedOutcome = "edit.xhtml";
    return "edit.xhtml";
}
  • If the method is triggered by <f:event>, we must retrieve the id parameter value directly from the request parameter map.
  • As a GET request would now trigger both the <f:event> and the <f:viewAction>, we want to make sure that it only runs through once for performance reasons.
Why not just kicking out <f:viewAction>? It’s because <f:viewAction> has the ability to redirect (e.g. on error) through the String return value of the method. Yes, you could achieve the same with some hacks in <f:event>, but I don’t like that. With the current design, one could set the controller back to @ViewScoped, delete the <f:event> tag, and everything would still be best practices.

Bugfix: @RequestScoped commandButton in dataTable

Unrelated to RESTful navigation, there is a problem with <commandButton> / <commandLink> when rendered inside a <column> of a <dataTable> if their action is backed by a @RequestScoped backing bean: this button’s action will not be invoked. This is the case e.g. for the Delete button (“X”) in the Delete column in customers/list.xhtml’s dataTable.

This behavior is explained in this stackoverflow answer. Apparently, JSF cannot invoke a button’s method in this situation. Of course, the suggestion to switch to a @ViewScoped bean is not acceptable here.

There is, however, another workaround which is here realized using some OmniFaces functionality:
    <h:column>
        <f:facet name="header">
            <h:outputText value="Delete"/>
        </f:facet>
        <a href="#" onclick="deleteAction({ deleteId: '#{item.id}'})">X</a>
    </h:column>
</h:dataTable>
<o:commandScript name="deleteAction" action="#{customerController.delete}" immediate="true"
                 oncomplete="window.location='list.xhtml';"/>

  • <o:commandScript> registers a JavaScript function of the given name with triggers an AJAX request to the given backing bean action.
  • This function is triggered by an <a> element’s onclick attribute (<o:commandScript> supports providing HTTP request parameters to the backing bean action). Because <a> must define a href attribute, we set that to "#" to prevent navigation.
  • The <o:commandScript> also registers an AJAX callback (oncomplete) which here reloads the page. Note that we must explicitly redirect, not just reload, in order to get rid of that "#" again.
Here’s the implementation of the backing bean method:
public String delete() {
    Long id = Long.parseLong(Faces.getRequestParameter("deleteId"));
    return delete(id);
}
This parses the deleteId param from the HTTP request parameter map and then invokes the actual business method.

Warning: If the dataTable is part of a <o:form includeRequestParams="true"> you must not use a parameter name which clashes with one of the <f:viewParam>s; otherwise, on form submit, the parameter value explicitly set in the JavaScript method call would be overridden by the <f:viewParam>’s value.

Because in the example application, we want to reuse the same logic for /customers/edit.xhtml’s payments dataTable where a <f:viewParam name="id"> is already present, I chose the more explicit deleteId parameter name.

Bugfix: @RequestScoped commandButton with conditional rendered attribute

Unrelated to RESTful navigation, there is another problem with <commandButton> / <commandLink> with a conditional rendered or disabled attribute if their action is backed by a @RequestScoped backing bean: this button’s action will simply not be invoked. This is the case e.g. for the Delete button in customers/edit.xhtml.

The causes are explained in this stackoverflow answer and here as well. Apparently, JSF’s design prevents proper action invocation in this situation for any conditionally rendered / disabled <commandButton> / <commandLink>.

As a workaround, I created a phase listener which sets the rendered attribute on all components “hard-coded” to true right before APPLY_REQUEST_VALUES phase and sets it back to the original value after APPLY_REQUEST_VALUES phase.

Note that this knocks out that “invocation safety” check which is hard-wired in JSF. On the other hand, I think that in order to really prevent the user from pressing a button, you should anyways do more than just making that button invisible. In this application for example, we set the Delete button to invisible only because it would not make sense to delete a not-yet-persisted entity; it would just trigger an Exception.

Anyway, I you want to apply this solution, you have to register the phase listener within <f:view>:
<f:view beforePhase="#{forceRenderActionSourceListener.forceRenderActionSource}"
    afterPhase="#{forceRenderActionSourceListener.forceRenderActionSourceReset}">
The listener must be a bean with a scope greater than request scope. Due to its stateless nature, I’ve used @ApplicationScoped here.

Please refer to the application’s source code for the complete implementation of ForceRenderActionSourceListener.

Bugfix: commandButton with immediate="true" attribute based on <f:event> values

Unrelated to RESTful navigation, there is yet another problem with <commandButton> / <commandLink> with the immediate="true" attribute if their action relies on a backing bean value being set / initialized within an <f:event> invocation: as the event would be fired too late in the JSF lifecycle, the value is not set yet, potentially leading to Exceptions. This is not a direct consequence of, but is likely always the case if the backing bean is @RequestScoped. This is the case e.g. for the Delete button in customers/edit.xhtml, which relies on the execution of BaseController#initCurrentEntity().

Setting immediate="true" on a <commandButton> is the default solution to skip the validation / model update phases of the JSF lifecycle.

Now observe this implementation of the Delete button:
<h:commandButton value="Delete" action="#{customerController.delete(customerController.currentEntity.id)}" 
                                 immediate="true" rendered="#{not empty customerController.currentEntity.id}"/>
Remember that we established in the POST-redirect-GET: Reload on PreValidate section, that customerController.currentEntity will be null during PROCESS_VALIDATIONS (3) phase; that’s why we re-initialized the controller with
<f:event type="preValidate" listener="#{customerController.initCurrentEntity}"/>
The problem is now that immediate="true" skips any phase after APPLY_REQUEST_VALUES (2); the preValidate event listener is thus never called, and customerController.currentEntity.id stays null.

The workaround is that instead of sending the parameter value in question as a EL method parameter, to set it with <f:param>.
<h:commandButton value="Delete" action="#{customerController.delete}" immediate="true"
                 rendered="#{not empty customerController.currentEntity.id}">
    <f:param name="deleteId" value="#{customerController.currentEntity.id}"/>
</h:commandButton>
In the backing bean method, we then have to retrieve the parameter value from the request parameter map:
public String delete() {
    Long id = Long.parseLong(Faces.getRequestParameter("deleteId"));
    return delete(id);
}
Yes, we re-use the server-side logic established in the Bugfix: @RequestScoped commandButton in dataTable section.

AJAX

As mentioned earlier, a major disadvantage of having a @RequestScoped backing bean is that you cannot use AJAX calls! An AJAX call would be handled as a new request, thus destroying and recreating the backing bean. This is harmful because the AJAX request will by definition only carry a fraction of the information a full page reload would request / receive. Thus state would get lost, triggering NullpointerExceptions and other undesired behavior.

My advice is to not try to cheat the system. Either embrace the statelessness of your controller or switch to a stateful implementation.

On the other hand, you can of course include dynamic behavior in your request scoped pages: by using JavaScript. If you think about it, this actually makes sense. With the pure stateless nature of the HTTP protocol, the only way to keep state is to keep it on the client. This is exactly how JavaScript based frameworks work. It may even be the superior solution in some cases: Rather than cluttering the server side with logic and state which belongs to the client, keep it local.

Our application carries an example of this. Do you remember this requirement we have for the customer edit view: “A customer of employment type unemployed must not have a company name.” In plain JSF, one might be tempted to implement this with a conditional rendered attribute which is changed by the dropdown’s onchange AJAX action:
<h:selectOneMenu id="employmentStatus" value="#{customerController.currentEntity.employmentStatus}" 
                 title="Employment status"
                 converter="omnifaces.GenericEnumConverter">
    <f:selectItems value="#{EmploymentStatus:values()}"/>
    <f:ajax event="change" render="@form:companyNameLabel @form:companyName"/>
</h:selectOneMenu>
<h:outputLabel id="companyNameLabel" value="Company name:" for="companyName"
               rendered="#{customerController.currentEntity.employmentStatus != 'Unemployed'}"/>
<h:inputText id="companyName" value="#{customerController.currentEntity.companyName}" title="Company name:" 
             rendered="#{customerController.currentEntity.employmentStatus != 'Unemployed'}"/>
But with a @RequestScoped backing bean, this will just not work. We have to come up with a JavaScript based solution. Of course, you would basically use any JavaScript framework however sophisticated you’d like it to be. For this example, I used a plain jQuery-based solution:
<o:onloadScript>CustomerEdit.companyNameInit('form:employmentStatus');</o:onloadScript>
…
<h:selectOneMenu id="employmentStatus" value="#{customerController.currentEntity.employmentStatus}" 
                 title="Employment status"
                 converter="omnifaces.GenericEnumConverter"
                 onchange="CustomerEdit.companyNameInit(this.id);">
    <f:selectItems value="#{EmploymentStatus:values()}"/>
</h:selectOneMenu>
where CustomerEdit.companyNameInit(employmentStatusComponentId) triggers hiding / unhiding and wiping of the companyNameLabel and companyName component, based on the current employment status.

Please refer to the complete source code if you’re interested in the JavaScript implementation.

I’d assert that from a software design as well as from a bandwith consumption point of view, this implementation is even superior to a server-side solution: If the problem is local, then solve it locally.

However, remember that no client side solution is save! You have to assume that the user is able to disable it. Thus you have to provide a server-side safety net. For this example, I thus created a validation constraint which prevents the user from submitting the form if that restriction is violated:
<o:validateMultiple components="employmentStatus companyName" 
                    validator="#{customerController.isCompanyEmptyWhenUnemployed}"
                    message="{0}: If unemployed, no company name must be set."/>
Again, please refer to the source code for the server-side implementation of the validation method.

Pages: 1 2 3 4 5

RESTful JSF with POST-redirect-GET (part 3 of 5)


Pages: 1 2 3 4 5

RESTful navigation (continued)

Implementation

GET without parameter

In the simplest case, a view doesn’t take any GET parameter. In above state diagram, these use cases are colored in blue. As an example, this is the case for /customers/list.xhtml.

However, the view has to be initialized on page load. Therefore, JSF 2.2 provides the new <f:viewAction> tag which offers some advantages over the older (but still valid and useful, as we’ll see later) <f:event> tag. We can specify
<f:metadata>
    <f:viewAction action="#{customerController.initEntities}"/>
</f:metadata>
Note that <f:viewAction>, <f:event> and <f:viewParam> must be placed inside <f:metadata>!

The view action is executed on page load and can point to any backing bean method. In customers/list.xhtml, it initializes the customer table (by fetching the data from the service):
public void initEntities() {
    this.entities = getService().findAll();
}
This method is implement in BaseController.

This mechanism is completely unrelated to annotating an “init” method with @PostConstruct as it is common practice in non-RESTful JSF application design. Actually, we will never use @PostConstruct throught this application as that mechanism is driven by the backing bean’s life cycle whereas <f:viewAction> / <f:event> is driven by actual view events. Thanks to REST, we have complete control over the latter whilst being independent of the former, and we don’t want to mix those two concepts.

How do you trigger GET navigation without parameter? Of course, this is trivial. GET navigation happens if the user types the URL (here, /customers/list.xhtml) and hits enter. This is how it works in the example application.

Creating an actual navigation link of course is trivial, too. Just any <a href="/customers/list.xhtml">Customer list</a> will do. However, we prefer using “proper” JSF components <h:link> and <h:button>, respectively, for full JSF support. The former will actually be rendered as an <a>-tag, the latter as a <button>.

For example, this is how the Cancel button on the /customers/edit.xhtml view is implemented, which navigates back to the list view:
<h:button value="Cancel" outcome="list.xhtml"/>
Yes, implementing Cancel really just means leaving the page. You don’t even need to put those links / buttons inside a <form>.

Also note that the application now is implicitly lazy-loading ready, e.g. when customers/list.xhtml does #initEntities(), it would respect FetchType.LAZY entity relations; the whole entity is loaded only on demand (e.g. in customers/edit.xhtml’s #initCurrentEntity().

GET with parameter

The interesting part is dealing with GET parameters. In above state diagram, these use cases are colored in magenta. Let’s begin with implementing the view, again. As an example, /customers/edit.xhtml takes an “id” parameter.

This will initialize the view:
<f:metadata>
    <f:viewParam name="id" value="#{customerController.currentEntityId}"/>
    <f:viewAction action="#{customerController.initCurrentEntity}"/>
</f:metadata>
<f:viewParam> takes the values of the GET parameter with the given name and binds it to the given backing bean property. Based on that value (plus any other information available), <f:viewAction> can then trigger the view initialization.
public String initCurrentEntity() {
    // without id param: CREATE
    if (currentEntityId == null) {
        currentEntity = createNewEntity();
    }
    else {
        // with id param: READ
        currentEntity = getService().findById(currentEntityId);
        if (currentEntity == null) {
            Messages.addGlobalError("Entity with id " + currentEntityId + " not found!");
            return "list.xhtml";
        }
    }
    return "edit.xhtml";
}
Just as we specified earlier:
  • Without an id param, a new entity is created.
  • With id param, the requested entity is fetched.
  • If the entity is not found, the user is redirected to the list view and an error message is shown.
Note that <f:viewAction> can optionally return a String (instead of void) which can be used to trigger a redirect rather than opening the requested view. This is useful for the “illegal id” case. This is implicitly a “proper” redirect with URL rewrite.

The method is implement in BaseController.

Triggering GET with parameter is of course trivial as well: For the user, it’s a matter of navigating to e.g. /customers/edit.xhtml?id=1.

Creating a navigation link is easy, too. It’s just a <a href="/customers/edit.xhtml?id=1">Edit customer 1</a>. However, JSF provides a means of creating those links more explicitly, as for example in the customer list view pointing to a single customer in the dataTable:
<h:link outcome="edit.xhtml" value="#{item.id}">
    <f:param name="id" value="#{item.id}"/>
</h:link>
This works for both <h:link> and <h:button> and is the preferred way of creating a GET link with parameter.

POST-redirect-GET

This is a key ingredient of RESTful navigation. Luckily, it is easily realized with JSF. It’s important to understand that POST-redirect-GET actually involves two JSF lifecycle runs. In above state diagram, these use cases are colored in red. As an example, let’s take the Save action on /customers/edit.xhtml.

Let’s take a look at the implementation.

As we are doing POST, we use a default <commandButton> / <commandLink>:
<h:commandButton value="Save" action="#{customerController.save(customerController.currentEntity)}"/>
Important: If you use PrimeFaces components, make sure to set the ajax="false" attribute: PrimeFaces components are implicitly “ajaxified” meaning that they would not trigger a page refresh, but update parts of the view instead. This is not what we want for RESTful navigation!

The save method triggers the service call and returns the navigation outcome:
public String save(T currentEntity) {
    getService().save(currentEntity);
    return "list.xhtml?faces-redirect=true";
}
The important part here is to set the faces-redirect=true request parameter in the navigation outcome. This is what actually triggers redirect, thus URL rewrite.

Let’s observe now how this fits in the JSF lifecycle:


The save method redirects to the list.xhtml page. Only after the page is opened, it’s <f:viewAction> / <f:event> is fired, which allows the page to initialize itself again. Thus, with a POST form submit, a GET to another page is triggered: POST-redirect-GET.

In order to navigate to a <a> anchor, e.g. for /customers/edit.xhtml#payments?id=1, you’ll have to apply some JavaScript hacks as a JSF action outcome must not contain an anchor reference. One possible solution is to add an auxiliary request parameter, e.g. ?anchor=payments, and on the target page onload, parse the URL for that parameter and make a redirect to the anchor. I will eventually build a similar solution in the “final” version of this application, featuring true RESTful URLs with PrettyFaces.

This is the last piece of the puzzle. With this knowledge, you can build any RESTful navigation case backed by a @ViewScoped controller. Please read on for more sophisticated solutions.

NullPointerException in <h:button> / <h:link> with parameter

The presence of a <h:button> / <h:link> with a <f:param> whose value's EL expression raises a NullPointerException immeditaely throws this NullPointerException all the ways up, without stacktrace:
FATAL:   JSF1073: java.lang.NullPointerException caught during processing of RENDER_RESPONSE 6 : UIComponent-ClientId=, Message=null
FATAL:   No associated message
java.lang.NullPointerException
On another occasion, I’ve met the following more chatty Exception in this situation which isn’t any more helpful though:
java.lang.NullPointerException
 at java.net.URLEncoder.encode(URLEncoder.java:204)
 at com.sun.faces.context.UrlBuilder.addValuesToParameter(UrlBuilder.java:318)
 at com.sun.faces.context.UrlBuilder.addParameters(UrlBuilder.java:127)
 at com.sun.faces.context.ExternalContextImpl.encodeBookmarkableURL(ExternalContextImpl.java:1054)
 at com.sun.faces.application.view.MultiViewHandler.getBookmarkableURL(MultiViewHandler.java:407)
 at javax.faces.application.ViewHandlerWrapper.getBookmarkableURL(ViewHandlerWrapper.java:272)
 at org.jboss.weld.jsf.ConversationAwareViewHandler.getBookmarkableURL(ConversationAwareViewHandler.java:132)
 at javax.faces.application.ViewHandlerWrapper.getBookmarkableURL(ViewHandlerWrapper.java:272)
 at com.sun.faces.renderkit.html_basic.OutcomeTargetRenderer.getEncodedTargetURL(OutcomeTargetRenderer.java:194)
 ...
 at java.lang.Thread.run(Thread.java:745)
For example, this is the case for the Reset button in payments/edit.xhtml when declared like this:
<h:button value="Reset" outcome="edit.xhtml">
    <f:param name="id" value="#{paymentController.currentEntity.id}"/>
    <f:param name="customer" value="#{paymentController.currentEntity.customer.id}"/>
</h:button>
In order to overcome the error, you have to use <f:param>’s disable flag to conditionally include the param or not, like this:
<h:button value="Reset" outcome="edit.xhtml">
    <f:param name="id" value="#{paymentController.currentEntity.id}" 
        disable="#{empty paymentController.currentEntity.id}"/>
    <f:param name="customer" value="#{paymentController.currentEntity.customer.id}" 
        disable="#{not empty paymentController.currentEntity.id}"/>
</h:button>
According to the domain model, id must be specified for the Read operation, customer must be specified for the Create operation.

Note that this problem may as well apply to <h:button>s / <h:link>s which are in a subsection of the page which has a conditional rendered attribute! That doesn’t prevent them from throwing this exception.

Bugfix: Restoring invalid null input

When setting the web.xml context parameter javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL to true, undesired behavior on validation error will been introduced: if a null input triggers @NotNull / required="true" validation, it will be reset to its previous non-null value, if available, instead of keeping the submitted null value.

This can be observed by omitting the required “name” input for /customers/edit.xhtml?id=1: After validation error, the view is reloaded with the validation error message displayed (“form:name: must not be empty“), but in the form, the previously present non-null “name” value has been restored. This does not match the behavior when violating a Bean Validation constraint, e.g. for illegal input in “name” (e.g. “1234”): in that case, the invalid value is kept after the page refresh. This is confusing for the user. Expected JSF default behavior is that invalid inputs are kept after page refresh so that the user can see the error he made. The exact problem is described in this stackoverflow answer.

I will here present a workaround which doesn’t force you to patch the JSF library: I registered yet another <f:event> with the exclusive duty to set invalid input component’s values to their (invalid) submitted values. It is registered within <f:metadata>:
<f:metadata>
    <f:viewParam name="id" value="#{customerController.currentEntityId}"/>
    <f:event type="preValidate" listener="#{customerController.initCurrentEntity}"/>
    <f:event type="postValidate" listener="#{customerController.postValidate}"/>
    <f:viewAction action="#{customerController.initCurrentEntity}"/>
</f:metadata>
And implemented in BaseController:
public void postValidate() {
        Components.forEachComponent().invoke(new VisitCallback() {
            @Override
            public VisitResult visit(VisitContext context, UIComponent target) {
                if (target instanceof UIInput && !((UIInput)target).isValid()) {
                    ((UIInput) target).setValue(((UIInput) target).getSubmittedValue());
                    return VisitResult.REJECT;
                }
                return VisitResult.ACCEPT;
            }
        });
    }

Bugfix: Keep request parameters on validation error

There is one particular annoyance of the <h:form> component which can be fixed by using OmniFaces’ <o:form> instead. From the OmniFaces showcase: “The standard UIForm doesn't put the original view parameters in the action URL that's used for the post-back. The disadvantage of this invisible retention of view parameters is that the user doesn't see them anymore in the address bar of the browser”. In the example application, this behavior shows up if user input triggers a validation error, e.g. omit “name” in /customers/edit.xhtml?id=1: After form submit, the id param is removed from the URL.

Strictly speaking, because the parameter is still stored in the respective UIViewParameter component, this really is just a usability issue: If e.g. the user corrects the illegal input and re-submits the form, the parameter is still present, and everything works. Nonetheless, the behavior looks buggy and it breaks the premise that the user should be able to hit ENTER in the address bar at any time and be able to refresh the page.

Thus we use <o:form> instead of <h:form>:
<o:form id="form" includeRequestParams="true">
It’s the includeRequestParams="true" attribute which keeps GET parameters in the URL.

Pages: 1 2 3 4 5