第1 页 共1页1

为了实现向struts2的Action中注入ejb3,我写了一个Annotation用来定义要注入哪个ejb3,又写了一个struts2的interceptor用来实施注入。Annotation代码如下:

@Retention(value=RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD})
@Inherited
public @interface JndiLookup {
    String jndi();
    Class type();
}

Interceptor代码如下:

public class JndiLookupInterceptor implements Interceptor {
 
    private InitialContext contaxt;
 
    public void destroy() {
        ;
    }
 
    public void init() {
        try {
            contaxt = new InitialContext();
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
 
    public String intercept(ActionInvocation invocation)
            throws Exception {
        Method[] methods = invocation.getAction()
	    .getClass().getMethods();
        for(Method method : methods) {
            try{
                Class[] parameterTypes
		    = method.getParameterTypes();
                if(parameterTypes.length != 1) {
                    continue;
                }
 
                JndiLookup jndiLookup
		    = method.getAnnotation(JndiLookup.class);
                if(jndiLookup == null) {
                    continue;
                }
                if(jndiLookup.jndi() == null
		        || jndiLookup.jndi().length() == 0) {
                    continue;
                }
                if(jndiLookup.type() == null) {
                    continue;
                }
 
                Object object = this.contaxt.lookup(jndiLookup.jndi());
                method.invoke(invocation.getAction(),
		    new Object[] {jndiLookup.type().cast(object)});
            } catch (Exception e) {
                e.printStackTrace();
                ;
            }
 
        }
 
        return invocation.invoke();
    }
 
}

需要被注入的Action代码如下:

public class SomeAction {
    private DataSource ds;
 
    @JndiLookup(jndi="jdbc/mysqlDS", type=DataSource.class)
    public void setDs(DataSource ds) {
        this.ds = ds;
    }
 
    public String execute() {
        //do something about the ds
    }
}

经测试,在tomcat下注入DataSource成功了。看来Annotation和Struts2真的是个好东西呀!

Share/Save/Bookmark

j2ee难用,其中一个原因是jndi不好用,明明已经配置好名字为dataSource的数据源,但是在部署JPA时,老是抛异常说找不到数据源。今天在用jboss时,终于又明白了一些。

原来j2ee中的组件是有它自己独自的环境的,位于java:/comp/env这个jndi目录下。每个组件不能访问另外一个组件的私有环境,实现组件各自独立。同时,又有一些jndi目录和名字是公共的,如java:/下的其它一些名字,还有一些是只能给本地访问的,还有一些是能够给远程访问的,这个就不说了。

如果一个组件想要获得另外一个组件,那么需要在它的部署描述符里说明,比如:

<resource-ref>
  <description>Dollys DataSource</description>
  <res-ref-name>jdbc/mydatasource</res-ref-name>
  <res-ref-type>javax.sql.DataSource</res-ref-type>
  <res-auth>Container</res-auth>
</resource-ref>

这里说这个组件需要依赖于一个叫java:/comp/env/jdbc/mydatasource的数据源。但是这个数据源又从哪里来呢??!!注意了!原来是要在部署时写另外一个特定于服务器种类的数据源映射文件,如下面的jboss示例:

<resource-ref>
   <res-ref-name>jdbc/mydatasource</res-ref-name>
   <jndi-name>java:DefaultDS</jndi-name>
</resource-ref>

上面这一段可能位于jboss-web.xml等jboss特定的部署描述符里。目的就是告诉jboss,把全局的java:DefaultDS映射到这个组件的java:/comp/env/jdbc/mydatasource。就是这一步,很时候之所以部署失败,找不到jndi都是因为少了这样一个映射导致的。

如果不想写上面的特定于服务器的部署描述符,我估计可以通过指定一个公共的jndi来解决,如下:

<resource-ref>
  <description>Dollys DataSource</description>
  <res-ref-name>java:DefaultDS</res-ref-name>
  <res-ref-type>javax.sql.DataSource</res-ref-type>
  <res-auth>Container</res-auth>
</resource-ref>

问题虽然解决了,可是突然觉得好恶心,搞得这么复杂有必要吗?!!j2ee果然不是为了做小项目来的。

Share/Save/Bookmark


第1 页 共1页1
© 2007 涂0实验室 | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress