ejb Name Environment

Posted mosmith

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ejb Name Environment相关的知识,希望对你有一定的参考价值。

关于EJB3.x的命名空间一直都很迷惑,有些地方规范上写得也不是很清楚。在网上搜索了一些资料做个整理:

EJB reference,是指一个EJB引用另一个EJB的business interface, non-interface views或者home接口。

我们可以在部署描述符ejb-jar.xml中:

1、在同一ejb-jar.xml中一个EJB对另一个EJB的引用,因此大多数情况下,。

2、同一应用(企业应用)中一个EJB对另一个EJB的引用(它们在不同的ejb-jar.xml中被声明)。

3、java:global中的引用(这一点为什么规范中没有说?)。

 

JAVAEE中EJB的JNDI有下面几个命名空间:

java:global

java:app

java:module

java:comp

 

<ejb-link>在下面的情况下会使用:

Here are some scenarios that hopefully clarify why <ejb-link/> (or @EJB(beanName="...")) and EJB ref bindings are both useful and complementary:

    An application can itself be logically broken up into components, and the developer chooses to use EJBs to implement those components. In this case, the application developer knows the target EJB component that the client wants to use. If there are multiple components implementing the same interface, then some disambiguation is required, and <ejb-link/> can be used.

    An application has a dependency on an external service. In this case, the application knows it has a dependency on an external service, so <ejb-link/> cannot be used since the service implementation does not exist in the same application.

    An application has a dependency on an external service, but a minimal implementation is provided in the same application. In this case, the developer might use an <ejb-link/> as in #1, but the deployer has the flexibility to override that choice as in #2.


<resource-ref>和<resource-env-ref>

<resource-ref>与<resource-env-ref>本质上没有太大的区别:

1、他们都使用@Resource注解来标记,有些类型甚至还可以互换。

2、<resource-ref>与<resource-env-ref>不同之处在于,<resource-ref>是指引用我们在JavaEE应用服务器上配置的资源,比如jdbc,ConnectionFacotry等等这一类型的资源,通常来说这些资源具有Factory性质,当然不是Factory性质也可以,这没有明确的规定。

但<resource-env-ref>一般是指引用我们应用服务器的组件,比如下面这些类型,它们很多是bean运行时涉及的上下组件,也有一些像Queue,Topic之类的配置性资源,它们大部分是直接的组件(非factory性质):

    public static final Set<String> knownResourceEnvTypes = new TreeSet<String>(Arrays.asList(
        "javax.ejb.EJBContext",
        "javax.ejb.SessionContext",
        "javax.ejb.EntityContext",
        "javax.ejb.MessageDrivenContext",
        "javax.transaction.UserTransaction",
        "javax.jms.Queue",
        "javax.jms.Topic",
        "javax.xml.ws.WebServiceContext",
        "javax.ejb.TimerService",
        "javax.enterprise.inject.spi.BeanManager",
        "javax.validation.Validator",
        "javax.validation.ValidatorFactory"
    ));

 

resource-ref是指Connection Factory类的资源,用于获取连接到资源的Connection,比如DataSource, JavaMailFactory等等,可以配置连接认证等选项。

而resource-env-ref是直接的资源,它在ejb2.0被引进,在message-driven中用于获取javax.jms.Queue/Topic。下面连接是一个论坛上对些的争论:

http://www.coderanch.com/t/157993/java-EJB-OCEEJBD/certification/Difference-resource-ref-resource-env

Good question (and one you should know for the exam)
resource-ref is for "resource manager connection factory" objects that can give you connections to a resource manager. The typical example is for javax.sql.DataSource from which you can get JDBC connections (javax.sql.Connection).
The resource-ref is so that you can have a ‘logical name‘ used in code -- that the deployer then binds to the *actual* resource factory configured into the server. So when you think of resource-ref, think of "Programmer‘s made-up/fake name for the datasource." Since the programmer may not know, at the time of coding, what the *real* name is going to be (and since the component model demands that the name of these things is something that can be configured at deploy-time without changing code.)
So... what‘s the deal with resource-env-ref?
1) It is new to EJB 2.0
2) It was added because of message-driven beans/JMS
3) It has the WORST name, designed, I‘m certain, just to confuse you.
For example, a resource manager connection factory is certainly an entry in the bean‘s environment -- so it would be perfectly logical to assume that resource-env-ref is an appropriate name for what is actually resource-ref.
But...you have to memorize it differently.

A resource-env-ref is for "administered objects associated with resources", and the most obvious example (and the reason it was added) was for JMS destinations. The idea is the same as resource-ref (or security-role-ref) in that it stands for "programmer‘s made-up/fake name", only instead of a name for a resource factory, it is a name for a ‘resource‘.
The main difference:
resource-ref:
things that give you CONNECTIONS (including URL connection - JavaMail connection factory, JDBC connection -- DataSource, and -- for the really confusing one -- QueueConnectionFactory for obtaining JMS connections.)
resource-env-ref:
things that give you access to a resource, but which are NOT factories that give you connections. In other words, with resource-ref you are getting something that you then can use to GET to a resource, but with resource-env-ref, you get right to the resource without going through a factory.
The way I think of it, for the purposes of the exam is:
resource-ref: "Programmer‘s made-up name for the database driver"
[just a way to remember, not the exact technically correct way to say it]
resource-env-ref: "Programmer‘s made-up name for the JMS destination"
From what I‘ve heard, the resource-env-ref really should have just been called JMS-resource-ref, but that would have been more limiting. Much clearer, though.
The only resource example used in the spec is for JMS destination, and although I‘m sure there may be other examples, I have no idea what they might be.

 

类似的还有@PersistenceContext,@PersistenceUnit:

@PersistenceContext用于注入/引用 EntityManager

@PersistenceUnit用于注入EntityManagerFactory

 

 glassfish中的mappedName并不是指将ejb映射到java:global下,而是指全局jndi,全局jndi跟java:global并不是一个东西,而且从glassfish的jndi结构上来看,java:global只是全局jndi下面的一个子context。

 

在EJB中我们通常称JNDI为ENC,也就是Enterprise Naming Context的缩写。

 

resource-ref的ref-name:指程序代码中所使用的进行lookup的jndi name,如果我们不指定它所注入资源的jndi名称,则默认注入名为jjava:comp/env/full-qualified.class.name/member的资源。

resource-ref的mapped-name:指所引用的外部(全局)的资源的id。

 

resource-env-ref与resource-ref差不多,但resource-env-ref是直接的资源,针对 queue 和topic这一类的。

 

new InitialContext()的时候,这个InitialContext并不一定是指向java:comp/env,有的应用服务器会指向这个位置,但规范里面并没有这个规定,因为这样子的程序并不是portable的。比如Tomcat的InitialContext就不是(今天同事遇到这个问题了)。

 

ejb-ref(@Remote类型的接口/View引用), ejb-local-ref(Local类型的接口/View引用),(区别于env-entry,env-entry只能声明基本类型的引用如string, int, boolean等):

可以往bean的NamingContext(也就是java:comp命名空间下面)bind其它bean的reference。这样子我们可以lookup到这些引用,并在适当的时候可以通过修改ejb-jar.xml来改变bean的引用,而不需要去修改代码。

ejb规范建议,bean所有的对其它bean的引用都应该位于java:comp/env/ejb下面。但通过注解所声明的引用将不会在任何subContext下面。

另外,我们还可以使用注解来进行声明ejb-ref,如下:

@EJB(name="ejb/EmplRecord", beanInterface=EmployeeRecordHome.class)
@Stateless public class EmployeeServiceBean 
implements EmployeeService {
    public void changePhoneNumber(...) {
        ...
        // Obtain the default initial JNDI context.
        Context initCtx = new InitialContext();
        // Look up the home interface of the EmployeeRecord
        // enterprise bean in the environment.
        Object result = initCtx.lookup(
        "java:comp/env/ejb/EmplRecord");
        // Convert the result to the proper type.
        EmployeeRecordHome emplRecordHome = (EmployeeRecordHome)
        javax.rmi.PortableRemoteObject.narrow(result,
        EmployeeRecordHome.class);
        ...
    }
}

 

ejb-ref-name就是我们要绑定到java:comp下面的jndi名字,我们进行lookup的时候需要用这个name进行lookup,

ejb-ref-type是可选填写的,可以是Entity/Session

home/remote/local-home/local用于指定引用bean的接口类型,如果引用ejb2.x的bean的话,home是必须指定的。

ejb-link/lookup-name用于指定所引用的外部bean(target)。两者不能同时使用,ejb-link是可选的,如果不填写的话,则在当前的ejb-jar.xml(包括注解)中查找具有相应接口的bean。ejb-link的值是需要引用的bean的<ejb-name>,当然也可以用注解来进行声明 。

与<ejb-ref>/<ejb-local-ref>相对应的注解是@EJB

@EJB.name => <ejb-ref-name>

@EJB.beanName => <ejb-link>

@EJB.lookup => <lookup-name>

@EJB.mappedName => <mapped-name>

以上是关于ejb Name Environment的主要内容,如果未能解决你的问题,请参考以下文章

带有 JPA/EJB 代码的“分离实体传递给持久错误”

@EJBs注释有什么作用?

C#程序员经常用到的10个实用代码片段

Wildfly 远程 EJB 调用

C#程序员经常用到的10个实用代码片段 - 操作系统

ejb 查找失败并出现 NamingException