Getting Hibernate3 to work in JDeveloper 10.1.3

31

Our company focuses mainly on Oracle related products. Our Java developers use JDeveloper in combination with JHeadstart to build web applications. But that doesn’t mean we’re not interested and involved in other technologies as well. We are investing lots of time into frameworks like Spring, Java Server Faces and Hibernate. In this article I will describe how I got Hibernate3 to work in Jdeveloper 10.1.3 and an Oracle 10g database.

In order to get Hibernate to work in JDeveloper, I followed these steps:

  1. Create a DataSource to use within my application
  2. Use the DataSource from within a JSP page
  3. Enable Hibernate on my project
  4. Configure Hibernate to query a table in my database using a servlet

1. Create a DataSource to use within my application
Creating a DataSource is quite simple. In JDeveloper, first open the Connections Navigator tab (select “View -> Connection Navigator” or press [CTRL-SHIFT-O]) and create a new database connection. In my case I used the OE schema on our local play-around database.
Then, select “Tools -> Embedded OC4J Server Preferences” and make sure the database connection is listed there. I chose to only use this connection in the current workspace. Since I named my database connection “oe” I have an entry called “jdev-connection-oe” in my Data Sources list.

The jdev-connection-oe database connection.

Inspecting the properties for this DataSource I notice the JNDI Name is “jdbc/oeDS”. If your connection doesn’t show up, click the [Refresh Now] button in the “Data Sources” section.

The Data Sources section with the Refresh button.

2. Use the DataSource from within a JSP page
For testing the DataSource I created a simple JSP page connecting to the DataSource and querying a table. Since I am using the OE schema I decided to query the CUSTOMERS table. First I created a new workspace in JDeveloper and created an empty project in this workspace. I then added a JSP page by right clicking the project name in the “Applications Navigator” and selecting “New…”. From the “New Gallery” window I opened “Web Tier” in the Category list and selected JSP. From the Items list I selected JSP and named it “index.jsp”. In the Tag Libraries section I selected “JSTL Core 1.1″ and “JSTL SQL 1.1″ and I then clicked [Finish]. This prepared my project for being a web application and made sure the needed SQL taglib is enabled on this project.
Next, I added code to query my DataSource. To do so, I selected “JSTL 1.1 SQL” in the “Components Palette” and clicked “Query”. In the “Enter Common Properties” section I entered the value “queryresults” for my variable and in the “Enter Advanced Properties” section I entered the value “jdbc/oeDS” (which is the JNDI name for my DataSource, remember?) for the DataSource. I also enetered “SELECT * FROM CUSTOMERS ORDER BY CUSTOMER_ID” as value for the “Sql” field.
In order to display the query results, I entered this code below the query statement:

<table border=1>
  <tr>
    <th>ID</th><th>First Name</th><th>Last Name</th>
  </tr>
  <c:forEach var="row" items="${queryresults.rows}">
    <tr>
      <td><c:out value="${row.CUSTOMER_ID}" /></td>
      <td><c:out value="${row.CUST_FIRST_NAME}" /></td>
      <td><c:out value="${row.CUST_LAST_NAME}" /></td>
    </tr>
  </c:forEach>
</table>

Finally, in order to make the DataSource available to the application, make sure to include this section in the web.xml file in the WEB-INF directory of the application:

<resource-ref>
  <res-ref-name>jdbc/oeDS
  <res-type>oracle.jdbc.driver.OracleDriver
  <res-auth>Container
</resource-ref>

Done! Upon running the project, I got to see this in my bowser:

The output of the JSP page.

3. Enable Hibernate on my project
Next I’d like to do the same thing using Hibernate. In order to be able to do that, I first have to prepare both my project and JDeveloper for Hibernate3.
Hibernate3 can be downloaded from this link. For preparing this article, I used Hibernate version 3.0.5. Simply download the .zip or .tar.gz file to your hard disk, unpack it and remember where you put it. One small pitfall of the JDeveloper 10.1.3 and Hibernate 3 combination, is the fact that Hibernate 3 uses slightly newer ASM and ANT jar files, which are not compatible with JDeveloper 10.1.3. Fortunately, for both there is a workaround.
In order to make the ASM jars that come with Hibernate3 work with JDeveloper 10.1.3, I went to the directory where JDeveloper was installed into. There is an asm.jar file hidden in the j2ee/home/lib directory. I replaced this jar file with the asm.jar file shipped with Hibernate3 to prevent the “java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit” error as described in this post from happening. After replacing this jar file, I restarted JDeveloper to be sure the new jar file was picked up.
Next I imported the hibernate3.jar and required third party jar files into my project. In order to do so, I right clicked my project again and selected “Project Properties…” again. In the Libraries section I clicked “Add Library…” and then “New…”. I chose a name for the new library (“Hibernate3″) and then clicked the “Add Entry…” button.
Next I browsed to the directory containing the hibernate3.jar file and selected it. After this I clicked the “Add Entry…” button again and went to the “lib” directory below the one containing the hibernate3.jar file. Here I selected “antlr-2.7.5H3.jar”, “asm.jar”, “cglib-2.1.jar”, “commons-collections-2.1.1.jar”, “commons-logging-1.0.4.jar”, “dom4j-1.6.jar” and “echache-1.1.jar”. Please note that the Hibernate documentation specifies Log4j to be an optional jar to be loaded. Doing so with JDeveloper 10.1.3 will generate an error when the OC4J server is started up, so don’t include this one. After having added the jar files, click [OK] and make sure the “Export” checkbox is checked. This will ensure the libraries will be available in the OC4J server.

Make sure the Export checkbox is checked!

4. Configure Hibernate to query a table in my database using a servlet
So, now I was able to create my Hibernate table mapping and use this in a servlet. Since I decided to query the CUSTOMERS table in the OE schema, I created a POJO called Customer.java which has private members for id, custFirstName and custLastName as well as getters and setters for these members. Next I created a configuration file called Customer.hbm.xml like this.
I right clicked the project and selected “New…”. I then expanded the “General” category and selected “XML”. In the “Items” section, I selected “XML Document”. I made sure it’s called “Customer.hbm.xml” and was put it the public_html/WEB-INF/classes directory. Since this directory didn’t exist yet, I created it. Please note this config file can be put anywhere, as long as the reference to it in the hibernate.cfg.xml file, which we will create in a moment, references it correctly. I just chose to put it there so I can keep all my Hibernate config files together. Next I made sure the contents of the “Customer.hbm.xml” file looks like this:

<?xml version="1.0"?>< !DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="nl.amis.wouter.hibernate.Customer" table="CUSTOMERS">
    <id name="id" type="int" column="Customer_Id">
      <generator class="native"/>
    </id>
    <property name="custFirstName" column="CUST_FIRST_NAME"/>
    <property name="custLastName" column="CUST_LAST_NAME"/>
  </class>
</hibernate-mapping>

Next I created the “hibernate.cfg.xml” file in the same way as the “Customer.hbm.xml” file (apart from specifying a different name of course) and made sure the contents were this:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.datasource">java:comp/env/jdbc/oeDS</property>
        <property name="show_sql">false</property>
        <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
        <property name="query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>

        <mapping resource="Customer.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Remember I told you there was a problem related to the versions of ANT being different between JDeveloper 10.1.3 and Hibernate3? This link tells you what is the cause of the problem. It also says to either make sure the Hibernate3 jar files are loaded before the BEA Weblogic (or in our case, the OC4J) jar files, or to use the Hibernate 2.1 query parser. Here you can find that setting the “hibernate.query.factory_class” to “org.hibernate.hql.classic.ClassicQueryTranslatorFactory” will tell Hibernate3 to use the Hibernate2.1 query parser, which solved the problem of the “ClassNotFoundException: org.hibernate.hql.ast.HqlToken” error I got. By the way, I found the link to this workaround here.

So, the last thing I had do now was to create a servlet that uses Hibernate to query my database and disply the results. Again I right clicked the project and selected “New…”. This time I expanded the “Web Tier” category and selected “Servlets”. In the “Items” section I selected “HTTP Servlet”. I named the servlet “HibernateServlet” and put it in the “nl.amis.wouter.servlets” package. I also selected the methods “doGet()” and “doPost()” to be created. I then specified no parameters to be taken into account but I did specify a name and a mapping for the servlet, which were “HibernateServlet” and “/hibernateservlet” respectively. I then clicked [Finish]. When I was done modifying the code, my servlet looked like this:

package nl.amis.wouter.servlets;

import java.util.Iterator;
import nl.amis.wouter.hibernate.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.PrintWriter;
import java.io.IOException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class HibernateServlet extends HttpServlet {
    SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        Query query = session.createQuery("select c from Customer as c");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head><title>HibernateServlet</title></head>");
        out.println("<body>");
        out.println("<table border=1>");
        out.println("<tr>");
        out.println("<th>ID</th><th>First Name</th><th>Last Name</th>");
        out.println("</tr>");
        for (Iterator it = query.iterate(); it.hasNext();) {
            Customer c = (Customer)it.next();
            out.println("<tr><td>" + c.getId() + "</td><td>" + c.getCustFirstName() + "</td><td>" + c.getCustLastName() + "</td></tr>");
        }
        out.println("</table>");
        tx.commit();
        session.close();

        out.println("</body></html>");
        out.close();
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
}

Upon starting the servlet by selecting it in the Code Editor and hitting the [F11] key, I saw this output appear in my browser window:

Output of the Hibernate3 enabled servlet.

Yes, it looks pretty much the same. As a matter of fact, the output IS the same. So, it works!

Please note this article only goes to prove it is possible to get Hibernate3 and JDeveloper 10.1.3 work together. I know my SQL code isn’t the most effective in the world (which is the first reason for me to want to use a mapping framework like Hibernate). Besides that, I am not sure what the effect of replacing the asm.jar file in JDeveloper will do in the long run. Finally, using the Hibernate2.1 query parser rather than the Hibernate3 version may very well mean some of the new Hibernate features may not work as expected. But it’s a start and I am happy about it :-)

Share.

About Author

31 Comments

  1. Hi there, I am trying to get this working in JDeveloper 11g but some of the above instructions don’t map exactly to that version.  Can anyone point me to material that will help with this?  Thanks.

  2. Alejandro Alves on

    Hi, I am trying to develop an application using hibernate, but it seems I am not able to create a build.xml file that works I have been looking at some manuals but it doesn´t seem to work. Everyone gives a solution, but they don´t work. Can you help me out? please…
    Regards

  3. I don’t know what’s changed in jdev, but I basically followed the main steps and _it_just_worked_. I didn’t futz with the asm.jar or the 2.1 query parser or anything. Also, I did my example by moving the query code into a separate facade-like class that returns a List, added a jsp:useBean tag to create an instance of the facade-like class, and then just added another c:foreach that sets the list as the items and then loops over them (ie. no raw servlet code required). And the hibernate generated table displays right under the sql tag generated table.

  4. Wouter van Reeven on

    Hi Mark,

    Thank you very much for your comments. I am aware of making OC4J load local classes and jars before classes and jars shipped with OC4J. Please be aware that on JDeveloper 10.1.2 setting this option in oc4j-config.xml is overwritten everytime JDeveloper is started. In one of our projects we ended up making this file readonly. This problem does not occur with JDeveloper 10.1.3.
    I will definately try loading local ASM jars out on JDeveloper 10.1.3 in an Hibernate3 context, cause I haven’t tried that. It certainly sounds like a better option than to completely replace the OC4J jars.

    Thanks, Wouter

  5. What I forgot to mention is, the problem describbed above is the case with the embedded version of oc4j.

  6. As I was reading your article I notice the work around for ASM and ant jar files. This reminded me of a fundamental problem that I am experiencing with jdevelopers oc4j.

    I ran in to a problem with jdevelopers embedded OC4J container when using web service libraries such as wsdl4j, saaj, jax-rpc.

    With the code that I am currently writing, for example I used wsdl4j from Axis:

    import javax.wsdl.factory.WSDLFactory;
    import javax.wsdl.xml.WSDLReader;

    WSDLFactory wsdlFactory = WSDLFactory.newInstance();
    WSDLReader reader = wsdlFactory.newWSDLReader();

    As this code runs normal in the jvm, it didn’t work any more ones I had deployed to oc4j and ran it from a servlet.

    When I started the debugger, I noticed that the ‘reader’ variable in the code example above, was of type oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl instead of type javax.wsdl.xml.WSDLReader.

    Apparently oc4j’s class-loader can’t resolve the wsdl4j.jar and uses the standard webservice jar files that are contained in the Oracle JAX-RPC CLIENT library that come with the jdeveloper installation. If I am not mistaken these are located at …\jdev1013\webservices\lib\ .

    I also notices that in this lib directory oracle contains jar files for saaj, jax-rpc ect.

    Does this mean you are tied down to using the oracle implementation’s of these components, or is there a way to use libraries of your chosing ?

    If not I have a huge problem, either I refactor my code to work with the oracle libraries or I abandon jdeveloper completely.

    Without being able to deploy my own jar files to oc4j, jdeveloper is of no use to me.. unfortunately because until now I found it a great tool.

  7. Wouter van Reeven on

    Hi Hank,

    I have no experience with C3PO. Also, I have never tried to let OC4J manage a SessionFactory for Hibernate, or any other JDBC framework for that matter. Sorry but I cannot be of any help here.

    Greets, Wouter

  8. I see that you are managing the connection pooling through the oc4j container. We are using C3P0 for this. However, as we deploy to production, we probably should let the container manage the connection pool, so thanks for the help. Do you have any thoughts on C3P0 vs. oc4j managed data sources?

    Another question…Is it possible to let the oc4j container manage the SessionFactory through JNDI? Not just the connection pool, but the entire factory. I’m concerned about running out of of Hibernate sessions in a high traffic website.

    Thanks again. Any comments would be appreciated.

  9. Wouter van Reeven on

    OK sorry, the tags don’t show. Sorry about that. Here’s another attempt:

    <servlet>
    <servlet-name>Hibernate Servlet</servlet-name>
    <servlet-class>vacation.servlets.HibernateServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>Hibernate Servlet</servlet-name>
    <url-pattern>*</url-pattern>
    </servlet-mapping>

  10. Wouter van Reeven on

    Hi Ash,

    If you create a servlet you need to add a reference to it in the web.xml file in the WEB-INF directory in your app. It would look something like this (hoping the XML tags show correctly) :

    Hibernate Servlet
    vacation.servlets.HibernateServlet
    1

    Hibernate Servlet
    *

    I guess you have done that. The servlet doesn’t need to be in a jar though.

    HTH, Wouter

  11. Hi Wouter, I’ve got the above problems corrected, and now have created a servlet in
    my own package: vacation.servlets

    However when I run the application, I now get this error:

    500 Internal Server Error

    Servlet error: Error instantiating servlet ‘HibernateServlet’. Servlet class vacation.servlets.HibernateServlet not found in web-application HibernateWS-AnotherProject-webapp

    Would you know why the project can’t file the servlet? When I look at the project directory, there is a classes
    folder with the package hierarchy and compiled servlet. However, there are no .jar files created, and
    I believe that the application is not finding the compiled class files on its classpath.

  12. Wouter van Reeven on

    This seems to be ok. Did you try to rename the connection to start with a lowercase v? I recall having had a problem with uppercase connection names.

    Wouter

  13. Hi Wouter,

    Thanks so much for your quick reply — I’ve been working on this for about 8 hours.

    Verbatim copy of what is in my web.xml file:

    jdbc/VacationTestDS
    oracle.jdbc.driver.OracleDriver
    Container

  14. Wouter van Reeven on

    Hi Ash,

    Can you please check and verify that your web.xml really does contain the correct settings? I noticed that the settings are WRONG in the article. Every tag, e.g. the tag with name “res-ref-name” and value “jdbc/oeDS” should have a closing tag as well. If they are missing, please add them and try again.

    HTH, Wouter

  15. Hi Wouter,

    I’ve been trying to get started with your Hibernate tutorial; but I can’t get past
    the first few steps.

    I’ve created a database connection named VacationTest – which is an oracle 8i db.
    I can expand it under Connections and traverse the tables.

    I’ve added a query to my index.jsp page using VacationTestDB and added it also to the web.xml file.
    I can see the Data Sources in the OC4J server preferences under the workspace.

    When I run the application however, oc4j returns this message:
    WARNING J2EE JNDI0002 Resource reference jdbc/VacationTestDS not found. Allowing J2EEContext creation to continue anyway.

    The workspace-data-source.xml has the correct details – and jdbc/VacationTestDB
    is present.

    Do you have any ideas?

  16. Wouter van Reeven on

    Hi Alex,

    In our email conversation you told me to replace the antlr jar file shipped with JDeveloper/OC4J with the Hibernate one and try again. I ran into this same issue while writing this article and I’m sorry I didn’tr mention it here. Thanks for pointing it out to me though!

    Greets, Wouter

  17. Hi Wouter,

    Pleased to read your interesting article, helped me to workaround the ast.HqlToken error. Instead of it,
    i get now a funny error when i’m playing with Hibernate. if I ever try a Hql query such as “from Cats where kitten.color = ‘black’”, kitten as a set of cat, i get an illegal query exception !! Seems that the deep-in query skill is not included with the classic hql parser. I’m trying to fix it putting the antlr library in the oc4j classpath, if it’s possible. Any suggestions ? Am I going by the narrow path ? Any easier solution ?

    Thanks a lot !!!

  18. Hi Eduardo,

    I am glad my article was of help to you and anybody else who appreciated it. Unfortunately, I am not aware of any Hibernate mapping tools for JDeveloper. If you, or anyone else, would ever find out, please let me know!

    Thanks, Wouter

  19. This is a very nice article and answers many Hibernate/JDeveloper integration questions…

    I have one question though. Is there any tool to help Hibernate mapping in JDeveloper. I know Hibernate Tools can be used with Eclipse and
    TopLink has the nicest tool in JDeveloper. I wonder if there’s a tool like this to help Hibernate/JDeveloper…

    Thanks

  20. I have tried using Hibernate for the first time and I was successful and thanks a lot for the same.
    I had a small problem while adding the Hibernate Library. I had selected the directory where the Hibernate.jar was present and then selected the specified jar files from the lib folder. But still the Hibernate.jar was not available and it was throwing compilation errors and I had to add the Hibernate.jar once again ( instead of the directory ) and overcame the problem.

    Best Regards
    Ashok

  21. Thanks a lot for this article. I was suffering from the asm.jar issue and your workaround has been very apreciated!

    Best regards.

  22. Thanks a lot. I overcame the ClassNotFoundException: org.hibernate.hql.ast.HqlToken after rading this article.

  23. Wouter van Reeven on

    Thanks a lot for pointing me to this link. As a matter of fact, I already have seen it and followed the instructions in it to get Hibernate to work with JDeveloper. Unfortunately, the tutorial leads to enabling Hibernate2.1 and I wanted to have Hibernate3.