【问题标题】:Pass Default Application Context to Remote EJB Anonymously将默认应用程序上下文匿名传递给远程 EJB
【发布时间】:2014-08-11 16:09:07
【问题描述】:

我有一个复杂的场景,我不知道该怎么做:

我的 ejb 在远程服务器上运行。

而我的 Web 应用程序在不同的服务器上运行。

我有一个 ApplicationContext,它会根据域、语言、国家等不同而有所不同。

我希望将此应用程序上下文匿名传递给远程 EJB,这样开发人员就不必使用 ApplicationContext 作为参数来调用他们的所有后端请求。

这是场景,假设我有一个远程无状态 EJB:

@Stateless
public class MyStateless implements MyStatelessRemote{

  //The application context that needs to be supplied form the front-end
  @Inject //probably define a producer method to always supply a new one.
  private ApplicationContext applicationContext;

  public void doCheckSomething(final MySomethingData data){}

}

在前端:

@SessionScoped
@Named
public class MyController implements Serializable{

  @EJB
  private MyStatelessRemote statelessRemote
  //The current application/session context to be passed to the Stateless ejb on every invocation.
  @Inject
  private ApplicationContext executionContext;

  public void doSomeOrderOrSomethingSimilar(){
    //At this point, the current application context needs to be supplied to the remote EJB
    //Which it may use to check on order validity based on configurations such as country
    //language etc.
    statelessRemote.doCheckSomething(mySomething);
  }
}

拥有超过 20 个 EJBS,每个 EJBS 平均有 8 到 10 个方法,并且考虑到几乎每个 ejb 都可能需要知道调用者的执行上下文的可能性, 是否可以在调用任何方法期间通过配置或其他方式解析当前执行上下文到 ejb?

  1. 我将 Wildfly8 与远程 ejb3.1、CDI1.1、JSF2.2 一起使用
  2. 应用程序上下文可能会在例如用户更改他/她的语言时发生变化

编辑:

我正在寻找类似于 Web Service 入站和出站拦截器的东西。

【问题讨论】:

    标签: java jakarta-ee cdi ejb-3.1 wildfly-8


    【解决方案1】:

    如果不将参数传递给远程 EJB,您所描述的内容是不可能使用 CDI/EJB 实现的。

    【讨论】:

    • 请看看我更新的答案。我也做过研究,现在我知道你可以基于 glassfish 上的 CORBA IIOP 来做到这一点。
    【解决方案2】:

    在 jboss/wildfly 服务器上工作了几个月后,我终于找到了实现这个功能的方法:

    客户端代码:(基于jboss ejbclient)

    package com.mycompany.view.service.wildfly.invocationcontext;
    
    import com.mycompany.ejb.internal.MyCompanyAccount;
    import com.mycompany.view.service.account.LoggedInAccount;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.annotation.PostConstruct;
    import javax.ejb.Singleton;
    import javax.ejb.Startup;
    import javax.enterprise.inject.Instance;
    import javax.inject.Inject;
    import org.jboss.ejb.client.AttachmentKey;
    import org.jboss.ejb.client.EJBClientContext;
    import org.jboss.ejb.client.EJBClientInterceptor;
    import org.jboss.ejb.client.EJBClientInvocationContext;
    
    import static com.mycompany.management.wildfly.invocationcontext.MyCompanyInvocationContextKey.MYCOMPANY_ACCOUNT_NUMBER;
    
    /**
     * Registers itself as a jboss client interceptor.
     * @author marembo
     */
    @Singleton
    @Startup
    public class MyCompanyInvocationContextInterceptor implements EJBClientInterceptor {
    
        private static final Logger LOG = Logger.getLogger(MyCompanyInvocationContextInterceptor.class.getName());
        private static final AttachmentKey<Long> MYCOMPANY_ACCOUNT_NUMBER_KEY = new AttachmentKey<>();
    
        @Inject
        @LoggedInAccount
        private Instance<MyCompanyAccount> loggedInAccount;
    
        @PostConstruct
        void registerSelf() {
            EJBClientContext.requireCurrent().registerInterceptor(0, this);
        }
    
        @Override
        public void handleInvocation(final EJBClientInvocationContext ejbcic) throws Exception {
            LOG.log(Level.INFO, "Intercepting invocation on: {0}", ejbcic.getInvokedMethod());
    
            final EJBClientContext clientContext = ejbcic.getClientContext();
            if (!loggedInAccount.isUnsatisfied()) {
                final MyCompanyAccount mycompanyAccount = loggedInAccount.get();
                if (mycompanyAccount != null) {
                    final Long accountNumber = mycompanyAccount.getAccountNumber();
                    clientContext.putAttachment(MYCOMPANY_ACCOUNT_NUMBER_KEY, accountNumber);
                }
            }
            ejbcic.getContextData().put(MYCOMPANY_ACCOUNT_NUMBER, "348347878483");
    
            ejbcic.sendRequest();
        }
    
        @Override
        public Object handleInvocationResult(final EJBClientInvocationContext ejbcic) throws Exception {
            return ejbcic.getResult();
        }
    
    }
    

    在服务器端,我注册了一个全局拦截器:

    package com.mycompany.management.wildfly.extension;
    
    import com.mycompany.management.facade.account.MyCompanyAccountFacade;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.annotation.Resource;
    import javax.ejb.EJB;
    import javax.ejb.EJBContext;
    import javax.interceptor.AroundInvoke;
    import javax.interceptor.InvocationContext;
    
    /**
     * Default interceptor does not require @Interceptor
     * @author marembo
     */
    public class MyCompanyInvocationContextReceiver {
    
        private static final Logger LOG = Logger.getLogger(MyCompanyInvocationContextReceiver.class.getName());
    
        @Resource
        private EJBContext ejbContext;
        @EJB
        private MyCompanyInvocationContext mycompanyInvocationContext;
        @EJB
        private MyCompanyAccountFacade mycompanyAccountFacade;
    
        @AroundInvoke
        public Object setMyCompanyAccount(final InvocationContext invocationContext) throws Exception {
            final Map<String, Object> contextData = ejbContext.getContextData();
            LOG.log(Level.INFO, "EJBContext data: {0}", contextData);
            LOG.log(Level.INFO, "InvocationContext data: {0}", invocationContext.getContextData());
    
            return invocationContext.proceed();
        }
    }
    

    和 ejb-jar.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"
             version = "3.1"
             xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
        <interceptors>
            <interceptor>
                <interceptor-class>com.mycompany.management.wildfly.extension.MyCompanyInvocationContextReceiver</interceptor-class>
            </interceptor>
        </interceptors>
    
        <assembly-descriptor>
            <interceptor-binding>
                <ejb-name>*</ejb-name>
                <interceptor-class>com.mycompany.management.wildfly.extension.MyCompanyInvocationContextReceiver</interceptor-class>
            </interceptor-binding>
        </assembly-descriptor>
    </ejb-jar>
    

    如服务器端拦截器所示,您可以从 InvocationContext 或 EJBContext 获取客户端发送的数据。

    【讨论】:

    • 您在此处所做的任何事情都是特定于容器的。
    • 你正在做我提到的 - 将参数传递给你的远程 EJB(在这种情况下,它是通过一个拦截器)
    • 当你说传递参数时,我得到的意思是我有一个 ejb 方法,它接受我想要传递给它们的参数,但是我在这里,我正在使用 ejbcontext 发送额外的数据,所以除非您清楚如何传递参数,否则我会理解,但我只是了解方法参数的含义,任何人都会。
    猜你喜欢
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多