Wednesday, September 24, 2008

Usage of Interceptors and Timer Service in EJB3

Interceptors are used to intercept business method invocations og EJB3 bean class. The interceptors can be defined either class level or method level.
Also the interceptors can be in a seperate class using @Interceptor annotation or a method annotated with @AroundInvoke with signature Object methodname (InvocationContext ic)in the same class.
More than one interceptor classes can also be defined for a bean, using @Interceptor annotation. Interceptors have same life cycle as of that of associated bean and can have dependency injection in the same context.

Invocation Context

InvocationContext allows you to propagate through a chain of interceptors, along with its get/set methods, which even provides reference to the bean. Following are the methods that can be accessed by the handle provided.

Object getBean(): Provides the reference to the bean for which the Interceptor is defined.
Method getMethod():Provides information of about which method in the bean is called
Object[] getParameters():Provides infomation of the parameters passed to the bean.
void setParameters(): Set the parameter values
Map getContextData(): Provides context data that can be shared by the chain.
Object proceed(): Proceeds to the next interceptor in the chain or to the business method of the bean.

A simple example of using the Interceptor is illustrated below

package com.test;


import javax.ejb.Remote;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TimedObject;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;
import javax.ejb.TimerService;


@Stateless
@RemoteBinding(jndiBinding="Welcome")
@Remote(UpdateEJB.class)
@Interceptors(TestInterceptor.class)
public class UpdateEJBBean implements UpdateEJB {

private String message;

@Resource
private SessionContext ctx;

@Interceptors(TestInterceptor1.class)
public String sayHello(String name) {
System.out.println("Inside EJB method");
return "Hello " + name + message;
}


@AroundInvoke
public Object log(InvocationContext invocationContext) throws Exception {
System.err.println(invocationContext.getMethod().getName() + " called from interceptor 3");
return invocationContext.proceed();
}

}
The @RemoteBinding(jndiBinding="Welcome") is used to bind the EJB Bean to the JNDI name which we specify, instead using default JNDI name, provided by appserver vendors
The interceptor class will be like the one shown below.

public class TestInterceptor{

@AroundInvoke
public Object log(InvocationContext invocationContext) throws Exception {
System.err.println(invocationContext.getMethod().getName() + " called from interceptor 1");
return invocationContext.proceed();
}

}

public class TestInterceptor1{

@AroundInvoke
public Object log(InvocationContext invocationContext) throws Exception {
System.err.println(invocationContext.getMethod().getName() + " called from interceptor 1");
return invocationContext.proceed();
}

}

The order of Interceptor Invocation will be like
1.EJB Bean Class level Interceptor
2.EJB Bean Method level interceptor annotated by @Interceptor above the method
3.The method annotated with @AroundInvoke annotation.

Timer Service


Using EJB3 we can create a timely triggers and method invocations using the TimerService, provided by EJB3. You can either implement TimedObject interface, or you can
annotate method that you need to trigger after each timer expiration using @Timeout annotation.

package com.test;

import javax.ejb.Remote;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TimedObject;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;
import javax.ejb.TimerService;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionManagement;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;


@Stateless
@RemoteBinding(jndiBinding="Welcome")
@Remote(UpdateEJB.class)
public class UpdateEJBBean implements UpdateEJB,TimedObject {

private String message;

@Resource
private SessionContext ctx;

public String sayHello(String name) {
ctx.getTimerService().createTimer(6000, "HAI");
ctx.getTimerService().createTimer(6000,6000, "HAI");
return "Hello " + name + message;
}

public void ejbTimeout(Timer handle) {
System.out.println("handle.getTimeRemaining()"+handle.getTimeRemaining());
System.out.println("handle.getNextTimeout()"+handle.getNextTimeout());

}
}

To create the timer ctx.getTimerService().createTimer method is used, the timer timeout can be only once or frequently in a timed manner.
createTimer(6000,6000, "HAI") this says that the timer will expire in a period of 6000ms with initial delay of 6000ms.

The argument, Timer provides the handle to the timer, which has getTimeRemaining and getNextTimeout methods.

Instead of implementing interface you can also use annotation @Timeout above the method that needs to be triggered after each timer expiration.

Hope the article was useful.

Tuesday, September 16, 2008

Annotations and Interceptors in struts2

The power of annotation is now available in struts2. All your validations can be made easy just by annotating the field, which you want to validate. Example, you can make a null check, email validation and some more built in validation annotators.

You can get the power of annotation in your application just , by annotating the getter method of the respective field in the JSP page.
Example
If I have a field name username in my struts2 JSP page, and I want to make a validation on it(If value is not entered, a message should be thrown) then, just annotate the action class using @validation and you can do the validation for textfield like

@RequiredStringValidator(message="Enter username ")
public String getUsername() {
return username;
}
And in the JSP page you can get the message in the same way, as how you get when you add a fielderror.

You can also invoke a method, before invoking your action class method, after execution of your action class method and before returning result from action method, by using @before, @after, and @before result annotations. For this to work you have to configure interceptor stack in your struts.xml .

<interceptors>

<interceptor name="annotationWorkFlow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor"/>
<interceptor-stack name="demostack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="annotationWorkFlow"/>
/span>interceptor-stack>
interceptors>
<default-interceptor-ref name="demostack" />
If you add the above line within action tag then the interceptor tag will be applicable for that particular action alone. If you add the line out of the action tag then all the actions will pass through the set of interceptors.

You can also define your own interceptor classes.
For that your interceptor class should implement the interceptor interface. The example class is as shown below. Your request will pass through this interceptors in the order specified in the struts.xml file .

public class TestInterceptor implements Interceptor{

public String intercept(ActionInvocation next) throws Exception {
long t1 = System.currentTimeMillis();
String s= next.invoke();
long t2 = System.currentTimeMillis();
System.out.println("From Interceptor Action "+next.getAction().getClass().getName()+" took "+(t2-t1)+" millisecs");
return s;
}


public void destroy() {
}


public void init() {
// TODO Auto-generated method stub

}
}
Here the interceptor class just calculates the time taken to fullfill the request. The ActionInvoactions , invoke method will invoke the corresponding method in the action class.

To access the request and response within the Interceptor class, you need to getInvocationContext() and you need to get the HttpServletRequest and HttpServletResponse like this
HttpServletRequest request=(HttpServletRequest)next.getInvocationContext().get(StrutsStatics.HTTP_REQUEST);

HttpServletResponse response=(HttpServletResponse)next.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE);

Thus annotations and Interceptors gives flexibility and ease of development of our application.

Saturday, September 13, 2008

Accessing Scope Variables in struts2 from Action class

Here in this post, I am going to show how to access variables in different scope , in struts2. In struts 2 we can set objects in the following scopes, say request, session, page and application.
To share the object between Java and Jsp expressions, we need to set the java object in any of the above said scopes and can access it using the struts tag in Jsp page.

For Example....
If I have a variable named foodCollection which contains a collection of different food items, I can set this in different scopes and can access it.
1. Session
In Java Action class
ActionContext.getContext().getSession().setAttribute("foodCollection",foodCollection);
In Struts2 Jsp page
#session.foodCollection
2.Request
request.setAttribute("foodCollection",foodCollection);
In Struts2Jsp
#request.foodCollection
3.Page
pageContext.setAttribute("foodCollection",foodCollection);
In Struts2Jsp
#attr.foodCollection

Here is a simple example of using struts2.
First add the following entry in your web.xml, so that all your requests pass through the filterdispatcher filter instead Action servlet in struts1.2.
<filter
filter-namestruts2filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcherfilter-class>
filter>

<filter-mapping>
<filter-name>struts2filter-name>
<url-pattern>*.dourl-pattern>
filter-mapping>

The default URL pattern is .action which can be changed by using the struts.properties file.

Next write your struts.xml file and place it in the package where you want.
Struts.xml contains the mapping between the request and the corresponding action class.
<package name="struts2" extends="struts-default">
<action name="showLogin">
<result>/jsp/master/login.jsp</result>
action>

action name="doLogin" class="action.Login">
<result name="input">/jsp/master/login.jspresult>
<result name="error">/jsp/master/login.jspresult>
<result>/jsp/master/loginsuccess.jspresult>
action>

package>

Write a java class which extends ActionSupport class of struts2, you can either have a default execute method or any method name according to the requirements.

In the action class you cant access the request and session directly, you need to either use ActionContext class like this,

ActionContext.getContext().getSession().put("TestLoop1",testingVos);

or need to implement the ServletRequestAware and ,ServletResponseAware and override its setter method, also you define your getter method which returns the request and response and you can access like the one shown below

getServletRequest().getSession().setAttribute("testSessionVar", "From Action class set in session");
getServletRequest().setAttribute("TestVariable", "From Action class set in request");

Suppose if you want to access a collection in the action class in JSP page you dont have to set the collection in session or request, you can access it in the JSP page by just having the name of the collection and a getter method for that collection in the StrutsAction class like this
I have a collection named testingVos which is a collection of testing vo
In Action class, the code snippet will be like the one....
public ArrayList getTestingVos(){
return testingVos;
}


In JSP page the code snippet will be

<s:iterator value="testingVos">
<s:property value="code"/><s:property value="type"/>
s:iterator>