当前位置: 首页 > 面试题库 >

匿名将默认应用程序上下文传递给远程EJB

夹谷斌蔚
2023-03-14
问题内容

我有一个复杂的场景,对此我不知道如何处理:

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

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


问题答案:

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



 类似资料:
  • 我有一个aws设置,它要求我承担角色并获得相应的凭据,以便写入s3。例如,要使用aws cli编写,我需要使用标志。如果我自己用boot编写代码,我将通过扮演角色,获取凭据,并创建新会话。 但是,有许多应用程序和包依赖于boto3的配置,例如,内部代码运行如下: 从文档中,boto3可以设置为使用默认配置文件,使用(除其他外)env变量,并且它显然“工作”在与变量匹配,但应用程序仍然不会写入s3。

  • 问题内容: 我正在这样运行我的JavaFX应用程序: 类扩展。在特殊的FX线程中启动JavaFX窗口,但是在我的main方法中,我什至没有类的实例。 如何将非字符串参数(在我的情况下为 控制器 )传递给实例?它是有缺陷的设计吗? 问题答案: 通常,除了传递给您的主程序的程序参数外,无需将参数传递给主应用程序。想要这样做的唯一原因是创建一个可重用的对象。但这并不需要是可重用的,因为这是组装您的应用程

  • 我有在Tomcat 8服务器上运行的应用程序。应用程序使用log4j2进行内部日志记录。我想有一个application.war和两个不同的日志配置文件,如:log4j2_dev.xml和log4j2_prod.xml取决于环境。 在生产环境中,我希望部署应用程序。war并使用log4j2_prod.xml,在开发环境中部署应用程序。war并使用log4j2_dev.xml 那么,我如何指定在应用

  • 问题内容: 在通过构造函数传递给匿名类的最终变量中,Jon Skeet提到了变量是通过自动生成的构造函数传递给匿名类实例的。在这种情况下,为什么我看不到使用反射的构造函数: } 输出为: 问题答案: 这是您的程序在我的系统上输出的内容: 因此,构造函数在那里。但是,它是无参数的。从反汇编来看,发生的事情是编译器发现它不需要传递给它,因为它的值在编译时就知道了。 如果我这样更改代码: 现在生成的构造

  • 本文向大家介绍C#程序将参数传递给线程,包括了C#程序将参数传递给线程的使用技巧和注意事项,需要的朋友参考一下 要使用线程,请在代码中添加以下命名空间- 首先,您需要在C#中创建一个新线程- 上面,threadDemo是我们的线程函数。 现在将参数传递给线程- 上面设置的参数是- 示例 让我们看完整的代码,以将参数传递给C#中的线程。 输出结果

  • 问题内容: 我有一个运行自定义gradle任务的Java应用程序,该应用程序在被调用时需要一些参数。这些是: Gradle任务如下所示: 我已尝试运行,但无法正常工作。 问题答案: 从Gradle 4.9开始,可以使用–args传递命令行参数。例如,如果要使用命令行参数启动应用程序,则可以使用 gradle run –args =’foo –bar’ 另请参阅Gradle应用程序插件 如何升级Gr