0

I've the above EJB:

    @Stateless
public class ItilEJB  {
    @PersistenceContext
    protected EntityManager em;

    public <T> T find(Class<T> clazz, Long id) {
        if (clazz == null || id == null) {
            return null;
        }

        return em.find(clazz, id);
    }


public Chamado atender(Long chamadoId) {

        Chamado chamado = find(Chamado.class, chamadoId);

        if (!isChamadoAtendido(chamadoId)) {
            Status emAndamento = new Status(Status.EM_ANDAMENTO);

            HistoricoChamado historico = new HistoricoChamado();
            historico.setDescricao("Início do atendimento do chamado.");
            historico.setChamado(chamado);
            historico.setStatus(emAndamento);
            historico.setSla(chamado.getSla());

            chamado.setStatus(emAndamento);

            save(historico);

            save(chamado);
        }

        return chamado;
    }

public void save(BaseEntity entity) {

        if (entity.getId() == null) {
            if (!helper.canInsert(this, entity)) {
                throw new AlertMessageRuntimeException("user.db.constraint");
            }
            em.persist(entity);
        } else {
            if (!helper.canUpdate(this, entity)) {
                throw new AlertMessageRuntimeException("user.db.constraint");
            }
            em.merge(entity);
        }
    }

}

If my second save, save(chamado); throws one Exception (Both runtime or not) the first save is not rolled back, I can't understand why. For me, every EJB call would be encapsulate in one transaction and if a Exception occurs, the whole interaction with the DB layer would be rolled back.

How can I accomplish this behavior? If my second save throws a error, I want the first save action be rolled back.

Thanks


I'm using MySQL as DBMS and Wildfly 8.1 as Application Server. I haven't changed any of the defaults, so I don't think that auto-commit mode is enable.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="primary">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/MySQLDS</jta-data-source>

        <properties>
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

This is my datasource configuration in standalone.xml

<datasource jndi-name="java:jboss/datasources/MySQLDS" enabled="${mysql.enabled}" use-java-context="true" pool-name="MySQLDS" use-ccm="true">
                    <connection-url>jdbc:mysql://${env.OPENSHIFT_MYSQL_DB_HOST}:${env.OPENSHIFT_MYSQL_DB_PORT}/${env.OPENSHIFT_APP_NAME}</connection-url>
                    <driver>mysql</driver>
                    <security>
                      <user-name>${env.OPENSHIFT_MYSQL_DB_USERNAME}</user-name>
                      <password>${env.OPENSHIFT_MYSQL_DB_PASSWORD}</password>
                    </security>
                    <validation>
                        <check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
                        <background-validation>true</background-validation>
                        <background-validation-millis>60000</background-validation-millis>
                        <!--<validate-on-match>true</validate-on-match>-->
                    </validation>
                    <pool>
                        <flush-strategy>IdleConnections</flush-strategy>
                    </pool>
                </datasource>
  • It should be rolled back. Which DBMS are you using? And how is the persistence unit configured? The only reason why it should fail is if there is some kind of auto-commit mode activated. – Gimby Nov 10 '14 at 13:07
  • By chance do you have any deployment descriptor? Is it possible you override TransactionAttribute for your save method in a descriptor? – jjd Nov 11 '14 at 14:50

2 Answers2

2

If you by chance are using JBoss there is high probability that datasoruce is incorrectly define not to use JTA transactions. Check if you have <datasource jta="true" .. set in JBoss config. For more details check Transactions don't rollback

Community
  • 1
  • 1
Gas
  • 17,601
  • 4
  • 46
  • 93
  • Hi Gas, thank you! This is true, I've added the definition of my datasource in standalone.xml and it didn't have the jta="true" attribute . I'll try now with that added. – Cristiano Passos Nov 14 '14 at 11:55
0

You didn't mention how save() method was defined. If it's using BMP then it can't join transactions from CMP such as atender().

If not, then try this:

Over atender(Long chamadoId) put the annotation @TransactionAttribute(TransactionAttributeType.REQUIRED). And over the the definition of the save() method put this annotation @TransactionAttribute(TransactionAttributeType.MANDATORY)

hope that help

  • Thanks for your reply! I think that I've, look a little down in the question. – Cristiano Passos Nov 14 '14 at 11:53
  • Sorry, I didn't notice the slide bar. However, You can try my second suggestion. I have read that REQUIRED attribute type is not always translated to join a transaction if it exists and sometimes it creates a new transaction as if REQUIRES_NEW attribute was defined. Honestly, I can't remember where I found this but I had a similar problem to yours; However, try to use the second part of my previous reply, it should force the save() method not to start a new transaction and to join the transaction of the caller. Also, try –  Nov 15 '14 at 17:21