【问题标题】:Dynamic Remote EJB call动态远程 EJB 调用
【发布时间】:2017-04-27 21:18:22
【问题描述】:

我找了很久,但实际上还没有找到适合我的情况的正确答案。

一般我想在不知道所有方法的情况下调用远程 EJB。 据我所知,我需要使用反射来完成它。

问题是我是否应该在客户端使用接口? 通常我使用接口进行 EJB 调用,但我想我需要在运行时使用字节码操作来创建动态接口???

最后的想法是在运行时将新应用程序部署到 jboss 服务器(热部署),并通过管理服务器(来自 EJB 的主应用程序)从新部署的应用程序调用 EJB。 所以我可以在运行时添加/删除/更新逻辑/EJB。

但远程 EJB 并非每次都相同(取决于它应该执行的任务)。 所以我需要为每个我想调用的新部署的应用程序/ejb 动态地创建一个接口或类。 客户/管理员只知道 JNDI 名称。

假设这是我的界面和来自热部署应用程序的 ejb 代码。 请考虑这只是 n 个 EJB 中的一个。

远程 EJB 接口:

import javax.ejb.Remote;

@Remote
public interface EJBInterface {

    public void www();
    public void store();
}

远程 EJB:

import javax.ejb.Stateless;

import com.xx.yy.EJBInterface;

@Stateless
public class EJBStuff implements EJBInterface{

    @Override
    public void www() {
       //Do some stuff
    }

    @Override
    public void store() {
       //Do some stuff
    }
}

在客户端/管理员方面,我想调用 EJB。 我应该使用接口还是直接使用一个类来实现??? 此外,我假设我需要为每个 hotdeploy 应用程序添加一个通用 EJB,它为我提供了我想要调用的 EJB 的信息,以便我可以在客户端/管理员端创建一个类或接口。

如果我应该在客户端/管理端或类上创建一个接口并在没有接口视图的情况下调用 EJB,那么有人有什么建议吗? 我需要另一个类来为我提供来自远程 EJB 的信息???

感谢您的建议。

【问题讨论】:

  • 远程 EJB-s 总是通过定义业务方法的接口工作。如果您需要动态更改“命令”,请使用命令设计模式实现而不是 EJB-s。您也可以通过 EJB-s 实现此模式。您将命令类型和 List 作为参数映射传递。这个接口在服务器端的实现可以独立于客户端改变。
  • 此 CommandBean 使用适当的参数(取决于命令类型)调用不断变化的 bean 方法。
  • 嗨 Bitman thx 的评论我会这样做。
  • 如果这对您来说是一个很好的解决方案,我将其写为答案。没事吧?
  • 是的,我想这对我的情况来说是一个很好的解决方案。我将在 EJB 中创建一个方法(命名为执行),在其中传递我想要实际执行的方法名称作为参数。然后我将在执行方法中按名称调用此方法。所以我只需要创建一个带有执行方法的接口,我想从 EJB 调用哪个方法并不重要。感谢您的帮助,我过去查看了错误的方法。

标签: java reflection ejb


【解决方案1】:

您的问题的解决方案是“命令设计模式”。我的示例是一个 Web 客户端,以避免 JNDI 查找造成的不便(无论如何这不是问题的一部分)

EJB 模块代码(Command、CommandType、CommandMgr、HelloBean)

Command 类用于以抽象的方式调用 SLSB 的参数化方法:

package x;

import java.util.HashMap;
import java.util.Map;

public class Command
{
  private int type;
  private final Map<String,Object> params = new HashMap<>();

  public Command( int type_ ) { type = type_; }
  public int getType() { return type; }
  public Map<String,Object> getParams() { return params; }
  public Object getParamByKey( String key_ ) { return params.get( key_ ); }
}

CommandType 枚举描述的可用命令类型:

public enum CommandType { UNKNOWN, HELLO }

CommandMgr 是一个接收Command消息的远程业务接口:

package x;

import javax.ejb.Remote;

@Remote
public interface CommandMgr
{
  public Object send( Command command_ );
}

CommandMgrImpl 类实现业务接口:

package x;

import java.security.InvalidParameterException;
import javax.ejb.Stateless;
import javax.inject.Inject;

@Stateless( name = "commandMgr" )
public class CommandMgrImp implements CommandMgr
{

  @Inject
  private HelloBean helloBean;

  @Override
  public Object send( Command command_ )
  {
    if ( command_ != null )
      switch ( command_.getType() )
      {
        case 1:
          return helloBean.sayHello( (String) command_.getParamByKey( "name" ) );
        default:
          return null;
      }
    else
      throw new InvalidParameterException( "CommandMgrImp.send() : command_=null");
  }

}

HelloBean 是通过远程接口间接访问的会话 bean 之一:

package x;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;

@Named
@ApplicationScoped
public class HelloBean
{
  public String sayHello( String name_ )
  {
    return "Hello " + name_ + "!";
  }
}

Web 客户端代码是一个常见的 JSF Web 模块(一个页面和一个 EJB 注入的支持 bean):

hellopage.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
  <h:head>
    <title>Facelet Title</title>
  </h:head>
  <h:body>
    <h:form>
    <h:panelGrid columns="3">
      Enter your name:<h:inputText id="name" value="#{commandClient.name}"/>
      <h:commandButton value="Submit">
        <f:ajax listener="#{commandClient.updateMessage}" execute="@form" render="msg"/>
      </h:commandButton>
    </h:panelGrid>
      <h:messages id="msg"/>
    </h:form>
  </h:body>
</html>

CommandClient 是一个视图范围的托管 bean:

package x;

import java.io.Serializable;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class CommandClient implements Serializable
{
  private String name;

  @EJB
  private CommandMgr commandMgr;

  public String getName()
  {
    return name;
  }

  public void setName( String name_ )
  {
    name = name_;
  }

  public void updateMessage( AjaxBehaviorEvent event_ )
  {
    Command cmd = createHelloCommand();
    FacesMessage msg = new FacesMessage( (String) commandMgr.send( cmd ) );
    FacesContext.getCurrentInstance().addMessage( "name", msg );
  }

  protected Command createHelloCommand()
  {
    Command cmd = new Command( CommandType.HELLO.ordinal() );
    cmd.getParams().put( "name", name );
    return cmd;
  }

}

【讨论】:

    猜你喜欢
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多