JMS MessageDriven bean - 如何同步线程?

时间:2015-07-08 17:57:17

标签: java multithreading jpa jms

尽管messagedriven bean基于异步逻辑,但我有以下场景:

  1. 包含用户凭据(jdbc和ldap)的2个领域
  2. 当用户在表单中放置用户名和密码时,它会尝试在两个域(jdbc和ldap)中进行身份验证
  3. 对于每个领域尝试登录,我发送一条消息与JMS进行登录
  4. 我的问题在于onMessage(消息消息)覆盖方法。

    考虑下面的JMS消息Bean的Java-Pseudocode:

    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
        }
    }
    

    现在我的问题场景:

    1. 我在表单中输入了用户名和密码,然后按“登录”
    2. 尝试登录JDBC并触发JMS以记录它
    3. 尝试登录LDAP并触发JMS进行记录
    4. onMessage几乎同时收到2条消息(第2项和第3项)
    5. 消息1创建一个新用户,因为它不存在于数据库
    6. 消息2还会创建具有相同用户名的新用户
    7. 我需要消息2在消息1上使用创建的用户(否则是逻辑)(如果是逻辑),但是我认为它(消息2)是如此之快以至于条目没有在DB中持久存在并且两个消息都被捕获"如果逻辑"。

      如果我的主题混淆且没有被挪用,请提供建议。

      [编辑]到现在为止我已经得到了:

      服务器中有一个POOL of MessageDriven Beans(MDB),对于到达的2条消息,您将同时运行2个MDB,因此您将保留相同的信息2次。

      我在Annotation Message Driven Bean中使用了一个名为maxSession的属性

      @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
      

      现在我在池中只有一个MDB,我在方法上放了一个SYNCHRONIZED,负责检查'用户名'的所有逻辑。登录审核。

      [编辑2]根据下面的尼古拉斯观察:

      删除了池限制,我为数据库检查创建了一个静态方法(检查用户名是否存在或是否需要创建和保留)。

      静态,因为它需要与MDB的所有实例共享,并且还需要同步以避免在DB处复制条目。

      谢谢

1 个答案:

答案 0 :(得分:1)

在不知道这个代码实际上应该做什么的情况下,MDB似乎仍然是实现同步的错误位置。据推测,您将拥有有限数量的用户,并且您将为每个用户处理多条消息。通过将MDB池限制为一个实例,您将严格限制MDB处理器上的吞吐量。

我建议您不要尝试在MDB中进行同步,而是在用户名持久性机制中实现同步,或者如您在代码中所描述的那样:

Creates a new entry at database for 'username'

这样,可以同时处理多条消息,但它们会暂时阻止,而fortune决定哪个线程保存用户名,(一个会保存它,然后得到它,其他人会等待然后得到它)。之后,您不会多次阻止单个用户名,您可以运行完整的MDB池。