从EJB3中访问资源的5种方式

来源:互联网 发布:液压原理图软件 编辑:程序博客网 时间:2024/06/04 23:56

原文地址:http://javahowto.blogspot.com/2006/06/5-ways-to-get-resources-in-ejb-3.html


1.通过运行时信息映射进行资源注入

例如:

packagecom.foo.ejb;

import javax.ejb.Remote;

@Remote

public interface ResourceRemote {

public void hello();
}

package com.foo.ejb;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.sql.DataSource;

@Stateless
public class ResourceBean implements ResourceRemote {
@Resource(name="jdbc/employee")

private DataSource employeeDataSource;


你不需要使用ejb-jar.xml.文件。对于可移植的应用,需要使用应用服务器特定的部署方案,将逻辑名 (jdbc/employee)映射到目标运行环境中的实际DataSource配置。对于JavaEE SDK 5、Glassfish、 和 Sun Java System Application Server 9, 这个文件是 sun-ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
<sun-ejb-jar>
<enterprise-beans>
<ejb>
<ejb-name>ResourceBean</ejb-name>
<jndi-name>ResourceBean</jndi-name>
<resource-ref>
  <res-ref-name>jdbc/employee</res-ref-name>
    <jndi-name>jdbc/__default</jndi-name>
</resource-ref>
</ejb>
</enterprise-beans>
</sun-ejb-jar>


2.不需要移植的应用,可以不需要这个应用服务器特定的部署方案:可以只采用@Resource的mappedName()域:

@Stateless
public class ResourceBean implements ResourceRemote {
@Resource(name="jdbc/employee",  mappedName="jdbc/__default")
private DataSource employeeDataSource;

如果应用可移植性不是个大问题,你不需要这个例子中的任何一个描述符。 mappedName()域将逻辑名 jdbc/employee映射到目标服务器运行环境中对应的(jdbc/__default) 。

需要注意的是,JavaEE平台不要求应用服务器支持mappedName()域。所以,当需要将你的应用迁移到别的server上时,可能会有问题。JavaEE SDK, 和SJSAS 9支持mappedName()。


3. 另一个选择是在一些应用服务器中使用默认的映射规则,而不使用运行时部署方案。这种方案也是不可移植的,一些服务器可能也不提供这个功能。在Glassfish, JavaEE SDK, and SJSAS 9这些服务器中,如果资源逻辑名(不带前缀)与物理名相同,它们可以不使用sun-ejb-jar.xml关联在一起。例如:

@Stateless
public class ResourceBeanimplements ResourceRemote {
@Resource(name="jdbc/__default")
private DataSource defaultDataSource;

不需要任何描述,通过默认的资源映射就可以正常工作。


4.使用EJBContext.lookup(String name),一个在EJB3中新的便利的方法。命名参数相对于java:comp/env,例如:
package com.foo.ejb;
import java.sql.Connection;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.sql.DataSource;

@Stateless
public class ResourceBean implements ResourceRemote {
public void hello()  {
DataSource employeeDataSource = (DataSource) sctx.lookup("jdbc/employee");
try {
    Connection conn = employeeDataSource.getConnection();
} catch(SQLException ex) {
    ex.printStackTrace();
}
}

需要使用ejb-jar.xml文件声明这个资源引用。除非使用默认映射机制,服务器特定的部署方案也是需要的。

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" metadata-complete="false" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
<enterprise-beans>
<session>
<ejb-name>ResourceBean</ejb-name>
<resource-ref>
<res-ref-name>jdbc/employee</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
</session>
</enterprise-beans>
</ejb-jar>

sun-ejb-jar.xml文件内容和1相同。


5. 使用传统的JNDI查询。这个方法基本上与EJBContext.lookup(String name)相同,除了JNDI查询需要更多的代码行外,还需要使用以java:comp/env或java:comp/开头的绝对引用名。
@Stateless
public class ResourceBeanimplements ResourceRemote {
@Resource

private SessionContext sctx;

public void hello() {
DataSource ds = null;
try {
InitialContext ic = new InitialContext();
 ds = (DataSource) ic.lookup("java:comp/env/jdbc/employee");
} catch (NamingException ex){
throw new IllegalStateException(ex);
}
try {
Connection conn = ds.getConnection();
} catch(SQLException ex) {
throw new IllegalStateException(ex);
}
}

需要在 ejb-jar.xml文件中声明资源引用,并在 sun-ejb-jar.xml文件中进行映射,内容与4相同。

JNDI查询的最大问题是我不得不try-catch 需要检查的异常javax.naming.NamingException。因为它是低级别的异常,再将它抛出不太合适。很可能就是因为这一原因,EJBContext.lookup(String name)在名字找不到时只抛出 java.lang.IllegalArgumentException。



原创粉丝点击