Miles to go …

August 12, 2009

TOTD #92: Session Failover for Rails applications running on GlassFish

Filed under: General — arungupta @ 3:00 am

The GlassFish High Availability allows to setup a cluster of GlassFish instances and achieve highly scalable architecture using in-memory session state replication. This cluster can be very easily created and tested using the “clusterjsp” sample bundled with GlassFish. Here are some clustering related entries published on this blog so far:

  • TOTD #84 shows how to setup Apache + mod_proxy balancer for Ruby-on-Rails load balancing
  • TOTD #81 shows how to use nginx to front end a cluster of GlassFish Gems
  • TOTD #69 explains how a GlassFish cluster can be front-ended using Sun Web Server and Load Balancer Plugin
  • TOTD #67 shows the same thing using Apache httpd + mod_jk

#67 & #69 uses a web application “clusterjsp” (bundled with GlassFish) that uses JSP to demonstrate in-memory session replication state replication. This blog creates a similar application “clusterrails” – this time using Ruby-on-Rails and deploy it on GlassFish v2.1.1. The idea is to demonstrate how Rails applications can leverage the in-memory session replication feature of GlassFish.

Rails applications can be easily deployed as a WAR file on GlassFish v2 as explained in TOTD #73. This blog will guide through the steps of creating the Controller and View to mimic “clusterjsp” and configuring the Rails application for session replication.

  1. Create a template Rails application and create/migrate the database. Add a Controller/View as:

    ~/samples/jruby/session >~/tools/jruby/bin/jruby script/generate controller home index
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
          exists  app/controllers/
          exists  app/helpers/
          create  app/views/home
          exists  test/functional/
          create  test/unit/helpers/
          create  app/controllers/home_controller.rb
          create  test/functional/home_controller_test.rb
          create  app/helpers/home_helper.rb
          create  test/unit/helpers/home_helper_test.rb
          create  app/views/home/index.html.erb

  2. Edit the controller in “app/controllers/home_controller.rb” and change the code to (explained below):
    class HomeController < ApplicationController
      include Java

      def index
        @server_served = servlet_request.get_server_name
        @port = servlet_request.get_server_port
        @instance = java.lang.System.get_property “com.sun.aas.instanceName”
        @server_executed = java.net.InetAddress.get_local_host().get_host_name()
        @ip = java.net.InetAddress.get_local_host().get_host_address
        @session_id = servlet_request.session.get_id
        @session_created = servlet_request.session.get_creation_time
        @session_last_accessed = servlet_request.session.get_last_accessed_time
        @session_inactive = servlet_request.session.get_max_inactive_interval

        if (params[:name] != nil)
          servlet_request.session[params[:name]] = params[:value]
        end

        @session_values = “”
        value_names = servlet_request.session.get_attribute_names
        unless (value_names.has_more_elements)
          @session_values = “<br>No parameter entered for this request”
        else
            @session_values << “<UL>”
            while (value_names.has_more_elements)
                param = value_names.next_element
                unless (param.starts_with?(“__”))
                  value = servlet_request.session.get_attribute(param)
                  @session_values << “<LI>” + param + ” = ” + value + “</LI>”
                end
            end
            @session_values << “</UL>”
        end

      end

      def adddata
        servlet_request.session.set_attribute(params[:name], params[:value])
        render :action => “index”
      end

      def cleardata
        servlet_request.session.invalidate
        render :action => “index”
      end
    end

    The “index” action initializes some instance variables using the “servlet_request” variable mapped from “javax.servlet.http.ServletRequest” class. The “servlet_request” provides access to different properties of the request received such as server name/port, host name/address and others. It also uses an application server specific property ”com.sun.aas.instanceName” to fetch the name of particular instance serving the request. In this blog we’ll create a cluster with 2 instances. The action then prints the servlet session attributes name/value pairs entered so far.

    The “adddata” action takes the name/value pair entered on the page and stores them in the servlet request. The “cleardata” action clears any data that is storied in the session.

  3. Edit the view in “app/views/home/index.html.erb” and change to (explained below):
    <h1>Home#index</h1>
    <p>Find me in app/views/home/index.html.erb</p>
    <B>HttpSession Information:</B>
    <UL>
    <LI>Served From Server:   <b><%= @server_served %></b></LI>
    <LI>Server Port Number:   <b><%= @port %></b></LI>
    <LI>Executed From Server: <b><%= @server_executed %></b></LI>
    <LI>Served From Server instance: <b><%= @instance %></b></LI>
    <LI>Executed Server IP Address: <b><%= @ip %></b></LI>
    <LI>Session ID:    <b><%=
    @session_id %></b></LI>
    <LI>Session Created:  <%= @session_created %></LI>
    <LI>Last Accessed:    <%= @session_last_accessed %></LI>
    <LI>Session will go inactive in  <b><%= @session_inactive %> seconds</b></LI>
    </UL>
    <BR>
    <% form_tag “/session/home/index” do %>
      <label for=”name”>Name of Session Attribute:</label>
      <%= text_field_tag :name, params[:name] %><br>

      <label for=”value”>Value of Session Attribute:</label>
      <%= text_field_tag :value, params[:value] %><br>

        <%= submit_tag “Add Session Data” %>
    <% end  %>
    <% form_tag “/session/home/cleardata” do %>
        <%= submit_tag “Clear Session Data” %>
    <% end %>
    <% form_tag “/session/home/index” do %>
        <%= submit_tag “Reload Page” %>
    <% end %>
    <BR>
    <B>Data retrieved from the HttpSession: </B>
    <%= @session_values %>

    The view dumps the property value retrieved from the servlet context in the action. Then it consists of some forms to enter the session name/value pairs, clear the session and reload the page. The application is now ready, lets configure it for WAR packaging.

  4. Generate a template “web.xml” and copy it to “config” directory as:
    ~/samples/jruby/session >~/tools/jruby/bin/jruby -S warble war:webxml
    mkdir -p tmp/war/WEB-INF
    ~/samples/jruby/session >cp tmp/war/WEB-INF/web.xml config/
    1. Edit “tmp/war/WEB-INF/web.xml” and change the first few lines from:

      <!DOCTYPE web-app PUBLIC
        “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”
        “http://java.sun.com/dtd/web-app_2_3.dtd”>
      <web-app>

      to

      <web-app version=”2.4″ xmlns=”http://java.sun.com/xml/ns/j2ee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”>

      This is required because the element to be added next is introduced in the Servlet 2.4 specification.

    2. Add the following element:
      <distributable/>

      as the first element, right after “<web-app>”. This element marks the web application to be distributable across multiple JVMs in a cluster.

  5. Generate and configure “warble/config.rb” as described in TOTD #87. This configuration is an important step otherwise you’ll encounter JRUBY-3789. Create a WAR file as:
    ~/samples/jruby/session >~/tools/jruby/bin/jruby -S warble
    mkdir -p tmp/war/WEB-INF/gems/specifications
    cp /Users/arungupta/tools/jruby-1.3.0/lib/ruby/gems/1.8/specifications/rails-2.3.2.gemspec tmp/war/WEB-INF/gems/specifications/rails-2.3.2.gemspec

    . . .

    mkdir -p tmp/war/WEB-INF
    cp config/web.xml tmp/war/WEB-INF
    jar cf session.war  -C tmp/war .

  6. Download latest GlassFish v2.1.1, install/configure GlassFish and create/configure/start a cluster using the script described here. Make sure to change the download location and filename in the script. This script creates a cluster “wines” with two instances – “cabernet” runing on the port 58080 and “merlot” running on the port 58081.
  7. Deploy the application using the command:
    ~/samples/jruby/session >asadmin deploy –target wines –port 5048 –availabilityenabled=true session.war

Now, the screenshots from the two instances are shown and explained below. The two (or more) instances are front-ended by a load balancer so none of this is typically visible to the user but it helps to understand.
Here is a snapshot of this application deployed on “cabernet”:

The instance name and the session id is highlighted in the red box. It also shows the time when the session was created in “Session Created” field.

And now the same application form “merlot”:

Notice, the session id exactly matches the one from the “cabernet” instance. Similarly “Session Created” matches but “Last Accessed” does not because the same session session is accessed from a different instance.

Lets enter some session data in the “cabernet” instance and click on “Add Session Data” button as shown below:

The session attribute is “aaa” and value is “111″. Also the “Last Accessed” time is updated. In the “merlot” page, click on the “Reload Page” button and the same session name/value pairs are retrieved as shown below:

Notice, the “Last Accessed” time is after the time showed in “cabernet” instance. The session information added in “cabernet” is automatically replicated to the “merlot” instance.

Now, lets add a new session name/value pair in “merlot” instance as shown below:

The “Last Accessed” is updated and the session name/value pair (“bbb”/”222″) is shown in the page. Click on “Reload page” in “cabernet” instance as shown below:

This time the session information added to “merlot” is replicated to “cabernet”.

So any
session information added in “cabernet” is replicated to “merlot” and vice versa.

Now, lets stop “cabernet” instance as shown below:

and click on “Reload Page” in “merlot” instance to see the following:

Even though one instance from which the session data was added is stopped, the replicating instance continues to serve both the session values.

As explained earlier, these two instances are front-ended by a load-balancer typically running at port 80. So the user makes a request to port 80 and the correct session values are served even if one of the instance goes down and there by providing in-memory session replication.

Please leave suggestions on other TOTD that you’d like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish clustering rubyonrails jruby highavailability loadbalancer

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 11, 2009

TOTD #91: Applying Java EE 6 “web-fragment.xml” to Apache Wicket – Deploy on GlassFish v3

Filed under: web2.0 — arungupta @ 4:00 am

“Extensibility” is a major theme of Java EE 6. This theme enables seamless pluggability of other popular Web frameworks with Java EE 6.

Before Java EE 6, these frameworks have to rely upon registering servlet listeners/filters in “web.xml” or some other similar mechanism to register the framework with the Web container. Thus your application and framework deployment descriptors are mixed together. As an application developer you need to figure out the magical descriptors of the framework that will make this registration.

What if you are using multiple frameworks ? Then “web.xml” need to have multiple of those listeners/servlets. So your deployment descriptor becomes daunting and maintenance nightmare even before any application deployment artifacts are added.

Instead you should focus on your application descriptors and let the framework developer provide the descriptors along with their jar file so that the registration is indeed magical.

For that, the Servlet 3.0 specification introduces “web module deployment descriptor fragment” (aka “web-fragment.xml”). The spec defines it as:

A web fragment is a logical partitioning of the web app in such a way that the frameworks being used within the web app can define all the artifacts without asking devlopers to edit or add information in the web.xml.

Basically, the framework configuration deployment descriptor can now be defined in “META-INF/web-fragment.xml” in the JAR file of the framework. The Web container picks up and use the configuration for registering the framework. The spec clearly defines the rules around ordering, duplicates and other complexities.

TOTD #86 explained how to get started with Apache Wicket on GlassFish. This Tip Of The Day (TOTD) explains how to leverage ”web-fragment.xml” to deploy a Wicket application on GlassFish v3. The basic concepts are also discussed here.

For the “Hello World” app discussed in TOTD #86, the generated “web.xml” looks like:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<web-app xmlns=”http://java.sun.com/xml/ns/j2ee”
         xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
         xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”
         version=”2.4″>

        <display-name>helloworld</display-name>

         <!– 
              There are three means to configure Wickets configuration mode and they are
              tested in the order given.
              1) A system property: -Dwicket.configuration
              2) servlet specific <init-param>
              3) context specific <context-param>
              The value might be either “development” (reloading when templates change)
              or “deployment”. If no configuration is found, “development” is the default.
        –>

        <filter>
                <filter-name>wicket.helloworld</filter-name>
                <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
                <init-param>
                        <param-name>applicationClassName</param-name>
                        <param-value>org.glassfish.samples.WicketApplication</param-value>
                </init-param>
        </filter>

 <filter-mapping>
  <filter-name>wicket.helloworld</filter-name>
        <url-pattern>/*</url-pattern>
 </filter-mapping>

</web-app>

This deployment descriptor defines a Servlet Filter (wicket.helloworld) that registers the Wicket framework with the Web container. The filter specifies an initialization parameter that specifies the class name of the Wicket application to be loaded. And it also contains some other information that is also relevant to the framework. None of this application is either required or specified by the application. And so that makes this fragment a suitable candidate for “web-fragment.xml”.

Here are the simple steps to make this change:

  1. Remove “src/main/webapp/WEB-INF/web.xml” because no application specific deployment descriptors are required.
  2. Include “wicket-quickstart-web-fragment.jar” in the “WEB-INF/lib” directory of your application by adding the following fragment in your “pom.xml”:
        <dependencies>

            . . .
            <!– web-fragment –>
            <dependency>
                <groupId>org.glassfish.extras</groupId>
                <artifactId>wicket-quickstart-web-fragment</artifactId>
                <version>1.0</version>
                <scope>runtime</scope>
            </dependency>
        </dependencies>

       . . .

        <repositories>
            <repository>
                <id>maven2-repository.dev.java.net</id>
                <name>Java.net Repository for Maven</name>
             &nbsp
    ;  <url>http://download.java.net/maven/2/</url>
            </repository>
        </repositories>

    This file contains only “META-INF/web-fragment.xml” with the following content:

    <web-fragment>
            <filter>
                    <filter-name>wicket.helloworld</filter-name>
                    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
                    <init-param>
                            <param-name>applicationClassName</param-name>
                            <param-value>org.glassfish.samples.WicketApplication</param-value>
                    </init-param>
            </filter>

            <filter-mapping>
                    <filter-name>wicket.helloworld</filter-name>
                    <url-pattern>/*</url-pattern>
            </filter-mapping>
    </web-fragment>

  3. Create the WAR file without “web.xml” by editing “pom.xml” and adding the following fragment:
          <plugins>
                . . .
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.1-beta-1</version>
                    <configuration>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
                . . .
          </plugins>

That’s it, now you can create a WAR file using “mvn package” and deploy this web application on GlassFish v3 latest promoted build (58 as of today) as explained in TOTD #86.

The updated WAR file structure looks like:

helloworld-1.0-SNAPSHOT
helloworld-1.0-SNAPSHOT/META-INF
helloworld-1.0-SNAPSHOT/WEB-INF
helloworld-1.0-SNAPSHOT/WEB-INF/classes
helloworld-1.0-SNAPSHOT/WEB-INF/classes/log4j.properties
helloworld-1.0-SNAPSHOT/WEB-INF/classes/org
helloworld-1.0-SNAPSHOT/WEB-INF/classes/org/glassfish
helloworld-1.0-SNAPSHOT/WEB-INF/classes/org/glassfish/samples
helloworld-1.0-SNAPSHOT/WEB-INF/classes/org/glassfish/samples/HomePage.class
helloworld-1.0-SNAPSHOT/WEB-INF/classes/org/glassfish/samples/HomePage.html
helloworld-1.0-SNAPSHOT/WEB-INF/classes/org/glassfish/samples/WicketApplication.class
helloworld-1.0-SNAPSHOT/WEB-INF/lib
helloworld-1.0-SNAPSHOT/WEB-INF/lib/log4j-1.2.14.jar
helloworld-1.0-SNAPSHOT/WEB-INF/lib/slf4j-api-1.4.2.jar
helloworld-1.0-SNAPSHOT/WEB-INF/lib/slf4j-log4j12-1.4.2.jar
helloworld-1.0-SNAPSHOT/WEB-INF/lib/wicket-1.4.0.jar
helloworld-1.0-SNAPSHOT/WEB-INF/lib/wicket-quickstart-web-fragment-1.0.jar

Notice, there is no “web.xml” and the additional “wicket-quickstart-web-fragment-1.0.jar” and everything works as is!

It would be nice if the next version of wicket-*.jar can include “META-INF/web-fragment.xml” then everything will work out-of-the-box :)

Here is a snapshot of the deployed application:

Are you deploying your Wicket applications on GlassFish ?

Technorati: totd glassfish v3 wicket javaee6 servlet web-fragment

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 10, 2009

“Miles to go” is 4 years old … yaay!

Filed under: General — arungupta @ 4:00 am

Last week (Aug 2 to be precise), this blog turned 4 years old.

All the way from Hello Blogsphere more than 4 years ago to multiple tips, screencasts, deep dive technical entries, fun stuff, running tips and lots more … I’ve thoroughly enjoyed publishing content on this blog. Hope you did too :)

Here are some comparable statistics with blogs.sun.com …

blogs.sun.com Miles to go …
Age 5 yrs, 4 months 4 years and 1 week
First Entry Apr 27, 2004 Aug 2, 2005
Total Entries 138248 944 (0.68%)
Total Comments 156060 3537 (2.26%)

Some “Miles to go …” analytics …

  • 732,251 visits and 984,877 page views since Jan 5, 2007 according to Google Analytics
  • 21,862 cities from 211 countries according to Google Analytics. Surprisingly (pleasant) London is far exceeding other cities :)
  • 837,889 visits since Jun 12, 2006 according to clustrmaps
  • 63.04% is organic search (58.37% from Google, 2.54% from Yahoo), 23.66% from referring sites, 13.2% is direct traffic
  • 50% of the visits come from Firefox, 38% from IE
  • 80% from Windows, 10.04% from Macintosh, 7.74% from Linux

From 3rd birthday

  • 287 blog entries & 1598 comments
  • Visitors from 12 new countries
  • 334,545 page visits & 427,352 page views

And here are some snapshots …

Visitors from all over the world …

Weekly page visits …

Here are the topics with more than 50 entries …

And now the complete tag cloud …
 

Now lets see if this blog ever reaches 1000th entry ;-)

Technorati: milestogo birthday

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 7, 2009

TOTD #91: Retrieve JSON libraries using Maven dependency: json-lib

Filed under: web2.0 — arungupta @ 3:00 am

So you need to include JSON libraries in your Maven project. The only option that seems to be currently available is using json-lib with the following dependencies:

        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.3</version>
            <classifier>jdk15</classifier>
        </dependency>

The APIs are based upon the original work done at json.org/java.

If you are using NetBeans for adding the Maven dependency then it nicely shows the different versions for the artifact as shown below:

The usage guide and samples at json-lib have lots of documentation to get you started. Don’t forget the package names are changed so “org.json.JSONObject” is ”net.sf.json.JSONObject” and similarly other classes.

Please leave suggestions on other TOTD (Tip Of The Day) that you’d like to see. A complete archive of all the tips is available here.

Technorati: json maven json-lib netbeans

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 6, 2009

TOTD #90: Migrating from Wicket 1.3.x to 1.4 – “Couldn’t load DiskPageStore index from file” error

Filed under: General — arungupta @ 3:00 am

Now that Apache Wicket 1.4 is available, migrating from previous versions is pretty straight forward.

Change the version in your POM file as:

<wicket.version>1.4.0</wicket.version>

And that’s it!

The complete dependency may look like:

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket</artifactId>
  <version>1.4.0</version>
</dependency>

or

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket</artifactId>
  <version>${wicket.version}</version>
</dependency>

You may encounter the following error:

2009-08-05 05:58:49.387::INFO:  No Transaction manager found – if your webapp requires one, please configure one.
ERROR – DiskPageStore              – Couldn’t load DiskPageStore index from file /Users/arungupta/workspaces/runner~subversion/wicket/runner/target/work/wicket.runner-filestore/DiskPageStoreIndex.
java.lang.ClassNotFoundException: org.apache.wicket.util.concurrent.ConcurrentHashMap
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:319)

At least I did :)

Fortunately the fix is simple and intuitive. Instead of running “mvn jetty:run”, invoke the command:

mvn clean jetty:run

Basically, “clean” will clean out references to older version of Wicket jars in your project and voila!

If you are deploying as WAR file, then bundle Wicket jars in WEB-INF/lib instead of copying them to the shared folder of your application server.

Other Wicket tips on this blog are available here. Specifically TOTD #86 shows how to get started with Apache Wicket on GlassFish.

Please leave suggestions on other TOTD (Tip Of The Day) that you’d like to see. A complete archive of all the tips is available here.

Technorati: wicket glassfish migration

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 5, 2009

TOTD #89: How to add pagination to an Apache Wicket application

Filed under: web2.0 — arungupta @ 1:00 am

TOTD #86 explained how to get started with deploying a Apache Wicket application on GlassFish. This Tip Of The Day (TOTD) will show how to add pagination to your Wicket application.

The blog entry “JPA/Hibernate and Wicket Repeating Views with Netbeans” Part 1 and 2 explain in detail how to create a CRUD application using NetBeans, JPA, Hibernate and Wicket. This blog uses the data created in TOTD #38 for the database table.

  1. After creating the JPA Controller, adding the IDataProvider and DataView implementations and hooking together, the application is available at “http://localhost:8080/helloworld” and looks like:

    As noticed in the output, all the states are listed in one page. The HTML markup looks like:

    <html>
        <head>
            <title>Wicket Quickstart Archetype Homepage</title>
        </head>
        <body>
            <strong>Wicket Quickstart Archetype Homepage</strong>
            <br/><br/>
            <span wicket:id=”message”>message will be here</span>
            <table>
                <tr>
                    <th>ID</th>
                    <th>Abbreviation</th>
                    <th>Name</th>
                </tr>
                <tr wicket:id=”rows”>
                    <td><span wicket:id=”id”>ID</span></td>
                    <td><span wicket:id=”abbrev”>Abbreviation</span></td>
                    <td><span wicket:id=”name”>Name</span></td>
                </tr>
            </table>

        </body>
    </html>

    The backing POJO looks like:

    package org.glassfish.samples;

    import java.util.Iterator;
    import org.apache.wicket.PageParameters;
    import org.apache.wicket.markup.html.basic.Label;
    import org.apache.wicket.markup.html.WebPage;
    import org.apache.wicket.markup.repeater.Item;
    import org.apache.wicket.markup.repeater.data.DataView;
    import org.apache.wicket.markup.repeater.data.IDataProvider;
    import org.apache.wicket.model.CompoundPropertyModel;
    import org.apache.wicket.model.IModel;
    import org.apache.wicket.model.LoadableDetachableModel;
    import org.glassfish.samples.controller.StatesJpaController;
    import org.glassfish.samples.model.States;

    /**
     * Homepage
     */
    public class HomePage extends WebPage {

        private static final long serialVersionUID = 1L;

        // TODO Add any page properties or variables here

        /**
         * Constructor that is invoked when page is invoked without a session.
         *
         * @param parameters
         *            Page parameters
         */
        public HomePage(final PageParameters parameters) {

            // Add the simplest type of label
            add(new Label(“message”, “If you see this message wicket is properly configured and running”));

            // TODO Add your page’s components here

                    // create a Data Provider
            IDataProvider statesProvider = new IDataProvider() {
                public Iterator iterator(int first, int count) {
                    StatesJpaController sc = new StatesJpaController();
                    return sc.findStatesEntities(count, first).iterator();
                }

                public int size() {
                    StatesJpaController sc = new StatesJpaController();
                    return sc.getStatesCount();
                }

                public IModel model(final Object object) {
                    return new LoadableDetachableModel() {
                        @Override
                        protected States load() {
                            return (States)object;
                        }
                    };
                }

                public void detach() {
                }
            };

            // TODO Add your page’s components here

          &nbsp
    ; DataView dataView = new DataView(“rows”, statesProvider) {

                @Override
                protected void populateItem(Item item) {
                    States state = (States)item.getModelObject();
                    item.setModel(new CompoundPropertyModel(state));
                    item.add(new Label(“id”));
                    item.add(new Label(“abbrev”));
                    item.add(new Label(“name”));
                }
            };

            add(dataView);
        }
    }

    and “persistence.xml” looks like:

    <?xml version=”1.0″ encoding=”UTF-8″?>
    <persistence version=”1.0″ xmlns=”http://java.sun.com/xml/ns/persistence” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd”>
      <persistence-unit name=”helloworld” transaction-type=”RESOURCE_LOCAL”>
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>org.glassfish.samples.model.States</class>
        <properties>
          <property name=”hibernate.connection.username” value=”app”/>
          <property name=”hibernate.connection.driver_class” value=”org.apache.derby.jdbc.ClientDriver”/>
          <property name=”hibernate.connection.password” value=”app”/>
          <property name=”hibernate.connection.url” value=”jdbc:derby://localhost:1527/sample”/>
        </properties>
      </persistence-unit>
    </persistence>
  2. Lets add pagination to this simple sample.
    1. In the POJO, change DataView constructor so that it looks like:

              DataView dataView = new DataView(“rows”, statesProvider, 5)

      where “5″ is the number of entries displayed per page. Alternatively you can also set the number of items per page by invoking:

      dataView.setItemsPerPage(5);

    2. In the HTML page, add the following right after “<table/>”:
      <span wicket:id=”pager”>message will be here</span><br>

      as the last line. This is the placeholder for pagination controls.

    3. In the POJO, add the following:
              PagingNavigator pager = new PagingNavigator(“pager”, dataView);
              add(pager);

      right after “add(dateView);”.

      The output now looks like:

      and clicking on “>” shows:

      And finally clicking on “>>” shows

      The information is now nicely split amongst multiple pages.

So just adding a pagination controls placeholder in the HTML and a corresponding configuration in DataView (in the backing POJO) did the trick for us.

Please leave suggestions on other TOTD (Tip Of The Day) that you’d like to see. A complete archive of all the tips is available here.

Technorati: wicket glassfish pagination

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 4, 2009

San Francisco Marathon 2009 Finishers Certificate & Pictures

Filed under: Running — arungupta @ 3:00 am

Here is my official San Francisco Half Marathon finishers certificate:

And here are some pics (credits marathonfoto.com):

$20 for a 8×10 photograph is expensive for me and I’m content with the smaller size pics :)

Technorati: running runsfm results sanfrancisco marathon

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

August 3, 2009

TOTD #88: How add pagination to Rails – will_paginate

Filed under: web2.0 — arungupta @ 3:00 am

This Tip Of The Day (TOTD) explains how to add pagination to your Rails application.

  1. Create a simple Rails scaffold as:

    ~/samples/jruby >~/tools/jruby/bin/jruby -S rails paginate
    ~/samples/jruby/paginate >~/tools/jruby/bin/jruby script/generate scaffold book title:string author:string
    ~/samples/jruby/paginate >sed s/’adapter: sqlite3′/’adapter: jdbcsqlite3′/ <config/database.yml >config/database.yml.new
    ~/samples/jruby/paginate >mv config/database.yml.new config/database.yml
    ~/samples/jruby/paginate >~/tools/jruby/bin/jruby -S rake db:migrate

  2. Edit “test/fixtures/books.yml” and specify the content as:
    # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

    one:
      title: Ultramarathon Man Confessions of an All-Night Runner
      author: Dean Karnazes

    two:
      title: My Life on the Run
      author: Bart Yasso

    three:
      title: 50/50 Secrets I Learned Running 50 Marathons in 50 Days
      author: Dean Karnazes

    four:
      title: Born to Run
      author: Christopher Mcdougall

    five:
      title: Four Months to a Four-hour Marathon
      author: Dave Kuehls

    six:
      title:  Galloway’s Book on Running
      author: Jeff Galloway

    seven:
      title: Marathoning for Mortals
      author: John Bingham and Jenny Hadfield

    eight:
      title:  Marathon You Can Do It!
      author: Jeff Galloway

    nine:
      title: Marathon The Ultimate Training Guide
      author: Hal Higdon

    ten:
      title: Running for Mortals
      author: John Bingham and Jenny Hadfield

    and load the fixtures as:

    ~/samples/jruby/paginate >~/tools/jruby/bin/jruby -S rake db:fixtures:load
    (in /Users/arungupta/samples/jruby/paginate)

  3. Run the application as:
    ~/samples/jruby/paginate >~/tools/jruby/bin/jruby -S glassfish -l
    Starting GlassFish server at: 129.145.132.8:3000 in development environment…
    Writing log messages to: /Users/arungupta/samples/jruby/paginate/log/development.log.

    . . .

    Jul 29, 2009 2:06:44 PM com.sun.grizzly.scripting.pool.DynamicPool$1 run
    INFO: New instance created in 7,488 milliseconds

    The application is accessible at “http://localhost:3000/books” and looks like:

    The page shows 10 rows, all in one page.

  4. Lets add pagination to this simple sample.
    1. Install will_paginate gem as:

      /tools/jruby >./bin/jruby -S gem install will_paginate
      JRuby limited openssl loaded. gem install jruby-openssl for full support.
      http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
      Successfully installed will_paginate-2.2.2
      1 gem installed
      Installing ri documentation for will_paginate-2.2.2…
      Installing RDoc documentation for will_paginate-2.2.2…

      There are other methods of installation as well.

    2. Edit “config/environment.rb” and add
      require “will_paginate”

      as the last line.

    3. Edit the “index” action in “app/controllers/books_controller.rb” as:
      @books = Book.paginate(:page => params[:page], :per_page => 5)
      #@books = Book.all

      “:per_page” specifies the number of items to be displayed in each page.

    4. In “app/views/books/index.html.erb”, add:
      <%= will_paginate @books %>

      right after “</table>”.

      The output now looks like:

      and clicking on “Next” shows:

      The information is nicely split amongst 2 pages.

An important point to remember is that will_paginate only adds pagination to your Rails app. You are still required to display all the values.

But essentially replacing “@books = Book.all” with “@books = Book.paginate(:page => params[:page], :per_page => 5)” in the Controller and adding
“<%= will_paginate @books %>” did the trick for us.

Clean and simple!

Please leave suggestions on other TOTD (Tip Of The Day) that you’d like to see. A complete archive of all the tips is available here.

Technorati: jruby rubyonrails glassfish pagination will_paginate

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
« Newer Posts

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress