Tuesday, March 26, 2013

Java EE 7 and EJB 3.2 support in JBoss AS 8

Some of you might be aware that the Public Final Draft version of Java EE 7 spec has been released. Among various other new things, this version of Java EE, brings in EJB 3.2 version of the EJB specification. EJB 3.2 has some new features compared to the EJB 3.1 spec. I'm quoting here the text present in the EJB 3.2 spec summarizing what's new:

The Enterprise JavaBeans 3.2 architecture extends Enterprise JavaBeans to include the following new functionality and simplifications to the earlier EJB APIs:
  • Support for the following features has been made optional in this release and their description is moved to a separate EJB Optional Features document:
    • EJB 2.1 and earlier Entity Bean Component Contract for Container-Managed Persistence
    • EJB 2.1 and earlier Entity Bean Component Contract for Bean-Managed Persistence
    • Client View of an EJB 2.1 and earlier Entity Bean
    • EJB QL: Query Language for Container-Managed Persistence Query Methods
    • JAX-RPC Based Web Service Endpoints
    • JAX-RPC Web Service Client View

  • Added support for local asynchronous session bean invocations and non-persistent EJB Timer Service to EJB 3.2 Lite.

  • Removed restriction on obtaining the current class loader; replaced ‘must not’ with ‘should exercise caution’ when using the Java I/O package.

  • Added an option for the lifecycle callback interceptor methods of stateful session beans to be executed in a transaction context determined by the lifecycle callback method's transaction attribute.

  • Added an option to disable passivation of stateful session beans.

  • Extended the TimerService API to query all active timers in the same EJB module.

  • Removed restrictions on javax.ejb.Timer and javax.ejb.TimerHandle references to be used only inside a bean.

  • Relaxed default rules for designating implemented interfaces for a session bean as local or as remote business interfaces.

  • Enhanced the list of standard activation properties.

  • Enhanced embeddable EJBContainer by implementing AutoClosable interface.



As can be seen, some of the changes proposed are minor. But there are some which are useful major changes. We'll have a look at a couple of such changes in this article.

1) New API TimerService.getAllTimers()


EJB 3.2 version introduces a new method on the javax.ejb.TimerService interface, named getAllTimers. Previously the TimerService interface had (and still has) a getTimers method. The getTimers method was expected to return the active timers that are applicable for the bean on whose TimerService, the method had been invoked (remember: there's one TimerService per EJB).

In this new EJB 3.2 version, the newly added getAllTimers() method is expected to return all the active timers that are applicable to *all beans within the same EJB module*. Typically, an EJB module corresponds to a EJB jar, but it could also be a .war deployment if the EJBs are packaged within the .war. This new getAllTimers() method is a convenience API for user applications which need to find all the active timers within the EJB module to which that bean belongs.

2) Ability to disable passivation of stateful beans


Those familiar with EJBs will know that the EJB container provides passivation (storing the state of the stateful bean to some secondary store) and activation (loading the saved state of the stateful bean) capability to stateful beans. However, previous EJB versions didn't have a portable way of disabling passivation of stateful beans, if the user application desired to do that. The new EJB 3.2 version introduces a way where the user application can decide whether the stateful bean can be passivated or not.

By default, the stateful bean is considered to be "passivation capable" (like older versions of EJB). However, if the user wants to disable passivation support for certain stateful bean, then the user has the option to either disable it via annotation or via the ejb-jar.xml deployment descriptor.

Doing it the annotation way is as simple as setting the passivationCapable attribute on the @javax.ejb.Stateful annotation to false. Something like:

 @javax.ejb.Stateful(passivationCapable=false) // the passivationCapable attribute takes a boolean value  
 public class MyStatefulBean {  
 ....  
 }  

Doing it in the ejb-jar.xml is as follows:


 <?xml version="1.0" encoding="UTF-8"?>  
 <ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee  
      http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd"  
      version="3.2">  
   <enterprise-beans>  
     <session>  
       <ejb-name>foo-bar-bean</ejb-name>  
       <ejb-class>org.myapp.FooBarStatefulBean</ejb-class>  
       <session-type>Stateful</session-type>  
       <!-- passivation-capable element takes either a true or a false value -->  
       <passivation-capable>false</passivation-capable>  
     </session>  
     ...  
   </enterprise-beans>  
 </ejb-jar>  


Two important things to note in that ejb-jar.xml are the version=3.2 attribute (along with the http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd schema location) on the ejb-jar root element and the passivation-capable element under the session element.

So, using either of these approaches will allow you to disable passivation on stateful beans, if you want to do so.

Java EE 7 and EJB 3.2 support in JBoss AS8:


JBoss AS8 has been adding support for Java EE 7 since the Public Final Draft version of the spec has been announced. Support for EJB 3.2 is already added and made available. Some other Java EE 7 changes have also made it to the latest JBoss AS 8 builds. To keep track of the Java EE 7 changes in JBoss AS8, keep an eye on this JIRA https://issues.jboss.org/browse/AS7-6553.

To use the already implemented features of Java EE 7 in general or EJB 3.2 in particular, you can download the latest nightly build/binary of JBoss AS from here. Give it a try and let us know how it goes. For any feedback, questions or if you run into any kind of issues, feel free to open a discussion thread in our user forum here.



Sunday, January 27, 2013

Custom error pages for expired conversations involving CDI and JSF

It's been a while since I last blogged. I keep thinking of blogging something technical but end up getting busy with other things. This last week there was a very interesting discussion at the coderanch forums. It was even more interesting because it involved JBoss :)

Developers familiar with Java EE web applications would know that the web application deployment descriptor (web.xml) allows you to specify "error pages" which the container will display when a specific exception (class) or a error code is thrown by the server for a web request. Here's a quick example of how it looks like:

 <web-app>  
   ...  
   <!-- A custom error page for error code == 500 -->  
   <error-page>   
     <error-code>500</error-code>   
     <location>/my-foo-bar-500-page.html</location>   
   </error-page>   
     
   <!-- A custom error page for exception type org.myapp.foo.bar.MyException -->  
   <error-page>   
     <exception-type>org.myapp.foo.bar.MyException</exception-type>   
     <location>/my-foo-bar-exception-page.html</location>   
   </error-page>   
   ...  
     
 </web-app>  
   


Simple enough - a couple of custom error pages defined for a specific error code and an exception type respectively. All of this works fine.

In current days, more and more programming models and frameworks come into picture while developing web applications. CDI and JSF are some of those. CDI has this concept of scopes (ex: request scope, session scope, application scope, conversation scope). We won't go into the details of what those are and when those are used, but let's consider conversation scope in this blog since that's what the discussion was about in the forum thread that prompted this blog.

So CDI allows multiple requests to be part of a "conversation scope". A conversation has a "start" and an "end", both of which can be managed by the application. When the application involves JSF, any conversation (id) gets auto-propagated to the JSF request(s). Apart from an explicit start/end demarcation of conversations, a conversation can also timeout. A request which refers to a conversation which has ended or timed out will run into an exception.

So we know have a bit of background on CDI conversation scope. So let's consider a case where the application wants to present a good looking page when the "conversation no longer present" exception is thrown (maybe because of a timeout). We have seen how to write a web.xml for error-page configurations - it would be as simple as:

 <web-app>  
   ...  
     
   <!-- A custom error page for exception type org.jboss.weld.context.NonexistentConversationException -->  
   <error-page>   
     <exception-type>org.jboss.weld.context.NonexistentConversationException</exception-type>   
     <location>/my-foo-bar-exception-page.html</location>   
   </error-page>   
   ...  
     
 </web-app>  
   

Simple enough. The org.jboss.weld.context.NonexistentConversationException is the exception class type which gets thrown when the conversation has timed out (note that we are assuming that the web application is relying on Weld as the CDI spec implementation library). The above configuration works fine. The my-foo-bar-exception-page.html gets displayed when the org.jboss.weld.context.NonexistentConversationException is thrown.

BUT, let's now consider that we want to involve JSF in the error page just like the other parts of our application. So let's point the error-page to a URL pattern which maps to the JSF servlet:

 <web-app>  
   ...  
     
   <!-- A custom error page for exception type org.jboss.weld.context.NonexistentConversationException -->  
   <error-page>   
     <exception-type>org.jboss.weld.context.NonexistentConversationException</exception-type>   
     <location>/my-foo-bar-exception-page.xhtml</location>   
   </error-page>   
   ...  
     
 </web-app>  
   

Note that we changed the error page mapping to my-foo-bar-exception-page.xhtml (notice the xhtml extension) from my-foo-bar-exception-page.html. We'll again assume that the .xhtml resources are mapped to the JSF servlet so those requests are considered as JSF requests.

With this change to the web.xml, you'll notice that the my-foo-bar-exception-page.xhtml will no longer be displayed in you see a big stacktrace with repeatedly shows org.jboss.weld.context.NonexistentConversationException exception in the stacktrace thus giving an impression that the error-page configuration went wrong.

So what did we do wrong? Well, remember that earlier I mentioned that for JSF requests the conversation id gets propagated automatically. That's exactly what's happening here. The server notices the org.jboss.weld.context.NonexistentConversationException exception and then tries to render the error-page which is backed by JSF and since the conversation id gets propagated the server tries to find that non-existent conversation and ends up failing with the same org.jboss.weld.context.NonexistentConversationException and ultimately fails to render the error page. It's like going in circles to render that error page.

So how does one get past it? Keeping aside all the technical details, the obvious thing would be to not propagate the non-existent conversation id while rendering the (JSF backed) error page. So that's what we are going to do. CDI 1.1 (and Weld 1.1.2 and later) allows you to explicitly specify that a conversation shouldn't be propagated for a particular request. You can do this by passing along a parameter named "nocid" within that request. With that knowledge, let's now modify our web.xml to do the necessary changes so that our error page gets rendered properly:


 <web-app>  
   ...  
     
   <!-- A custom error page for exception type org.jboss.weld.context.NonexistentConversationException.  
     Notice the "nocid" parameter being passed to make sure that the non-existent conversation id  
     isn't passed to the error page  
   -->  
   <error-page>   
     <exception-type>org.jboss.weld.context.NonexistentConversationException</exception-type>   
     <location>/my-foo-bar-exception-page.xhtml?nocid=true</location>   
   </error-page>   
   ...  
     
 </web-app>  
   


Notice that we are passing the "nocid" parameter as part of the query string of the error page location. The value for "nocid" parameter really doesn't matter but for the sake of keeping that value logical, we have used the value "true" here. Once this change is done, you'll start noticing that the error page (backed by JSF) now renders correctly!

It took a while for us to get to this solution in that forum thread because it looked so simple that it should have "just worked", but it didnt' Here's the forum thread at coderanch that I've been talking about. Credit goes to Greg Charles for figuring out how to pass that nocid parameter.


Sunday, October 07, 2012

JBoss AS is being renamed

Those of you who missed this year's JavaOne event and still haven't heard about it, here's some news that all JBoss AS followers should be aware of - your favourite application server, JBoss AS, is being renamed.

JBoss AS or just JBoss, as we have all called it since the 3.x days will now be called something else. The reasons for the rename have been explained in this "Why rename JBoss AS, FAQ?". Mark Little has blogged about the this rename in his posts here and here. Read through those pages to understand what's being proposed.

So what's the new name going to be for the JBoss AS project? We don't know yet. In fact, the name will be picked by the community. Everyone is allowed to submit a name of their choice and those names will go through a voting process and one out of those names will be chosen. So if you can think of a name for JBoss AS then go suggest it here before the 14th of this month. Don't leave it for later, this is your chance to be known as the one who chose the new name!