3

我有一個onMessage方法,我從隊列中接收一個ObjectMessage並使用該信息來填充和保存一個JPA實體對象。但是當持久化實體對象出現問題時,它將重新執行onMessage()。我的猜測是它將ObjectMessage推回隊列,因此onmessage再次被執行。這樣我就進入了一個無限循環。如何停止onMessage()再次執行或控制執行次數。這是我的代碼。 saveAuditData(auditInfo)發生錯誤。如何在MDB中停止回滾?

public void onMessage(Message inMessage) { 
    log.debug("Entering onMessage() Method."); 
    AuditInfo auditInfo = null; 
    try { 
     ObjectMessage om = (ObjectMessage) inMessage; 
     auditInfo = (AuditInfo) om.getObject(); 
     log.debug("Message received : " + auditInfo.getApiUsed()); 
     log.debug("Calling saveAuditData()."); 
     saveAuditData(auditInfo); 
     log.debug("Leaving onMessage() Method."); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     log.debug("Error persisting Audit Info.",e); 
     log.debug("Printing Audit Info:"); 
     log.debug(auditInfo.toString()); 
    } 

} 
private void saveAuditData(AuditInfo auditInfo) { 
    log.debug("Entering saveAuditData() Method."); 
    log.debug("Populating Audit Object."); 
    IdmAudit idmAudit = new IdmAudit(); 
    idmAudit.setApiUsed("API"); 
    idmAudit.setAppClientIpAddress("localhost"); 
    idmAudit.setAuditActivity("activity1"); 
    idmAudit.setAuditData(auditInfo.getAuditData()); 
    idmAudit.setAuditGroup(AUDIT_GROUP); 
    idmAudit.setAuditType("Type"); 
    idmAudit.setIdmAuditCreationDate(new Date()); 
    idmAudit.setLocationCd("Location"); 
    idmAudit.setPurgeDate(null); 
    idmAudit.setSubscriberId(new BigDecimal(0)); 
    idmAudit.setSuccessInd("Y"); 
    idmAudit.setUserId(new BigDecimal(0)); 
    idmAudit.setAuditSource("Source"); 
    idmAudit.setVersionNumber(new BigDecimal(0)); 

    log.debug("Saving Audit."); 
    entityManager.persist(idmAudit); 
    entityManager.flush(); 
    log.debug("Leaving saveAuditData() Method."); 
} 

回答

8

當容器管理的事務是由容器開始處理JMS消息,在JDBC連接或異常的線程拋出的任何故障將導致到全局XA事務的回滾。所以消息回到隊列,並且將在稍後根據隊列配置重試:重試之間的時間段,在將消息移動到死信隊列之前的最大重試次數。

所以,你有以下幾種選擇:

  • 選擇自己的MDB部署描述符「豆管理」的交易模式,並使用的UserTransaction從查找到java:comp/UserTransaction手動調用begincommitrollback,所以不在乎你的異常處理。

  • 保留「容器管理」事務,但查詢JMS消息上的redelivery count屬性以決定接下來要做什麼:再次嘗試可能失敗的事情或者跳過此步驟並將數據保存到數據庫中。如果您的JMS提供商提供它,您可以從Message.getJMSRedelivered()Message.getLongProperty("JMSXDeliveryCount")獲得郵件的重新傳遞信息。

  • 否則,從而創建一個新的事務,你的數據被保存無論發生什麼事你MDB事務中部署描述符將您saveAuditData方法將EJB StatelessBean與事務支持RequiresNew。該選項可以與前一個選項結合使用。

2

你可以簡單地標記onMessage方法與TRANSACTIONTYPE註釋:

@TransactionAttribute(value=TransactionAttributeType.REQUIRES_NEW) 
public void onMessage(Message message) { 
    ..... 
} 
+0

嗨Acasolla。當你試圖告訴我得到這個消息:在該行 多個標記 \t - 實現javax.jms.MessageListener.onMessage \t - JSR 345:EJB 3.2,8.37:本REQUIRES_NEW事務屬性類型值是無效的消息驅動的bean消息偵聽器方法。指定REQUIRED或 \t NOT_SUPPORTED值。 我認爲這是行不通的。 – 2017-08-02 22:25:50