我很长一段时间都在寻找,但实际上我找不到正确答案。
一般我想在不知道它的所有方法的情况下调用远程EJB。 据我所知,我需要用反射来完成它。
问题是我应该在客户端使用接口吗? 通常我使用EJB调用的接口,但我想我需要使用字节码操作在运行时创建动态接口???
最后,我们的想法是在运行时将新应用程序部署到jboss服务器(hotdeploy),并通过管理服务器(来自EJB的主应用程序)从新部署的应用程序中调用EJB。 所以我可以在运行时添加/删除/更新逻辑/ EJB。
但远程EJB并非每次都相同(取决于它应该执行的任务)。 所以我需要为我想调用的每个新部署的应用程序/ ejb动态创建一个接口或类。 客户/管理员只知道JNDI名称。
我们假设这是来自hotdeployed应用程序的接口和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,那么有人有一个adivse吗? 我需要另一个类,为我提供远程EJB ???
的信息谢谢你的建议。
答案 0 :(得分: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是一个用于接收命令消息的远程业务接口:
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;
}
}