X

Java EE 6 and NoSQL/MongoDB on GlassFish using JPA and EclipseLink 2.4 (TOTD #175)



href="https://blogs.oracle.com/arungupta/entry/totd_166_using_nosql_database">TOTD
#166 explained how to use MongoDB in your Java EE 6
applications. The code in that tip used the APIs exposed by the href="http://www.mongodb.org/display/DOCS/Java+Language+Center#JavaLanguageCenter-JavaDriver">MongoDB
Java driver and so requires you to learn a new API. However if
you are building Java EE 6 applications then you are already
familiar with Java Persistence API (JPA). href="http://wiki.eclipse.org/EclipseLink/Development/2.4.0">Eclipse
Link 2.4, scheduled to release as part of href="http://wiki.eclipse.org/Juno/Simultaneous_Release_Plan">Eclipse
Juno, provides support for href="http://wiki.eclipse.org/EclipseLink/Development/2.4.0">NoSQL
databases by mapping a JPA entity to a document. Their href="http://wiki.eclipse.org/EclipseLink/Examples/JPA/NoSQL">wiki
provides complete explanation of how the mapping is done.



This Tip style="font-weight: bold;">Of The Day
(TOTD) will show how you can leverage that support in your Java EE 6
applications deployed on href="http://glassfish.java.net/downloads/3.1.2-final.html">GlassFish
3.1.2.



Before we dig into the code, here are the key concepts ...
  • A POJO is mapped to a NoSQL data source using @NoSQL or
    <no-sql> element in "orm.xml".
  • A subset of JPQL and Criteria query are supported, based upon
    the underlying data store

  • Connection properties are defined in "persistence.xml"


Now, lets lets take a look at the code ...

  1. Download the latest href="http://www.eclipse.org/eclipselink/downloads/nightly.php">EclipseLink
    2.4 Nightly Bundle. There is a Installer, Source, and
    Bundle - make sure to download the Bundle link (href="http://www.eclipse.org/downloads/download.php?file=/rt/eclipselink/nightly/2.4.0/20120410/eclipselink-plugins-2.4.0.v20120410-r11137.zip">20120410)
    and unzip.
  2. Download href="http://download.java.net/glassfish/3.1.2/release/glassfish-3.1.2.zip">GlassFish
    3.1.2 zip and unzip.

  3. Install the Eclipse Link 2.4 JARs in GlassFish
    • Remove the following JARs from "glassfish/modules":
      org.eclipse.persistence.antlr.jar
      org.eclipse.persistence.asm.jar
      org.eclipse.persistence.core.jar
      org.eclipse.persistence.jpa.jar
      org.eclipse.persistence.jpa.modelgen.jar
      org.eclipse.persistence.moxy.jar
      org.eclipse.persistence.oracle.jar

    • Add the following JARs from Eclipse Link 2.4 nightly build
      to "glassfish/modules":
      org.eclipse.persistence.antlr_3.2.0.v201107111232.jar
      org.eclipse.persistence.asm_3.3.1.v201107111215.jar
      org.eclipse.persistence.core.jpql_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.core_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.jpa.jpql_2.0.0.v20120407-r11132.jar
      org.eclipse.persistence.jpa.modelgen_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.jpa_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.moxy_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.nosql_2.4.0.v20120407-r11132.jar
      org.eclipse.persistence.oracle_2.4.0.v20120407-r11132.jar

  4. Start MongoDB

    1. Download latest MongoDB
      from here
      (2.0.4 as of this writing).
    2. Create the default data directory for MongoDB as:
      sudo mkdir -p /data/db/
      sudo chown `id -u` /data/db

      Refer to href="http://www.mongodb.org/display/DOCS/Quickstart">Quickstart
      for more details.

    3. Start MongoDB as:
      arungup-mac:mongodb-osx-x86_64-2.0.4 <arungup> ->./bin/mongod
      ./bin/mongod --help for help and startup options
      Mon Apr  9 12:56:02 [initandlisten] MongoDB starting : pid=3124 port=27017 dbpath=/data/db/ 64-bit host=arungup-mac.local
      Mon Apr  9 12:56:02 [initandlisten] db version v2.0.4, pdfile version 4.5
      Mon Apr  9 12:56:02 [initandlisten] git version: 329f3c47fe8136c03392c8f0e548506cb21f8ebf
      Mon Apr  9 12:56:02 [initandlisten] build info: Darwin erh2.10gen.cc 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386 BOOST_LIB_VERSION=1_40
      Mon Apr  9 12:56:02 [initandlisten] options: {}
      Mon Apr  9 12:56:02 [initandlisten] journal dir=/data/db/journal
      Mon Apr  9 12:56:02 [initandlisten] recover : no journal files present, no recovery needed
      Mon Apr  9 12:56:02 [websvr] admin web console waiting for connections on port 28017
      Mon Apr  9 12:56:02 [initandlisten] waiting for connections on port 27017


  5. Check out the JPA/NoSQL sample from href="http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.nosql.mongo/">SVN
    repository. The complete source code built in this TOTD
    can be href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/e7f4ba87bd6b79fc6925e35eaa6234f2/totd175_javaee_nosql.zip">downloaded
    here.

  6. Create Java EE 6 web app

    1. Create a Java EE 6 Maven web app as:
      mvn archetype:generate
      -DarchetypeGroupId=org.codehaus.mojo.archetypes
      -DarchetypeArtifactId=webapp-javaee6
      -DgroupId=model -DartifactId=javaee-nosql
      -DarchetypeVersion=1.5 -DinteractiveMode=false

    2. Copy the model files from the checked out workspace to the
      generated project as:
      cd javaee-nosql
      cp -r ~/code/workspaces/org.eclipse.persistence.example.jpa.nosql.mongo/src/model src/main/java

    3. Copy "persistence.xml"
      mkdir src/main/resources
      cp -r ~/code/workspaces/org.eclipse.persistence.example.jpa.nosql.mongo/src/META-INF ./src/main/resources

    4. Add the following dependencies:
      <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.jpa</artifactId>
      <version>2.4.0-SNAPSHOT</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.nosql</artifactId>
      <version>2.4.0-SNAPSHOT</version>
      </dependency>
      <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongo-java-driver</artifactId>
      <version>2.7.3</version>
      </dependency>



      The first one is for the EclipseLink latest APIs, the second
      one is for EclipseLink/NoSQL support, and the last one is the
      MongoDB Java driver.



      And the following repository:
      <repositories>
      <repository>
      <id>EclipseLink Repo</id>
      <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
      <snapshots>
      <enabled>true</enabled>
      </snapshots>
      </repository> 
      </repositories>

    5. Copy the "Test.java" to the generated project:
      mkdir src/main/java/example
      cp -r ~/code/workspaces/org.eclipse.persistence.example.jpa.nosql.mongo/src/example/Test.java ./src/main/java/example/

      This file contains the source code to CRUD the JPA entity to
      MongoDB. This sample is explained in detail on href="http://wiki.eclipse.org/EclipseLink/Examples/JPA/NoSQL">EclipseLink
      wiki.

    6. Create a new Servlet in "example" directory as:
      package example;

      import java.io.IOException;
      import java.io.PrintWriter;
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      /**
      * @author Arun Gupta
      */
      @WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
      public class TestServlet extends HttpServlet {

      protected void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();
      try {
      out.println("<html>");
      out.println("<head>");
      out.println("<title>Servlet TestServlet</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<h1>Servlet TestServlet at " + request.getContextPath() + "</h1>");
      try {
      Test.main(null);
      } catch (Exception ex) {
      ex.printStackTrace();
      }
      out.println("</body>");
      out.println("</html>");
      } finally {
      out.close();
      }
      }

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

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


  7. Build the project and deploy it as:


    mvn clean package
    glassfish3/bin/asadmin deploy --force=true target/javaee-nosql-1.0-SNAPSHOT.war

  8. Accessing href="http://localhost:8080/javaee-nosql/TestServlet">http://localhost:8080/javaee-nosql/TestServlet
    shows the following messages in the server.log:

    connecting(EISLogin(
    platform=> MongoPlatform
    user name=> ""
    MongoConnectionSpec()
    ))

    . . .

    Connected:
    User:
    Database: 2.7  Version: 2.7

    . . .

    Executing MappedInteraction()
    spec => null
    properties => {mongo.collection=CUSTOMER, mongo.operation=INSERT}
    input => [DatabaseRecord(
    CUSTOMER._id => 4F848E2BDA0670307E2A8FA4
    CUSTOMER.NAME => AMCE)]

    . . .


    Data access result: [{TOTALCOST=757.0, ORDERLINES=[{DESCRIPTION=table,
    LINENUMBER=1, COST=300.0}, {DESCRIPTION=balls, LINENUMBER=2, COST=5.0},
    {DESCRIPTION=rackets, LINENUMBER=3, COST=15.0}, {DESCRIPTION=net,
    LINENUMBER=4, COST=2.0}, {DESCRIPTION=shipping, LINENUMBER=5,
    COST=80.0}, {DESCRIPTION=handling, LINENUMBER=6, COST=55.0},
    {DESCRIPTION=tax, LINENUMBER=7, COST=300.0}], SHIPPINGADDRESS=
    [{POSTALCODE=L5J1H7, PROVINCE=ON, COUNTRY=Canada, CITY=Ottawa,
    STREET=17 Jane St.}], VERSION=2, _id=4F848E2BDA0670307E2A8FA8,
    DESCRIPTION=Pingpong table, CUSTOMER__id=4F848E2BDA0670307E2A8FA7,
    BILLINGADDRESS=[{POSTALCODE=L5J1H8, PROVINCE=ON, COUNTRY=Canada,
    CITY=Ottawa, STREET=7 Bank St.}]}]



    You'll not see any output in the browser, just the output in the
    console. But the code can be easily modified to do so.

Once again, the complete Maven project can be href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/e7f4ba87bd6b79fc6925e35eaa6234f2/totd175_javaee_nosql.zip">downloaded
here.

Do you want to try accessing relational and non-relational (aka
NoSQL) databases in the same PU ?


Join the discussion

Comments ( 10 )
  • Bob Treacy Tuesday, May 22, 2012

    This is awesome! Just what I needed for a project at IQSS


  • Janko Friday, June 22, 2012

    Hi Arun, excellent description - many thanks ! There is an intriguing question at the end :

    "Do you want to try accessing relational and non-relational (aka NoSQL) databases in the same PU ?"

    That is a subject I would be really interested in, are you working on that article? :-)

    Many thanks

    Janko


  • Arun Gupta Friday, June 22, 2012

    Janko,

    Glad you liked it!

    This was on my list of TODOs and I know somebody else within the team was also looking at it. I've already pinged that person and will let you know if he responds back.


  • guest Friday, June 29, 2012

    This is great Arun. Thanks greatly for this example. I would really like to see an example for JEE6-mongo persistency with Jboss AS7


  • Bob Wednesday, July 18, 2012

    This example has motivated me to remove all the manual MongoDB interaction from my project! I have a question about how the EclipseLink dependency is handled. For the purpose of source/version control and installation simplicity, it is better for me to package all the project dependencies in the war. That way, if it is necessary to reproduce a deployment or troubleshoot an installation, there is no question about what jars have been installed in the customer's application server. Is there a way to get glassfish to correctly find and load EclipseLink without adding the jars directly to the glassfish/modules? Thanks!


  • Yue Wednesday, August 22, 2012

    Hi,Arun

    I am just begin doing mongodb. My project needs to be connect Mongodb with JPA,Eclipselink2.4, and run on glassfish.Beside I need to use JSF framework also.

    Now I just write about db and it come cross an question.

    When it run, it has this problem:

    Config: connecting(EISLogin(

    platform=> MongoPlatform

    user name=> ""

    MongoConnectionSpec()

    ))

    Grave: java.lang.NoClassDefFoundError: com/mongodb/ServerAddress

    I don't konw why, can you give me some advice?Thanks!


  • guest Wednesday, August 22, 2012

    Hi,Arun

    I am just begin doing mongodb. My project needs to be connect Mongodb with JPA,Eclipselink2.4, and run on glassfish.Beside I need to use JSF framework also.

    Now I just write about db and it come cross an question.

    When it run, it has this problem:

    Config: connecting(EISLogin(

    platform=> MongoPlatform

    user name=> ""

    MongoConnectionSpec()

    ))

    Grave: java.lang.NoClassDefFoundError: com/mongodb/ServerAddress

    I don't konw why, can you give me some advice?Thanks!


  • guest Sunday, September 2, 2012

    Want to handle your registered users in MongoDB?

    You might want to check out my Camofish module for Glassfish and MongoDB.

    More information here: http://4thex.com/products/camofish/camofish.xhtml


  • jmcollin92 Friday, February 15, 2013

    Before starting an important project with those technologies, you have to know that there is many limitations which makes the solution unusable in a professional way.

    EclipseLink nosql won't transform MongoDB to a relational DB. That's evident but you it means that you can't do JPQL like this :

    TypedQuery<AttachmentRequest> q = em.createQuery("Select ar from AttachmentRequest ar join ar.emitterAccount em where em.id=:emitterId", AttachmentRequest.class);

    Cf. http://www.eclipse.org/forums/index.php/t/453373/

    Other important point to notice is that nativeQuery are very limitated. You can only do findOne request. Find, aggregation does not work.

    Cf. http://www.eclipse.org/forums/index.php/m/1009524/#msg_1009524

    All this limitations makes the use of this technologies very frustating and inefficient.

    JM


  • Janko Tuesday, July 16, 2013

    Hi Arun,

    referring to my previous comment regarding relational and non-relational databases in the same PU, this has slipped a little off my radar but is back on now.

    Was wondering if have given this subject more thought or even have practical experience you could share.

    Many thanks

    Janko


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services