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. Inthis 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. Inthis 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>本質上沒有太大的區別:
[email protected],有些類型甚至還可以互換。
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.
[email protected],@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>[email protected]
@EJB.name => <ejb-ref-name>
@EJB.beanName => <ejb-link>
@EJB.lookup => <lookup-name>
@EJB.mappedName => <mapped-name>
ejb Name Environment