TOTD #167: Automatic Resource Management or try-with-resources - Using Java 7 in Java EE 6/GlassFish


Java 7 is now available, NetBeans 7.0.1 provide complete tooling around it, and GlassFish 3.1.1 allow you to leverage JDK7 features in your Java EE 6 applications. This Tip Of The Day (TOTD) will explain a new feature introduced in JDK7 and how it can be used to simplify your Java EE 6 application code.

Automatic Resource Management (ARM) or try-with-resources is one of the functionality coming from Project Coin as part of Java 7. It simplifies working with external resources such as JDBC connection/statement and xxxInput/OutputStream which need to be explicitly closed in case of an error or successful completion of a code block.

The code originally published in TOTD #164 is given below:

@javax.annotation.PostConstruct
void startup() {
   Connection c = null;
   Statement s = null;
   try {
     InitialContext ctx = new InitialContext();
     DataSource ds = (DataSource)ctx.lookup("jdbc/__default");
     c = ds.getConnection();
     s = c.createStatement();

// invoke SQL here

   } catch (SQLException ex) {
     System.err.println("ouch!");
   } catch (NamingException ex) {
     System.err.println("ouch!");
   } finally {
     try {
       if (s != null)
         s.close();
       if (c != null)
         c.close();
     } catch (SQLException ex) {
       System.err.println("ouch!");;
     }
   }
}
This is a lot of boilerplate code, couple of specific points to note here:
  • Because Connection and Statement need to be closed in "finally" block, they need to be declared outside of the "try" block.
  • "s.close()" and "c.close()" can further throw an SQLException and so there is a nested exception in the "finally" block.
 This code can also be rewritten as:
@Resource(name="jdbc/sample")
DataSource ds;

@javax.annotation.PostConstruct
void startup() {
   Connection c = null;
   Statement s = null;
   try {
     c = ds.getConnection();
     s = c.createStatement();

     // invoke SQL here

   } catch (SQLException ex) {
     System.err.println("ouch!");
   } finally {
     try {
       if (s != null)
         s.close();
       if (c != null)
         c.close();
     } catch (SQLException ex) {
       System.err.println("ouch!");;
     }
   }
}
It still has tons of boilerplate code. This can be easily simplified using JDK 7 Automatic Resource Management by changing the code to:

@Resource(name="jdbc/sample")
DataSource ds;

@javax.annotation.PostConstruct
void startup() {
try (Connection c = ds.getConnection();
     Statement s = c.createStatement())

       // invoke SQL here
     } catch (SQLException ex) {
       System.err.println("ouch!");;
     }
   }
}

The resources defined in the "try" block are automatically closed as they get out of scope and there is no boilerplate code here. The code is much more semantically readable and contains 285 characters instead of 629 in the first version.

NOTE: The code fragments in this blog are updated because throwing a checked exception from a @PostConstruct method is not permitted by the Managed Beans specification. See the comments below for more detailed discussion.

How does this all work under the hood ?

A new java.lang.Autocloseable API has been added to the platform which has a single "close()" method that automatically closes the resource. The java.io.Closeable extends this new API ensuring that xxxInputStream and xxxOutputStream are candidates for ARM. Any resource implementing this interface can be used for ARM so if there are any custom resources in your project then they can leverage this functionality as well.

NetBeans 7.0.1 provide hints to take advantage of JDK7 features. Have you downloaded it yet ? Check out screencast #35 highlighting Project Coin features in NetBeans.

How are you using JDK7 features in your Java EE 6 applications ?

Comments:

The autoclose interface and ARM blocks will spare us a lot of boilerplate code, now lets wait until we get to use jdk7 on our projects :-)

Posted by guest on August 04, 2011 at 04:39 PM PDT #

ARM Blocks are a real nice feature, but I don't think we'll use it much in our enterprise applications. We can't do I/O and JPA is mostly used to handle our persistence. When doing JMS on the other hand, it a very nice feature. Nice read, thanks.

Posted by Jelle Victoor on August 04, 2011 at 04:43 PM PDT #

This screencast from the GlassFish YouTube channel shows some very similar code on action : http://www.youtube.com/watch?v=zdYxdx3FuX0

Posted by Alexis on August 04, 2011 at 04:59 PM PDT #

I think that the use of try with resources without a catch block in a managed bean life cicle method is not permitted according to the java ee specs.

The java ee API documentation state that a method annotated with @PostConstruct MUST NOT throw a checked exception.

see http://download.oracle.com/javaee/6/api/javax/annotation/PostConstruct.html

The example works fine in glassfish 3.1.1, is it a bug?

Best regards,
Roberto

Posted by guest on August 04, 2011 at 08:09 PM PDT #

Roberto,

Your comment led to the following bugs in NetBeans:

http://netbeans.org/bugzilla/show_bug.cgi?id=200715
http://netbeans.org/bugzilla/show_bug.cgi?id=200716

NetBeans is not detecting if @PostConstruct was throwing a checked exception and if there are multiple methods tagged with @PostConstruct.

In GlassFish, if the above bean is marked @Startup and the SQLException is indeed thrown in @PostConstruct then the app is not even deployed. If the above bean is lazily initialized and SQLException is thrown in @PostConstruct then the correct message is thrown in the server.log as:

Caused by: javax.ejb.CreateException: Initialization failed for Singleton NewSessionBean
at com.sun.ejb.containers.AbstractSingletonContainer.createSingletonEJB(AbstractSingletonContainer.java:547)
at com.sun.ejb.containers.AbstractSingletonContainer.access$100(AbstractSingletonContainer.java:79)
at com.sun.ejb.containers.AbstractSingletonContainer$SingletonContextFactory.create(AbstractSingletonContainer.java:719)
... 40 more

If SQLExeption is not thrown in either case, then the bean behaves as normal.

Do you see any discrepancy with the expected behavior ?

Posted by Arun on August 05, 2011 at 10:31 AM PDT #

According to my opinion a more "compliant" (see paragraph 2.5 of common annotations specs) behavior is:

1) stop the deployment of the application with an error message saying that a @PostConstruct method throwing a checked exception is not permitted by the java ee specs

or

2) let the application be deployed but with a warning saying that a @PostConstruct method throwing a checked exeption is in violation of java ee specs an so non portable

From my understanding of the ejb specs the bottom line in exception handling is:
- dealing with unchecked exceptions / ejbexceptions is a responsibility of the ejb container (transaction rollback, take ejb out of service etc.)
- dealing with checked exceptions is a responsibility of the application (the client invoking the ejb method throwing the exception)

In case of a @PostConstruct annotated method the application (application developer) should deal with the checked exception inside the method and not throws it, delegating the responsibility to the container.

Best regards,
Roberto

Posted by guest on August 05, 2011 at 10:39 PM PDT #

Thanks Roberto for your valuable input.

1) is indeed the behavior in case of eager initialization. Should 1) or 2) be enforced in case of a lazy initialization as well ?

Agreed, that the application developer should deal with the checked exception inside @PostConstruct. I've updated the code fragment to reflect that.

Posted by Arun on August 06, 2011 at 01:35 AM PDT #

Great example, one of the best in Java 7 world. Here is another <a href="javarevisited.blogspot.hk/2011/09/arm-automatic-resource-management-in.html">example of Automatic resource management in Java</a>. I like to reduce clutter and my policy of clean code.

Posted by guest on September 06, 2012 at 12:49 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today