1

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

我的 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 服务入站和出站拦截器的东西。

4

2 回答 2

1

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

于 2014-08-11T17:05:27.583 回答
1

在 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 获取客户端发送的数据。

于 2015-02-11T22:29:45.807 回答