users@glassfish.java.net

Re: Glassfish / Hibernate / ejb3 dao issue

From: Josh Donkersloot <josh_at_geomaxmobile.com>
Date: Thu, 20 Sep 2007 15:06:29 -0500

Thanks for your help. Your example does exactly what I was hoping for,
I am going to start a new project and rewrite the web service without
the non-portable options now that I know it works as I like without them.

Thank you again,
Josh

Sahoo wrote:
> 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
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: users-help_at_glassfish.dev.java.net
>
>