views:

1208

answers:

3

Hi, I have resource local datasource (Oracle9i) deployed at JBoss 5.1.0:

<datasources>
  <local-tx-datasource>
    <jndi-name>OracleDS</jndi-name>
    <connection-url>jdbc:oracle:thin:@IP_ADDRESS:1521:inv9i</connection-url>
    <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
    <user-name>***</user-name>
    <password>***</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <metadata>
        <type-mapping>Oracle9i</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

persistence unit:

<persistence version="1.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_1_0.xsd"&gt;
    <persistence-unit name="myEJB" transaction-type="RESOURCE_LOCAL">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <non-jta-data-source>java:OracleDS</non-jta-data-source>
     <class>hr.bel.model.Instrument</class>
     <class>hr.bel.model.Order</class>
     <class>hr.bel.model.OrderAdditionalData</class>
     <class>hr.bel.model.OrderCondition</class>
     <class>hr.bel.model.Trade</class>
     <class>hr.bel.model.TradeAdditionalData</class>
     <class>hr.bel.model.Tradeticker</class>
     <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.show_sql" value="true" />
     </properties>
    </persistence-unit>
</persistence>

Within an MDB, when onMessage method is invoked I'm trying to persist an bean and fetch latest 5 beans of that type via an namedQuery:

@PersistenceContext
    EntityManager em = null;
    public void onMessage(MyMessage msg) {
        Map message = msg.getMessageTree(false);
        Instrument instrument = em.find(Instrument.class, 55);   

        Tradeticker tt = createTradeticker(message);
        tt.setInstrument(instrument);

        log.info("Persisting tradeticker: " + tt.getTradeType());         
        em.persist(tt);       
        log.info("Tradeticker persisted...");

        List<Tradeticker> last5 = em.createNamedQuery("getLast5").setParameter(1,instrument.getInstrumentId()).setMaxResults(5).getResultList();
        log.info("Persisted tradetickers size: " + last5.size());
    }

My problem is that there is no any trace of an error but still there is no any persisted objects in my Oracle database. After great number of messages call last5.size() returns 0. Log is perfectly clean.

Only restrictions for MDBs I found are I have to use REQUIRED or NOT_SUPPORTED transaction attribute on methods. My onMessage is not annotated so it uses REQUIRED as default. Also I have no any annotations on MDB class so bean should use container managed transaction.

What I'm doing wrong?

A: 

In passing: a common pattern is to put the business logic into a SLSB and call that from your MDB - allows for other use of the logic. Should make no difference to your problem though.

I would expect the default transaction attribute to be Requried. I don't see a reason why this should fail.

I would do these things:

1). Put a try/catch around the business logic. Are any exceptions thrown?

2). Remove the query, I can't see why it should be failing, but lets remove any possibility taht it might be interfering with the insertion. Let's rely on the database. Use a command-line SQL statement or other utility to see what's in the DB after a few messages have gone through.

3). Check the logs again, is an error appearing anywhere?

djna
after changing descriptors as I explained in my solution all works fine. Anyway regarding putting business logic into a SLSB I skip that because there was important performance requirement by customer. How SLSB-s would be used just from MDBS I skiped them avoiding all proxy logic around them. It would be nice if there is some good link/literature about performance issues when running ejbs.
igor.beslic
+1  A: 

Shouldn't you manage the transaction yourself when working with a non-jta data source? That is, get a transaction and commit the data yourself? I leave that kind of stuff to JTA myself, but when I read this correctly it looks like in your case you need to commit explicitely.

fvu
Yes, you're right! I figure that later... What was new to me is that if I manage my own transaction I'm not allowed to use injected EM but one obtained via JNDI lookup call. Obviously I should read more detailed about ejb3.
igor.beslic
`Shouldn't you manage the transaction yourself when working with a non-jta data source?` Actually, the OP would have to commit explicitly because he's using a *resource-local* entity manager, not because of the `non-jta-datasource` (which is not really appropriate though since MDB + JPA would require a global transaction).
Pascal Thivent
+2  A: 

OK. This is how I solved problem, 1st define tx datasource, 2nd define jta model and jta-datasource in persistence.xml.

New datasource definition:

<datasources>
  <xa-datasource>
    <jndi-name>OracleDS</jndi-name>
    <isSameRM-override-value>false</isSameRM-override-value>
    <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
    <xa-datasource-property name="URL">jdbc:oracle:thin:@IP_ADDRESS:1521:inv9i</xa-datasource-property>
    <xa-datasource-property name="User">***</xa-datasource-property>
    <xa-datasource-property name="Password">***</xa-datasource-property>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <no-tx-separate-pools/>
    <metadata>
      <type-mapping>Oracle9i</type-mapping>
    </metadata>
  </xa-datasource>

jboss:service=TransactionManager

new persistence.xml:

<persistence version="1.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_1_0.xsd"&gt;
    <persistence-unit name="myEJB" transaction-type="JTA">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <jta-data-source>java:OracleDS</jta-data-source>
     <class>hr.bel.model.Instrument</class>
        <class>hr.bel.model.Order</class>
        <class>hr.bel.model.OrderAdditionalData</class>
        <class>hr.bel.model.OrderCondition</class>
        <class>hr.bel.model.Trade</class>
        <class>hr.bel.model.TradeAdditionalData</class>
        <class>hr.bel.model.Tradeticker</class>

     <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.show_sql" value="true" />
     </properties>
    </persistence-unit>
</persistence>

My java code is same and now I'm getting my object persisted! After discussion with my colleagues who use mysql dbms we figure that Oracle with its tx and no-tx datasources made strict restrictions on how and where datasources will be used. Thank you all!

igor.beslic
Yes, since you want the Entity Manager to be injected, you must use a container-manager entity manager (which must be a `JTA` entity manager) and supply a `jta-data-source`.
Pascal Thivent