Wednesday, September 3, 2008

What happens with an Exception during a lifecycle callback interceptor?

Because lifecycle methods are invoked by the container, there really is no sense in throwing application specific exceptions during the invocation of a lifecycle interceptor method. As such, lifecycle interceptor methods may not throw application exceptions, although they are allowed to throw RuntimeExceptions. If a runtime exception is thrown during an EJB3 lifecycle callback interceptor method, the interceptor chain unwinds, and the EJB instance is discarded. Of course, what else can you really do when a RuntimeException is thrown?

"Lifecycle callback interceptor methods may throw system runtime exceptions, but not application exceptions.

A runtime exception thrown by any lifecycle interceptor callback method causes the bean instance and its interceptors to be discarded after the interceptor chain unwinds. The lifecycle callback interceptor methods for a lifecycle event run in the same Java call stack as the lifecycle callback method on the bean class. InvocationContext.proceed() will throw the
same exception as any thrown by another lifecycle callback interceptor method or lifecycle callback method on the bean class unless an interceptor further down the Java call stack has caught it and thrown a different exception. A lifecycle callback interceptor method (other than a method on the bean call or its superclasses) may catch an exception thrown by another lifecycle callback interceptor method in the invocation chain, and clean up before returning. Exceptions and initialization and/or cleanup operations should typically be handled in try/catch/finally blocks around the proceed() method. The PreDestroy callbacks are not invoked when the bean and the interceptors are discarded as a result of such exceptions: the lifecycle callback interceptor methods in the chain should perform any necessary clean-up operations as the interceptor chain unwinds."

What is the order of invocation on lifecycle interceptor methods for EJB3 beans - Passivate, Activate, PostContruct & PreDestroy annotations and xml

One of the confusing things about lifecycle interceptors is the fact that they can be defined in a variety of places, including a superclass, a deployment descriptor that references a class that acts as an interceptor, and even the EJB3 bean itself. So, the question arises, what is the order that a given set of lifecycle interceptor methods will be invoked if they are defined in a variety of different, yet valid, locations? Well, the EJB specification, namely page 306 of the core contracts document, specifically addresses this very question. Check it out!

"If multiple callback interceptor methods are defined for a lifecycle event for a bean, the following rules governing their invocation order apply. The deployment descriptor may be used to override the interceptor invocation order specified in annotations, as described in section 12.8.
• Default interceptors, if any, are invoked first. Default interceptors can only be specified in the deployment descriptor. Default interceptors are invoked in the order of their specification in the deployment descriptor.
• If there are any interceptor classes defined on the bean class, the lifecycle callback interceptor methods defined by those interceptor classes are invoked before any lifecycle callback interceptor methods defined on the bean class itself.
• The lifecycle callback interceptor methods defined on those interceptor classes are invoked in the same order as the specification of the interceptor classes in the Interceptors annotation.
• If an interceptor class itself has superclasses, the lifecycle callback interceptor methods defined by the interceptor class’s superclasses are invoked before the lifecycle callback interceptor method defined by the interceptor class, most general superclass first.
• After the lifecycle callback interceptor methods defined on interceptor classes have been invoked, then

• If a bean class has superclasses, any lifecycle callback interceptor methods defined on those superclasses are invoked, most general superclass first.
• The lifecycle callback interceptor method, if any, on the bean class itself is invoked.

• If a lifecycle callback interceptor method is overridden by another method (regardless of
whether that method is itself a lifecycle callback interceptor method (of the same or different
type)), it will not be invoked.

The deployment descriptor may be used to override the interceptor invocation order specified in annotations, as described in section 12.8.2. All lifecycle callback interceptor methods for a given lifecycle event run in the same Java call stack. If there is no corresponding callback method on the bean class (or any of its superclasses), the InvocationContext.proceed invocation on the last interceptor method defined on an interceptor class in the chain will be a no-op. The InvocationContext object provides metadata that enables interceptor methods to control the invocation of further methods in the chain. See Section 12.5."

Identify correct statements about the lifecycle of EJB instances, including the use of the @PostConstruct and @PreDestroy callback methods

SCBCD Objective: Identify correct and incorrect statements or examples about the lifecycle of all 3.0 Enterprise Bean instances, including the use of the @PostConstruct and @PreDestroy callback methods.

One of the things you need to understand about EJBs, especially Session Beans and Message Driven Beans, is that the lifecycle of these objects are managed by the application server. As a developer, you will never call the constructor of a Session bean, or invoke the finalize method on a Message Driven Bean. To do so would imply that you, the developer, have some part in managing the lifecycle of an EJB, and alas, you simply do not. Session Beans and Message Driven beans have their entire lifecycle managed by the application server, and there's nothing you, as a developer, can do about it.

Of course, as developers, sometimes it would be nice to do something, or take some action, or perform some type of initialization when the application server creates, or initializes, a real-live instance of one of the EJBs you have created. Similarly, it might be nice to perhaps release some resources, or perform some type of clean-up when a given EJB is take out of service by the EJB container. Certainly, this isn't an unreasonable request for a developer to ask, so as you could imagine, the EJB3 spec provides a very simple facility that allows the developer to respond to various EJB lifecycle events. This facility is known as lifecycle method interceptor callbacks.

Basically, if you want to perform some logic immediately after an EJB has been created by the EJB container, you simply code a method in your EJB bean class, and decorate that method with the @PostConstruct annotation. If you would like to have some funky logic performed immediately before an EJB is taken out of service and garbage collected, you simply code a method in the EJB bean class and decorate that method with the @PreDestroy annotation. It's all just that simple!


******************************

package com.mcnz.ejb;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.Stateful;

@Stateful
public class StatefulTimerBean implements StatefulTimerLocal {

private Long startTime;
public StatefulTimerBean() {System.out.print("Constructor");}

@PostConstruct
void negate() {
startTime = new Long(-1);
System.out.println("PostCreate");
}

@PreDestroy
void nullify() {
startTime = null;
System.out.println("PreDestroy");
}

public void start(){
startTime = System.currentTimeMillis();
}
public long getStartTime() {
return startTime;
}
public long getElapsedTime() {
return System.currentTimeMillis() - startTime;
}
public boolean isStarted() {
if (! (startTime > 0) ){return false;}
else {return true;}
}

@PrePassivate
public void customSave() {
System.out.println("Container is Passivating!");
}

@PostActivate
public void customLoad() {
System.out.println("Container has Activated!");
}
}

******************************

What types of EJBs can have lifecycle interceptor methods?

"Lifecycle callback interceptor methods may be defined for session beans and message driven beans.

Interceptor methods for lifecycle event callbacks can be defined on an interceptor class and/or directly on the bean class. The PostConstruct, PreDestroy, PostActivate, and PrePassivate annotations are used to define an interceptor method for a lifecycle callback event. If the deployment descriptor is used to define interceptors, the post-construct, pre-destroy, post-activate, and pre-passivate elements are used.

Lifecycle callback interceptor methods and business method interceptor methods may be defined on the same interceptor class. Lifecycle callback interceptor methods are invoked in an unspecified transaction and security context. Lifecycle callback interceptor methods may be defined on superclasses of the bean class or interceptor classes. However, a given class may not have more than one lifecycle callback interceptor method for the same lifecycle event. Any subset or combination of lifecycle callback annotations may be specified on a given class. A single lifecycle callback interceptor method may be used to interpose on multiple callback events (e.g., PostConstruct and PostActivate). Lifecycle callback interceptor methods defined on an interceptor class have the following signature:

void
(InvocationContext)

Lifecycle callback interceptor methods defined on a bean class have the following signature:

void
()

Lifecycle callback interceptor methods can have public, private, protected, or package level access. A lifecycle callback interceptor method must not be declared as final or static." -Core Contracts EJB 3 Document pg 305

Tuesday, September 2, 2008

rules for writing a web service endpoint interface and use of the @WebService and @WebMethod annotations.

Identify correct and incorrect statements or examples about implementing a session bean as a web service endpoint, including rules for writing a web service endpoint interface and use of the @WebService and @WebMethod annotations.

"To support web service interoperability, the EJB specification requires compliant implementations tosupport XML-based web service invocations using WSDL and SOAP or plain XML over HTTP in conformance with the requirements of the JAX-WS [32], JAX-RPC [25], Web Services for Java EE [31], and Web Services Metadata for the Java Platform [30] specifications."


You know, it's amazing, but turning Stateless Session EJBs into Web Services is just as simple as adding an annotation after the @Stateless decoration. Here's the little EJB I created to test the @WebService annotation. All I had to do was add the annotation, deploy, and I was able to test it with WebSphere 7's Web Services explorer.

package com.mcnz.ejb;

import javax.ejb.Stateless;
import javax.jws.WebService;


@Stateless
@WebService
public class StatelessTimerBean implements StatelessTimerLocal {


public StatelessTimerBean() {
}

public String helloWorld() {
return "Hello World";
}
}


One thing I didn't really understand was how the EJB container knew how to deploy my EJB as a web service. I mean, I guess it just deployed the EJB, but how did all the Web Service razzle dazzle happen? I mean, that has to go through an HTTP port, right? So does that mean an EJB3 SLSB with a @WebService decoration uses a web project or web container? I'm perplexed right now, but I'll dig into the WebSphere Application Server and see exactly what is going on behind the scenes. Here's what the spec says:

"Session Bean’s Web Service Endpoint Interface

EJB 3.0 does not require the definition of a web service endpoint interface for session beans that implement a web service endpoint.


The following are requirements for session beans with JAX-RPC web service endpoint interfaces. The JAX-WS and Web Services for Java EE specifications do not require that a separate interface be defined for a web service endpoint.

The following are the requirements for a stateless session bean’s web service endpoint interface. The web service endpoint interface must follow the rules for JAX-RPC service endpoint interfaces.

• The web service endpoint interface must extend the java.rmi.Remote interface.
• The methods defined in the interface must follow the rules for JAX-RPC service endpoint interfaces. This means that their argument and return values must be of valid types for JAX-RPC, and their throws clauses must include the java.rmi.RemoteException.

The throws clause may additionally include application exceptions.

Note that JAX-RPC Holder classes may be used as method parameters. The JAX-RPC specification requires support for Holder classes as part of the standard Java mapping of WSDL operations in order to handle out and inout parameters. Holder classes implement the javax.xml.rpc.holders.Holder interface

• For each method defined in the web service endpoint interface, there must be a matching method in the session bean’s class. The matching method must have:

• The same name.
• The same number and types of arguments, and the same return type.
• All the exceptions defined in the throws clause of the matching method of the session bean class must be defined in the throws clause of the method of the web ser vice endpoint interface.
• The web service endpoint interface must not include an EJBObject or EJBLocalObject as either a parameter or return type. An array or JAX-RPC value type must not include an EJBObject or EJBLocalObject as a contained element. The web service endpoint interface methods must not expose business interface types, local or remote interface types, local or remote home interface types, timers or timer handles, or the managed collection classes that are used for entity beans with container-managed persistence as arguments or results or as fields of value types.
• JAX-RPC serialization rules apply for any value types that are used by the web service endpoint interface. If it is important that Java serialization semantics apply, the Bean Provider should use the restricted set of JAX-RPC value types for which the semantics of Java serialization apply under JAX-RPC serialization. See the JAX-RPC specification [25] for details.
• The web service endpoint interface must not include constant (as public final static) declarations.
• The Bean Provider must designate the web service endpoint interface in the deployment descriptor by means of the service-endpoint element. The service endpoint itself is only exposed within a web service if it is referenced by a web service deployment descriptor.


The implementation class for a stateless session bean’s web service endpoint is generated by the container’s deployment tools. This class must handle requests to the web service endpoint, unmarshall the SOAP request, invoke any business method interceptor methods, and invoke the stateless session bean method that matches the web service endpoint method that corresponds to the request."

Creating & Testing EJB3 Web Services with IBM Rational IRAD 7.5 for WebSphere



So, I'm playing with IRAD 7.5 Beta, and I'm testing the tools ability to create a Web Service out of a simple Stateless Session Bean (SLSB). In theory, creating it should be as easy as simply decorating the EJB with the @WebService annotation and deploying it, so that's what I did.


Now, I did see a Wizard that said Web Services --> Create Web Services, so I figured I'd give it a try. However, a huge wizard came up, and it looked like it was the same old wizard from before. I created a web service based on a FooEJB, but the IRAD 7.5 beta tool didn't actually decorate my version 3 EJB with @WebService annotations, so I knew that whatever it was doing, it was doing it the old way, not the new way. Still, I let the wizard run. The good thing about the wizard is that it brings up a whole Web Service test environment, and I figured that'd be good, just to see the URL that WebSphere creates for the test Web Service.

So, I deployed my project with the Wizard created Web Service, along with my annotated @WebService EJB. The Web Service test window came up, and the Web Service created by the tool seemed to work.


Now, one thing I did before using the wizard was click on something called a Web Service Endpoint Enabler.

Anyways, under Services in my EJB module, the web service created with the wizard was listed, so I right clicked and selected "Test with Web Service Explorer." The wizard created WS worked!

So, I dug around, and somehow, under WebSphere Web Service WSDL documents, a link to my EJB3.0 @WebService was listed. I clicked GO, and then tested my HelloWorld method, and lo and behold, it worked!

I must say, I was pretty impressed! Good job, IBM!


















****************************************************

package com.mcnz.ejb;

import javax.ejb.Stateless;
import javax.jws.WebService;

@Stateless
@WebService
public class StatelessTimerBean implements StatelessTimerLocal {
public StatelessTimerBean() {
}

public String helloWorld() {
return "Hello World";
}
}

*** ********** **** ********** * ******** **** ******* ****
package com.mcnz.ejb;
import javax.ejb.Local;

@Local
public interface StatelessTimerLocal {

String helloWorld();

}
****************************************************