users@glassfish.java.net

Re: Glassfish / Hibernate / ejb3 dao issue

From: Sahoo <Sahoo_at_Sun.COM>
Date: Thu, 20 Sep 2007 10:39:52 +0530

I don't know why you have to use all those non-portable options. I tried
a simple example with your requirements, and it works. Although I used
GlassFish persistence provider, TopLink Essentials, I am sure it will
work in Hibernate as well.

[imports & package declarations have been removed for sake of brevity]

// RecordService.java
@WebService()
public class RecordService {
    @Resource UserTransaction utx;
    @EJB private MyDAOLocal myDAOBean;

    @WebMethod public String newRecord(int id) {
        try {
            utx.begin();
            Record r = myDAOBean.newRecord(id);
            utx.commit();
            return r.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @WebMethod public String updateRecord(int id) {
        try {
            utx.begin();
            Record r = myDAOBean.getRecord(id);
            r.incrVersion();
            utx.commit();
            return r.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

// MYDAOLocal.java
@Local public interface MyDAOLocal {
    Record newRecord(int id);
    Record getRecord(int id);
}

// MyDAOBean.java
@Stateless public class MyDAOBean implements MyDAOLocal {
    @PersistenceContext private EntityManager em;

    public MyDAOBean() { }

    public Record getRecord(int id) { return em.find(Record.class, id);}

    public Record newRecord(int id) {
        Record r = new Record(id);
        em.persist(r);
        return r;
    }
}

// Record.java
@Entity public class Record implements Serializable {

    @Id
    private int id;

    private int version;

    public Record() {}

    public Record(int id) {this.id = id;}

    public int getId() {return this.id; }

    public int getVersion() {return version;}

    public int incrVersion() { return ++version;}

    @Override public String toString() { return "foo.Record[id=" +
getId() + ", version=" + getVersion()+"]"; }
}

// persistence.xml
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="ws-ejb-dao-ejbPU">
    <properties>
      <property name="toplink.ddl-generation" value="create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

Make war file with RecordService.class, a jar with Record.class,
MYDAO*.class, META-INF/persistence.xml. Package the war and jar in an
ear file, deploy it. You can use a nice feature in admin console to test
the web service and see it working. Hope that helps.

Thanks,
Sahoo

Josh Donkersloot wrote:
> I changed my web service to be an EJB based web service by annotating
> the class with @Stateless, but still the problem persists. I have
> made another discovery though - don't know if it is related.
> If I remove <property name="hibernate.transaction.factory_class"
> value="org.hibernate.transaction.CMTTransactionFactory"/> from my
> persistence.xml file the 1st transaction I run through the web service
> has the desired behavior, ie it is committed at the end of the http
> request. Though after that 1st time nothing else is committed to the
> database by the web service. If I leave the line in, then I have the
> problem where the web service is one step behind with committing,
> always committing data from the last time the method was run.
>
> My persistence.xml looks as follows:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <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">
> <persistence-unit name="GeomaxPU" transaction-type="JTA">
> <provider>org.hibernate.ejb.HibernatePersistence</provider>
> <jta-data-source>jdbc/GeomaxDataSource</jta-data-source>
> <properties> <property
> name="hibernate.show_sql" value="true"/> <property
> name="hibernate.transaction.factory_class"
> value="org.hibernate.transaction.CMTTransactionFactory"/>
> <property name="hibernate.dialect"
> value="org.hibernate.dialect.MySQLMyISAMDialect"/>
> <property name="hibernate.cache.provider_class"
> value="org.hibernate.cache.NoCacheProvider"/> <property
> name="hibernate.transaction.manager_lookup_class"
> value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
> </properties>
> </persistence-unit>
> </persistence>
>
> Thanks for all the advice,
> Josh
>
> Sahoo wrote:
>> OK, the problem is with your WebService. I did not notice earlier
>> that it was *not* an EJB end point, instead you have it as an servlet
>> end point. You can't use @javax.ejb.TransactionAttribute in a
>> servlet. You can change the WebService to be an EJB based web
>> service, simply by *annotating* your class as @Stateless, or use a
>> UserTransaction to begin and end a transaction explicitly like this:
>>
>> @WebService
>> public class WebService{
>>
>> *_at_Resource javax.transaction.UserTransaction utx;*
>>
>> @EJB private MyDAO myDAO;
>>
>> @WebMethod
>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>> public void updateRecord( ) throws Exception{
>> *utx.begin();*
>> Record theRecord = myDAO.getRecord();
>> theRecord.setStuff( "test" );
>> *utx.commit();*
>> }
>>
>> Thanks,
>> Sahoo
>>
>> Josh Donkersloot wrote:
>>> Thank you for your suggestions,
>>> I tried, as you suggested, changing the getRecord method as shown
>>> below.
>>> -------------------------
>>> @Stateless
>>> public class MyDAOBean
>>> extends GenericEJB3DAO<Record, Integer>
>>> implements MyDAO {
>>>
>>>
>>> @TransactionAttribute(TransactionAttributeType.REQUIRED)
>>> public Record getRecord(){ Criteria criteria =
>>> ((org.hibernate.ejb.HibernateEntityManager)em).getSession()
>>> .createCriteria(getPersistentClass());
>>> criteria.setMaxResults(1);
>>> Record toReturn =
>>> (Record)criteria.uniqueResult(); return toReturn;
>>> }
>>> }
>>> ---------------------------
>>> But the results were the same as before. The web service seems to
>>> be "one step" behind, always writing out the value that was set
>>> during the previous call to the method.
>>>
>>> All I would like to be able to do is just a single transaction per
>>> http request on my web service?
>>>
>>> Thanks you kindly for you help,
>>> Josh
>>>
>>> Sahoo wrote:
>>>> What is the transaction attribute of /MyDAO.getRecord()/? Setting
>>>> it to REQUIRED should give the desired result.
>>>>
>>>> Sahoo
>>>> Josh Donkersloot wrote:
>>>>> Good morning all,
>>>>>
>>>>> I have been trying to use glassfish / hibernate / ejb3 to write a
>>>>> webservice but I ran into a problem. My EJBs are reading correctly
>>>>> from the database, but I am having issues writing to the database.
>>>>>
>>>>> When I call updateRecord() (in the code below) for the 1st time
>>>>> the changes to theRecord are not persisted in the database. When
>>>>> I call updateRecord() for the second time the changes from the 1st
>>>>> call are persisted. I believe that this is due to a new
>>>>> transaction being created for each call, forcing the previous
>>>>> transaction to be committed?
>>>>>
>>>>> What I need to be able to do is that for each time I call
>>>>> updateRecord() a new transaction is created and it is committed
>>>>> (the changes are written) to the db when it reaches the end of the
>>>>> updateRecord() function.
>>>>>
>>>>> Any ideas how I can get this functionality without having to
>>>>> manually lookup the session and commit it?
>>>>>
>>>>> Thanks,
>>>>> Josh
>>>>>
>>>>> @WebService
>>>>> public class WebService{
>>>>> @EJB private MyDAO myDAO;
>>>>>
>>>>> @WebMethod
>>>>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>> public void updateRecord( ) throws Exception{
>>>>> Record theRecord = myDAO.getRecord();
>>>>> theRecord.setStuff( "test" );
>>>>> }
>>>>>
>>>>> }
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
>>>> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>>>>
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
>>> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
>> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>