Child pages
  • Using the Sakai global sessionFactory
Skip to end of metadata
Go to start of metadata
  • This is the preferred way to use Hibernate in Sakai, however, it requires strict usage of the Sakai tool structure (app,api,impl,hbm,pack), the following should be added to your components.xml file (it must be named components.xml)
  • Note: you must deploy your hbm files and value object implementations to shared and you must deploy your components and api-implementations to components or the global session factory will not be able to work with your HBM files
  1. Define additional hibernate mappings
    This allows us to add our HBMs directly to the global Sakai SessionFactory bean
    Note: You should place your HBM files and your value object implementations in the same location, this will make them easier to deploy to shared since Hibernate needs to access both of them
    <bean id="org.sakaiproject.yourapp.hibernate.AdditionalHibernateMappings"
    	class="org.sakaiproject.springframework.orm.hibernate.impl.AdditionalHibernateMappingsImpl">
    	<property name="mappingResources">
    		<list>
    			<value>org/sakaiproject/yourapp/impl/hbm/Item1.hbm.xml</value>
    			<value>org/sakaiproject/yourapp/impl/hbm/Item2.hbm.xml</value>
    		</list>
    	</property>
    </bean>
    
  2. Define a manager implementation bean based on your manager implementation (org.sakaiproject.tool.yourapp.impl.MyToolManagerDaoImpl) which uses the Sakai GlobalSessionFactory
    Note: name it as a target since we do not want to access this directly or we will be outside of the transaction
    <bean id="org.sakaiproject.yourapp.dao.MyToolDaoTarget" 
    	class="org.sakaiproject.yourapp.dao.impl.MyToolDaoImpl">
    	<property name="sessionFactory">
    		<ref bean="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" />
    	</property>
    </bean>
    
  3. Define a declarative transaction interceptor (TransactionProxyFactoryBean) using the GlobalTransactionManager(org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager) and pointing it at our tool DAO (org.sakaiproject.yourapp.dao.MyToolDaoTarget)
    <bean id="org.sakaiproject.yourapp.dao.MyToolDao"
    	class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    	<property name="transactionManager">
    		<ref bean="org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager" />
    	</property>
    	<property name="target">
    		<ref bean="org.sakaiproject.yourapp.dao.MyToolDaoTarget"/>
    	</property>
    	<property name="transactionAttributes">
    		<props>
    			<prop key="*">PROPAGATION_REQUIRED</prop>
    		</props>
    	</property>
    </bean>
    
    • This will do a lot of nice things for us, like manage our rollbacks and propogate changes
  4. Spring config samples (components.xml)
  • No labels

1 Comment

  1. Here some information that we've found out by trial and error:

    First, this page tells you how to get hibernate to see your hbm.xml files. That's part of the job, but you also need to get the tables created, and you need to create the classes. We create the classes manually, by creating appropriate .java files. I believe there's a way to automatically create classes from the hbm files. To create the tables we use Aaron's DDL generator POM, http://confluence.sakaiproject.org/display/BOOT/Maven2+hibernate+DDL+generator+POM. That will generate .sql files from the hbm. As long as you put them in your tool's WEB-INF/classes, Sakai appears to pick them up and create the tables. (We found out the hard way that if there's something wrong with the .sql file you won't get any kind of error message. The table just won't get created. We ended up pasting the file into mysql to test it, and that showed the problem.)

    We create the classes manually. I put them in the project's API jar or some other jar in tomcat/shared/lib. (I actually don't know whether it's required. The text above implies that they should go in components, but the tasklist example puts them in a jar in shared/lib. If you use separate interface and implementation, I believe only the interface needs to be in shared. The implementations are typically in components.) One thing that is required is to put the .hbm.xml files in that place. Because Hibernate (at least as used on this page) ia global to all of Sakai, it looks for the hbm files in Sakai's global class path, which includes the jar files in tomcat/shared/lib. Normally the shared jar files are created in a subproject whose pom.xml includes the following:

    <packaging>jar</packaging>

    <properties>
    <deploy.target>shared</deploy.target>
    </properties>

    In the mappingResources property above, a path is shown for each .hbm.xml file. If you do "jar tf" on your jar file in tomcat/shared/lib these paths should all show up exactly as specified in the mappingResources propery.

    Now, finally, to get the instructions on this page to work, your hbm files must be in Sakai's global class path, and the first bit of XML on this page, which defines the hbm files, most be in components.xml. As far as I know, components.xml must appear in WEB-INF in a subproject that gets deployed to your project's subdirectory in tomcat/components. Normally this is created by a subproject whose pom.xml includes the following:

    <packaging>sakai-component</packaging>

    <properties>
    <deploy.target>components</deploy.target>
    </properties>

    Older projects sometimes call the subproject "pack" rather than "components", but normally the pack subproject is deployed to components just like a components subproject. If you dont need a components section for other reasons, it is perfectly valid to have a components directory that includes only WEB-INF/components.xml, and a components.xml that includes only the XML fragment shown on this page, plus the normal stuff around it, i.e. DOCTYPE, and <beans> </beans>. The other pieces of XML on this page can go in other files, wherever you would define the beans that are involved. We successfully used them in applicationContext.xml.

    One other thing we found out the hard way: the class files that define your objects must appear in only one place. Otherwise you'll get type conversion errors in very mysterious ways. If any other project or subproject needs to refer to the objects (i.e. the classes used the hbm files), the pom.xml file for that project/subproject will include a <dependency> pointing to subproject containing the class files (probably the same subproject where your hbm files appear). But make sure that the <dependency> declaration includes <scope>provided</scope>. Otherwise, the default is to put a new copy of the jar file into that project/subproject. This will cause Really Bad Things to happen.