【问题标题】:Use @EJB as injection annotation in Weld在 Weld 中使用 @EJB 作为注入注解
【发布时间】:2011-11-29 13:21:12
【问题描述】:

我有一个应用程序,它是 JavaEE(服务器端)和 JavaSE(客户端)的一部分。由于我希望该客户端具有良好的架构,因此我在其中使用 Weld 来注入各种组件。其中一些组件应该是服务器端的@EJB。

我打算扩展 Weld 架构以提供“组件”,允许 Weld 执行 JNDI 查找以在客户端尝试引用 EJB 实例时加载它们。但是我该怎么做呢?

换句话说,我想要拥有

在客户端

public class ClientCode {
    public @Inject @EJB MyEJBInterface;
}

在服务器端

@Stateless
public class MyEJB implements MyEJBInterface {
}

使用 Weld 在创建 ClientCode 对象时“隐式”执行 JNDI 查找。我该怎么做?

【问题讨论】:

    标签: java cdi jboss-weld


    【解决方案1】:

    基本上,这样做需要写一个所谓的portable CDI extension

    但是,由于它很长并且需要一些调整,让我进一步解释一下。

    便携式扩展

    就像weld doc 解释的那样,第一步是创建一个实现Extension 标记接口的类,在其中编写与感兴趣的CDI 事件对应的代码。在这种情况下,在我看来,最有趣的事件是AfterBeanDiscovery。事实上,这个事件是在 CDI impl 找到所有“本地”bean 之后发生的。

    因此,编写扩展程序是,更多操作更少,为该事件编写处理程序:

    public void loadJndiBeansFromServer(
            @Observes AfterBeanDiscovery beanDiscovery, BeanManager beanManager)
            throws NamingException, ClassNotFoundException, IOException {
        // Due to my inability to navigate in server JNDI naming (a weird issue in Glassfish naming)
        // This props maps interface class to JNDI name for its server-side
        Properties interfacesToNames = extractInterfacesToNames();
    
        // JNDI properties
        Properties jndiProperties = new Properties();
        Context context = new InitialContext();
        for (Entry<?, ?> entry : interfacesToNames.entrySet()) {
            String interfaceName = entry.getKey().toString();
            Class<?> interfaceClass = Class.forName(interfaceName);
            String jndiName = entry.getValue().toString();
            Bean<?> jndiBean = createJndIBeanFor(beanManager, interfaceClass, jndiName, jndiProperties);
            beanDiscovery.addBean(jndiBean);
        }
    }
    

    创建 bean 不是一个简单的操作:它需要将“基本”Java 反射对象转换为更高级的焊接对象(在我的例子中)

    private <Type> Bean<Type> createJndIBeanFor(BeanManager beanManager, Class<Type> interfaceClass,
            String jndiName, Properties p) {
        AnnotatedType<Type> annotatedType = beanManager
                .createAnnotatedType(interfaceClass);
        // Creating injection target in a classical way will fail, as interfaceClass is the interface of an EJB
        JndiBean<Type> beanToAdd = new JndiBean<Type>(interfaceClass, jndiName, p);
        return beanToAdd;
    }
    

    最后,必须编写 JndiBean 类。但在此之前,需要在注释领域进行一次小旅行。

    定义使用的注解

    一开始,我用的是@EJBbad 想法:Weld 使用限定符注释方法调用结果来构建 bean 的哈希码!因此,我创建了自己的 @JndiClient 注释,它不包含任何方法,也不包含常量,以使其尽可能简单。

    构造一个 JNDI 客户端 bean

    两个概念在这里合并。

    • 一方面,Bean 接口似乎(在我看来)定义了 bean 是什么。
    • 另一方面,InjectionTarget 在一定程度上定义了该 bean 的生命周期。

    从我能够找到的文献中,这两个接口实现通常至少共享它们的一些状态。所以我决定使用一个独特的类来推动他们:JndiBean

    在那个 bean 中,除了大多数方法之外,大多数方法都是空的(或默认值)

    • Bean#getTypes,它必须返回 EJB 远程接口和所有扩展的@Remote 接口(因为这些接口的方法可以通过这个接口调用)
    • Bean#getQualifiers 返回一个只包含一个元素的 Set :一个 AnnotationLiteral 对应于 @JndiClient 接口。
    • Contextual#create(你忘记了 Bean 扩展的上下文,不是吗?)执行查找:

      @Override
      public T create(CreationalContext<T> arg0) {
          // Some classloading confusion occurs here in my case, but I guess they're of no interest to you
      
          try {
              Hashtable contextProps = new Hashtable();
              contextProps.putAll(jndiProperties);
              Context context = new InitialContext(contextProps);
              Object serverSide = context.lookup(jndiName);
              return interfaceClass.cast(serverSide);
          } catch (NamingException e) {
              // An unchecked exception to go through weld and break the world appart
              throw new LookupFailed(e);
          }
      }
      

    仅此而已

    用途?

    好吧,现在,在我的 glassfish java 客户端代码中,我可以编写诸如

    之类的东西
    private @Inject @JndiClient MyRemoteEJB instance;
    

    它可以正常工作

    未来?

    好吧,目前,用户凭据不受管理,但我想使用 CDI 的 C 完全有可能:上下文...哦不!不是上下文:scopes

    【讨论】:

      【解决方案2】:

      CDI 规范的第 3.5 节应该会有所帮助。您可能还想使用 EJB 注释上的一些属性。此外,(可能不需要告诉您这一点)确保您在客户端上正确设置了 JNDI 以引用服务器,并将任何需要的接口打包到您的客户端 jar 中。

      【讨论】:

        猜你喜欢
        • 2012-05-11
        • 2012-10-26
        • 2012-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-15
        • 2011-09-19
        • 1970-01-01
        相关资源
        最近更新 更多