2014-12-05 10 views
6

Non ho molta familiarità con J2EE così potrei fare alcuni errori mentre spiegavo l'errore. Per favore, sopportami.glassfish throwing org.postgresql.xa.PGXAException

Sto cercando di eseguire una query sulla mia applicazione enterprise Java ma glassfish tiri la seguente eccezione:

[#|2014-12-05T15:31:00.412+0200|WARNING|glassfishv3.0|javax.enterprise.system.core.transaction.com.sun.jts.CosTransactions|_ThreadID=86;_ThreadName=Thread-1;|JTS5031: Exception [java.lang.RuntimeException: org.postgresql.xa.PGXAException: Error preparing transaction] on Resource [prepare] operation.|#] 

[#|2014-12-05T15:31:00.413+0200|SEVERE|glassfishv3.0|javax.enterprise.system.core.transaction.com.sun.jts.CosTransactions|_ThreadID=86;_ThreadName=Thread-1;|JTS5031: Exception [org.omg.CORBA.INTERNAL: vmcid: 0x0 minor code: 0 completed: Maybe] on Resource [rollback] operation.|#] 

[#|2014-12-05T15:31:00.439+0200|WARNING|glassfishv3.0|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=86;_ThreadName=Thread-1;|A system exception occurred during an invocation on EJB OFReportTimeoutService method public void com.companyname.appname.service.OFReportTimeoutService.ofTimeout() 
javax.ejb.EJBException: Unable to complete container-managed transaction. 
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:4962) 
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4716) 
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1941) 
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1892) 
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:198) 
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:84) 
    at com.sun.proxy.$Proxy307.ofTimeout(Unknown Source) 
    at com.companyname.appname.service.__EJB31_Generated__OFReportTimeoutService__Intf____Bean__.ofTimeout(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at com.companyname.appname.servlet.GFv3EJBInvokerJob.execute(GFv3EJBInvokerJob.java:88) 
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213) 
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) 
Caused by: javax.transaction.SystemException: org.omg.CORBA.INTERNAL: JTS5031: Exception [org.omg.CORBA.INTERNAL: vmcid: 0x0 minor code: 0 completed: Maybe] on Resource [rollback] operation. vmcid: 0x0 minor code: 0 completed: No 
    at com.sun.jts.jta.TransactionManagerImpl.commit(TransactionManagerImpl.java:330) 
    at com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.commitDistributedTransaction(JavaEETransactionManagerJTSDelegate.java:169) 
    at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:843) 
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:4951) 
    ... 14 more 
|#] 

Un altro sistema con le stesse versioni di glassfish, postgresql, e l'applicazione web non gettare alcuna eccezione. Entrambi hanno gli stessi file domain.xml e postgresql.conf.

ho cambiato max_prepared_transactions100-10000 e shared_buffers32MB-320MB, ma non ha funzionato.

Qualche idea?

MODIFICA: codiceofTimeout aggiunto.

@Startup 
@Singleton(mappedName="OFReportTimeoutService") 
public class OFReportTimeoutService { 

    @EJB 
    protected QueueManagerService queueManagerService; 

    @EJB 
    protected AnalyzerService analyzerService; 

    @EJB 
    protected ErrorReportJpaController errorReportJpaController; 

    @EJB 
    protected ReportJpaController reportJpaController; 

    protected Boolean isProcessing = Boolean.FALSE; 

    private Boolean exceptionPresent = Boolean.FALSE; 
    private String errorText = "error"; 
    private Integer reportId = 0; 

    //@Schedule(second="*/10", minute="*", hour="*", persistent=false) 
    public void ofTimeout() { 
     //System.out.println("STATE : " + "OfReportTimeOutService is running...") ; 
     if(exceptionPresent) { 
      ErrorReport errorReport = errorReportJpaController.create(); 
      errorReport.setErrorDate(new Date()); 
      errorReport.setErrorText(errorText); 
      errorReport.setReport(reportJpaController.find(reportId)); 
      errorReportJpaController.persist(errorReport); 
      exceptionPresent = Boolean.FALSE; 
      if (queueManagerService.getLastReport() != null) 
       queueManagerService.resetLastReport(); 
      isProcessing = Boolean.FALSE; 
     } 

     if (isProcessing) 
      return; 

     if (queueManagerService.reportQueueSize() > 0) 
      isProcessing = Boolean.TRUE; 
     else { 
      //System.out.println("STATE : " + "queueManagerService.reportQueueSize == 0 !!!") ; 
      return; 
     }   

     while (queueManagerService.reportQueueSize() > 0) 
      try { 
       Report report = queueManagerService.pullReport(); 
       reportId = report.getId(); 
       if (reportId != null) 
        System.out.println("STATE : " + "reportId var") ; 
       analyzerService.process(report); 
      } catch (ReportJPAException rex) { 
       Logger.getLogger(OFReportTimeoutService.class.getName()).log(Level.SEVERE, null, rex); 
       exceptionPresent = Boolean.TRUE; 
       errorText = rex.toString(); 
       break; 
      } catch (RuntimeException rex) { 
       Logger.getLogger(OFReportTimeoutService.class.getName()).log(Level.SEVERE, null, rex); 
       exceptionPresent = Boolean.TRUE; 
       errorText = rex.toString(); 
       break; 
      } catch (Exception ex) { 
       Logger.getLogger(OFReportTimeoutService.class.getName()).log(Level.SEVERE, null, ex); 
       exceptionPresent = Boolean.TRUE; 
       errorText = ex.toString(); 
       break; 
      } 

     if(exceptionPresent) { 
      return; 
     } 

     isProcessing = Boolean.FALSE; 
     queueManagerService.resetLastReport(); 


    } 

    public Boolean isProcessing() { 
     return isProcessing; 
    } 

    public void setProcessing(Boolean isProcessing) { 
     this.isProcessing = isProcessing; 
    } 

} 
+0

Puoi aggiungere il codice del metodo 'ofTimeout()' alla domanda? – unwichtich

+0

Ho modificato il mio post e aggiunto il codice @unwichtich – Alptugay

+0

C'è qualche ragione particolare per utilizzare una transazione XA? Le transazioni XA devono essere utilizzate solo quando è necessario sincronizzare lo stato su più risorse, ad esempio le scritture devono avvenire su 2 database o broker JMS. Se stai solo cercando di leggere da una coda, assicurati che autoAck sia disabilitato e gestisca le eccezioni manualmente. – JVXR

risposta

1

Ho risolto il problema. Stiamo utilizzando bucardo per la replica del nostro database postgresql. Questa è stata la causa del mio problema. nei log di PostgreSQL vidi un log di errore come questo:

ERROR: cannot PREPARE a transaction that has executed LISTEN, UNLISTEN or NOTIFY 

Nel this blog post la causa del problema è stato spiegato:

Il problema è che le Postgres LISTEN/sistema NOTIFY non può essere utilizzato con transazioni preparate. Bucardo utilizza un trigger sulle tabelle di origine che emette un NOTIFY per consentire al demone Bucardo principale di sapere che qualcosa è cambiato e deve essere replicato. Tuttavia, la loro richiesta stava emettendo una PREPARAZIONE TRANSAZIONALE come una parte occasionale del suo lavoro. Pertanto, aggiornerebbero la tabella, che genererebbe il trigger, che invierebbe NOTIFY. Quindi l'applicazione emetterebbe PREPARE TRANSACTION che ha prodotto l'errore sopra riportato. Bucardo è impostato per far fronte a questa situazione; piuttosto che usare i trigger di notifica, il daemon di Bucardo può essere impostato per cercare eventuali modifiche a intervalli regolari. I passaggi per cambiare il comportamento di Bucardo per una data sincronizzazione sono semplicemente:

La soluzione sul post del blog non ha funzionato per noi. Potremmo permetterci di non replicare il database che causa l'errore. Così abbiamo rimosso la replica con i seguenti comandi:

[[email protected] config]# bucardo deactivate synclrms 
Deactivating sync synclrms 

[[email protected] config]# bucardo purge synclrms 
Purging name synclrms 

[[email protected] config]# bucardo remove sync synclrms 
Removed sync "synclrms" 
Note: table triggers (if any) are not automatically removed! 

Poiché i trigger non vengono rimossi automaticamente, essi devono essere rimossi manualmente: Nel nostro caso ci sono stati tre fattori scatenanti.I loro nomi erano: bucardo_delta, bucardo_kick_synclrms, bucardo_note_trunc_synclrms bucardo_note_trunc_synclrms

far cadere un trigger viene utilizzato il seguente comando:

drop TRIGGER trigger_name on table_name; 

Solo nel caso ci possono essere altri trigger su un tavolo posto da Bucardo, è possibile utilizzare il seguente comando in PostgreSQL per vedere tutti i trigger su un tavolo:

\dS table_name; 

Dopo questi passaggi, il sistema ha iniziato a lavorare normalmente senza gettare eccezioni.