[jboss-jira] [JBoss JIRA] (AS7-4552) JBoss AS 7 produces non-transactional (autocommit) EntityManager within transactional EJB methods when using 3rd party javax.sql.DataSource via @DataSourceDefinition

Craig Ringer (JIRA) jira-events at lists.jboss.org
Fri Apr 20 10:16:19 EDT 2012


    [ https://issues.jboss.org/browse/AS7-4552?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12686077#comment-12686077 ] 

Craig Ringer edited comment on AS7-4552 at 4/20/12 10:16 AM:
-------------------------------------------------------------

I've tested -ds.xml deployment with the postgresql tests without success so far. Creating the module and loading it was fuss-free*. I now have:

{code}
[standalone at localhost:9999 /] /subsystem=datasources/jdbc-driver=postgresql-driver:read-resource
{
    "outcome" => "success",
    "result" => {
        "driver-class-name" => "org.postgresql.Driver",
        "driver-module-name" => "org.postgresql",
        "driver-name" => "postgresql-driver"
    }
}
{code}

If I remove the @DataSourceDefinition from JBossAS7ContainerTransactionsWith3rdPtyDataSource and instead place the following contents in src/main/webapp/WEB-INF/postgresql-ds.xml:

{code}
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <datasource jndi-name="java:app/test-ds" enabled="true" use-java-context="true"  
        pool-name="test-ds-pool">
    <connection-url>jdbc:postgresql:regress</connection-url>
    <driver>postgresql-driver</driver>
    <security>
      <user-name>regress</user-name>
      <password>regress</password>
    </security>
  </datasource>
</datasources>
{code}

where persistence.xml is:

{code}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="test-PU" transaction-type="JTA">
    <jta-data-source>java:app/test-ds</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>
{code}

then the deployment succeeds and so does the transaction test. So it looks like a bundled *-ds.xml file is working, though it's non-portable and requires the manual installation and enabling of a new server module. It's another approach, anyway.

I'm guessing there's no way for a -ds.xml to reference a driver within the deployment archive, allowing fully self-contained deployments to be produced?

For the record and for anyone else reading this while troubleshooting, my module was:

{code}
modules/org/postgresql/main:
  module.xml
  postgresql-9.1-901-1.jdbc4.jar
{code}

where module.xml was:

{code}
<module xmlns="urn:jboss:module:1.1" name="org.postgresql">
   <!-- Load with jboss-cli command:
        /subsystem=datasources/jdbc-driver=postgresql-driver:add(driver-name=postgresql-driver, driver-class-name=org.postgresql.Driver, driver-module-name=org.postgresql)
   -->
   <resources>
     <resource-root path="postgresql-9.1-901-1.jdbc4.jar"/>
   </resources>
   <dependencies>
     <module name="javax.api"/>
     <module name="javax.transaction.api"/>
   </dependencies>
 </module>
{code}

(* though it made me realize how good a module repository for JBoss would be to contain pre-packaged versions of DB drivers etc, like a ports tree. Or stub modules that could fetch the jar archives from maven repos on demand w/o having to bloat the jboss downloads; same deal)
                
      was (Author: ringerc):
    I've tested -ds.xml deployment with the postgresql tests without success so far. Creating the module and loading it was fuss-free*. I now have:

{code}
[standalone at localhost:9999 /] /subsystem=datasources/jdbc-driver=postgresql-driver:read-resource
{
    "outcome" => "success",
    "result" => {
        "driver-class-name" => "org.postgresql.Driver",
        "driver-module-name" => "org.postgresql",
        "driver-name" => "postgresql-driver"
    }
}
{code}

If I remove the @DataSourceDefinition from JBossAS7ContainerTransactionsWith3rdPtyDataSource and instead place the following contents in src/main/webapp/WEB-INF/postgresql-ds.xml:

{code}
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <datasource jndi-name="java:app/test-ds" enabled="true" use-java-context="true"  
        pool-name="test-ds-pool">
    <connection-url>jdbc:postgresql:regress</connection-url>
    <driver>postgresql-driver</driver>
    <security>
      <user-name>regress</user-name>
      <password>regress</password>
    </security>
  </datasource>
</datasources>
{code}

where persistence.xml is:

{code}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="test-PU" transaction-type="JTA">
    <jta-data-source>java:app/test-ds</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>
{code}

then the deployment succeeds and so does the transaction test. So it looks like a bundled *-ds.xml file is working, though it's non-portable and requires the manual installation and enabling of a new server module. It's another approach, anyway.

I'm guessing there's no way for a -ds.xml to reference a driver within the deployment archive, allowing fully self-contained deployments to be produced?

(* though it made me realize how good a module repository for JBoss would be to contain pre-packaged versions of DB drivers etc, like a ports tree. Or stub modules that could fetch the jar archives from maven repos on demand w/o having to bloat the jboss downloads; same deal)
                  
> JBoss AS 7 produces non-transactional (autocommit) EntityManager within transactional EJB methods when using 3rd party javax.sql.DataSource via @DataSourceDefinition
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: AS7-4552
>                 URL: https://issues.jboss.org/browse/AS7-4552
>             Project: Application Server 7
>          Issue Type: Bug
>          Components: EJB, JPA / Hibernate, Transactions
>    Affects Versions: 7.1.1.Final
>         Environment: java version "1.7.0_01"
> Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
> Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
> Linux ayaki.localdomain 3.3.0-4.fc16.x86_64 #1 SMP Tue Mar 20 18:05:40 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
>            Reporter: Craig Ringer
>            Assignee: Scott Marlow
>              Labels: autocommit, ejb, h2, h2sql, jdbc, jta, postgresql, transaction, transaction_manager, xa
>         Attachments: h2-test-logs.zip, JBossAS7ContainerTransactionsWith3rdPtyDataSource.zip, JBossAS7ContainerTransactionsWith3rdPtyDataSourceFixed.zip, JBossAS7ContainerTransactionsWithJBossDataSource.zip, JBossAS7H2Tests.zip
>
>
> When using a javax.sql.DataSource via @DataSourceDefinition to create the JTA datasource for a persistence unit, transactional EJB business methods run without transactions. No warning or error is emitted.
> Business method calls annotated @TransactionAttribute(TransactionAttributeType.REQUIRED) receive an EntityManager that *is in autocommit mode*, ie is *not* in a transaction.
> This violates the EJB3 spec and is a nasty problem.
> I discovered this when testing some code against PostgreSQL that uses deferred constraints to create two interdependent database objects; record A must have at least one record B referencing it, but record B also has a foreign key reference to record A. This can be satisfied only with deferred constraints, and works fine in SQL-level testing. When testing with Arquillian at the JBoss AS 7 / Hibernate / JPA level, though, it was breaking.
> Further investigation showed that the entity manager was in autocommit despite the method being transactional, as demonstrated by a test that tries to create and fetch from a cursor.
> I've now verified that the issue exists when using PostgreSQL or H2 as the database, so it's not specific to PostgreSQL. I've attached test cases for both databases.
> JBoss AS 7 clearly has some validation and checking to do because it *must* not allow an autocommit entity manager to be injected for transactional business methods. That's a really critical error, as it effectively means that transaction isolation is always at DIRTY_READ (which most DBs don't even support) rather than the requested level, and it's impossible to roll back work!
> As a workaround, it should be possible to deploy an archive with an embedded jboss-ds.xml instead of using @DataSourceDefinition . I haven't tested this - struggling to find documentation on in-archive deployment of jboss-ds.xml or equivalent jboss-specific descriptor like a datasource definition for jboss-web.xml .
> Using the jboss admin cli, or deploying a jboss datasource definition xml file to the deployments folder separately to the program archive, isn't subject to the problem. That's a PITA when unit testing, though.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.jboss.org/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the jboss-jira mailing list