1

I have this code in EJB:

try{
    em.persist(joueur);
    em.persist(p);
    em.persist(astre);
    em.persist(planet);
    em.flush();         
}catch(Exception e){    
       logger.log(Level.FATAL, "test");
    // ExceptionManager.manageExceptions(e);             
}

This code must throw Exception because I have made trigger (via PostGreQSL) to check some constraint and I use test values to launch my trigger.

I have a weird result because my logs display test so I enter the catch block but my code does not catch "all" or the "complete" Exception because my server log displays all Exception stack and I don't know why...It's look like this code throws Exception after...

I know that I have to call flush() method to immediately store entities into my database but it's look like it doesn't work here and an Exception is still propagated into my code.

Few weeks ago this code worked but I have worked on another project facet and now it seems that I have some kind of regression and I don't know why...

So my question is this one : does EntityManager.flush() always perform persist action immediately?

EDIT : here are my logs (a little epurated) (first->GF log, second->Log4j personnal log) : Sorry it's French version, but Exception name remain the same ;)

[#|2013-01-10T15:03:28.218+0100|WARNING|glassfish3.1.2|org.eclipse.persistence.session.file:/E:/softs/serveurs/glassfish3_1122/glassfish/domains/domain1/applications/ear-0.0.1-SNAPSHOT/lib/entities-0.0.1-SNAPSHOT.jar_01|_ThreadID=72;_ThreadName=Thread-2;|Local 

Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): 



  org.eclipse.persistence.exceptions.DatabaseException
    Internal Exception: org.postgresql.util.PSQLException: ERREUR: le pseudo est déjà pris (player_name)=(hghghghggg)
    Error Code: 0
Call: INSERT INTO pretoria.pseudos (ID, CHANGEMENT, PSEUDO, VERSION, joueur_id) VALUES (?, ?, ?, ?, ?)
    bind => [5 parameters bound]
Query: InsertObjectQuery(com.sim.entities.Pseudo@190c460)
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1494)
    ................
Caused by: org.postgresql.util.PSQLException: ERREUR: le pseudo est déjà pris (player_name)=(hghghghggg)
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    ................
|#]

[#|2013-01-10T15:03:28.218+0100|WARNING|glassfish3.1.2|org.eclipse.persistence.session.file:/E:/softs/serveurs/glassfish3_1122/glassfish/domains/domain1/applications/ear-0.0.1-SNAPSHOT/lib/entities-0.0.1-SNAPSHOT.jar_01|_ThreadID=72;_ThreadName=Thread-2;|Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
de la transaction
Error Code: 0
Call: INSERT INTO pretoria.joueurs (ID, BLOQUE, cle_validation, creation, EMAIL, LANGAGE, maj_temperament, NEWSLETTER, PASSWORD, POUSSIERE, SEL, TEMPERAMENT, VACANCES, VERSION, alliance_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    bind => [15 parameters bound]
Query: InsertObjectQuery(com.sim.entities.Joueur@1a21ad9)
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1494)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:838)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:592)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1717)
    ................
Caused by: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
de la transaction
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
    ................
|#]

[#|2013-01-10T15:03:28.234+0100|WARNING|glassfish3.1.2|org.eclipse.persistence.session.file:/E:/softs/serveurs/glassfish3_1122/glassfish/domains/domain1/applications/ear-0.0.1-SNAPSHOT/lib/entities-0.0.1-SNAPSHOT.jar_01.transaction|_ThreadID=72;_ThreadName=Thread-2;|Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
de la transaction
Error Code: 0
Call: INSERT INTO pretoria.joueurs (ID, BLOQUE, cle_validation, creation, EMAIL, LANGAGE, maj_temperament, NEWSLETTER, PASSWORD, POUSSIERE, SEL, TEMPERAMENT, VACANCES, VERSION, alliance_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    bind => [15 parameters bound]
Query: InsertObjectQuery(com.sim.entities.Joueur@1a21ad9)
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1494)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:838)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
    ................
Caused by: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
de la transaction
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
    ................
|#]

[#|2013-01-10T15:03:28.234+0100|WARNING|glassfish3.1.2|javax.enterprise.system.core.transaction.com.sun.jts.jta|_ThreadID=72;_ThreadName=Thread-2;|JTS5054: Unexpected error occurred in after completion
Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
de la transaction
Error Code: 0
Call: INSERT INTO pretoria.joueurs (ID, BLOQUE, cle_validation, creation, EMAIL, LANGAGE, maj_temperament, NEWSLETTER, PASSWORD, POUSSIERE, SEL, TEMPERAMENT, VACANCES, VERSION, alliance_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    bind => [15 parameters bound]
Query: InsertObjectQuery(com.sim.entities.Joueur@1a21ad9)
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1494)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:838)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:592)
    ................
Caused by: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
de la transaction
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
    ................
|#]

[#|2013-01-10T15:03:28.234+0100|WARNING|glassfish3.1.2|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=72;_ThreadName=Thread-2;|EJB5184:A system exception occurred during an invocation on EJB AccountBean, method: public void com.sim.ejbs.stateless.AccountBean.createAccount(java.lang.String,char[],java.lang.String,com.sim.basics.enums.TemperamentEnum,com.sim.dtos.xml.universes.Universe,int,int,int,java.lang.String,java.lang.String) throws com.sim.basics.exceptions.SimRuntimeException|#]

[#|2013-01-10T15:03:28.234+0100|WARNING|glassfish3.1.2|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=72;_ThreadName=Thread-2;|javax.ejb.EJBException: Transaction aborted
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5142)
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4901)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
    ................
Caused by: javax.transaction.RollbackException
    at com.sun.jts.jta.TransactionManagerImpl.commit(TransactionManagerImpl.java:334)
    at com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.commitDistributedTransaction(JavaEETransactionManagerJTSDelegate.java:185)
    at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:861)
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5136)
    ... 53 more
|#]

Log4j log :

2013-01-10 15:03:28,218 FATAL   [com.sim.ejbs.stateless.AccountBean] 

javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERREUR: le pseudo est déjà pris (player_name)=(hghghghggg)
Error Code: 0
Call: INSERT INTO pretoria.pseudos (ID, CHANGEMENT, PSEUDO, VERSION, joueur_id) VALUES (?, ?, ?, ?, ?)
    bind => [5 parameters bound]
Query: InsertObjectQuery(com.sim.entities.Pseudo@190c460)
2013-01-10 15:03:28,234 FATAL   [com.sim.web.beans.LoginBean] 123
Cœur
  • 37,241
  • 25
  • 195
  • 267
Olivier J.
  • 3,115
  • 11
  • 48
  • 71
  • 1
    What do you use as the proof that an exception is propagated into your code? And what is the exception and its stacktrace? – Marko Topolnik Jan 10 '13 at 13:22
  • Are you in a transaction? As per http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#flush%28%29 if you are not in a transaction the flush method will throw a TransactionRequiredException – ThanksForAllTheFish Jan 10 '13 at 13:31
  • The code you are showing is pretty much just ignoring the exception. Depending on the exception, the EM will be unuseable afterward and the transaction should be marked for rollback- any operation on it should result in an exception. – Chris Jan 10 '13 at 13:32
  • See also [this](http://stackoverflow.com/questions/14222121/try-catch-inside-or-outside-functions/14222313#14222313) – Roman C Jan 10 '13 at 13:33
  • @Marko : my logger destination file is not the same as my Glassfish log file and logs are written in both. Usually, when I catch Exception, the stacktrace isn't written in GF logs since Exception aren't propagated. The Exception is `org.postgresql.util.PSQLException` as it should because my trigger is launched. – Olivier J. Jan 10 '13 at 13:49
  • @mardavi : I'am in a transaction inside EJB. TransactionRequiredException is not launched – Olivier J. Jan 10 '13 at 13:50
  • @Roman : when I use `RuntimeException` I fall into it but my logs are still writting in GF logs, I don't think this is normal – Olivier J. Jan 10 '13 at 13:55
  • You failed to provide the full stacktrace, with a due explanation of the key entries in it. – Marko Topolnik Jan 10 '13 at 13:57
  • @OlivierJ. Just add corresponding appender. – Roman C Jan 10 '13 at 13:58
  • I add the server GF logs and log4j log to my post – Olivier J. Jan 10 '13 at 14:11

2 Answers2

1

IIRC some databases may actually execute the statements on transaction commit, so please try to invoke commit (instead of flush(), just for testing) and see if it happens too.

EDIT: On the other hand JPA needs to get ID of persisted entity right after it's done (if the generation strategy is IDENTITY or SEQUENCE), so probably it's not right what I said above...

Adam Dyga
  • 8,666
  • 4
  • 27
  • 35
0

Yes, flush will always flush. You may not be executing the code you think you are, or may not be getting the exception you expect. Enable logging on finest, and try debugging.

James
  • 17,965
  • 11
  • 91
  • 146