之后,我开始使用JSF,它只需要带有@EJB或@Resource的带注释的属性即可与业务层进行通信。 到目前为止,在他们让我评估Vaadin作为用于商业应用程序的前端技术之前,这一直是一个很棒的经验。
在深入探讨之前,我已经阅读了Vaadin Wiki上发布的文章“ Adding JPA to the Address Book Demo ”,其中介绍了如何从Vaadin的类中调用EJB,以检索和持久化业务层的数据。 EJB使用JPA来获取数据并将其放入数据库中。 他们建议从自定义servlet调用EJB,根据Java EE规范,该自定义servlet具有使用CDI进行EJB调用的能力。
如果要调用1个或3个EJB,这似乎是一个合适的解决方案,但是当要处理大约40个EJB时,在Servlet中该怎么办? 如何将所有这些引用传递给Vaadin的应用程序类? 此类的接口可能会发疯! 这就是为什么我认为使用JNDI进行查找是可取的。
以下代码是我在概念证明(PoC)中使用的服务定位器。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;public class MyServiceLocator {private Context initialContext;private Map cache;private static ClientServiceLocator ourInstance = new ClientServiceLocator();public static ClientServiceLocator getInstance() {return ourInstance;}private ClientServiceLocator() {try {this.initialContext = new InitialContext();this.cache = Collections.synchronizedMap(new HashMap());}catch(NamingException ne) { System.err.printf("Error in CTX looking up %s because of %s while %s",ne.getRemainingName(),ne.getCause(),ne.getExplanation());}}public Object lookupEjb(String ejbName) {if(this.cache.containsKey(ejbName)) {return this.cache.get(ejbName);}else {try {Object ejbRef = initialContext.lookup("java:comp/env/"+ ejbName);this.cache.put(ejbName, ejbRef);return ejbRef;} catch (NamingException ne) {throw new RuntimeException(ne);} catch (Exception e) {throw new RuntimeException(e);}}}
}
MyServiceLocator类遵循Singleton设计模式,请确保只有一个对象实例可以满足来自Web应用程序的所有请求。 唯一实例是在类的初始化过程中创建的,并且由于构造函数是私有的,因此该类不能被另一个类实例化,只能通过方法getInstance ()获得。 构造函数初始化上下文,并创建一个同步映射,其中存储了所有已创建的引用。 方法lookupEjb ( 字符串ejbName )查找名称在本地JNDI上下文中可用的EJB。 此方法仅适用于在web.xml文件中声明了其引用的EJB,如下所示。
<web-app version="2.5"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><display-name>Information Systems</display-name>...<ejb-local-ref><ejb-ref-name>InformationSystemBean</ejb-ref-name><ejb-ref-type>Session</ejb-ref-type><local>example.business.InformationSystemBeanLocal</local><ejb-link>eac-architecture-ejb.jar#InformationSystemBean</ejb-link></ejb-local-ref>
</web-app>
标记<ejb-local-ref>用于声明对本地EJB的引用。 上面的示例仅映射一个EJB。 因此,您必须对要映射的每个EJB重复此操作。 有关此标签的详细信息,请参见此处 。 声明之后,我们可以使用以下代码在应用程序的任何部分中获取EJB的实例:
private InformationSystemLocal informationSystemBsn = (InformationSystemLocal)MyServiceLocator.getInstance().lookupEjb("InformationSystemBean");
变量是使用EJB本地接口(即InformationSystemLocal )键入的。 服务定位器返回名为InformationSystemBean的EJB实例,默认情况下是EJB的实现类。 请注意,当我们使用CDI时,上面的代码都不是必需的。 AjudaBsn的调用就像这样:
@EJB
private InformationSystemLocal informationSystemBsn;
CDI很好且优雅,但不能广泛应用。 今天实现它的方式是Java EE规范的主要弱点。 也许有很强的理由为什么EJB的注释不能在每个Java类中都起作用。 我根本看不到这个错误的原因,因为Spring自从很久以前就已经使用方面取向解决了这个问题。
参考: Hildeberto博客上的 JCG合作伙伴 Hildeberto Mendonca提供的Vaadin应用程序中的EJB查找
相关文章 :
- JBoss AS 7 EJB3池配置
- Java EE6 CDI,命名组件和限定符
- EJB程序化查找
- EJB 3.0注入和查找简介
- 什么是CDI,它与@EJB和Spring有什么关系?
翻译自: https://www.javacodegeeks.com/2012/01/ejb-lookup-in-vaadin-application.html