【问题标题】:start transaction AFTER not BEFORE start of synchronized method in singleton bean在单例 bean 中同步方法的开始之后而不是之前开始事务
【发布时间】:2014-08-25 14:59:13
【问题描述】:

我在 glassfish 中部署了一个战争文件。我们有一个 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

【问题讨论】:

  • 这是一个很好的问题。据我所知,由于代理的工作方式,这是不可能的。你能解释一下你想要达到的目标吗?

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


【解决方案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 中作为额外的保护措施。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      相关资源
      最近更新 更多