[RESOLVIDO]Transações EJB

10 respostas
C

Olá pessoal! A minha situação é bem complexa, uma vez que estou usando Weblogic 12C, padrão da empresa.

No meu servidor eu tenho o data source normal para um banco Oracle, não é XA.

Então, eu tenho o meu EJB Stateless anotado e lindinho como segue, e a transação é controlada pelo Container:

@Stateless(mappedName = "ejb/GrupoAtividade")
@Local(value = GrupoAtividadeRemote.class)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class Grupos implements GruposLocal {

	@PersistenceContext(name = "slaDS")
	protected EntityManager em;

Com esse EJB eu consigo listar os Grupos e fazer update nos mesmos, sem problemas, conforme nos métodos:

public List<Grupo> listar() {

		List<Grupo> retorno = new ArrayList<Grupo>();

		retorno = em.createQuery(" SELECT S from Grupos", Grupo.class).getResultList();

		return retorno;

	}

@Transactional
	public void gravar(Grupo grupo) {

		Grupo grupoBanco = null;

		try {
			grupoBanco = em.find(GrupoAtividade.class, grupoAtividade.getId());
		} catch (Exception e) {
			System.out.println("Entidade nova");//TODO remover
		}

		try {

			if (grupoBanco == null) {
				
				em.persist(grupo);//aqui dá pau
			} else {
				em.merge(grupo);
			}
		} catch (Exception t) {

			e.printstactrace();

		}

	}

Porém quando vou persistir eu tenho problemas: stack trace. Note que ainda são feitas 5 tentativas para pegar o ID novo do objeto a ser persistido, mas a transação está morta.

Se alguém souber qual o configuração do Weblogic eu preciso mexer, eu agradeço.

<03/04/2013 15h25min58s BRT>    <2013-04-03 15:25:58.804ClientSession(10120026)Communication failure detected when attempting to perform read query outside of a transaction. Attempting to retry query. Error was: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException

Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction]

Error Code: 0

Call: SELECT SEQ_SLA.NEXTVAL FROM DUAL

Query: ValueReadQuery(sql=SELECT SEQ_SLA.NEXTVAL FROM DUAL).>

<03/04/2013 15h25min58s BRT>    <2013-04-03 15:25:58.804ClientSession(10120026)Communication failure detected when attempting to perform read query outside of a transaction. Attempting to retry query. Error was: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException

Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction]

Error Code: 0

Call: SELECT SEQ_SLA.NEXTVAL FROM DUAL

Query: ValueReadQuery(sql=SELECT SEQ_SLA.NEXTVAL FROM DUAL).>

<03/04/2013 15h26min03s BRT>    <2013-04-03 15:26:03.805ClientSession(10120026)Communication failure detected when attempting to perform read query outside of a transaction. Attempting to retry query. Error was: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException

Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction]

Error Code: 0

Call: SELECT SEQ_SLA.NEXTVAL FROM DUAL

Query: ValueReadQuery(sql=SELECT SEQ_SLA.NEXTVAL FROM DUAL).>

<03/04/2013 15h26min08s BRT>    <2013-04-03 15:26:08.806ClientSession(10120026)Communication failure detected when attempting to perform read query outside of a transaction. Attempting to retry query. Error was: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException

Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction]

Error Code: 0

Call: SELECT SEQ_SLA.NEXTVAL FROM DUAL

Query: ValueReadQuery(sql=SELECT SEQ_SLA.NEXTVAL FROM DUAL).>

<03/04/2013 15h26min13s BRT>    <2013-04-03 15:26:13.807ClientSession(10120026)Communication failure detected when attempting to perform read query outside of a transaction. Attempting to retry query. Error was: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException

Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction]

Error Code: 0

Call: SELECT SEQ_SLA.NEXTVAL FROM DUAL

Query: ValueReadQuery(sql=SELECT SEQ_SLA.NEXTVAL FROM DUAL).>

<03/04/2013 15h26min13s BRT>    <2013-04-03 15:26:13.808ClientSession(10120026)Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException

Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction]

Error Code: 0

Call: SELECT SEQ_SLA.NEXTVAL FROM DUAL

Query: ValueReadQuery(sql=SELECT SEQ_SLA.NEXTVAL FROM DUAL)>

org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:309)

org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:135)

org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)

org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.connectInternal(DatasourceAccessor.java:330)

org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.connectInternal(DatabaseAccessor.java:293)

org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.reconnect(DatasourceAccessor.java:565)

org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.reconnect(DatabaseAccessor.java:1508)

org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.incrementCallCount(DatasourceAccessor.java:305)

org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:579)

org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)

org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1717)

org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:566)

org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)

org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)

org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:264)

org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelect(DatasourceCallQueryMechanism.java:246)

org.eclipse.persistence.queries.DataReadQuery.executeNonCursor(DataReadQuery.java:197)

org.eclipse.persistence.queries.DataReadQuery.executeDatabaseQuery(DataReadQuery.java:152)

org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:844)

org.eclipse.persistence.queries.DataReadQuery.execute(DataReadQuery.java:137)

org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:2831)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1516)

org.eclipse.persistence.internal.sessions.AbstractSession.retryQuery(AbstractSession.java:1586)

org.eclipse.persistence.sessions.server.ClientSession.retryQuery(ClientSession.java:593)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1552)

org.eclipse.persistence.internal.sessions.AbstractSession.retryQuery(AbstractSession.java:1586)

org.eclipse.persistence.sessions.server.ClientSession.retryQuery(ClientSession.java:593)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1552)

org.eclipse.persistence.internal.sessions.AbstractSession.retryQuery(AbstractSession.java:1586)

org.eclipse.persistence.sessions.server.ClientSession.retryQuery(ClientSession.java:593)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1552)

org.eclipse.persistence.internal.sessions.AbstractSession.retryQuery(AbstractSession.java:1586)

org.eclipse.persistence.sessions.server.ClientSession.retryQuery(ClientSession.java:593)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1552)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1498)

org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1449)

org.eclipse.persistence.sequencing.QuerySequence.select(QuerySequence.java:309)

org.eclipse.persistence.sequencing.QuerySequence.updateAndSelectSequence(QuerySequence.java:254)

org.eclipse.persistence.sequencing.StandardSequence.getGeneratedVector(StandardSequence.java:71)

org.eclipse.persistence.sequencing.Sequence.getGeneratedVector(Sequence.java:257)

org.eclipse.persistence.internal.sequencing.SequencingManager$Preallocation_NoTransaction_State.getNextValue(SequencingManager.java:664)

org.eclipse.persistence.internal.sequencing.SequencingManager.getNextValue(SequencingManager.java:1067)

org.eclipse.persistence.internal.sequencing.ClientSessionSequencing.getNextValue(ClientSessionSequencing.java:70)

org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:349)

org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:308)

org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.assignSequenceNumber(UnitOfWorkImpl.java:465)

org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist(UnitOfWorkImpl.java:4231)

org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist(RepeatableWriteUnitOfWork.java:513)

org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4176)

org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:440)

sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

java.lang.reflect.Method.invoke(Method.java:597)

weblogic.persistence.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:111)

weblogic.persistence.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:82)

weblogic.persistence.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:92)

$Proxy86.persist(Unknown Source)

com.gvt.sla.session.grupo.GruposSession.gravar(GruposSession.java:81)

com.gvt.sla.session.grupo.GruposSession_rfefeo_GrupoAtividadeRemoteImpl.__WL_invoke(Unknown Source)

weblogic.ejb.container.internal.SessionLocalMethodInvoker.invoke(SessionLocalMethodInvoker.java:31)

com.gvt.sla.session.grupo.GruposSession_rfefeo_GrupoAtividadeRemoteImpl.gravar(Unknown Source)

de.com.dcr.usuario.MBCadastroGruposAtividade.addRow(MBCadastroGruposAtividade.java:79)

sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

java.lang.reflect.Method.invoke(Method.java:597)

com.sun.el.parser.AstValue.invoke(AstValue.java:255)

com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)

com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)

javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:148)

javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)

javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:769)

javax.faces.component.UICommand.broadcast(UICommand.java:300)

javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)

javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)

com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)

com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)

com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)

javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)

weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:242)

weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:216)

weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:132)

weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:338)

weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)

weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:74)

weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)

weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:74)

weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3288)

weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3254)

weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)

weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)

weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)

weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2163)

weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2089)

weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2074)

weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1513)

weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)

weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)

weblogic.work.ExecuteThread.run(ExecuteThread.java:221)

Editei para colocar as mudanças do código.

10 Respostas

G

A transação costuma ficar marcada para rollback quando já aconteceu algum erro na mesma e por isso nenhuma outra operação pode ser realizada.

Procure debugar o programa para ver se deu algum erro que ficou oculto por não receber o tratamento adequado. Veja passo-a-passo se ele passa por todos os pontos esperados.

E uma coisa: porque colocou em.merge() e em seguida em.persist() ?

C

Eu coloco merge pois eu não vou ter esse novo objeto (Grupo) dentro do contexto persistência, uma vez que é criado dentro da camada de apresentação, que é JSF2.
Então com o merge eu coloco dentro da persistência e o persist para persistir.

C

A pedidos, eu retestei usando apenas persist e apenas merge e tenho o mesmo erro:

org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback.

G

caverna2k:
A pedidos, eu retestei usando apenas persist e apenas merge e tenho o mesmo erro:

org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Transaction BEA1-00070031DE273057A4BD not active anymore. tx status = Marked rollback.


Agora pelo menos essa parte está certa!
O merge você usa para colocar no contexto de persistência um objeto que representa uma entidade já existente, atualizando-o na base de dados - processo também conhecido como update :slight_smile:
O persist inclui uma nova entidade no contexto de persistência E na base de dados.

Agora mais uma coisa suspeita:

try { grupoBanco = em.find(GrupoAtividade.class, grupoAtividade.getId()); } catch (Exception e) { System.out.println("Entidade nova");//TODO remover }
Essa exceção engolida pode estar marcando a transação como rollback, mesmo assim a execução continua até a operação persist().
Certifique-se que NÃO está caindo na exceção, e só para garantir coloque um tratamento de erro mais conservador:

try { grupoBanco = em.find(GrupoAtividade.class, grupoAtividade.getId()); } catch (Exception e) { throw new RuntimeException("Erro no find(): " + e.getMessage(), e); }

C

Está caindo na exceção o find, justamente! Vou mudar aqui.

C

Ganhou uma caixinha de Heineken!
Na mosca, a exceção do find estava matando a transação.

Me sinto como Kiko na escola do Professor Girafales: que burro, mereço 0.

G

Por isso que eu tenho pavor desse tipo de coisa:

} catch (Exception e) { System.out.println("Erro: " + e.getMessage()); //ou e.printStackTrace(); } // continua normalmente como se nada tivesse acontecido....

O programa continua rodando com algum estado inconsistente, e a exceção original (que poderia ser fácil de resolver) é substituída mais à frente por algum erro totalmente maluco.

C

Mas existe algum jeito de eu recuperar a transação depois que ela está marcada como rollback?

G

Que eu saiba não tem como não… mas isso faz bastante sentido: a própria idéia da transação é permitir tudo ou nada. Se uma das operações falhou a transação pode estar inconsistente. Ressuscitar a transação seria como dizer:

  • O importante é o meu método executar até o fim, mesmo que a base fique inconsistente, e para isso vou usar força bruta! :evil:

A coisa certa a se fazer é descobrir a causa do erro e fazer o fluxo mais correto, sem causar erros na camada de persistência porque senão o JPA vai marcar a transação para rollback.

Por exemplo: o erro está dando em um em.find(). É difícil ter um erro nesse método que possa ser considerado “normal”. Provavelmente é um erro de programação mesmo.
Será que esse grupoAtividade.getId() não está nulo?? Crie sua lógica considerando isso… um objeto que tem ID nulo não está no banco e portanto não pode ser localizado com find(). O programa deve então tomar a providência adequada, ou passando por um fluxo alternativo quando o objeto tal não existe, ou gravando-o na base com persist()… tudo depende da regra de negócio, mas o que tem que evitar é situações “absurdas” (do ponto de vista do JPA) como tentar dar find() em um objeto que sequer tem ID, dar persist() em um objeto que já existe, etc…

A

Em algum lugar vc tá usando algo como setRollbackOnly() .

Qualdo é utilizado isso a transação é marcada p/ dar rollback e não comitar.

No instante que a transação iria fazer o commit ela lanã uma except e faz rollback de tudo.

Criado 3 de abril de 2013
Ultima resposta 9 de out. de 2014
Respostas 10
Participantes 3