【发布时间】:2015-09-26 19:22:57
【问题描述】:
尽管messagedriven bean是基于异步逻辑的,但我有以下场景:
- 2 个包含用户凭据的领域(jdbc 和 ldap)
- 当用户在表单中输入用户名和密码时,它会尝试在两个领域(jdbc 和 ldap)中进行身份验证
- 对于每个领域的登录尝试,我都会使用 JMS 发送一条消息以记录它
我的问题在于 onMessage(Message message) 覆盖方法。
考虑下面的 JMS 消息 Bean 的 Java 伪代码:
public void onMessage(Message message){
String username = (cast message to Map and get username);
Login login = (Login)loginDAO.filter( queryByUsername, username );
if( login == null ){
Creates a new entry at database for 'username'
}else{
Uses 'username' already created
}
}
现在我的问题场景:
- 我在表单中输入了我的用户名和密码,然后按登录
- 尝试登录 JDBC 并触发 JMS 以记录它
- 尝试在 LDAP 上登录并触发 JMS 来记录它
- onMessage 几乎同时收到 2 条消息(第 2 项和第 3 项)
- 消息 1 创建一个新用户,因为它在数据库中不存在
- 消息 2 还会创建一个具有相同用户名的新用户
我需要消息 2 在消息 1(如果逻辑)上使用创建的用户(其他逻辑),但我认为它(消息 2)是如此之快,以至于条目尚未在 DB 中持久化,并且两条消息都被捕获“如果逻辑”。
如果我的主题令人困惑且不合适,请提出建议。
[编辑] 到目前为止我所拥有的:
服务器中有一个 MessageDriven Beans (MDB) 的 POOL,对于 2 条消息到达,您将获得 2 个 MDB 同时运行,因此您将保留相同的信息 2 次。
我在 Annotation Message Driven Bean 中使用了一个名为 maxSession 的属性
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
现在我在池中只有一个 MDB,我在负责检查“用户名”登录审核的所有逻辑的方法中放置了一个 SYNCHRONIZED。
[编辑 2] 如下尼古拉斯所观察到的:
删除了池限制,我创建了一个静态方法来检查数据库(检查用户名是否存在或需要创建和持久化)。
静态,因为它需要与 MDB 的所有实例共享,并且还需要同步以避免在 DB 上重复条目。
谢谢
【问题讨论】:
-
您的数据库没有存储用户详细信息的表的 PK 吗?第二次插入肯定会抛出异常。
-
是的。我正在使用 JPA,所以休眠会在持久实体管理器中增加 ID
标签: java multithreading jpa jms