在 EJB 单例上调用异步和同步方法

Calling Async and Sync Method on EJB Singleton

我正在努力实现以下目标:

EJB3 单例

@Singleton
@Startup
public class SomeSingleton implements SomeSingletonRemote  {

    @override
    @Asynchronous
    public void someLongStuff(){
        method1();
        Thread.sleep(3000);
        method2();
        Thread.sleep(3000);
        // ...
    }

    public void method1(){
        // Insert an Event in a Database.
    }

    public void method2(){
        // Insert an Event in a Database.
    }

    public void someShortStuff(){
        // ...
    }
}

托管 Bean

@ManagedBean
@RequestScoped
public class SomeManagedBean{

    @EJB
    private SomeSingletonRemote _singleton;

    public void someLongStuff(){
        _singleton.someLongStuff();
    }

    public void someShortStuff(){
        _singleton.someShortStuff();
    } 
}

使用 PrimeFace 的 JSF

<h:form>
    <p:commandButton value="Start Long Stuff" 
        actionListener="#{SomeManagedBean.someLongStuff}" />
    <p:commandButton value="Start Short Stuff"
        actionListener="#{SomeManagedBean.someShortStuff}" />
</h:form>

以上代码不能异步运行。当 "Start Long Stuff" 按钮被按下时,我们必须等到方法完成才能按下另一个按钮。
你能告诉我我错了吗?

默认情况下,单例会话 bean 使用带有写锁的容器管理并发,这意味着所有方法都是排他的。如果你想允许在 EJB 上同时调用多个方法,你要么需要使用 bean 管理并发:

@Singleton
@Startup
@ConcurrencyManagement(BEAN)
public class SomeSingleton implements SomeSingletonRemote  {

...或者您需要指定读锁:

@override
@Asynchronous
@Lock(READ)
public void someLongStuff(){ ... }
...

@Lock(READ)
public void someShortStuff(){
    // ...
}

如果您的 bean 方法正在执行写操作,那么从概念上讲,使用 bean 管理的并发比 @Lock(READ) 更有意义。