You are viewing a plain text version of this content. The canonical link for it is here.
Posted to docs@cocoon.apache.org by Apache Wiki <wi...@apache.org> on 2005/10/15 20:31:00 UTC

[Cocoon Wiki] Trivial Update of "CocoonAndHibernateTutorial" by PeteFarmer

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Cocoon Wiki" for change notification.

The following page has been changed by PeteFarmer:
http://wiki.apache.org/cocoon/CocoonAndHibernateTutorial

The comment on the change is:
fixed a few tiny but significant typos, added note for Hibernate3 DOCTYPE

------------------------------------------------------------------------------
  
  2005/08/10:
  
- Finally added a minimal example to show how Cocoon and Hibernate interact. 
+ Finally added a minimal example to show how Cocoon and Hibernate interact.
  
- 2005/07/25: 
+ 2005/07/25:
  
  If you have visited this page before, you should check out the new Servlet Filter. It now
  finally uses the request object instead of the servlet session to communicate with cocoon,
- with is MUCH cleaner and most importantly does not require the creation of a Session ... 
+ with is MUCH cleaner and most importantly does not require the creation of a Session ...
- Sorry for taking so long to clean this up ! 
+ Sorry for taking so long to clean this up !
  
- I am now using all of the code in a project with Hibernate 3. Probably the code snippets will 
+ I am now using all of the code in a project with Hibernate 3. Probably the code snippets will
- soon be updated to use the new Hibernate version by default. 
+ soon be updated to use the new Hibernate version by default.
  
  === What you will get from this page ===
  
- This page proposes a very basic way of using Hibernate from your Cocoon application. This is '''not''' an 
+ This page proposes a very basic way of using Hibernate from your Cocoon application. This is '''not''' an
  introduction to Hibernate or Cocoon itself. It just covers the specific issues of integration
- between the two. 
+ between the two.
  
- The approach presented here is very simple in that it tries to use facilities already provided by 
+ The approach presented here is very simple in that it tries to use facilities already provided by
  Cocoon to perform database connection pooling. However, without using another framework you will have
  direct interaction between Hibernate and Cocoon, which means calling Hibernate from flowscript. Many
  people don't want to do this and prefer to use the Spring framework for additional abstraction. If
- you are not sure if this approach is right for you, make sure you read the "Conceptual Overview" 
+ you are not sure if this approach is right for you, make sure you read the "Conceptual Overview"
- section first. 
+ section first.
  
  === Topics covered ===
  
- The two main problems you have when integrating Hibernate into Cocoon are the following: 
+ The two main problems you have when integrating Hibernate into Cocoon are the following:
  
- * Hibernate's builtin connection pool is for testing purposes only, so sooner or later you will have to use another one. 
+ * Hibernate's builtin connection pool is for testing purposes only, so sooner or later you will have to use another one.
  
- * When persistent objects are navigated by the view, closing Hibernate sessions from flowscript (=the control) 
+ * When persistent objects are navigated by the view, closing Hibernate sessions from flowscript (=the control)
-  may lead to exceptions due to race conditions. 
+  may lead to exceptions due to race conditions.
  
- The approach presented here addresses these problems by covering the following topics: 
+ The approach presented here addresses these problems by covering the following topics:
  
- * Installing Hibernate 
+ * Installing Hibernate
  
  * Configuring Hibernate to use cocoon.xconf datasources
  
- * Setting up a Servlet Filter for managing the disposal of Hibernate sessions 
+ * Setting up a Servlet Filter for managing the disposal of Hibernate sessions
  
  === Your basic skills ===
  
- Time. If you are new to the topic of O/R mapping, you will need a lot 
+ Time. If you are new to the topic of O/R mapping, you will need a lot
  of time and patience, because it is not an easy topic. Learning Cocoon already
  made you re-think your concept of a Web Application; learning Hibernate, you
- will have to do it again. 
+ will have to do it again.
  
  You should have basic Cocoon knowledge, i.e. about the Sitemap, Flowscript,
- and JX Templates. The samples included will also use CForms. Did I mention 
+ and JX Templates. The samples included will also use CForms. Did I mention
- Flowscript ? That one is especially important. 
+ Flowscript ? That one is especially important.
  
  If you want to use Hibernate you should also be fluent in Java. Be warned that
- you are going beyond the "no programming required" - statement of the Cocoon 
+ you are going beyond the "no programming required" - statement of the Cocoon
- definition. If you want to understand what you are doing, you should have a 
+ definition. If you want to understand what you are doing, you should have a
  basic notion of what Avalon is. We are also going to write a Servlet Filter which
- takes care of Hibernate Session, so if you don't know what a Servlet Filter is 
+ takes care of Hibernate Session, so if you don't know what a Servlet Filter is
- get your favourite book or search engine and read up :) 
+ get your favourite book or search engine and read up :)
  
  You will have a basic notion of what Hibernate is and what it does, otherwise
  you would not have come to this page :) But make sure you have understood what
- lazy collection initialization is and what it does. 
+ lazy collection initialization is and what it does.
  
  === Technical prerequisites ===
  
- A running cocoon installation. I tried this on Cocoon 2.1.6 and Cocoon 2.1.7. 
+ A running cocoon installation. I tried this on Cocoon 2.1.6 and Cocoon 2.1.7.
  This is written for Hibernate v 2.1.X, but it also works with Hibernate 3.0.
  When using Hibernate 3, you'll have to adjust the Hibernate package name,
  which has changed from {{{net.sf.hibernate}}} to {{{org.hibernate}}}.
@@ -84, +84 @@

  
  === Conceptual overview ===
  
- The approach presented here is built to work with Cocoon and Hibernate alone, 
+ The approach presented here is built to work with Cocoon and Hibernate alone,
  without any further frameworks. This creates a dependency between Cocoon and Hibernate since
  you will need to manage Hibernate sessions from flow script. Creating such a dependency
  is considered bad design by many people. For example, you might build a webshop which
  stores articles in a database. Using Hibernate, you will be able to replace the database
- without too much hassle (switching from MySQL to Oracle, for example), but it will still 
+ without too much hassle (switching from MySQL to Oracle, for example), but it will still
  be a database. When you want to manage your articles via a remote web service (or a flat
  text file or whatever means of data storage), you'll have to rewrite your flowscript.
  
- You can avoid this dependency by using an additional framework like Spring or Avalon which 
+ You can avoid this dependency by using an additional framework like Spring or Avalon which
  supports the "Inversion of Control" and "Data Access Object" design patterns. This will yield
- a cleaner and more modular designed web application. 
+ a cleaner and more modular designed web application.
  
  So before you begin, think if the approach presented here is right for you. I use it for smaller
- projects, when even a change in the underlying database is very unlikely, and I know the 
+ projects, when even a change in the underlying database is very unlikely, and I know the
  customer will never switch to something else than a database for data storage. Moreover, adding
- yet another framework - like Spring - to the mix, the learning curve for new developers gets 
+ yet another framework - like Spring - to the mix, the learning curve for new developers gets
- even steeper, and the resulting web application even larger, which is too costly for some 
+ even steeper, and the resulting web application even larger, which is too costly for some
- projects. 
+ projects.
  
- However, if you have a larger application or want a clean implementation of the IOC and DAO 
+ However, if you have a larger application or want a clean implementation of the IOC and DAO
- design patterns, you should definately have a look at the Spring framework. The starting 
+ design patterns, you should definately have a look at the Spring framework. The starting
- point is the SpringPetstore at cocoondev.org. 
+ point is the SpringPetstore at cocoondev.org.
  
  == Setting up ==
  
- First of all, you need an active database connection set up and configured in cocoon.xconf. 
+ First of all, you need an active database connection set up and configured in cocoon.xconf.
  There are several wiki and documentation pages on how to do this. For instance, if you use
- MySQL have a look at [MySQL]. 
+ MySQL have a look at [MySQL].
  
- For now, I will assume that your SQL datasource is named "test". 
+ For now, I will assume that your SQL datasource is named "test".
  
  Now download hibernate from [http://www.hibernate.org]. I tried this with the current production
- release, 2.1.6. The following jars from the Hibernate distribution need to be copied to your 
+ release, 2.1.6. The following jars from the Hibernate distribution need to be copied to your
  WEB-INF/lib directory:
  
  * hibernate2.jar
  
- From the "lib" directory of the Hibernate distribution: 
+ From the "lib" directory of the Hibernate distribution:
  
- * dom4j-1.4.jar 
+ * dom4j-1.4.jar
  * cglib-full-2.0.2.jar
  * jta.jar
  
  If you build cocoon exclude ojb block,this lib requried too:
  * odmg-3.0.jar
  
- '''Hibernate 3 note''': Hibernate 3 also depends on "asm.jar" and "asm-attrs.jar". 
+ '''Hibernate 3 note''': Hibernate 3 also depends on "asm.jar" and "asm-attrs.jar".
  In Cocoon 2.1.7, these JARs are already provided in the WEB-INF/lib directory.
- Unfortunately, the versions provided by Cocoon are not compatible with 
+ Unfortunately, the versions provided by Cocoon are not compatible with
  Hibernate 3. You'll have to delete those JARs and replace them with those shipped
- with Hibernate, although i'm not sure if some parts of Cocoon rely on those 
+ with Hibernate, although i'm not sure if some parts of Cocoon rely on those
- particular versions (it works fine for me so far). 
+ particular versions (it works fine for me so far).
  
  == Registering Hibernate with Avalon ==
  
- Now we will register Hibernate with Cocoon. If you are like me, you will 
+ Now we will register Hibernate with Cocoon. If you are like me, you will
- fire up Eclipse to accomplish the following part. 
+ fire up Eclipse to accomplish the following part.
  
- The first thing we'll do is create an interface {{{PersistenceFactory}}} that 
+ The first thing we'll do is create an interface {{{PersistenceFactory}}} that
- extends the Component interface from Avalon: (Note: {{{PersistenceFactory}}} 
+ extends the Component interface from Avalon: (Note: {{{PersistenceFactory}}}
  and {{{HibernateFactory}}} originate from the Page CformsHibernateAndFlow!)
  
  {{{
- package org.test; // Put the name of the target package here. Using the default package is not recommended! 
+ package org.test; // Put the name of the target package here. Using the default package is not recommended!
- 	
+ 
  import org.apache.avalon.framework.component.Component;
- 	
+ 
  public interface PersistenceFactory extends Component {
  	String ROLE = PersistenceFactory.class.getName();
- 	
+ 
  	public net.sf.hibernate.Session createSession();
  }
- }}} 
+ }}}
  
- As you can see the {{{PersistenceFactory}}} will be responsible for the creation 
+ As you can see the {{{PersistenceFactory}}} will be responsible for the creation
- of Hibernate Sessions. This is the point where we'll have to decide how Hibernate will 
+ of Hibernate Sessions. This is the point where we'll have to decide how Hibernate will
  connect to the database. My preffered solution is using the cocoon connection pool.
  
- However, most tutorials will tell you to create a file called hibernate.properties and 
+ However, most tutorials will tell you to create a file called hibernate.properties and
  put your database access information in there. This will work, but Hibernate will use its
- own builtin connection pool, and the documentation states clearly that ''''the Hibernate 
+ own builtin connection pool, and the documentation states clearly that ''''the Hibernate
- builtin connection pool is not for production use''''. 
+ builtin connection pool is not for production use''''.
  
  For example, when using MySQL, you will experience problems when leaving the webapp running
- overnight and coming back in the morning. MySQL connections die after 8 hours of idletime, and the 
+ overnight and coming back in the morning. MySQL connections die after 8 hours of idletime, and the
  Hibernate builtin pool is not capable of dealing with this. So the first thing you will see
  is an error message. It goes away after reloading the page, but still it's unacceptable for
  production use. That's why I encourage you to spend the little extra effort and use Coccoon
- connection pooling right away. 
+ connection pooling right away.
  
- Where we will do this is in the actual implementation of the {{{PersistenceFactory}}} interface, 
+ Where we will do this is in the actual implementation of the {{{PersistenceFactory}}} interface,
- in a class called {{{HibernateFactory}}} 
+ in a class called {{{HibernateFactory}}}
  
  '''IMPORTANT NOTE:''' Make sure you check out the comments in {{{initialize()}}} for instructions on how to add persistent
- classes. If you are using this to port an existing Hibernate / Cocoon application to the Cocoon 
+ classes. If you are using this to port an existing Hibernate / Cocoon application to the Cocoon
- connection pool, you will need to change that part according to your configuration. 
+ connection pool, you will need to change that part according to your configuration.
  
  {{{
  package org.test;
@@ -198, +198 @@

  import org.apache.avalon.excalibur.datasource.DataSourceComponent;
  import org.apache.avalon.framework.service.ServiceSelector;
  
- // import all classes from your package so you can later persist them  
+ // import all classes from your package so you can later persist them
  import org.test.*;
  
  public class HibernateFactory
@@ -258, +258 @@

                cfg = new net.sf.hibernate.cfg.Configuration();
  
                /* ***** ADD PERSISTENT CLASSES, VARIANT 1 ***** */
-               // persistent classes can be added here using 
+               // persistent classes can be added here using
  
-               // cfg.addClass(org.test.myClass.class); 
+               // cfg.addClass(org.test.myClass.class);
  
-               // Make sure the corresponding .class and .hbm.xml files are located in 
+               // Make sure the corresponding .class and .hbm.xml files are located in
-               // (the same directory of) your classpath (e.g. WEB-INF/classes) 
+               // (the same directory of) your classpath (e.g. WEB-INF/classes)
                sf = cfg.buildSessionFactory();
  
                /* ***** ADD PERSISTENT CLASSES, VARIANT 2 ***** */
  	      // alternatively, you might be using a hibernate.cfg.xml file to load mappings,
-               // then use the following line instead: 
+               // then use the following line instead:
  
                // sf = cfg.configure().buildSessionFactory();
  
                // no additional cfg.addClass(...) statements needed, since you can define
-               // mappings in the XML config file 
+               // mappings in the XML config file
          }
          catch ( Exception e) {
                getLogger().error("Hibernate:" + e.getMessage());
@@ -305, +305 @@

      public net.sf.hibernate.Session createSession() {
        net.sf.hibernate.Session hs;
        DataSourceComponent datasource = null;
-       
+ 
- 	// When creating a session, use a connection from 
+ 	// When creating a session, use a connection from
-         // cocoon's connection pool 
+         // cocoon's connection pool
-       try {			
+       try {
- 	// Select the DataSourceComponent named "test" 
+ 	// Select the DataSourceComponent named "test"
-         // This is a normal SQL connection configured in cocoon.xconf 
+         // This is a normal SQL connection configured in cocoon.xconf
        	ServiceSelector dbselector =
              (ServiceSelector) manager.lookup(DataSourceComponent.ROLE+"Selector");
-         datasource = (DataSourceComponent) dbselector.select("test"); 
+         datasource = (DataSourceComponent) dbselector.select("test");
          	//name as defined in cocoon.xconf
        	hs = sf.openSession(datasource.getConnection());
        }
@@ -326, +326 @@

  }
  }}}
  
- The crucial part is createSession(), where we tell Hibernate to use a connection from the 
+ The crucial part is createSession(), where we tell Hibernate to use a connection from the
- Cocoon pool. This connection is selected using the avalon framework API. 
+ Cocoon pool. This connection is selected using the avalon framework API.
  
- Compile these two files. I needed the following jars in my classpath: avalon-framework-api-4.1.5.jar, 
+ Compile these two files. I needed the following jars in my classpath: avalon-framework-api-4.1.5.jar,
- excalibur-datasource-1.1.1.jar, and hibernate2.jar. All these should be in your WEB-INF/lib 
+ excalibur-datasource-1.1.1.jar, and hibernate2.jar. All these should be in your WEB-INF/lib
- folder anyway. When you're done, copy the .class files to a directory "org/test" (which obviously 
+ folder anyway. When you're done, copy the .class files to a directory "org/test" (which obviously
  depends on the package name you chose) in the "WEB-INF/classes/" folder of your cocoon installation.
  
- To register your {{{HibernateFactory}}} with Cocoon, put the following line in cocoon.xconf: 
+ To register your {{{HibernateFactory}}} with Cocoon, put the following line in cocoon.xconf:
  
  {{{
  	<component class="org.test.HibernateFactory" role="org.test.PersistenceFactory"/>
  }}}
  
  (Not sure whether it is actually important where you put this. There is a bunch of other component ... class ...
- statements in cocoon.xconf, so I just put mine above the Xalan XSLT processor component. Need some feedback here!) 
+ statements in cocoon.xconf, so I just put mine above the Xalan XSLT processor component. Need some feedback here!)
  
- Now, you need a hibernate.properties file in your "WEB-INF/classes" folder. A very basic config file I 
+ Now, you need a hibernate.properties file in your "WEB-INF/classes" folder. A very basic config file I
- use is the following: 
+ use is the following:
  
  {{{
  hibernate.cglib.use_reflection_optimizer = false
@@ -353, +353 @@

  }}}
  
  It basically tells hibernate to turn off the reflection optimizer (whatever that means? :) ) and the
- statement cache (although statement caching can boost performance, you should leave it turned off until you 
+ statement cache (although statement caching can boost performance, you should leave it turned off until you
- are really sure how to use it). The most important line is where you tell Hibernate about the actual SQL 
+ are really sure how to use it). The most important line is where you tell Hibernate about the actual SQL
  dialect you are using. If you do not supply this information, Hibernate won't be able to behave accordingly.
  For example, Hibernate will try to use subqueries which are not supported if you use MySQL.
  
  Now restart cocoon. If everything went right, you will see the following line in your servlet container log
- file (catalina.out if you are using Tomcat): 
+ file (catalina.out if you are using Tomcat):
  
  {{{ Hibernate initialize called }}}
  
  This means that Hibernate is ready for action. At this point you may start to deploy your beans and store,
- get and edit them following the instructions on the Yet To Be Written page. 
+ get and edit them following the instructions on the Yet To Be Written page.
  
- However, at some point you will notice that there is still no proper way of managing Hibernate Sessions. 
+ However, at some point you will notice that there is still no proper way of managing Hibernate Sessions.
  Of course you can create and dispose Hibernate Session from Flow Script, but very probably you will sooner
  or later experience the (in)famous Lazy Initialization Problem (tm). The solution for this problem is to
- create a servlet filter to manage Hibernate Sessions, so if you are'nt fed up on Java yet read on :) 
+ create a servlet filter to manage Hibernate Sessions, so if you are'nt fed up on Java yet read on :)
  
  == A Servlet Filter for Disposing Hibernate Sessions ==
  
  === Why ? ===
  
  (If you just want to continue installing and are not bothering about the Why, skip this part and come
- back later ...) 
+ back later ...)
  
  If you're getting serious about Hibernate, sooner or later you will want to use lazy collection initialization
  (Read the corresponding section in GettingStartedWithCocoonAndHibernate for an introduction on this topic).
- Say you are accessing Hibernate sessions from flowscript, i.e. as follows: 
+ Say you are accessing Hibernate sessions from flowscript, i.e. as follows:
  
  {{{
    var factory = cocoon.getComponent(Packages.org.test.PersistenceFactory.ROLE);
@@ -388, +388 @@

  
    var data = hs.find("from org.test.Data");
  
-   cocoon.sendPage("data-pipe", {data: data} ); 
+   cocoon.sendPage("data-pipe", {data: data} );
  
    hs.close();
  }}}
@@ -399, +399 @@

  won't load its items from the database. But it is still possible that your view pipeline wants to access {{{otherData}}}.
  
  Now the problem is that the flowscript will just continue to process right after it has invoked the view pipeline,
- so it is possible that the {{{hs.close()}}} will occur BEFORE your view has rendered completely. So when the view 
+ so it is possible that the {{{hs.close()}}} will occur BEFORE your view has rendered completely. So when the view
- will access {{{otherData}}} after that, you will get an exception telling you that Hibernate failed to lazily 
+ will access {{{otherData}}} after that, you will get an exception telling you that Hibernate failed to lazily
- initialize the collection. A classical Race Condition. 
+ initialize the collection. A classical Race Condition.
  
- Obviously that's no good. The solution is to move Hibernate session disposal out of the flowscript layer and even 
+ Obviously that's no good. The solution is to move Hibernate session disposal out of the flowscript layer and even
- out of cocoon. I.e., we will create a servlet filter. A servlet filer is invoked before the request is passed to cocoon 
+ out of cocoon. I.e., we will create a servlet filter. A servlet filer is invoked before the request is passed to cocoon
  and will be notified when the request is processed completely. At that point we can safely close the Hibernate session,
  given we will not continue to work with it from flowscript after the view pipeline has been invoked. However, invoking
  the view pipeline should be the last thing you do in a flow script anyway, so that won't be too much of a problem.
  
  === Creating the filter ===
  
- Our filter needs to communicate with cocoon. Unfortunately, this cannot be done via the Avalon framework. The most 
+ Our filter needs to communicate with cocoon. Unfortunately, this cannot be done via the Avalon framework. The most
- straightforward way to get around this limitation is using the request object. 
+ straightforward way to get around this limitation is using the request object.
  
  The example filter below will search the current request for an attribute called  {{{DisposeHibernateSession}}}. If found,
- it will try to cast the attribute value to a Hibernate Session, and close this session and the related 
+ it will try to cast the attribute value to a Hibernate Session, and close this session and the related
- JDBC connection if successful. 
+ JDBC connection if successful.
  
  Note that the session is always flushed before closing. Like this, you can be sure that any changes made to persistent
  objects are reflected in the database after the session has been closed. You might want to alter this behaviour later
- on. 
+ on.
  
  To compile the filter you need the following jars in your classpath:
  
   * hibernate2.jar
-  * servlet.jar (e.g. from the common/lib directory of a Tomcat distribution) 
+  * servlet.jar (e.g. from the common/lib directory of a Tomcat distribution)
  
  {{{
  package org.test;
@@ -453, +453 @@

  
    public void doFilter(ServletRequest request, ServletResponse response,
                       FilterChain chain) throws IOException, ServletException {
-     // Pass the request on to cocoon 
+     // Pass the request on to cocoon
      chain.doFilter(request, response);
-     
+ 
-     // After cocoon has finished processing, close the 
+     // After cocoon has finished processing, close the
-     // corresponding Hibernate session if it has been opened 
+     // corresponding Hibernate session if it has been opened
      if( request.getAttribute("DisposeHibernateSession") != null )
      {
       Session hs = (Session) request.getAttribute("DisposeHibernateSession");
@@ -481, +481 @@

  === Installing the filter ===
  
  In the file WEB-INF/web.xml, insert the following code avove the "Servlet Configuration" part: (as always, insert
- your favourite package name) 
+ your favourite package name)
  
  {{{
  <!-- Filter Configuration ========================================== -->
@@ -497, +497 @@

  </filter-mapping>
  }}}
  
- This tells the container to invoke our filter on all requests. That is OK since our filter 
+ This tells the container to invoke our filter on all requests. That is OK since our filter
- will only dispose sessions that have previously been opened. However, you might want to 
+ will only dispose sessions that have previously been opened. However, you might want to
  use the filter only on URLs that require the opening of a Hibernate session. In that case,
  modify the url-pattern accordingly. You may also define multiple filter mappings.
  
@@ -507, +507 @@

  Since the filter only cares for disposing open sessions, you still have to open them yourself
  using the {{{PersistenceFactory}}} class designed above. Also you need to make sure that every
  time a session is opened, it is correctly stored in the servlet request such that the
- filter will later close it. 
+ filter will later close it.
  
  It might be a good idea to create a
  little helper function for doing this. I like to have the session as a global variable since
  it is often used across functions during the processing of a pipeline. In the code snippet below,
  this variable is called {{{hs}}}. From cocoon 2.1.6 onwards, an Exception will be thrown if you
- do not explicitly declare this global variable. And oh, the package name ... :) 
+ do not explicitly declare this global variable. And oh, the package name ... :)
  
  {{{
- var hs; 
+ var hs;
  
  function openHibernateSession()
  {
  	// Make sure Hibernate Sessions are not opened twice
  	if(hs && hs.isOpen())
  		return;
- 		
+ 
  	// Get new Session from PersistenceFactory
- 	factory = cocoon.getComponent(Packages.org.test.PersistenceFactory.ROLE);
+ 	var factory = cocoon.getComponent(Packages.org.test.PersistenceFactory.ROLE);
  	hs = factory.createSession();
- 	if (hs == null) { 
+ 	if (hs == null) {
  		throw new Packages.org.apache.cocoon.ProcessingException("Hibernate session is null ");
  	}
- 	
+ 
  	// Release PersistenceFactory
  	cocoon.releaseComponent(factory);
- 	
+ 
  	// Send "Message" to HibernateFilter to dispose the session after the view was rendered
  	cocoon.request.setAttribute("DisposeHibernateSession",hs);
  }
  }}}
  
- After calling {{{openHibernateSession()}}}, you are finally ready to use the session for doing some 
+ After calling {{{openHibernateSession()}}}, you are finally ready to use the session for doing some
- Persistence. 
+ Persistence.
  
- Note: 
+ Note:
  Of course now you need to make sure that you manage a session (I.E. add the session action to your pipeline). If you will not add the session management, the filter will crash with "Cannot create a session after the response has been committed".
  
  === A first Example ===
  
- "Now that Hibernate is installed, how do I continue?" - Well the answer is up to you, since there are so many ways of using Hibernate. What follows is some kind of a minimal example so you get a feeling how Hibernate '''could''' interact with Cocoon. 
+ "Now that Hibernate is installed, how do I continue?" - Well the answer is up to you, since there are so many ways of using Hibernate. What follows is some kind of a minimal example so you get a feeling how Hibernate '''could''' interact with Cocoon.
  
- In this example we'll use Hibernate to manage a list of ISO language codes. So the first thing we need is a Java Bean that represents those language codes. Our bean will just have two attributes, the code and a name for each language, plus a numerical ID (I use one for each and every class). The code doesn't look all that interesting: 
+ In this example we'll use Hibernate to manage a list of ISO language codes. So the first thing we need is a Java Bean that represents those language codes. Our bean will just have two attributes, the code and a name for each language, plus a numerical ID (I use one for each and every class). The code doesn't look all that interesting:
  
  {{{
  package org.test;
@@ -559, +559 @@

  	private String IsoCode;
  	private String Name;
  	/**
- 	 * 
+ 	 *
  	 */
  	public DCLanguage() {
  		super();
@@ -604, +604 @@

  }
  }}}
  
- Compile this class and store it in the corresponding subfolder of WEB-INF/classes (Package name ...). 
+ Compile this class and store it in the corresponding subfolder of WEB-INF/classes (Package name ...).
- Next, we shall create a table in our database to store the objects in. 
+ Next, we shall create a table in our database to store the objects in.
  
  {{{
  CREATE TABLE `dclanguage` (
@@ -616, +616 @@

  )
  }}}
  
- Fill in some sample values, or use the following if you're too lazy: :) 
+ Fill in some sample values, or use the following if you're too lazy: :)
  
  {{{
   INSERT INTO `dclanguage` VALUES (1,'de','german');
@@ -627, +627 @@

   INSERT INTO `dclanguage` VALUES (6,'da','danish');
  }}}
  
- The glue between our POJO and the SQL table is the hibernate mapping definition. This is an XML file which should be called {{{DCLanguage.hbm.xml}}}, since our class is called {{{DCLanguage.class}}}. Create the file with the following content and put it into the subfolder of WEB-INF/classes where your DCLanguage class resides: 
+ The glue between our POJO and the SQL table is the hibernate mapping definition. This is an XML file which should be called {{{DCLanguage.hbm.xml}}}, since our class is called {{{DCLanguage.class}}}. Create the file with the following content and put it into the subfolder of WEB-INF/classes where your DCLanguage class resides:
  
  {{{
  <?xml version="1.0"?>
@@ -645, +645 @@

  </hibernate-mapping>
  }}}
  
- Attention, there is a catch: The {{{<generator class="native"/>}}} only works if your database is able to generate IDs automatically. (MySQl, for example, is). Refer to the Hibernate documentation if that does not hold in your case (HSQL?). 
+ Attention, there is a catch: The {{{<generator class="native"/>}}} only works if your database is able to generate IDs automatically. (MySQl, for example, is). Refer to the Hibernate documentation if that does not hold in your case (HSQL?).
  
- Note that Hibernate comes with some tools which can automatically generate Java and SQL source code from a mapping file. They only work up to a certain level of complexity, though. 
+ Note that Hibernate comes with some tools which can automatically generate Java and SQL source code from a mapping file. They only work up to a certain level of complexity, though.
  
+ One other thing to note: make sure that the DOCTYPE declaration is correct for the version of Hibernate which you are using. Hibernate3 will need this:
+ {{{
+ <!DOCTYPE hibernate-mapping PUBLIC
+       "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+       "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+ }}}
+ 
- Now you're almost done. Just insert the following statement: 
+ Now you're almost done. Just insert the following statement:
  
  {{{cfg.addClass(DCLanguage.class);}}}
  
- into the {{{HibernateFactory}}} (see ''ADD PERSISTENT CLASSES, VARIANT 1'' in the source code), recompile it, overwrite it in WEB-INF/classes and restart Cocoon. Congratulations, you should now be able to manage your ISO language codes via Hibernate and Cocoon :) 
+ into the {{{HibernateFactory}}} (see ''ADD PERSISTENT CLASSES, VARIANT 1'' in the source code), recompile it, overwrite it in WEB-INF/classes and restart Cocoon. Congratulations, you should now be able to manage your ISO language codes via Hibernate and Cocoon :)
  
- To verify this, create a testing sub-sitemap, attach a flowscript and insert the following function into it: 
+ To verify this, create a testing sub-sitemap, attach a flowscript and insert the following function into it:
  
  {{{
  function language_list()
  {
- 	openHibernateSession(); // as defined in Tutorial 
+ 	openHibernateSession(); // as defined in Tutorial
  
  	var languages = hs.find("from org.test.DCLanguage order by IsoCode asc");
  		// HQL String to get a list of all beans, ordered by their IsoCode
- 	
+ 
- 	cocoon.sendPage("language-list.jxt", { 
+ 	cocoon.sendPage("language-list.jxt", {
  		languages:languages
- 	}); // Send objects to the view layer (here: JX Template) 
+ 	}); // Send objects to the view layer (here: JX Template)
  
- 	// Hibernate Session will be closed automatically 
+ 	// Hibernate Session will be closed automatically
- 	// by the servlet filter 
+ 	// by the servlet filter
  }
  }}}
  
- Create the corresponding pipelines in your sitemap: 
+ Create the corresponding pipelines in your sitemap:
  
  {{{
  <map:match pattern="language-list.jxt">
- 	<map:generate type="jxt" src="documents/language-list.jxt"/>
+ 	<map:generate type="jx" src="documents/language-list.jxt"/>
  	<map:serialize type="xml"/>
  </map:match>
  
@@ -687, +694 @@

  </map:match>
  }}}
  
- And save the following as {{{documents/language-list.jxt}}} (relative to your sitemap): 
+ And save the following as {{{documents/language-list.jxt}}} (relative to your sitemap):
  
  {{{
  <?xml version="1.0" encoding="iso-8859-1"?>
@@ -698, +705 @@

  </languages>
  }}}
  
- Alas, you're done. Surf to "base-uri-of-your-sitemap"/language-list and contemplate the power of Cocoon and Hibernate :) 
+ Alas, you're done. Surf to "base-uri-of-your-sitemap"/language-list and contemplate the power of Cocoon and Hibernate :)
  
- As said before, this is a minimal example. Now you're ready to continue on your own, the Hibernate docs will be your friend. Note that this example does not represent the recommended way of doing things - particularly since your querying your objects from Flowscript. Many people will rather want to do this from a Data Access Object (DAO) written in Java. The next part of this tutorial will cover this. 
+ As said before, this is a minimal example. Now you're ready to continue on your own, the Hibernate docs will be your friend. Note that this example does not represent the recommended way of doing things - particularly since your querying your objects from Flowscript. Many people will rather want to do this from a Data Access Object (DAO) written in Java. The next part of this tutorial will cover this.
  
  == Appendix ==