在单例bean中启动同步方法之前不启动事务

时间:2014-08-19 04:24:20

标签: java java-ee glassfish stateless-session-bean session-bean

我在glassfish中部署了一个war文件。我们有一个Singleton bean,我们有1个同步方法。

@TransactionAttribute (TransactionAttributeType.REQUIRED)
public synchronized void do()
{
    ...
}

但是,我注意到在调用方法之前已启动事务。在调用者获取bean类的监视器上的锁之后,如何启动事务?

谢谢。

更新:我们只是尝试使用一个只能由一个线程一次调用的bean方法。我们不希望任何其他线程调用此方法,直到前一个线程完全完成它。我创建了另一个线程,我想到了使用单例bean:synchronized method in stateless session bean not working as expected in glassfish

更新:在做了一些阅读之后,似乎我可以创建自己的事务UserTransaction。这会得到支持吗?没关系。我收到此错误消息:

Only session beans with bean-managed transactions can obtain UserTransaction

2 个答案:

答案 0 :(得分:1)

我认为一种方法是通过将对方法的调用包装到另一个bean中来将同步移出bean(YourBean将是bean类的接口):

public class WrapperBeanImpl implements WrapperBean {

  private YourBean yb;

  private final Object lock;

  @Resource
  private SessionContext ctx;

  @PostConstruct
  public void init() {
    yb = ctx.getBusinessObject(YourBean.class);
  }

  @TransactionAttribute(TransactionAttributeType.NEVER)
  public void synchronizedDo() {
    synchronized(lock) {
      yb.do();
    }
  } 
}

(从http://www.javahelp.info/2009/11/01/using-transactionattribute-in-submethods-on-same-ejb3-beans/略微修改的示例)

当然,这并没有真正阻止任何人直接绕过这种额外的同步调用do()方法,尽管这可能不是问题。您还可以选择将同步保留在bean中作为额外的保护措施。

答案 1 :(得分:0)

只需在类级别使用@ConcurrencyManagementType(CONTAINER),容器将保持同步。并使用没有synchronized指令的methond。