Sunday 10 November 2013

GenericMessage for DeltaSpike supporting JSF and REST

Introduction

In the post of January 2013, I described the feature of DeltaSpike to have type safe messages from within a CDI bean which are displayed within the <h:messages> tag of JSF.
It is a great feature which has a minor drawback, especially in the perspective of Java EE as a universal backend system. (see this post for the idea behind this)
In the case a CDI bean, like a service type of bean, is used in the context of JSF and REST contexts, because you have multiple types of clients, there is an issue with JsfMessage of DeltaSpike.

Custom version

Since DeltaSpike is an open source project, you can easily find out how the feature is coded. And you can create something similar which isn’t tied to JSF quit easy as you can see in this post.
First we need to define the alternative for the JsfMessage interface, lets call it BusinessMessage.
public interface BusinessMessage<T> {

    T failing();

    T warning();

    T information();
}

We have 3 methods, so that we can define an error, warning and information message. 

The usage of this interface will be identical to the JsfMessage one of DeltaSpike.  Se we need to define an interface which will be annotated as MessageBundle and we are ready to use it.
@MessageBundle
public interface ApplicationMessages {

    @MessageTemplate(value = "Person already registered")
    String personAlreadyRegistered();
}


@ApplicationScoped
public class AttendeeService {

    @Inject
    private BusinessMessage<ApplicationMessages> message;

    public void addPerson(Person person) {
        //....
        message.failing().personAlreadyRegistered();
    }
}

Within the implementation of the BusinessMessage interface we will make, we can now make sure it will work within a JSF and REST context.

BusinessMessage implementation details

I’m not going to describe all the implementation details in this post.  In a few weeks, the code of a demo application will be made available that highlights almost all of the things that kept me busy the last year. And it is using the BusinessMessage described here.

The code is using the org.apache.deltaspike.core.impl.message.MessageBundleInvocationHandler class of DeltaSpike to have a dynamic implementation of the @MessageBundle annotated interfaces like ApplicationMessages we have in the above example block.

Once we have the message text the user wants, we will store it in a Thread local variable, maintained by a new class BusinessMessageContext.  This class makes it possible to keep some messages independent of the view technology used. So it is supporting JSF and REST style of working.

Show the messages

The last step to solve our issue is that we need use the messages stored in the BusinessMessageContext and send it to the correct view.

For JSF we can create a PhaseListener implementation which is triggered before each Render Response phase.  It can add the messages to the JSF system using the facesContext.addMessage method.

For REST, we can use a javax.ws.rs.container.ContainerResponseFilter concept explained in this post, to send the messages to the client as a JSON response. Some of the aspects will be described in more detail in a future post on that blog.

In both cases, we need to do the clean up of the Thread local variable we have used to store the messages to reclaim the memory.  Therefor the class BusinessMessageContext has a method release() to perform this clean up.

Conclusion

JsfMessage of DeltaSpike is a great feature to have type safe messages. But in some cases your CDI bean will be used in multiple ‘environments’, JSF and REST for example. In that case, we need an alternative which works almost the same but stores the messages, at least initially, in a view neutral way.

Code will be available as part of the demo which will be released in a few weeks.