-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: JRUN issues with hibernate
PostPosted: Sat Oct 30, 2004 11:22 pm 
Newbie

Joined: Sat Oct 30, 2004 10:17 pm
Posts: 3
I have a problem with hibernate running on JRun. It seems when there are multiple users using the system at the same time then I get these exceptions thrown. I get a JDBC.BatchUpdate exception on RegistrationAction:select() on line 508 which is 'List coll = session.createQuery("from is.op.actionform.RegistrationForm as temp where temp.registrant.username = '"+registrationBean.getUsername()+"'").list();'. This is especially suprising because I dont do a write to the database within this session.open()/close(). But I know hibernate does batch Updates so it could be from a previous session.open()/close(), in LoginAction, where I do persist a User64 to the database. It seems hibernate tries to insert the User64 object twice into the database and therefore I get Constraint violations because I have a 'unique constraint for email'. Iam afraid that the hibernate session is not thread safe and somehow two different sessions are trying to persist the same object. I was under the impression that JRUN with its JTA manager and JNDI pooling should work in conjunction with hibernate. However while reading the 'Hibernate in Action' book, I saw there was no support for the application server JRUN. Is there a recent update which does provide support or do I need to do something special for JRun.


While reading further about sessions, I discovered the type of transactions I do are 'session-per-request-with-detached-objects'. Also I test the app on the tomcat 5 and I cant reproduce the problem. Also because Jrun is a production server, it is hard for me to do debugging on it and logging verbosely. (hope this helps. If you need any further information, i will definitely provide it. And Thank you all for taking your time to help.)


Hibernate version: 2.1

Code:
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping
   package="is.op">

   <class name="isc.db.User64" table="Users">
      <id name="id" type="long" >
           <column name="id" sql-type="number(20)" not-null="true"/>
          <generator class="native"/>
       </id>

          <property name="firstName">
              <column name="first_name" sql-type="varchar2(50)" not-null="true"/>
          </property>
          <property name="middleName">
              <column name="middle_name" sql-type="varchar2(50)"/>
          </property>
          <property name="lastName">
              <column name="last_name" sql-type="varchar2(50)" not-null="true"/>
          </property>
          <property name="email">
              <column name="email" sql-type="varchar2(50)" not-null="true"/>
          </property>
          <property name="phone">
              <column name="phone" sql-type="varchar2(50)"/>
          </property>
          <property name="fax">
              <column name="fax" sql-type="varchar2(50)"/>
          </property>
          <property name="username">
              <column name="username" sql-type="varchar2(30)" not-null="true"/>
          </property>
         <property name="company">
              <column name="company" sql-type="varchar2(50)"/>
          </property>
          <property name="department">
              <column name="department" sql-type="varchar2(50)"/>
          </property>
         <property name="title">
              <column name="job_title" sql-type="varchar2(50)"/>
          </property>
         <property name="adminStatus">
              <column name="admin_status" sql-type="char(1)"/>
          </property>
         
         
   </class>
      
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping
   package="is.op.actionform">

   <class name="is.op.actionform.RegistrationForm" table="Registrations">
      <id name="registrantId" type="long">
           <column name="registrant_id" sql-type="number(20)" not-null="true"/>
         <generator class="foreign" >
              <param name="property" >registrant</param><!-- ignored -->
          </generator>
       </id>
       <one-to-one name="registrant" class="isc.db.User64" constrained="true"/>
       

         <!--<property name="registeredById">
            <column name="registered_by_id" sql-type="number(20)" />
         </property> -->
         <property name="title">
              <column name="job_title" sql-type="varchar2(50)"/>
          </property>
          <property name="yearsAtLockheed">
              <column name="years_at_lockheed" sql-type="number(4)"/>
          </property>
          <property name="registrationYear">
              <column name="registration_year" sql-type="number(4)"/>
          </property>
          <property name="lmPeopleId">
              <column name="lmpeople_id" sql-type="varchar2(20)"/>
          </property>           
          <!-- <set name="guests" inverse="true" cascade="all-delete-orphan">
             <key column="guest_id"/>
             <one-to-many class="is.op.Guest"/>
          </set> -->

          <many-to-one name="lob" class="is.op.LineBusiness" column="lob_id"  />
          <many-to-one name="loc" class="is.op.Location" column="location_id"  />
          <many-to-one name="bus" class="is.op.Bus" column="bus_id"  />
          <!-- <many-to-one  name ="registrant" class="isc.util.User64" column="registrant_id" /> -->
          <many-to-one name="registeredBy" class="isc.db.User64" column="registered_by_id" />
   </class>
      
</hibernate-mapping>


Code:
Code between sessionFactory.openSession() and session.close():

Full stack trace of any exception that occurs:
public ActionForward select(
         ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response   
   )
   {   
      Session session = null;
      Transaction tr = null;
      ActionForward forward = mapping.findForward(Constants.DATA_FORM);
      try {            
         
         GregorianCalendar calendar = new GregorianCalendar();
         //retreive op deadline from database. If not found within the database a default date of jan 1 1970 will be used.
         Op op = OpService.getInstances().getBaseBean((long)calendar.get(Calendar.YEAR));
         if(op == null){
            op = new Op();
         }
         //check to see if deadline for registration has passed
         if (!calendar.getTime().before(op.getDeadline())){
            //TODO: Tell them why they are at a failure page.
            //the deadline has passed
            forward =  mapping.findForward(Constants.FAILURE);
         }else{      
            session = ApplicationBean.getSession();
            tr = session.beginTransaction();
            RegistrationForm registrationBean = (RegistrationForm)form;
            //TODO: Remove all commented code about registeredby if not required
            User64 loginUser = (User64)request.getSession().getAttribute(Constants.LOGIN_USER);
            User64 registrant = null;
            String registrant_username = registrationBean.getUsername();
            if(registrant_username.equals("") || loginUser.getUsername().equals(registrant_username)){
               //registering self
               registrant = loginUser;
               registrationBean=(RegistrationForm)BaseObjectService.getInstance().getBaseBean(RegistrationForm.class, registrant.getId());
               if(registrationBean == null){
                  registrationBean = new RegistrationForm();            
               }else{
                  registrationBean.setAlreadyRegistered(true);
               }
            }else{
               //registering someone else
               registrant = new is.db.User64(registrant_username, session);
               //check if the person is already registered and if the LoginUser is an admin
               //if admin they can register/update anyone
               List coll = session.createQuery("from is.op.actionform.RegistrationForm as temp where temp.registrant.username = '"+registrationBean.getUsername()+"'").list();
               if (!coll.isEmpty()){
                  //get first one because only one can be present since username must be unique within table
                  RegistrationForm regForm = (RegistrationForm)coll.get(0);
                  //cannot register person if the logged in user is not a admin or not the registrar of the person
                  if(loginUser.getAdminStatus()==false && !(regForm.getRegisteredBy().getId()==loginUser.getId())){         
                     if(regForm.getRegisteredById() != loginUser.getId()){
                        ActionErrors errors = new ActionErrors();
                        errors.add("registrant.registered", new ActionError("messages.general","The person has already been registered by someone else."));
                        saveErrors(request, errors);
                        tr.rollback();
                        session.close();
                        return mapping.findForward(Constants.MANAGER_PAGE_JSP);
                     }
                  }
                  //else let the admin/registrar update the user
                  BeanUtils.copyProperties(registrationBean, regForm);
                  registrationBean.setAlreadyRegistered(true);
                  forward = mapping.findForward(Constants.DATA_FORM);
               }else{//new Registrant
                  registrationBean= new RegistrationForm();
                  forward = mapping.findForward(Constants.DATA_FORM);
               }
            }
         
            registrationBean.setGuests(BaseObjectService.getInstance().getBaseBeanListWithFK(Guest.class,"host.registrantId", registrant.getId()));
            registrationBean.setRegistrant(registrant);
            registrationBean.setRegisteredBy(loginUser);
            //set boolean to true if guests is not empty
            registrationBean.setBringCustomers(!registrationBean.getGuests().isEmpty());
            //populate Bus Drop Down Menus
            populateDropdowns(registrationBean);
            BeanUtils.copyProperties((RegistrationForm)form,registrationBean);
            }   
            session.flush();
            tr.commit();
            
         }catch (Exception e){
            servlet.log("RegistrationAction:select().", e);
            e.printStackTrace();
            ActionErrors errors = new ActionErrors();
            errors.add("exception", new ActionError("messages.general", ""+this.getClass()+".select(): "+e));
            this.saveErrors(request, errors);
            try {
               tr.rollback();
            } catch (HibernateException e1) {
               servlet.log("RegistrationAction:select().", e);
               e1.printStackTrace();
            }
            forward =  mapping.findForward(Constants.ERROR);
         }finally{
            try{
               if(session!=null){
                  session.close();      
               }
            }catch(Exception e){
               servlet.log("RegistrationAction:select().", e);
               e.printStackTrace();
               ActionErrors errors = new ActionErrors();
               errors.add("exception", new ActionError("messages.general", ""+this.getClass()+".select(): "+e));
               this.saveErrors(request, errors);
               forward =  mapping.findForward(Constants.ERROR);               
            }
         }
         return  forward;

   }


Name and version of the database you are using:Oracle 9

The generated SQL (show_sql=true): The sql generated were straight forward and I dont think that is the issue but if Requested I will post it

Debug level Hibernate log excerpt: N/A


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 31, 2004 1:45 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
It sounds very error prone
Quote:
'session-per-request-with-detached-objects'

Are you sure, you do not store persistent objects or hibernate session in http session ? This kind of problems are not related to JRun , just all objects in http session must be thread safe and you must ensure it yourself. One of workarounds is to synchronize access to http session in filter using some fake attribute.


Top
 Profile  
 
 Post subject: JRUN
PostPosted: Mon Nov 01, 2004 10:58 am 
Newbie

Joined: Sat Oct 30, 2004 10:17 pm
Posts: 3
ACTUALLY ITS NOT HTTP SESSION BUT HIBERNATE SESSION THAT I THINK IS NOT THREADSAFE.


Top
 Profile  
 
 Post subject: JRUN ISSUE
PostPosted: Mon Nov 01, 2004 11:05 am 
Newbie

Joined: Sat Oct 30, 2004 10:17 pm
Posts: 3
First off sorry for the caps, i didnt realize it lol. I do store an already persisted object to the http session but the hibernate transaction is already committed and the hibernate session are closed prior to the User64 object being set to the http session.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.