【问题标题】:JMS TransactionRolledbackLocalException leads to GlassFish breakdownJMS TransactionRolledbackLocalException 导致 GlassFish 崩溃
【发布时间】:2015-03-19 22:12:02
【问题描述】:

我的基本问题:
MessageDriven bean 在某处抛出 Exception,这会导致 JMS Queue 回滚,直到它炸毁并且服务器崩溃。我什至找不到Exceptions 来解决问题,因为服务器日志在几分钟内就增长到几百 MB。

我在寻找什么:
一种首先清除JMS Queue然后停止一劳永逸地回滚的方法。

我就是这样做的:

对象无状态 bean 到这里它抛出的消息驱动 Bean 我想发送发送 ObjectMessage 以接收异常消息 +-----------+ +-----------------+ +----------------- + +----------+ |我的对象 |----->|消息生产者 |-------->|消息接收者 |---->|做事 | +-----------+ +-----------------+ +----------------- + +----------+

我发送的对象是一个简单的serializable POJO。

MessageProducer 如下所示:

@Stateless
public class MessageProducer{

    @Resource(mappedName = "jms/JMSConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(mappedName = "jms/MessageReceiver")
    Queue messageReceiver;

    public void sendMessage(PostContainer postContainer){          
        MessageProducer messageProducer;
        // try with resources to close everything on Exception
        try(Connection connection = connectionFactory.createConnection(); 
               Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)){
            messageProducer = session.createProducer(messageReceiver);

            ObjectMessage objectMessage = session.createObjectMessage();
            objectMessage.setObject(myObject);
            objectMessage.setJMSRedelivered(false);  // this doesn't seem to have any effect  
            messageProducer.send(objectMessage);
            messageProducer.close();
        }catch(Exception ex){
            System.out.err("error when sendingMessage .. ignoring"); // when "ignoring" the Exception I thought to at least save me the enormous log messages
        }
    }
}

消息 bean 如下所示:

@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/MessageReceiver")
})
public class MessageReceiver implements MessageListener{

    public MessageReceiver(){
    }

    @Override
    public void onMessage(Message message){
        try{
            if(message instanceof ObjectMessage){
                ObjectMessage objectMessage = (ObjectMessage) message;
                MyObject myObject = (MyObject) objectMessage.getObject();
                doStuff(myObject); // the method that handles the incoming object - here the Exception gets thrown
            }
        }catch(Exception ex){
           System.err.println("message could not be received: " + ex.getMessage());  // still trying to ignore exceptions here
        }
    }
}

异常的某些部分

javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
    at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionClientTx(EJBContainerTransactionManager.java:662)
    at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:507)
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
    ......... (and so on....)
    at com.me.MessageBeans.MessageReceiver.doStuff(MessageReceiver.java:86)
    at com.me.MessageBeans.MessageReceiver.onMessage(MessageReceiver.java:61)
    at sun.reflect.GeneratedMethodAccessor313.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
    at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
    at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
    at sun.reflect.GeneratedMethodAccessor310.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
    ......... (and so on....)
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.

 // I try to persist myObject with JPA into the database (that's what's not working right now.. but it's beside the point here
    ......... (and so on....)

现在是我的实际问题

:)
如何停止我的JMS Queue重新发送 消息(导致任何Exceptions 或由于任何其他原因无法成功发送)? (例如捕获异常,在发送消息时设置一些参数......)

在设置 DestinationResourcesConnectionFactories 时,我必须在 GlassFish 中设置一个参数/选项吗?

我该如何手动清除队列,因为现在它已满,带有“重新发送消息”,并且每次我部署我的应用程序时我在几分钟内就会收到大量的日志消息。

感谢大家的时间和阅读:)

【问题讨论】:

  • doStuff() 是否调用另一个 EJB?
  • @SteveC 是的,它确实调用了一些 JPA 门面,试图将我的对象持久保存到数据库中(这个东西现在不起作用,原来的 exception 被抛出)
  • 抱歉,我认为这无关紧要。这是一个ConstraintViolationException 被抛出。我试图弄清楚,但是随着日志消息的泛滥,调试起来并不容易:)我尝试持久化的实体与数据库中的其他实体有很多依赖关系和关系,这就是为什么我认为它会太复杂了这里就不解释了

标签: java jakarta-ee glassfish jms message-driven-bean


【解决方案1】:

MDB 中的事务管理很棘手。

正在发生的事情是从您的 JPA Facade 服务方法中抛出了一个 java.lang.RuntimeException,这会自动将当前事务标记为回滚。因此,当它到达 MDB 中的 catch 子句时已经太晚了。 JMS 将重试失败的事务。

任何从您的服务方法中转义的java.lang.RuntimeException 都会将MDB 的事务标记为回滚。您可以通过在服务方法中捕获它来防止这种情况。

您可能需要在 JPA 外观中使用 @TransactionAttribute(REQUIRES_NEW) 注释服务方法,以防 JPA 标记 Tx(不确定)或服务方法中的另一个 EJB 调用失败。

您可以按照To Purge Messages From a Physical Destination 的说明清除您的队列。

【讨论】:

  • 谢谢!!我听从了您的建议,并在 JPA Facade 中找到了 RuntimeException。这样做感觉不好,我当然会对此进行更深入的研究-但它有效:)我还尝试按照您共享的链接中的建议使用flush-jmsdest 清除队列,但是重新传递的消息全部出现尽管asadmin 告诉我命令已成功执行,但还是重头来过。无论如何,再次感谢你。现在我可以在服务器不崩溃的情况下搜索我的异常 :)
猜你喜欢
  • 2017-07-02
  • 2018-01-23
  • 2020-12-02
  • 2013-11-11
  • 2011-01-24
  • 2015-02-23
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多