3

I want to do an asynchronous transactional action in a ejb method by calling a stored procedure. When I call the methot I give below error:

java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()

Bean

@Stateless
public class FileSearchDAO {
    private static Logger logger = LoggerFactory.getLogger(FileSearchDAO.class);

    @PersistenceContext(unitName = "FileSearchPU")
    private EntityManager entityManager;

    @Asynchronous
    public Future<String> saveFile(String fileNo, List<String> runningFiles) {
        try {
            entityManager.getTransaction().begin();
            entityManager.createNativeQuery(
                    " BEGIN prc_save_file (:fileNo); END;")
                    .setParameter("fileNo", fileNo).executeUpdate();
            entityManager.getTransaction().commit();
            runningFiles.remove(fileNo);
            return new AsyncResult<>(fileNo);
        } catch (Exception ex) {
            ex.printStackTrace();
            return new AsyncResult<>(ex.getMessage());
        }
    }

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="FileSearchPU" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>jdbc/FileSearchDS</jta-data-source>
        <properties>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.transaction.jta.platform"
                      value="${hibernate.transaction.jta.platform}"/>
        </properties>
    </persistence-unit>
</persistence>

I haven't any Entity class. I just want to call the stored procedure which updates some table.

pirho
  • 11,565
  • 12
  • 43
  • 70
mohammad_1m2
  • 1,571
  • 5
  • 19
  • 38

1 Answers1

4

In a JTA managed datasource container handles transactions in a distributed way so also handling concurrency outside your application for example.

EntityManagers transaction can not be used because it is local transaction so something that is then not handled outside your application. Read also this post for more information.

If you need transaction you should use UserTransaction

@Resource
UserTransaction utx;

To use it your annotate your bean

@TransactionManagement(TransactionManagementType.BEAN)

and use transaction like

utx.begin();
   ...
utx.commit(); // utx.rollback();
pirho
  • 11,565
  • 12
  • 43
  • 70
  • 1
    Thanks. Is em.joinTransaction() also necessary? – mohammad_1m2 Dec 17 '17 at 08:16
  • 1
    @mohammad_1m2 I think it is not necessary or it does not matter in your case since the persistence context might not anyway be aware what happens in your stored procedure. But in case you were handling entities, yes. Still guess it will not harm if used. – pirho Dec 17 '17 at 08:25