Facing new challenges everyday

Creating JSF applications with JRuby and ActiveRecord-JDBC (Part 2)

March 16th, 2008

My last article about this topic showed how can we start the development of an JSF webapp with JRuby and ActiveRecord-JDBC, we will discuss on this article how can we create the dao, domain class and the view used to show costumer data.

In this example, CostumerDao illustrate how can we perform some data persistence/retrieval using ActiveRecord domain classes, we defined MyCostumer JRuby class to act as a proxy of our domain class:

CostumerDao.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#The line bellow allow to use some special
#statements for ruby -> java integration.
require 'java'  

#Importing Costumer domain class
require 'br/eti/faces/jruby/model/Costumer'

#Importing MyCostumer proxy class of Costumer class
require 'br/eti/faces/jruby/model/proxy/MyCostumer'

#Importing ICostumerDao java interface.
include_class 'br.eti.faces.jruby.dao.ICostumerDao'

#This class will be instantiated by Spring and
#injected as dependency on CostumerPage class.
class CostumerDao
    include ICostumerDao
   
    def add(name, address, country)
        #We are instantiating a domain class
        #to save using ActiveRecord-JDBC
        costumer = Costumer.new
        costumer.name = name
        costumer.address = address
        costumer.country = country
        costumer.save  
    end
   
    def getCostumers
        #This list will hold some proxy instances
        #of Costumer domain class.
        list = ArrayList.new

        Costumer.find(:all).each { | costumer |
          myCostumer = MyCostumer.new costumer
          list.add myCostumer
        }      

        return list    
    end
end

Click here download the Java interface of the class above.

Costumer is the domain class used by CostumerDao, this class will be handled by ActiveRecord-JDBC adding ORM capabilities to this application.

Costumer.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#Importing jrubygems, this class allow
#to use/load gems that are on gems/
#directory of classpath.
require 'jrubygems'

#Loading ActiveRecord-JDBC gems. We
#will use hsqldb adapter in this
#example.
gem 'jdbc-hsqldb'
gem 'activesupport'
gem 'activerecord'
gem 'activerecord-jdbc-adapter'
gem 'activerecord-jdbchsqldb-adapter'
require 'jdbc_adapter'
require 'active_record'

#The method below configures a database
#connection to be used by ActiveRecord-JDBC
#classes.
ActiveRecord::Base.establish_connection(  
   :adapter  => 'jdbchsqldb',  
   :username => 'sa',
   :driver   => 'org.hsqldb.jdbcDriver',
   :url      => 'jdbc:hsqldb:file:c:/temp/db/data.db')  

#Each domain class must extend ActiveRecord::Base
class Costumer < ActiveRecord::Base

end

Now we must create MyCostumer class, each MyCostumer instace holds one Costumer instance, we can’t access Costumer instances directly from JSF because ActiveRecord doesn’t allow Java interfaces on domain classes.

MyCostumer.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#The line bellow allow to use some special
#statements for ruby -> java integration.
require 'java'  

#Importing ArrayList class.
include_class 'java.util.ArrayList'

#Importing IMyCostumer java interface.
include_class 'br.eti.faces.jruby.model.proxy.IMyCostumer'

#This class implements IMyCostumer interface
#to allow integration with Spring and Java.

#Spring creates a proxy class of this Ruby
#class at runtime based on Java interface
#that this class implements.
class MyCostumer
    include IMyCostumer

    @name = ''
    @address = ''
    @country = ''  
   
    def initialize(costumer)
        @name = costumer.name
        @address = costumer.address
        @country = costumer.country
    end
   
    def getName
        @name
    end

    def getAddress
        @address
    end

    def getCountry
        @country
    end
end

You must click here to download the source code of IMyCostumer Java interface of MyCostumer JRuby class.

And now the view used to enter costumer data and display a list of costumers:

home.jsp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<%@ page session="false"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
    <head>
    </head>
    <body>
        <f:view>
            <h:form>
                <center>
            <h:panelGrid columns="2">
        <h:outputLabel
                           for="enterName" value="Name:"/>
        <h:inputText id="enterName"
                           value="#{costumerPage.name}"/>
   
        <h:outputLabel for="enterAddress"
                           value="Address:"/>
        <h:inputText id="enterAddress"
                           value="#{costumerPage.address}"/>
   
         <h:outputLabel for="enterCountry"
                           value="Country:"/>
         <h:inputText id="enterCountry"
                           value="#{costumerPage.country}"/>
             </h:panelGrid>    
             <h:commandButton value="Save"
                         action="#{costumerPage.save}"/>
             <br/>
             <h:dataTable value="#{costumerPage.costumers}"
                         var="costumer">
                 <h:column>
                    <f:facet name="header">
                       <h:outputText value="Name"/>
                    </f:facet>
                    <h:outputText value="#{costumer.name}"/>
                 </h:column>
                 <h:column>
                    <f:facet name="header">
                        <h:outputText value="Address"/>
                    </f:facet>
                    <h:outputText value="#{costumer.address}"/>
                 </h:column>
                 <h:column>
                    <f:facet name="header">
                        <h:outputText value="Country"/>
                    </f:facet>
                    <h:outputText value="#{costumer.country}"/>
                 </h:column>
             </h:dataTable>
          </center>        
            </h:form>
        </f:view>
    </body>
</html>
Share

6 Comments »

  1. Rafael Ponte says

    Wow! Excelent Rogerio!

    However, i still am thinking too hard to work this way. Maybe the integration between JSF and dynamic languages might become best soon.

    Finally, continue writting posts like this, i believe that soon you will get a best solution to integrate JSF and JRuby.

    Do you know to say if it released the materials of the JSFDay about JSF e dynamic languages?

    March 17th, 2008 | #

  2. Joeri says

    Hey,

    I don\\\’t have any experience with jruby and using Java classes from within Ruby, I just do pure Rails development
    but usually things like this:

    def getCostumers
    list = ArrayList.new

    Costumer.find(:all).each { | costumer |
    myCostumer = MyCostumer.new costumer
    list.add myCostumer
    }

    return list
    end

    are much shorter. For example, if we needed just a Ruby array, we could do it this way:

    def getCostumers
    Costumer.find(:all).collect{ | costumer | MyCostumer.new(costumer) }
    end

    this method returns an instance of Ruby Array (which is closer to ArrayList than to Java arrays). Return is not necessary, and methods like select, collect, ad reject are cool

    March 18th, 2008 | #

  3. Dinko says

    Hi Rogerio,

    You might want to know that in your MyCostumer class @name from the class (@name = \\\’\\\’) is not the same as @name instance variable from the methods getName and setName. To see the difference add static method like this:

    def MyCostumer.other_name
    @name
    end

    then check the values:

    costumer = MyCostumer.new()
    costumer.setName(\\

    March 19th, 2008 | #

  4. Dinko says

    Hm, it seems part of my post didn’t get through. Anyway, just set the name, than print it (puts costumer.getName) and than compare it with other_name (puts MyCostumer.other_name).

    March 19th, 2008 | #

  5. Kito D. Mann says

    Rafael, the JSFDays presentation is available here: http://conference.irian.at/conference/main/schedule.jsf?conversationContext=1#sess_9. It doesn’t cover active record, though. Just some integration scenarios.

    March 21st, 2008 | #

  6. rogerio says

    I checked the Kito presentation and it’s pretty similar to my approach but this article is only based on spring docs. In the end the Kito presentation and this article gives some ideas about the possibilities of web development using jsf.

    March 23rd, 2008 | #

Leave a comment

:mrgreen: :neutral: :twisted: :shock: :smile: :???: :cool: :evil: :grin: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad:

 

RSS feed for these comments. | TrackBack URI

Visitors Around the World

Polls

How Is My Site?

View Results

Loading ... Loading ...

Categories

Meta

Links

Advertising

hosted by easy2use.net