Using EJB Annotations Outside of EJB Blog
The Common Annotations and EJB 3
JSRs both provide a number of annotations that are useful to enterprise
Java developers. This blog entry examines the use of two from EJB3 that
I feel really should be in Common Annotations:@PostConstruct
and @PreDestroy
.
Let's review the purpose of these annotations.
@PostConstruct
* Designates a method to receive a callback during creation of a * session bean or message driven bean instance.
@PreDestroy
* Designates a method to receive a callback before a session bean or * message driven instance is destroyed.
These annotations are useful for any
container managed instance, not just session beans or message driven
beans. This blog shows how I leveraged the new ManagedBeanFactory
SPI in Sun's implementation of JSF technology to create a prototype
that allows JSF authors to use these annotations in their managed beans.
I'm doing this to make the case to move these two annotations out of
EJB and into Common Annotations. If this is done, it's easy to see that
using this feature will find its way into a future version of the JSF
spec.
The running code for this example is checked into the "components" jsf-demo in the JSF project on java.net. You have to get a nightly build more recent than 30 August 2005 to get a build with this code in it, though.
Details
The com.sun.faces.spi.ManagedBeanFactoryWrapper
class
in the Sun JSF implementation allows the user to decorate the internal
implementation class used to instantiate managed beans such that the
creation process can be intercepted and methods annotated with @PostConstruct
can be called. The listeners for request, session, and ServletContext
classes in the Servlet API can be used to intercept destruction events and call managed bean methods annotated with@PreDestroy
.
The following two classes leverage these hook points to implement the feature. The classes are presented in the form of a JSF project change-bundleTo see the real code, please get the source from java.net.
A components/src/java/components/model/LifecycleManagedBeanFactory.java
This class leverages the decorator pattern provided by the
ManagedBeanFactory
SPI to decorate thenewInstance()
method and inject calling the@PostConstruct
method on the ManagedBean instance being created, if present. It also establishes a contract with theLifecycleManagedBeanListener
to call the@PreDestroy
annotated methods, if present, when the time comes.
A components/src/java/components/model/LifecycleManagedBeanListener.java
This class implements ServletRequestListener, HttpSessionListener
, and ServletContextListener
and uses the *Destroyed
methods to look into the list established by the LifecycleManagedBeanFactory
for this scope and call any appropriately annotated methods.
M components/src/java/demo/model/RepeaterBean.java
annotate some methods to be called.
M components/web/WEB-INF/web.xml
Declare the above LifecycleManagedBeanListener
.
M components/build.xml
Declare a compile time dependency onjsf-impl.jar
.
Summary
It could be said that using annotations in this way is just making up for Java's lack of a proper destructor, as one has in Objective C and C++. However, using annotations in this way is far more flexible than constructors and destructors, while not adding any conceptual burden for the new developer. New developers can simply avoid using annotations until they feel ready to do so. Another factor to consider is that the servlet API could be enhanced to automatically call methods annotated with these or similar annotations when objects are added to the request, session, or application scope. I hope I've demonstrated the usefulness of these two annotations outside of EJB and made a good case for moving them out to Common Annotations.
Technorati Tags: edburns