Inject EJB to Struts 2 Action and Custom Validators

来源:互联网 发布:list数据排序 编辑:程序博客网 时间:2024/06/06 02:41

EJB annotation works in container managed instances such as servlet context listeners, servlets, fitlers, and even jsps. It however does not work in struts 2 actions, simply because the actions are not container managed instances and Struts 2 does not implement a hook that makes it happen. To do so, we need a “processor” that at run time checks the annotation, looks up the EJB instance and injects the EJB instance to action. The “processor” is a Struts 2 interceptor that is added to interceptor stack.

Step 1: Create the interceptor:

 public class EJBAnnotationProcessorInterceptor implements Interceptor{ public String intercept(ActionInvocation ai) throws Exception { EJBAnnotationProcessor.process(ai.getAction()); return ai.invoke(); } } public class EJBAnnotationProcessor { public static void process(Object instance)throws Exception{ Field[] fields = instance.getClass().getDeclaredFields(); if(fields != null && fields.length > 0){ EJB ejb; Context cxt = null; String jndiName; for(Field f : fields){ ejb = f.getAnnotation(EJB.class); if(ejb != null){ if(cxt == null){ cxt = new InitialContext(); } jndiName = getJndiName(f,ejb); f.setAccessible(true); f.set(instance, cxt.lookup(jndiName)); } } } } }

Step 2: Add the interceptor to interceptor stack in struts.xml:

 <package name="base-package" extends="struts-default">    <interceptors>    <interceptor name="ejbAnnotationProcessor"    class="com.xyz.interceptor.EJBAnnotationProcessorInterceptor"/>    <interceptor-stack name="baseStack">   <interceptor-ref name="defaultStack"/>    <interceptor-ref name="ejbAnnotationProcessor"/>    </interceptor-stack>    </interceptors>    <default-interceptor-ref name="baseStack"/>    </package>    <package name="package1" extends="base-package">    (action definitions)    </package>

Step 3: Annotate your EJB like this:

    @Stateless(name="TestSession", mappedName="TestSession")  @Remote  @Local  public class TestSession implements TestInterface{  }

Step 4: Use your EJB in action like this:

    @EJB(mappedName="TestSession")  private TestInterface test;  public void setTest(TestInterface test){ this.test = test;  }

As for custom validator, we need to replace struts 2 AnnotationValidatorManager with our implementation that processes EJB annotations.

Step 1: The new validator manager:

 public class EJBAnnotationProcessorValidatorManager extends AnnotationActionValidatorManager{ public List<validator> getValidators(Class clazz,String context,String method){ List<validator> validators = super.getValidators(clazz,context,method); for(Validator v : validators){ try{ EJBAnnotationProcessor.process(v); }catch(Exception e){ //proces exception } } return validators; }  }

Step 2: Define the new manager and replace struts 2 manager in struts.xml:

 <bean type="com.opensymphony.xwork2.validator.ActionValidatorManager" name="ejbAnnotationValidatorManager" class="com.xyz.validator.EJBAnnotationProcessorValidatorManager"/> <constant name="struts.actionValidatorManager" value="ejbAnnotationValidatorManager"/>

Step 3: Use your EJB in custom validator like this:

    @EJB(mappedName="TestSession")  private TestInterface test;  public void setTest(TestInterface test){ this.test = test;  }
原文:http://longsystemit.com/javablog/?p=40
原创粉丝点击