我仍然在学习适当的Java模式,并希望就如何使用最佳工具来解决这个问题提出建议。
我有一个需要管理多个智能代理实例的系统。客户端可以创建新实例或按名称访问所需的实例。多个客户端可以同时访问同一个代理。
我们的计划是通过REST接口向代理公开操作,因此调用可能类似于:
GET /sessions/
POST /sessions/{name}
PUT /sessions/{name}/doanaction
这些会话不会在重新启动后持续存在,所以我不需要资源管理。
我的想法是,我们可以使用@Singleton
会话bean来管理到代理的名称映射,然后将其注入到@Stateless
会话bean中,从而为REST web服务提供实用方法。
我想确保我没有在这里误用@Singleton。因为多个客户端可以访问同一个代理,所以似乎没有任何方法可以使用Java会话管理来促进跨会话的对象管理。除了@Singleton会话bean之外,还有其他可注入的对象吗?这通常是解决这个问题的正确方法吗?小贴士很感激!
发布于 2014-02-19 21:24:37
我不认为EJB的任何开箱即用的机制都不适合agent的概念--代理是一个有状态的实体,它在服务器中具有自己的生命周期,同时可以被多个客户机访问。
无状态会话bean没有状态,有状态会话bean仅用于一个客户端。
因此,一种可能的设计是将状态从代理中提取到AgentState
对象中。然后将每个代理的状态存储在ConcurrentHashMap
中,并按代理名称进行索引。散列映射可以包装在@Singleton
bean中。
然后,REST控制器代码可以按名称检索代理状态,动态实例化传递状态的代理new MyAgent(agentState)
,然后执行一些操作。
代理状态可以由多个客户端并发地从缓存中检索。关键是MyAgent
代码需要防止代理状态的损坏,方法是在代理对象执行复合操作时获得一个锁:
类MyAgent {
public void someCompoundOperation() {
synchronized (agentState) {
...
String propertyA = agentState.getPropertyA();
... compare A with something
agentState.setPropertyA(newA);
...
}
}
这将防止两个客户端读取属性的相同值并同时执行操作,而不是等待其他代理完成并释放代理状态时的争用条件。
https://stackoverflow.com/questions/21891127
复制相似问题