Skip to main content

Using JPA with Rails on GlassFish and MySQL

Posted by vivekp on March 21, 2008 at 12:56 AM PDT

In my last post I mentioned that "...with Rails there are some known limitations, such as the ORM in Rails is not pluggable" by which I basically meant that you can't plug in another ORM and the Rails Model creation and db migration will not generate the correct code for another kind of ORM. The good news is that with little bit of coding you can reuse your entity classes. caroljmcdonald commented on my blog that Brian in his blog succssfully tried out JPA and Rails on WEBRick using JavaDB. So, in this blog I would go over what you would need to do to make JPA and Rails work on GlassFish v2.

Let's first try to understand how it is going to work: Rails by default uses ActiveRecords for Object Relational Mapping purposes or ORM. JPA is another ORM technique in JavaEE. Model class and database migration in Rails is what Entity class and persistence provider does for you in Java. Essentially In Java you just provide the Entity class and on the Rails side, you would provide the Model corresponding to the Entity class to do CRUD and that is pretty much it. The JPA provider does the rest.

This just means that to use Rails with JPA we simply do not use ActiveRecords - this means we don't create Model using Rails and we dont migrate the database. Just define your Entity class and code up the Rails Model without extending from ActiveRecord::Base.

Here is how I did it, which is basically few changes in Brian's sample and setting up GlassFish v2 with JRuby on Rails UC module.

Setup GlassFish v2 and NetBeans

  1. Install NetBeans 6.1 Beata with Web and Java EE profile.
  2. Follow these directions to install and setup JRuby on GlassFish v2.
  3. Setup JRuby jars as shared libraries on Glassfish


    cd $GLASSFISH_HOME/jruby
    $ant -f install.xml setup-shared-env
  4. Copy MySQL driver from your NetBeans installation:

    cp "C:\Program Files\NetBeans 6.1 Beta\ide9\modules\ext\mysql-connector-java-5.1.5-bin.jar" c:/tools/glassfish/lib
    or from here to $GLASSFISH_HOME/lib.
  5. Start MySQL server and create test database if not already there


    mysqladmin -u root create test;

Create Java Entity Beans with MySQL

First we create an entity class and a persistence unit.

  1. Create a new Java Application named Post. There's no need for a Main Class.
  2. Create a new Persistence Unit. Select jdbc:mysql://localhost:3306/test [root on Default Schema] as the database connection and the persistence unit name as PostPUclick Finish. This will generate src/META-INF/persistence.xml
  3. .

  4. Create a new Entity Class named Posts. Set the package name to entity.
  5. Add fields and accessors for title and body. Your completed class should look as follows:



    package entity;

    import java.io.Serializable;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;

    /**
    *
    * @author vivek
    */
    @Entity
    public class Posts implements Serializable {
        private static final long serialVersionUID = 1L;
        private Long id;
        private String title;
        private String body;

        public void setId(Long id) {
            this.id = id;
        }

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        public Long getId() {
            return id;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            hash += (id != null ? id.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object object) {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(object instanceof Posts)) {
                return false;
            }
            Posts other = (Posts) object;
            if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "entity.Post[id=" + id + "]";
        }
       
        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getBody() {
            return body;
        }

        public void setBody(String body) {
            this.body = body;
        }

    }
       
  6. Create Post.jar by clicking Build->Clean and Build Main Project or Shift+F11. This will create dist/Post.jar inside your project.
  7. Copy Post.jar to $GLASSFISH_HOME/lib directory. $GLASSFISH_HOME is where you installed GlassFish.
        cp dist/Post.jar c:/tools/glassfish/lib
       

Create the Rails Application

Simply download the Rails application then do the following:

cd $GLASSFISH_HOME/jruby/samples
unzip jpa_blog.zip
cd jpa_blog

Brian's sample Rails application was created using Rails 1.2.3 and GlassFish v2 JRuby module includes Rails version 1.2.6. So edit config/environment.rb and replace RAILS_GEM_VERSION = '1.2.3' with RAILS_GEM_VERSION = '1.2.6'.

The last thing you want to do is prepare this rails application for deployment over GlassFish v2:

[/c/tools/glassfish/jruby/samples/jpa_blog]
$ant -f ../../install.xml create-shared
Buildfile: ..\..\install.xml

create-shared:
    [mkdir] Created dir: c:\tools\glassfish\jruby\samples\jpa_blog\WEB-INF
     [copy] Copying 1 file to c:\tools\glassfish\jruby\samples\jpa_blog\WEB-INF

BUILD SUCCESSFUL
Total time: 0 seconds

Simply deploy your rails application on to GlassFish (if you have not started Glassfish during GlassFish setup, you should do it now):

[/c/tools/glassfish/jruby/samples/jpa_blog]
$cd ..
[/c/tools/glassfish/jruby/samples]
$../../bin/asadmin.bat deploy jpa_blog
Command deploy executed successfully.

In the GlassFish server.log you should see:

[#|2008-03-20T17:46:32.250-0700|INFO|sun-appserver9.1|javax.enterprise.system.to
ols.deployment|_ThreadID=20;_ThreadName=Thread-28;|deployed with moduleid = jpa_
blog|#]

[#|2008-03-20T17:46:33.531-0700|INFO|sun-appserver9.1|javax.enterprise.system.co
ntainer.web|_ThreadID=21;_ThreadName=ObjectPoolManager;|PWC1412: WebModule[/jpa_
blog] ServletContext.log():JRuby init time: 94ms|#]

[#|2008-03-20T17:46:39.296-0700|INFO|sun-appserver9.1|javax.enterprise.system.co
ntainer.web|_ThreadID=21;_ThreadName=ObjectPoolManager;|PWC1412: WebModule[/jpa_
blog] ServletContext.log():Rails init time: 5750ms|#]

[#|2008-03-20T17:46:39.296-0700|INFO|sun-appserver9.1|javax.enterprise.system.co
ntainer.web|_ThreadID=21;_ThreadName=ObjectPoolManager;|PWC1412: WebModule[/jpa_
blog] ServletContext.log():Runtime 0 loaded|#]

[#|2008-03-20T17:46:39.296-0700|INFO|sun-appserver9.1|javax.enterprise.system.co
ntainer.web|_ThreadID=21;_ThreadName=ObjectPoolManager;|PWC1412: WebModule[/jpa_
blog] ServletContext.log():Requests can now be processed|#]

Now, accessing http://localhost:8080/jpa_blog/blog/ should show you:



index.PNG

Create a new Blog entry:


new.png

See the list of all the blogs:



list.PNG

I wanted to try it out on Glassfish gem but JPA is under development in GlassFish v3 and I get exception coming form inside GlassFish v3 where it can't find the PersistenceProvider:

javax.persistence.PersistenceException: No resource files named META-INF/services/javax.persistence.spi.PersistenceProvider were found. Please make sure that the persistence provider jar file is in your classpath.

Mitesh is working on JPA support in Glassfish v3, I would do a follow-up blog for GlassFish gem as soon as I see it working.

You can get the Rails and Entity code using the following link:

Continue using JRuby on GlassFish and keep sending us feedback on GlassFish forums, dev@glassfish or gem mailing list. For the latest information about the gem and JRuby Update Center module can be found at GlassFish JRuby wiki.

Related Topics >>

Comments

Never mind, I got my answer from here: http://forum.java.sun.com/thread.jspa?forumID=13&threadID=5264219 which sent me here: http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Id... Thanks.

Hi, Nice article. Just one question on the generated value. If you have a relation like: A(fk_id)->B(id) where id is a generated value. When you save A(null)->b(null), how do you set the A.fk_id = B.id ? Thanks