我想要实现的是利用EJB特性并使用某种自动池。
我认为SLSB可能适用于保留本地无状态变量(不知道它是否是合适的定义) - 至少来自客户端/来电者POV。
@Stateless
public class CommunicationService implements Serializable
{
private Process process;
@PostConstruct
//@PostActivate maybe?
public void startProcess()
{
try
{
process = new ProcessBuilder("running a temporary daemon").start();
}
catch(IOException e)
{
throw new RuntimeException(e.getMessage(), e);
}
}
@PreDestroy
//@PrePassivate maybe?
public void endProcess()
{
if(process.isAlive())
{
process.destroy();
boolean terminated = false;
try
{
terminated = process.waitFor(5, TimeUnit.SECONDS);
}
catch(InterruptedException e)
{
// ignore
}
if(!terminated)
{
process.destroyForcibly();
}
}
}
public int send(String message)
{
// do something with the process - may take a long time
// this is just an example
PrintStream printStream = new PrintStream(process.getOutputStream());
printStream.println(message);
try
{
return process.getInputStream().read();
}
catch(IOException e)
{
return -1;
}
}
}
请注意,我想要一个进程池,因此@Singleton
不合适。
@Stateless
EJB实例变量?@MessageDriven
更合适吗?由于
答案 0 :(得分:2)
与流行的看法相反,在SLSB中保持状态是完全可以的。它不能是客户端状态。 EJB 3.2规范的§4.7说:
术语“无状态”表示实例没有特定客户端的状态。但是,实例的实例变量可以包含跨客户端调用的方法调用的状态。此类状态的示例包括开放数据库连接和对企业bean对象的对象引用。
因此,这可能是一个可行的策略,但有一些注意事项:
规范说“无状态会话bean实例通常合并”。您需要检查所选择的JavaEE服务器实现是否确实实现了它们的集合,因为(至少有一段时间),其中一些只会每次都创建一个新实例;
控制池中的bean数可能会很棘手。即使池已满,实现也可以继续创建bean实例,它永远不会将它们返回池中;
如果从业务方法抛出任何类型的RuntimeException,那么将丢弃bean实例而不调用@PreDestroy回调(参见EJB 3.2 Spec的§9.3.1)。这将导致系统中的流程泄漏;
因此,您需要了解服务器管理SLSB池的方式。
答案 1 :(得分:-1)
对我来说,您需要实施工厂方法模式;
请阅读此信息EJB Factory Class