Arun Gupta, Miles to go ...

Arun Gupta is a technology enthusiast, a passionate runner, and a community guy who works for Sun Microsystems.
« Previous page | Main | Next page »

http://blogs.sun.com/arungupta/date/20090904 Friday September 04, 2009

TOTD #101: Applying Servlet 3.0/Java EE 6 “web-fragment.xml” to Lift – Deploy on GlassFish v3

TOTD #100 explained how to deploy Lift framework applications on GlassFish v3. As explained in TOTD #91, Java EE 6 defines how the framework configuration deployment descriptor can be defined in “META-INF/web-fragment.xml” in the JAR file of the framework instead of mixing it with "WEB-INF/web.xml" which is intended for application deployment descriptor aspects.

This Tip Of The Day (TOTD) explains how to leverage ”web-fragment.xml” to deploy a Lift application on a Java EE 6 compliant container. The original "lift-*.jar" files are untouched and instead a new JAR file is included that contains only the framework configuration deployment descriptor.

The generated "web.xml" from TOTD #100 looks like:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!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>
<filter>
 <filter-name>LiftFilter</filter-name>
 <display-name>Lift Filter</display-name>
 <description>The Filter that intercepts lift calls</description>
 <filter-class>net.liftweb.http.LiftFilter</filter-class>
</filter>
 

<filter-mapping>
 <filter-name>LiftFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

The deployment descriptor defines a Servlet Filter (LiftFilter) that registers the Lift framework with the Web container. And then it defines a URL mapping to "/*". All of this information is required by the Lift framework for request dispatching. And so that makes this fragment suitable for "web-fragment.xml".

Here are 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 “lift-web-fragment.jar” in the “WEB-INF/lib” of your application by adding the following fragment in your “pom.xml”:
    <dependencies>
            
    . . .
    
      <!– web-fragment –>
      <dependency>
        <groupId>org.glassfish.extras</groupId>
        <artifactId>lift-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>
        <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>LiftFilter</filter-name>
     <display-name>Lift Filter</display-name>
     <description>The Filter that intercepts lift calls</description>
     <filter-class>net.liftweb.http.LiftFilter</filter-class>
     </filter>
     
    
     <filter-mapping>
     <filter-name>LiftFilter</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:
    <build>
       . . .
      <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>
    </build>
    

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

Technorati: totd glassfish v3 lift scala javaee6 servlet web-fragment

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090903 Thursday September 03, 2009

TOTD #100: Getting Started with Scala Lift on GlassFish v3

Yaaay, 100th tip! Read earlier tips here.

Scala is a strongly typed JVM language that provides benefits of functional programming and dynamic languages on the JVM. As a result you get flexibility of language such as Ruby and performance of Java. Lift is an MVC-based Web framework, based on Scala, that claims to pick the best of Rails (ease of development), Seaside (highly granular sessions and security), Django (access control), and Wicket (designer-friendly templating system).

Lift applications can run inside any Java application server. GlassFish v3 can run Rails and Django applications natively and can also run Wicket applications. This Tip Of The Day (TOTD) explains how to get started with Lift applications and run inside GlassFish v3.

  1. Create a new Lift project using Maven as shown:

    ~/samples/v3/lift >mvn archetype:generate -U -DarchetypeGroupId=net.liftweb 
    -DarchetypeArtifactId=lift-archetype-blank -DarchetypeVersion=1.0 
    -DremoteRepositories=http://scala-tools.org/repo-releases 
    -DgroupId=demo.helloworld -DartifactId=helloworld 
    -Dversion=1.0-SNAPSHOT
     [INFO] Scanning for projects...
     [INFO] Searching repository for plugin with prefix: 'archetype'.
     [INFO] org.apache.maven.plugins: checking for updates from central
    
     . . .
    
     [INFO] ------------------------------------------------------------------------
     [INFO] BUILD SUCCESSFUL
     [INFO] ------------------------------------------------------------------------
     [INFO] Total time: 14 seconds
     [INFO] Finished at: Tue Sep 01 16:11:34 PDT 2009
     [INFO] Final Memory: 12M/80M
     [INFO] ------------------------------------------------------------------------
    


    This creates a directory "helloworld" which looks like:

    ~/samples/v3/lift/helloworld >find .
    .
    ./pom.xml
    ./src
    ./src/main
    ./src/main/resources
    ./src/main/scala
    ./src/main/scala/bootstrap
    ./src/main/scala/bootstrap/liftweb
    ./src/main/scala/bootstrap/liftweb/Boot.scala
    ./src/main/scala/demo
    ./src/main/scala/demo/helloworld
    ./src/main/scala/demo/helloworld/comet
    ./src/main/scala/demo/helloworld/comet/.keep
    ./src/main/scala/demo/helloworld/model
    ./src/main/scala/demo/helloworld/model/.keep
    ./src/main/scala/demo/helloworld/snippet
    ./src/main/scala/demo/helloworld/snippet/.keep 
    ./src/main/scala/demo/helloworld/snippet/HelloWorld.scala
    ./src/main/scala/demo/helloworld/view
    ./src/main/scala/demo/helloworld/view/.keep
    ./src/main/webapp
    ./src/main/webapp/index.html
    ./src/main/webapp/templates-hidden
    ./src/main/webapp/templates-hidden/default.html
    ./src/main/webapp/WEB-INF
    ./src/main/webapp/WEB-INF/web.xml
    ./src/test
    ./src/test/resources
    ./src/test/scala
    ./src/test/scala/demo
    ./src/test/scala/demo/helloworld
    ./src/test/scala/demo/helloworld/AppTest.scala
    ./src/test/scala/LiftConsole.scala
    ./src/test/scala/RunWebApp.scala
    


    In this directory, "src/main/scala" contains Scala source code, "src/main/webapp" contains the HTML and other related artifacts, and "src/test/scala" contains a simple test case to test the generated application. The "demo/helloworld/model" directory is used for models, "demo/helloworld/snippet" for controller, and "demo/helloworld/view" for views. The Lift Getting Started Guide provides a detailed explanation of how the different components work together to provide the end result.
  2. Create a WAR file of the application as:
    ~/samples/v3/lift/helloworld >mvn package [INFO] Scanning for projects...
     [INFO] ------------------------------------------------------------------------
     [INFO] Building helloworld
     [INFO] task-segment: [package]
     [INFO] ------------------------------------------------------------------------
     [INFO] artifact org.scala-tools:maven-scala-plugin: checking for updates from scala-tools.org
     [INFO] artifact org.scala-tools:maven-scala-plugin: checking for updates from central 
    
     . . . 
    
     [INFO] Building war: /Users/arungupta/samples/v3/lift/helloworld/target/helloworld-1.0-SNAPSHOT.war
     [INFO] ------------------------------------------------------------------------
     [INFO] BUILD SUCCESSFUL
     [INFO] ------------------------------------------------------------------------
     [INFO] Total time: 9 minutes 25 seconds
     [INFO] Finished at: Tue Sep 01 16:42:32 PDT 2009
     [INFO] Final Memory: 24M/80M
     [INFO] ------------------------------------------------------------------------
    


    This generates "target/helloworld-1.0-SNAPSHOT.war" file.
  3. The WAR file can be easily deployed to GlassFish v3. Download the latest GlassFish v3 promoted build (61 as of this writing) and unzip. Start the GlassFish server as:
    ~/tools/glassfish/v3/61/glassfishv3 >./bin/asadmin start-domain --verbose
    
    Sep 2, 2009 3:43:09 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
    INFO: JVM invocation command line:
    
    . . .
    
    Sep 2, 2009 3:46:01 PM OSGiModuleImpl start
    INFO: Started bundle org.glassfish.security [174]
    Sep 2, 2009 3:46:02 PM OSGiModuleImpl start
    INFO: Started bundle org.glassfish.deployment.javaee-full [51]
    

    and deploy the WAR file as:
    ~/samples/v3/lift/helloworld >~/tools/glassfish/v3/8-31/glassfishv3/bin/asadmin deploy target/helloworld-1.0-SNAPSHOT.war
    
    Command deploy executed successfully.
    


    The app is now accessible at "http://localhost:8080/helloworld-1.0-SNAPSHOT/" and the output looks like:

What application server are you using to deploy your Lift applications ?

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

Technorati: totd scala lift glassfish v3

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090819 Wednesday August 19, 2009

TOTD #96: GlassFish v3 REST Interface to Monitoring and Management - JSON, XML, and HTML representations


GlassFish Monitoring allows you to monitor the state of various runtime components of the application server. This information is used to identify performance bottlenecks and tuning the system for optimal performance, to aid capacity planning, to predict failures, to do root cause analysis in case of failures and sometimes to just ensure that everything is functioning as expected.

GlassFish Management allows you to manage the running Application Server instance such as query/create/delete resources (JDBC, JMS, etc), stop/restart the instance, rotate the log and other similar functions.

GlassFish v3 exposes Monitoring and Management data using a REST Interface. This Tip Of The Day (TOTD) shows how to play with this new functionality. Rajeshwar's blog has lot of useful information on this topic.

Most of the functionality available in web-based Admin Console and CLI (asadmin) is now available using the REST interface. Both of these are pre-built tools that ships with the GlassFish bundle. The REST interface is a lower level API that enables toolkit developers and IT administrators to write their custom scripts/clients using language of their choice such as Java, JavaScript, Ruby or Groovy.

The default URL for the REST interface of monitoring is "http://localhost:4848/monitoring/domain" and for the management is "http://localhost:4848/management/domain". Each URL provides an XML, JSON and HTML representation of the resources. If a web browser is used then a HTML representation is returned and displayed nicely in the browser. Rajeshwar's blog described a Java client written using Jersey Client APIs that can be used to make all the GET/PUT/POST/DELETE requests. This blog will use something more basic, and extremely popular, to make all the RESTful invocations - cURL.

At this time the monitoring resources are read-only (GET) and management can be done using GET/POST/DELETE methods. POST is used for creating and updating resources/objects and the updates can be partial.
 
Lets get started.

  1. Download the latest continuous build from the trunk and unzip. This functionality is also available in the Web profile bundle. This blog is using build #2023.
  2. Start the application server as:

    ~/tools/glassfish/v3/2023/glassfishv3 >./bin/asadmin start-domain --verbose

    Aug 19, 2009 9:52:45 AM com.sun.enterprise.admin.launcher.GFLauncherLogger info
    INFO: JVM invocation command line:
    /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java
    -cp

    . . .

    INFO: felix.fileinstall.dir            /Users/arungupta/tools/glassfish/v3/2023/glassfishv3/glassfish/domains/domain1/autodeploy-bundles
    Aug 19, 2009 9:53:05 AM 
    INFO: felix.fileinstall.debug          1
    Aug 19, 2009 9:53:05 AM 
    INFO: felix.fileinstall.bundles.new.start          true

  3. Monitoring information - Lets monitor this GlassFish instance using the REST interface.
    1. Retrieve JSON information - As mentioned above, the monitoring resources are read-only and so the information can be accessed as:

      ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/json" http://localhost:4848/monitoring/domain -v
      * About to connect() to localhost port 4848 (#0)
      *   Trying ::1... connected
      * Connected to localhost (::1) port 4848 (#0)
      > GET /monitoring/domain HTTP/1.1
      > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
      > Host: localhost:4848
      > Accept: application/json
      >
      < HTTP/1.1 200 OK
      < Content-Type: application/json
      < Transfer-Encoding: chunked
      < Date: Wed, 19 Aug 2009 17:40:29 GMT
      <
      {Domain:{},"child-resources":["http://localhost:4848/monitoring/domain/server"]}
      * Connection #0 to host localhost left intact
      * Closing connection #0

      The command explicitly asks for JSON representation of the resources. The outbound headers are prepended with ">" and inbound headers with "<". And the JSON representation is shown in the last line as:

      {Domain:{},"child-resources":["http://localhost:4848/monitoring/domain/server"]}

      The key element to remember here is "http://localhost:4848/monitoring/domain/server" which can be used to retrieve more monitoring information.
    2. XML represetation: Lets change the command to ask for XML representation as:

      ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/xml" http://localhost:4848/monitoring/domain -v
      * About to connect() to localhost port 4848 (#0)
      *   Trying ::1... connected
      * Connected to localhost (::1) port 4848 (#0)
      > GET /monitoring/domain HTTP/1.1
      > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
      > Host: localhost:4848
      > Accept: application/xml
      >
      < HTTP/1.1 200 OK
      < Content-Type: application/xml
      < Transfer-Encoding: chunked
      < Date: Wed, 19 Aug 2009 17:43:51 GMT
      <
      <Domain>
          <child-resource>http://localhost:4848/monitoring/domain/server</child-resource>
      </Domain>
      * Connection #0 to host localhost left intact
      * Closing connection #0

      The command changes the "Accept" header to "application/xml" and now the XML representation of the monitoring resources is returned as:

      <Domain>
          <child-resource>http://localhost:4848/monitoring/domain/server</child-resource>
      </Domain>

    3. HTML representation: The command can be altered to get the HTML representation as "curl -H "Accept: text/html" http://localhost:4848/monitoring/domain -v". But HTML is more pleasant when rendered by a browser and so viewing the page "http://localhost:4848/monitoring/domain" in the browser is shown as:

    4. Get more information: As mentioned above, more information about this GlassFish instance can be accessed by GETing from "http://localhost:4848/monitoring/domain/server" and here is the result:

      </tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/json" http://localhost:4848/monitoring/domain/server -v
      * About to connect() to localhost port 4848 (#0)
      *   Trying ::1... connected
      * Connected to localhost (::1) port 4848 (#0)
      > GET /monitoring/domain/server HTTP/1.1
      > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
      > Host: localhost:4848
      > Accept: application/json
      >
      < HTTP/1.1 200 OK
      < Content-Type: application/json
      < Transfer-Encoding: chunked
      < Date: Wed, 19 Aug 2009 17:56:41 GMT
      <
      {Server:{},"child-resources":["http://localhost:4848/monitoring/domain/server/webintegration",
      "http://localhost:4848/monitoring/domain/server/transaction-service",
      "http://localhost:4848/monitoring/domain/server/network",
      "http://localhost:4848/monitoring/domain/server/jvm",
      "http://localhost:4848/monitoring/domain/server/web",
      "http://localhost:4848/monitoring/domain/server/realm",
      "http://localhost:4848/monitoring/domain/server/http-service"]}
      * Connection #0 to host localhost left intact
      * Closing connection #0

      An HTML rendering of this representation looks like:



      You can keep clicking on the links and more detailed information about that resource is displayed. This is just one HTML representation and is purposely kept light-weight. You can certainly grab the XML representation and apply an XSLT to generate your own HTML rendering.

      The monitoring levels for different modules can be easily changed using the management REST interface as explained below.
  4. Management of the GlassFish instance
    1. Lets see all the options supported by management REST interface as:

      ~/tools/glassfish/v3/2023/glassfishv3 >curl -X OPTIONS http://localhost:4848/management/domain -v
      * About to connect() to localhost port 4848 (#0)
      *   Trying ::1... connected
      * Connected to localhost (::1) port 4848 (#0)
      > OPTIONS /management/domain HTTP/1.1
      > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
      > Host: localhost:4848
      > Accept: */*
      >
      < HTTP/1.1 200 OK
      < Content-Type: application/json
      < Transfer-Encoding: chunked
      < Date: Wed, 19 Aug 2009 18:07:14 GMT
      <
      {
        "Method":"GET"


        "Method":"PUT"
      }
      * Connection #0 to host localhost left intact
      * Closing connection #0

      Specifying "-X OPTIONS" switch displays the various HTTP methods supported by the REST interface. Even though the results show GET and PUT, but it really means GET and POST (issue #9177). Lets try "GET" first. 
    2. GET JSON information as:

      ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/json" http://localhost:4848/management/domain -v
      * About to connect() to localhost port 4848 (#0)
      *   Trying ::1... connected
      * Connected to localhost (::1) port 4848 (#0)
      > GET /management/domain HTTP/1.1
      > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
      > Host: localhost:4848
      > Accept: application/json
      >
      < HTTP/1.1 200 OK
      < Content-Type: application/json
      < Transfer-Encoding: chunked
      < Date: Wed, 19 Aug 2009 18:14:46 GMT
      <
      {Domain:{"log-root" : "${com.sun.aas.instanceRoot}/logs","application-root" : "${com.sun.aas.instanceRoot}/applications","locale" : "","version" : "re-continuous"},"child-resources":["http://localhost:4848/management/domain/configs",
      "http://localhost:4848/management/domain/resources","http://localhost:4848/management/domain/servers",
      "http://localhost:4848/management/domain/property","http://localhost:4848/management/domain/applications",
      "http://localhost:4848/management/domain/system-applications","http://localhost:4848/management/domain/stop",
      "http://localhost:4848/management/domain/restart","http://localhost:4848/management/domain/uptime",
      "http://localhost:4848/management/domain/version","http://localhost:4848/management/domain/rotate-log",
      "http://localhost:4848/management/domain/host-port"]}
      * Connection #0 to host localhost left intact
      * Closing connection #0

      As the result shows, there are several RESTful URLs available (in "child-resources" element) to manage this GlassFish instance. For example:
      1. Show the host/port of GlassFish instance as:

        curl -H "Accept: application/json" http://localhost:4848/management/domain/host-port -v

        will show the result as:

        {"GetHostAndPort":{"value" : "dhcp-usca14-132-79.SFBay.Sun.COM:8080"}}

      2. Show that web-based Admin Console is pre-installed as system application using:

        curl -H "Accept: application/json" http://localhost:4848/management/domain/system-applications/application/__admingui -v

        will show the result as:

        {__admingui:{"libraries" : "","availability-enabled" : "false","enabled" : "true","context-root" : "","location" : "${com.sun.aas.installRootURI}/lib/install/applications/__admingui","description" : "","name" : "__admingui","directory-deployed" : "true","object-type" : "system-admin"},"child-resources":["http://localhost:4848/management/domain/system-applications/application/__admingui/module"]}

      3. Query the monitoring levels of different modules as:

        curl -H "Accept: application/json" http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels -v

        to see the result as:

        {ModuleMonitoringLevels:{"transaction-service" : "OFF","ejb-container" : "OFF","jdbc-connection-pool" : "OFF","orb" : "OFF","http-service" : "OFF","connector-connection-pool" : "OFF","jms-service" : "OFF","connector-service" : "OFF","jvm" : "OFF","thread-pool" : "OFF","web-container" : "OFF"},"child-resources":[]}

        And then change the monitoring level of Web container as:

        ~/tools/glassfish/v3/2023/glassfishv3 >curl -X POST -d "web-container=ON" -H "Accept: application/json" http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels -v
        * About to connect() to localhost port 4848 (#0)
        *   Trying ::1... connected
        * Connected to localhost (::1) port 4848 (#0)
        > POST /management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels HTTP/1.1
        > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
        > Host: localhost:4848
        > Accept: application/json
        > Content-Length: 16
        > Content-Type: application/x-www-form-urlencoded
        >
        < HTTP/1.1 200 OK
        < Content-Type: application/json
        < Transfer-Encoding: chunked
        < Date: Wed, 19 Aug 2009 22:01:31 GMT
        <
        * Connection #0 to host localhost left intact
        * Closing connection #0
        "http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels" updated successfully

        The last line shows that the monitoring level is successfull updated and can be verified again as:

        ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/json" http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels -v
        * About to connect() to localhost port 4848 (#0)
        *   Trying ::1... connected
        * Connected to localhost (::1) port 4848 (#0)
        > GET /management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels HTTP/1.1
        > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
        > Host: localhost:4848
        > Accept: application/json
        >
        < HTTP/1.1 200 OK
        < Content-Type: application/json
        < Transfer-Encoding: chunked
        < Date: Wed, 19 Aug 2009 22:36:47 GMT
        <
        * Connection #0 to host localhost left intact
        * Closing connection #0
        {ModuleMonitoringLevels:{"transaction-service" : "OFF","ejb-container" : "OFF","jdbc-connection-pool" : "OFF","orb" : "OFF","http-service" : "OFF","connector-connection-pool" : "OFF","jms-service" : "OFF","connector-service" : "OFF","jvm" : "OFF","thread-pool" : "OFF","web-container" : "ON"},"child-resources":[]}
      4. Stop this GlassFish instance using:

        curl -H "Accept: application/json" http://localhost:4848/management/domain/stop -v

        Or restart the instance using:

        curl -H "Accept: application/json" http://localhost:4848/management/domain/restart -v
      5. Create a JDBC resource using an existing connection pool
        1. Lets see all the resources that are available:

          curl -H "Accept: application/json" http://localhost:4848/management/domain/resources -v

          and the results are shown as:

          {Resources:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-connection-pool",
          "http://localhost:4848/management/domain/resources/jdbc-resource"]}

        2. View all the JDBC connection pools as:

          curl -H "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc/connection-pool -v

          and the results are shown as:

          {JdbcConnectionPool:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-connection-pool/__TimerPool",
          "http://localhost:4848/management/domain/resources/jdbc-connection-pool/DerbyPool"]}

        3. See all the JDBC resources available as:

          curl "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc-resource -v

          and the results are shown as:

          {JdbcResource:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__TimerPool",
          "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__default"]}

        4. See all the OPTIONS accepted for JDBC resource creation as:

          curl -X OPTIONS -H "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc-resource -v

          with the result as:

          {
            "Method":"POST",
            "Message Parameters":{
              "id":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"false"},
              "enabled":{"Acceptable Values":"","Default Value":"true","Type":"class java.lang.Boolean","Optional":"true"},
              "description":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"true"},
              "target":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"true"},
              "property":{"Acceptable Values":"","Default Value":"","Type":"class java.util.Properties","Optional":"true"},
              "connectionpoolid":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"false"}
            }


            "Method":"GET"

        5. Finally, create the JDBC resource as:

          ~/tools/glassfish/v3/2023/glassfishv3 >curl -d "id=jdbc/sample&connectionpoolid=DerbyPool" http://localhost:4848/management/domain/resources/jdbc-resource -v
          * About to connect() to localhost port 4848 (#0)
          *   Trying ::1... connected
          * Connected to localhost (::1) port 4848 (#0)
          > POST /management/domain/resources/jdbc-resource HTTP/1.1
          > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
          > Host: localhost:4848
          > Accept: */*
          > Content-Length: 42
          > Content-Type: application/x-www-form-urlencoded
          >
          < HTTP/1.1 201 Created
          < Content-Type: text/html
          < Transfer-Encoding: chunked
          < Date: Wed, 19 Aug 2009 20:45:51 GMT
          <
          * Connection #0 to host localhost left intact
          * Closing connection #0
          "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/sample" created successfully.

          Note, this is a POST request. The JDBC resource name and JDBC connection pool id are passed as CLI parameters using "-d" switch. The last line shows that the JDBC resource was created successfully.
        6. And finally query the JDBC Resources again as:

          curl -H "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc-resource -v

          to see the updated result as:

          {JdbcResource:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__TimerPool",
          "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__default",
          "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/sample"]}

        Similarly JDBC connection pools can be created.
    3. POST can be used to update the top-level attributes such as "log-root" and "application-root". The name of these attributes are shown in the result of GET.
    4. As earlier, XML representation of management resources can be obtained as:

      ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/xml" http://localhost:4848/management/domain -v
      * About to connect() to localhost port 4848 (#0)
      *   Trying ::1... connected
      * Connected to localhost (::1) port 4848 (#0)
      > GET /management/domain HTTP/1.1
      > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
      > Host: localhost:4848
      > Accept: application/xml
      >
      < HTTP/1.1 200 OK
      < Content-Type: application/xml
      < Transfer-Encoding: chunked
      < Date: Wed, 19 Aug 2009 18:17:07 GMT
      <
      <Domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" locale="" version="re-continuous">
          <child-resource>http://localhost:4848/management/domain/configs</child-resource>
          <child-resource>http://localhost:4848/management/domain/resources</child-resource>
          <child-resource>http://localhost:4848/management/domain/servers</child-resource>
          <child-resource>http://localhost:4848/management/domain/property</child-resource>
          <child-resource>http://localhost:4848/management/domain/applications</child-resource>
          <child-resource>http://localhost:4848/management/domain/system-applications</child-resource>
          <child-resource>http://localhost:4848/management/domain/stop</child-resource>
          <child-resource>http://localhost:4848/management/domain/restart</child-resource>
          <child-resource>http://localhost:4848/management/domain/uptime</child-resource>
          <child-resource>http://localhost:4848/management/domain/version</child-resource>
          <child-resource>http://localhost:4848/management/domain/rotate-log</child-resource>
          <child-resource>http://localhost:4848/management/domain/host-port</child-resource>
      * Connection #0 to host localhost left intact
      * Closing connection #0

      Just changing the "Accept" header to "application/xml" did the trick.
    5. And an HTML representation can be obtained by viewing the URL "http://localhost:4848/management/domain" in the browser with result as:



Just like GlassFish v3, the REST interface is extensible as well. So if a new container is plugged in that generates data (possibly through probes) captured in the runtime tree, that is automatically exposed in the RESTful interface.

Now for the Mac users, Safari prefers XML over HTML. Basically a resource, that can be served using both XML and HTML representation (as our Management and Monitoring interface), is served as XML by Safari and HTML by Firefox. So use Firefox on Mac if you want HTML rendering.

How will you use GlassFish REST interface ?

Do your application server provide that level of administration capability ?

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 v3 rest management monitoring jersey

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090817 Monday August 17, 2009

TOTD #95: EJB 3.1 + Java Server Faces 2.0 + JPA 2.0 web application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3


TOTD #93 showed how to get started with Java EE 6 using NetBeans 6.8 M1 and GlassFish v3 by building a simple Servlet 3.0 + JPA 2.0 web application. TOTD #94 built upon it by using Java Server Faces 2 instead of Servlet 3.0 for displaying the results. However we are still using a POJO for all the database interactions. This works fine if we are only reading values from the database but that's not how a typical web application behaves. The web application would typically perform all CRUD operations. More typically they like to perform one or more CRUD operations within the context of a transaction. And how do you do transactions in the context of a web application ? Java EE 6 comes to your rescue.

The EJB 3.1 specification (another new specification in Java EE 6) allow POJO classes to be annotated with @EJB and bundled within WEB-INF/classes of a WAR file. And so you get all transactional capabilities in your web application very easily.

This Tip Of The Day (TOTD) shows how to enhance the application created in TOTD #94 and use EJB 3.1 instead of the JSF managed bean for performing the business logic. There are two ways to achieve this pattern as described below.

Lets call this TOTD #95.1

  1. The easiest way to back a JSF page with an EJB is to convert the managed bean into an EJB by adding @javax.ejb.Stateless annotation. So change the  "StateList" class from TOTD #94 as shown below:

    @javax.ejb.Stateless
    @ManagedBean
    public class StateList {
        @PersistenceUnit
        EntityManagerFactory emf;

        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    The change is highlighted in bold, and that's it!
Because of "Deploy-on-save" feature in NetBeans and GlassFish v3, the application is autodeployed. Otherwise right-click on the project and select Run (default shortcut "F6"). As earlier, the results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and looks like:



The big difference this time is that the business logic is executed by an EJB in a fully transactional manner. Even though the logic in this case is a single read-only operation to the database, but you get the idea :)

Alternatively, you can use the delegate pattern in the managed bean as described below. Lets call this #95.2.
  1. Right-click on the project, select "New", "Session Bean ..." and create a stateless session bean by selecting the options as shown below:



    This creates a stateless session with the name "StateBeanBean" (bug #170392 for redundant "Bean" in the name).
  2. Simplify your managed bean by refactoring all the business logic to the EJB as shown below:

    @Stateless
    public class StateBeanBean {
        @PersistenceUnit
        EntityManagerFactory emf;
        
        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    and

    @ManagedBean
    public class StateList {
        @EJB StateBeanBean bean;

        public List<States> getStates() {
            return bean.getStates();
        }
    }

    In fact the EJB code can be further simplified to:

    @Stateless
    public class StateBeanBean {
        @PersistenceContext
        EntityManager em;
       
        public List<States> getStates() {
            return em.createNamedQuery("States.findAll").getResultList();
        }
    }

    The changes are highlighted in bold.
If the application is already running then Deploy-on-Save would have automatically deployed the entire application. Otherwise right-click on the project and select Run (default shortcut "F6"). Again, the results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and are displayed as shown in the screenshot above.

The updated directory structure looks like:



The important point to note is that our EJB is bundled in the WAR file and no additional deployment descriptors were added or existing ones modified to achieve that. Now, that's really clean :)

The next blog in this series will show how managed beans can be replaced with WebBeans, err JCDI.

Also refer to other Java EE 6 blog entries.

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 v3 mysql javaee6 javaserverfaces jpa2 ejb netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090814 Friday August 14, 2009

TOTD #94: A simple Java Server Faces 2.0 + JPA 2.0 application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3


TOTD #93 showed how to get started with Java EE 6 using NetBeans 6.8 M1 and GlassFish v3 by building a simple Servlet 3.0 + JPA 2.0 web application. JPA 2.0 + Eclipselink was used for the database connectivity and Servlet 3.0 was used for displaying the results to the user. The sample demonstrated how the two technologies can be mixed to create a simple web application. But Servlets are meant for server-side processing rather than displaying the results to end user. JavaServer Faces 2 (another new specification in Java EE 6) is designed to fulfill that purpose.

This Tip Of The Day (TOTD) shows how to enhance the application created in TOTD #93 and use JSF 2 for displaying the results.

  1. Right-click on the project, select "Properties", select "Frameworks", click on "Add ..." as shown below:



    Select "JavaServer Faces" and click on "OK". The following configuration screen is shown:



    Click on "OK" to complete the dialog. This generates a whole bunch of files (7 to be accurate) in your project. Most of these files are leftover from previous version of NetBeans and will be cleaned up. For example, "faces-config.xml" is now optional and "forwardToJSF.jsp" is redundant.
  2. Anyway, lets add a POJO class that will be our managed bean. Right-click on "server" package and select "New", "Java Class ...", give the name as "StateList". Change the class such that it looks like:

    package server;

    import java.util.List;
    import javax.faces.bean.ManagedBean;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.PersistenceUnit;
    import states.States;

    /**
     * @author arungupta
     */
    @ManagedBean
    public class StateList {
        @PersistenceUnit
        EntityManagerFactory emf;

        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    Here are the main characterisitcs of this class:
    1. This is a POJO class with @ManagedBean annotation. This annotation makes this class a managed bean that can be used in the JSF pages. As no other annotations or parameters are specified, this is a request-scoped managed bean with the name "stateList" and lazily initialized. More details about this annotation are available in the javadocs.
    2. The persistence unit created in TOTD #93 is injected using @PersistenceUnit annotation.
    3. The POJO has one getter method that queries the database and return the list of all the states.
  3. In the generated file "template-client.xhtml", change the "head" template to:

    Show States

    and "body" template to:

                    <h:dataTable var="state" value="#{stateList.states}" border="1">
                        <h:column><h:outputText value="#{state.abbrev}"/></h:column>
                        <h:column><h:outputText value="#{state.name}"/></h:column>
                    </h:dataTable>

  4. This uses the standard JSF "dataTable", "column", and "outputText" tags and uses the value expression to fetch the values from the managed bean.

If the application is already running from TOTD #93, then Deploy-on-Save would have automatically deployed the entire application. Otherwise right-click on the project and select Run (default shortcut "F6"). The results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and looks like:



The updated directory structure looks like:



There were multiple files added by the JSF framework support in NetBeans. But as I said earlier, they will be cleaned up before the final release.

Also refer to other Java EE 6 blog entries.

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 v3 mysql javaee6 javaserverfaces jpa2 netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090813 Thursday August 13, 2009

TOTD #93: Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3 - A simple Servlet 3.0 + JPA 2.0 app


NetBeans 6.8 M1 introduces support for creating Java EE 6 applications ... cool!

This Tip Of The Day (TOTD) shows how to create a simple web application using JPA 2.0 and Servlet 3.0 and deploy on GlassFish v3 latest promoted build (58 as of this writing). If you can work with the one week older build then NetBeans 6.8 M1 comes pre-bundled with 57. The example below should work fine on that as well.

  1. Create the database, table, and populate some data into it as shown below:

    ~/tools/glassfish/v3/58/glassfishv3/bin >sudo mysql --user root
    Password:
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1592
    Server version: 5.1.30 MySQL Community Server (GPL)

    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

    mysql> create database states;
    Query OK, 1 row affected (0.02 sec)

    mysql> CREATE USER duke IDENTIFIED by 'glassfish';
    Query OK, 0 rows affected (0.00 sec)

    mysql> GRANT ALL on states.* TO duke;
    Query OK, 0 rows affected (0.24 sec)

    mysql> use states;
    Database changed

    mysql> CREATE TABLE STATES (
        ->       id INT,
        ->       abbrev VARCHAR(2),
        ->       name VARCHAR(50),
        ->       PRIMARY KEY (id)
        -> );
    Query OK, 0 rows affected (0.16 sec)

    mysql> INSERT INTO STATES VALUES (1, "AL", "Alabama");
    INSERT INTO STATES VALUES (2, "AK", "Alaska");

    . . .

    mysql> INSERT INTO STATES VALUES (49, "WI", "Wisconsin");
    Query OK, 1 row affected (0.00 sec)

    mysql> INSERT INTO STATES VALUES (50, "WY", "Wyoming");
    Query OK, 1 row affected (0.00 sec)

    The complete INSERT statement is available in TOTD #38. Most of this step can be executed from within the IDE as well as explained in TOTD #38.
  2. Download and unzip GlassFish v3 build 58. Copy the latest MySQL Connector/J jar in "domains/domain1/lib" directory of GlassFish and start the application server as:

    ~/tools/glassfish/v3/58/glassfishv3/bin >asadmin start-domain
  3. Create JDBC connection pool and JNDI resource as shown below:

    ~/tools/glassfish/v3/58/glassfishv3/bin >./asadmin create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --restype javax.sql.DataSource --property "User=duke:Password=glassfish:URL=jdbc\:mysql\://localhost/states" jdbc/states

    Command create-jdbc-connection-pool executed successfully.
    ~/tools/glassfish/v3/58/glassfishv3/bin >./asadmin ping-connection-pool jdbc/states

    Command ping-connection-pool executed successfully.
    ~/tools/glassfish/v3/58/glassfishv3/bin >./asadmin create-jdbc-resource --connectionpoolid jdbc/states jdbc/jndi_states

    Command create-jdbc-resource executed successfully.

  4. Download NetBeans 6.8 M1 and install "All" version. Expand "Servers" node and add the recently installed GlassFish server.
  5. Create a new Web project and name it "HelloEclipseLink". Make sure to choose "GlassFish v3" as the server and "Java EE 6 Web" as the Java EE version as shown below:



    Take defaults elsewhere.
  6. Create the Persistence Unit
    1. Right-click on the newly created project and select "New", "Entity Classes from Database ...". Choose the earlier created data source "jdbc/jndi_states" as shown below:

    2. Select "STATES" table in "Available Tables:" and click on "Add >" and then "Next >".
    3. Click on "Create Persistence Unit ...", take all the defaults and click on "Create". "EclipseLink" is the Reference Implementation for JPA 2.0 is the default choosen Persistence Provider as shown below:

    4. Enter the package name as "server" and click on "Finish".
  7. Create a Servlet to retrieve and display all the information from the database
    1. Right click on the project, "New", "Servlet ...".
    2. Give the Servlet name "ShowStates" and package "server".
    3. Even though you can take all the defaults and click on "Finish" but instead click on "Next >" and the following screen is shown:



      Notice "Add information to deployment descriptor (web.xml)" checkbox. Servlet 3.0 makes "web.xml" optional in most of the common cases by providing corresponding annotations and NetBeans 6.8 leverages that functionality. As a result, no "web.xml" will be bundled in our WAR file. Click on "Finish" now.

      The generated servlet code looks like:



      Notice @WebServlet annotation, this makes "web.xml" optional. TOTD #82 provide another example on how to use Servlet 3.0 with EJB 3.1.
    4. Inject the Persistence Unit as:

          @PersistenceUnit
          EntityManagerFactory emf;

      right above "processRequest" method.
    5. Change the "try" block of "processRequest" method to:

                  List<States> list = emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
                  out.println("<table border=\"1\">");
                  for (States state : list) {
                      out.println("<tr><td>" + state.getAbbrev() +
                              "</td><td>" + state.getName() +
                              "</td></tr>");
                  }
                  out.println("</table>");

      This uses a predefined query to retrieve all rows from the table and then display them in a simple formatted HTML table.
  8. Run the project
    1. Right click on the project, select "Properties" and change the "Relative URL" to "/ShowStates". This is the exact URL that you specified earlier.

    2. Right-click on the project and select "Run" to see the following output:



So we created a simple web application that uses Servlet 3.0, JPA 2.0, EclipseLink and deployed on GlassFish v3 using NetBeans 6.8 M1. NetBeans provides reasonable defaults making you a lazy programmer. Believe this is more evident when you start playing with Java EE support in other IDEs ;-)

Finally, lets look at the structure of the generated WAR file:



It's very clean - no "web.xml", only the relevant classes and "persistence.xml".

Also refer to other Java EE 6 blog entries. A future blog entry will show how to use JSF 2.0 instead of Servlet for displaying the results.

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 v3 mysql javaee6 servlet3 jpa2 netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090811 Tuesday August 11, 2009

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


"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>
                <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

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090702 Thursday July 02, 2009

Rails on GlassFish - "most performant of all", "simpler and just works", "blazing speed"


Here are some quotes about running Rails applications on GlassFish from user@jruby mailing list:

I find the glassfish gem to be the most performant of all -- and I don't need to war-up my app.

I also have some mongrel cluster stuff, but glassfish is simpler and just works.

Voila...blazing speed, can handle lots of traffic. Note that I am also cominging into apache from a dyndns name. So, whatever IP I have, I can go straight to execution on the glassfish gem and NO warring up! What could be easier deployment, or a faster execution?

It's running fantasticly and performing like nothing I've seen before :) Completely stable memory, no wirings or anything bad for 5 days now.. (with several ab/htperf stresstests).

It's always exciting to get good endorsements of our efforts in the GlassFish team :)

Other similar stories for using Rails/GlassFish in production are described at rubyonrails+stories.

Technorati: glassfish v3 gem rubyonrails stories jruby

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090618 Thursday June 18, 2009

TOTD #85: Getting Started with Django Applications on GlassFish v3

GlassFish v3 is an extensible App server. Basically the core App server functionality can be easily extended using add-ons such as an OSGi module. This allows to keep the core light-weight and install the required features on demand. The add-ons can be easily installed using the Update Center. The what/why/how about extensibility is described in the GlassFish v3 Extensibility One-pager.

GlassFish v3 provides support for Dynamic Languages and Web Frameworks such as Ruby-on-Rails, Groovy/Grails, and Python/Django using this extensibility. This blog has published multiple tips on using Ruby-on-Rails at rubyonrails+totd and a few tips on Groovy/Grails at grails+totd. This blog will explain how to get started with deploying Python/Django applications on GlassFish v3 Preview. The blog will use Jython interpreter which is the Java implemention of Python.

Vivek already blogged about the detailed instructions and this blog shows how to run the pre-bundled samples.

  1. Download GlassFish v3 Preview.
  2. Install Jython 2.5
    1. Download Jython 2.5 from here
    2. Install as:

      java -jar ~/Downloads/jython_installer-2.5.0.jar

      Choose the default options (pick your directory) as shown below:



      and click on "Next" to start the installation process.
    3. As mentioned in Django on Jython wiki, create the following aliases:

      alias jython25=~/tools/jython2.5.0/bin/jython
      alias django-admin-jy="jython25 ~/tools/jython2.5.0/bin/django-admin.py"

    4. Invoking the command "jython25" from the installation directory shows the Jython interpreter as:

      ~/tools/jython/jython2.5rc4 >jython25
      Jython 2.5rc4 (Release_2_5rc4:6470, Jun 8 2009, 13:23:16)
      [Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_13
      Type "help", "copyright", "credits" or "license" for more information.
      >>>

  3. Install Django
    1. Download Django 1.0.2 from here.
    2. Install Django 1.0.2 as:

      ~/tools >tar xzvf ~/Downloads/Django-1.0.2-final.tar.gz
      Django-1.0.2-final/
      Django-1.0.2-final/AUTHORS
      Django-1.0.2-final/django/
      . . .
      Django-1.0.2-final/scripts/rpm-install.sh
      Django-1.0.2-final/setup.cfg
      Django-1.0.2-final/setup.py
      ~/tools/Django-1.0.2-final >jython25 setup.py install
      running install
      running build
      running build_py
      . . .
      running install_egg_info
      Writing /Users/arungupta/tools/jython/jython2.5.0/Lib/site-packages/Django-1.0.2_final-py2.5.egg-info

  4. Install Jython container for GlassFish
    1. Start GlassFish v3 Preview Update Center using the following command:

      ~/tools/glassfish/v3/preview/glassfishv3/bin >./updatetool 

      to see the screen as:


    2. Select "GlassFish v3 Jython Container" and click on "Install", "Accept" the license and complete the installation. Close the Update Center window. This installs Jython Container OSGi module and Grizzly Adapter JARs in the "glassfish/modules" directory.
  5. Start and configure GlassFish
    1. Start GlassFish as:

      ~/tools/glassfish/v3/preview/glassfishv3/glassfish >./bin/asadmin start-domain

    2. Configure Jython in GlassFish as:

      ~/tools/glassfish/v3/preview/glassfishv3/glassfish >./bin/asadmin create-jvm-options -Djython.home=/Users/arungupta/tools/jython2.5.0
      created 1 option(s)

      Command create-jvm-options executed successfully.

      Make sure to specify the directory where Jython is installed.
  6. Deploy the samples bundled with the Django installation as:

    ~/tools/Django-1.0.2-final/examples >~/tools/glassfish/v3/preview/glassfishv3/glassfish/bin/asadmin deploy .

    Command deploy executed successfully.

    and now they are accessible at "http://localhost:8080/examples/" and shown as:



    Make sure to specify the end "/" otherwise the context root is not resolved correctly and none of the links will work.

    Click on "Hello World (HTML)" to see the output as:



    And click on "Displaying request metadata" to see output as:



    The same sample can, of course, run using the built-in development server as:

    ~/tools/Django-1.0.2-final/examples >jython25 manage.py runserver
    Validating models...
    0 errors found

    Django version 1.0.2 final, using settings 'examples.settings'
    Development server is running at http://127.0.0.1:8000/
    Quit the server with CONTROL-C.

    and then accessible at "http://localhost:8000" as:

More details are available in Django Tutorial. The subsequent blogs will provide more detailed samples.

If you are using GlassFish v2 then Django applications can be deployed as a WAR file as explained here.

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: totd glassfish v3 django python

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090519 Tuesday May 19, 2009

TOTD #82: Getting Started with Servlet 3.0 and EJB 3.1 in Java EE 6 using NetBeans 6.7


EJB 3.1 (JSR 318) and Servlet 3.0 (JSR 315) are the two new JSRs in Java EE 6 (JSR 316).

The EJB 3.1 specification provides multiple new features such as WAR packaging, Optional Local Business Interfaces, EJB.lite, Portable Global JNDI Names, Singleton Session Beans (Container-managed and Bean-managed concurrency), Application Initialization and Shutdown events, Timer Service enhancements, Simple/Light-weight Asynchrony, and many other features defined in the specification.

The Servlet 3.0 specification is an update to Servlet 2.5 and focuses on ease-of-use. It also adds several new features such as "web.xml" free deployment (mostly), Dynamic Registration of servlets/filters, Pluggability of frameworks using "web-fragment.xml", Asynchronous API, Security enhancements (Constraints via annotations, programmatic container authentication and logout), and several other miscellaneous additions like default error page, file upload, etc.

GlassFish v3 provides the most complete implementation of EJB 3.1 and Servlet 3.0 along with other Java EE 6 specifications. This Tip Of The Day (TOTD) will show how to create a simple EJB and invoke it from a Servlet, all in a deployment-descriptor free way.

  1. Enable support for v3 Preview in NetBeans
    1. Using NetBeans 6.7 latest nightly, enable support for recent GlassFish v3 builds either using the command-line switch or the marker module.
    2. Download and unzip GlassFish v3 Preview 47b. The latest promoted builds are always available here.
    3. In the "Services" tab, right-click on "Servers" and click on "Add Server". Select "GlassFish v3" as shown below:



      and click on "Next".
    4. Specify location of the previously unzipped bundle, click on "Next >", and press "Finish".
  2. Create a new Web project by right-click in the "Projects" pane, select "New Project", choose "Java Web" and "Web  Application" as categories and projects.
  3. Click on "Next >", choose "Java EE 5" as the Java EE version and click on "Finish". A future version of NetBeans will will provide direct support for Java EE 6.
  4. Add a POJO-based EJB
    1. Right-click on "Source Packages" and select "New", "Java Class..." as shown below:



      Give the class name as "HelloEJB" and package as "server" as shown below:



      and click on "Finish".
    2. Add "@Stateless" class-level annotation and press Shift+Command+I (default shortcut) to fix the imports. This annotation comes from the "javax.ejb" package.
    3. Add the following method:

          public String sayHello(String name) {
              return "Hello " + name;
          }

      to the class. And can you believe it, that's your complete EJB ready to be deployed and that too in a WAR file - the beauty of Java EE 6. The complete class looks like:


      package server;

      import javax.ejb.Stateless;

      /**
       * @author arungupta
       */
      @Stateless
      public class HelloEJB {
          public String sayHello(String name) {
              return "Hello " + name;
          }
      }
  5. Add a Servlet to invoke this EJB
    1. Add a new class "HelloServlet" in the "server" package as explained above.
    2. Add "@WebServlet" class-level annotation and Shift+Command+I to fix the imports. This annotation comes from the "javax.servlet.annotation" package. And specify a URL pattern as:

      @WebServlet(urlPatterns="/hello")
    3. According to the Servlet3 specification, the contract is inherited from the "javax.servlet.http.HttpServlet" interface. So add:

      extends HttpServlet

      to the class.
    4. Inject a local EJB reference using the code:

      @EJB HelloEJB ejbClient;
    5. Override the GET method as:

          @Override
          public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
              res.setContentType("text/html");
              res.getOutputStream().print("<h1>Hosted at: " + req.getContextPath() + "</h1>");
              res.getOutputStream().print("<h2>" + ejbClient.sayHello("Duke") + "</h2>");
          }

      and again Shift+Command+I to fix the imports. The complete class looks like:

      package server;

      import java.io.IOException;
      import javax.ejb.EJB;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      /**
       * @author arungupta
       */
      @WebServlet(urlPatterns="/hello")
      public class HelloServlet extends HttpServlet {
          @EJB HelloEJB ejbClient;

          @Override
          public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
              res.setContentType("text/html");
              res.getOutputStream().print("<h1>Hosted at: " + req.getContextPath() + "</h1>");
              res.getOutputStream().print("<h2>" + ejbClient.sayHello("Duke") + "</h2>");
          }
      }
That completes the project creation. Now lets make our application deployment descriptor free by expanding "WEB-INF" directory and deleting "sun-web.xml" and "web.xml". Java EE 6 makes the deployment descriptors optional by introducing equivalent annotations.

Lets run the project by right-click on the project and select "Run". The web application is deployed to GlassFish v3 Preview 47b and "http://localhost:8080/WebApplication1" shows the default "index.jsp" created by the IDE.

Our servlet is accessible at "http://localhost:8080/WebApplication1/hello" and shows the output as:



The directory of the generated WAR file looks like:



As evident "WEB-INF/classes" has only two POJO classes and yet this is a Java EE 6 application.

So we created a trivial Java EE 6 application using Servlet 3 and EJB 3.1 APIs and deployed successfully on GlassFish v3 Preview 47b using NetBeans 6.7.

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: totd glassfish v3 javaee6 servlet3 ejb3.1 netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090430 Thursday April 30, 2009

TOTD #81: How to use nginx to load balance a cluster of GlassFish Gem ?

nginx (pronounced as "engine-ex") is an open-source and high-performance HTTP server. It provides the common features such as reverse proxying with caching, load balancing, modular architecture using filters (gzipping, chunked responses, etc), virtual servers, flexible configuration and much more.

nginx is known for it's high performance and low resource consumption. It's a fairly popular front-end HTTP server in the Rails community along with Apache, Lighttpd, and others. This TOTD (Tip Of The Day) will show how to install/configure nginx for load-balancing/front-ending a cluster of Rails application running on GlassFish Gem.
  1. Download, build, and install nginx using the simple script (borrowed from dzone):

    ~/tools > curl -L -O http://sysoev.ru/nginx/nginx-0.6.36.tar.gz
    ~/tools > tar -xzf nginx-0.6.36.tar.gz
    ~/tools > curl -L -O http://downloads.sourceforge.net/pcre/pcre-7.7.tar.gz
    ~/tools > tar -xzf pcre-7.7.tar.gz
    ~/tools/nginx-0.6.36 > ./configure --prefix=/usr/local/nginx --sbin-path=/usr/sbin --with-debug --with-http_ssl_module --with-pcre=../pcre-7.7
    ~/tools/nginx-0.6.36 > make
    ~/tools/nginx-0.6.36 > sudo make install
    ~/tools/nginx-0.6.36 > which nginx
    /usr/sbin/nginx

    OK, nginx is now roaring and can be verified by visiting "http://localhost" as shown below:


  2. Create a simple Rails scaffold as:

    ~/samples/jruby >~/tools/jruby/bin/jruby -S rails runner
    ~/samples/jruby/runner >~/tools/jruby/bin/jruby script/generate scaffold runlog miles:float minutes:integer
    ~/samples/jruby/runner >sed s/'adapter: sqlite3'/'adapter: jdbcsqlite3'/ <config/database.yml >config/database.yml.new
    ~/samples/jruby/runner >mv config/database.yml.new config/database.yml
    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S rake db:migrate
  3. Run this application using GlassFish Gem on 3 separate ports as:

    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S glassfish
    Starting GlassFish server at: 192.168.1.145:3000 in development environment...
    Writing log messages to: /Users/arungupta/samples/jruby/runner/log/development.log.
    Press Ctrl+C to stop.

    The default port is 3000. Start the seond one by explicitly specifying the port using "-p" option ..

    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S glassfish -p 3001
    Starting GlassFish server at: 192.168.1.145:3001 in development environment...
    Writing log messages to: /Users/arungupta/samples/jruby/runner/log/development.log.
    Press Ctrl+C to stop.

    and the last one on 3002 port ...

    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S glassfish -p 3002
    Starting GlassFish server at: 192.168.1.145:3002 in development environment...
    Writing log messages to: /Users/arungupta/samples/jruby/runner/log/development.log.
    Press Ctrl+C to stop.

    On Solaris and Linux, you can run GlassFish as a daemon as well.
  4. Nginx currently uses a simple round-robin algorithm. Other load balancers such as nginx-upstream-fair (fair proxy) and nginx-ey-balancer (maximum connections) are also available. The built-in algorithm will be used for this blog. Edit "/usr/local/nginx/conf/nginx.conf" to specify an upstream module which provides load balancing:
    1. Create a cluster definition by adding an upstream module (configuration details) right before the "server" module:

      upstream glassfish {
              server 127.0.0.1:3000;
              server 127.0.0.1:3001;
              server 127.0.0.1:3002;
          }

      The cluster specifies a bunch of GlassFish Gem instances running at the backend. Each server can be weighted differently as explained here. The port numbers must exactly match as those specified at the start up. The modified "nginx.conf" looks like:



      The changes are highlighted on lines #35 through #39.
    2. Configure load balancing by specifying this cluster using "proxy_pass" directive as shown below:

      proxy_pass http://glassfish;

      in the "location" module. The updated "nginx.conf" looks like:



      The change is highlighted on line #52.
  5. Restart nginx by using the following commands:

    sudo kill -15 `cat /usr/local/nginx/logs/nginx.pid`
    sudo nginx
Now "http://localhost" shows the default Rails page as shown below:



"http://localhost/runlogs" now serves the page from the deployed Rails application.

Now lets configure logging so that the upstream server IP address and port are printed in the log files. In "nginx.conf", uncomment "log_format" directive and add "$upstream_addr" variable as shown:

    log_format  main  '$remote_addr - [$upstream_addr] $remote_user [$time_local] $request '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;

Also change the log format to "main" by uncommenting "access_log logs/access.log main;" line as shown above (default format is "combined"). Accessing "http://localhost/runlogs" shows the following lines in "logs/access.log":

127.0.0.1 - [127.0.0.1:3000] - [29/Apr/2009:15:27:57 -0700] GET /runlogs/ HTTP/1.1 "200" 3689 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3001] - [29/Apr/2009:15:27:57 -0700] GET /favicon.ico HTTP/1.1 "200" 0 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3002] - [29/Apr/2009:15:27:57 -0700] GET /stylesheets/scaffold.css?1240977992 HTTP/1.1 "200" 889 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"

The browser makes multiple requests (3 in this case) to load resources on a page and they are nicely load-balanced on the cluster. If an instance running on port 3002 is killed, then the access log show the entries like:

127.0.0.1 - [127.0.0.1:3000] - [29/Apr/2009:15:28:53 -0700] GET /runlogs/ HTTP/1.1 "200" 3689 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3002, 127.0.0.1:3000] - [29/Apr/2009:15:28:53 -0700] GET /favicon.ico HTTP/1.1 "200" 0 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3001] - [29/Apr/2009:15:28:53 -0700] GET /stylesheets/scaffold.css?1240977992 HTTP/1.1 "200" 889 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"

The second log line shows that server running on port 3002 did not respond and so it automatically fall back to 3000, this is nice!

But this is inefficient because a back-end trip is made even for serving a static file ("/favicon.ico" and "/stylesheets/scaffold.css?1240977992"). This can be easily solved by enabling Rails page caching as described here and here.

More options about logging are described in NginxHttpLogModule and upstream module variables are defined in NginxHttpUpstreamModule.

Here are some nginx resources:
Are you using nginx to front-end your GlassFish cluster ?

Apache + JRuby + Rails + GlassFish = Easy Deployment! shows similar steps if you want to front-end your Rails application running using JRuby/GlassFish with Apache.

Hear all about it in Develop with Pleasure, Deploy with Fun: GlassFish and NetBeans for a Better Rails Experience session at Rails Conf next week.

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

Technorati: rubyonrails glassfish v3 gem jruby nginx loadbalancing clustering

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090408 Wednesday April 08, 2009

TOTD #78: GlassFish, EclipseLink, and MySQL efficient pagination using LIMIT

EclipseLink JPA replaces TopLink Essentials as the JPA implementation in GlassFish v3. One of the benefits of using EclipseLink is that it provides efficient pagination support for the MySQL database by generating native SQL statements such as "SELECT ... FROM <table> LIMIT <offset>, <rowcount>".

The MySQL LIMIT clause definition says:

The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be non-negative integer constants (except when using prepared statements).

With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

So instead of fetching all rows from the database and then filtering from row 6-15, only rows 6 through 15 are fetched.

This TOTD (Tip Of The Day) explains how to create a JPA Persistence Unit for sakila (MySQL sample database) using NetBeans, use EclipseLink as the Persistence Provider, and then write a JPA query to leverage the pagination support - all on GlassFish v3.

  1. Create a Persistence Unit for "sakila" as explained in this blog using bullets #1 - 3. The differences are explained below:
    1. In 2.1, choose "GlassFish v3 Prelude" as the server. Even though "GlassFish v3 Prelude" is chosen as the server but it will be replaced with a recent promoted build because pagination feature is not implemented in the Prelude. Alternatively you can use NetBeans 6.7 M3 and GlassFish v3 as explained here.
    2. In 3.3, EclipseLink is shown as the default Persistence Provider as shown below:

    3. In 3.5, there is no need to specify the properties for "user" and "password as the JDBC resource is stored in the server configuration. Instead specify the following property:

      <properties>
          <property name="eclipselink.logging.level" value="FINE"/>
      </properties>

      This will log any SQL statement sent by JPA to the underlying persistence provider (EclipseLink in this case).
  2. If GlassFish v3 was configured using NetBeans 6.7 M3, then the JDBC Connection Pool and JDBC resource were created in the server directly. If not, then download and unzip the latest GlassFish v3 latest promoted build (b43 as of this writing). Create the JDBC Connection Pool as:

    ./asadmin create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --property user=duke:password=glassfish:ServerName=localhost:portNumber=3306:databaseName=sakila jdbc-mysql-pool

    and the JDBC resource:

    ./asadmin create-jdbc-resource --connectionpoolid jdbc-mysql-pool jndi/sakila

    GlassFish v3 b43 bundles "Eclipse Persistence Services - 2.0.0.r3652-M1". A later blog will explain how to replace the bundled EclipseLink version with a newer/different EclipseLink version.
  3. Create a new Servlet "QueryServlet". Inject the javax.persistence.EntityManagerFactory resource:

        @PersistenceUnit
        EntityManagerFactory emf;

    and change the "processRequest" operation to:

            EntityManager em = emf.createEntityManager();

            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();
            try {
                int startRow = Integer.valueOf(request.getParameter("start_row"));
                int howMany = Integer.valueOf(request.getParameter("how_many"));
                Query q = em.createNamedQuery("Film.findAll");

                q.setFirstResult(startRow);
                q.setMaxResults(startRow + howMany);
                for (Object film : q.getResultList()) {
                    out.print(((Film)film).toString() + "<br/>");
                }
            } finally {
                out.close();
            }

    This Servlet reads two parameters from the request and sets parameters on the JPA Query to enable pagination.
  4. Deploy the application on GlassFish v3.
    1. Using NetBeans 6.7 M3, select "Deploy" from the context-sensitive menu.
    2. Using NetBeans 6.5.1, select "Clean and Build" and then manually deploy the WAR file using "asadmin deploy dist/Pagination.war".
If the project name was "Pagination", then the Servlet is accessible at "http://localhost:8080/Pagination/QueryServlet?start_row=1&how_many=10" and shows ten rows starting at index "1". The output looks like:



The log file in "domains/domain1/logs/server.log" show the following SQL query generated by EclipseLink:

[#|2009-04-07T14:01:12.815-0700|FINE|glassfish|org.eclipse.persistence.session.file: /Users/arungupta/tools/glassfish/v3/b43/glassfishv3/glassfish/domains/domain1/applications/Pagination/WEB-INF/classes/-PaginationPU.sql| _ThreadID=15;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT film_id AS film_id1, special_features AS special_features2, last_update AS last_update3, rental_duration AS rental_duration4, release_year AS release_year5, title AS title6, description AS description7, replacement_cost AS replacement_cost8, length AS length9, rating AS rating10, rental_rate AS rental_rate11, language_id AS language_id12, original_language_id AS original_language_id13 FROM film LIMIT ?, ?
        bind => [1, 11]|#]

As you can see, the query uses the LIMIT clause which optimizes the data returned from the table.

If a different database, for example Derby, is used then the generated SQL query looks like as:

[#|2009-04-07T17:00:34.210-0700|FINE|glassfish|org.eclipse.persistence.session.file: /Users/arungupta/tools/glassfish/v3/b43/glassfishv3/glassfish/domains/domain1/applications/Pagination/WEB-INF/classes/-PaginationPU.sql| _ThreadID=15;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT film_id, special_features, last_update, rental_duration, release_year, title, description, replacement_cost, length, rating, rental_rate, language_id, original_language_id FROM film|#]

In this case, the entire table is fetched and the rows are filtered based upon the critieria specified on the client side.

If the number of rows is huge (a typical case for enterprise) then MySQL provides efficient fetching of records. And GlassFish v3, with EclipseLink JPA integrated, makes it much seamless for you.

Thanks to Mr GlassFish Persistence (aka Mitesh :) for helping me understand the inner workings.

Discuss this more at Creating Quick and Powerful Web Applications with MySQL, GlassFish, and NetBeans technical session in the upcoming MySQL Users Conference!

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: totd glassfish v3 eclipselink jpa mysql

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090320 Friday March 20, 2009

TOTD # 76: JRuby 1.2, Rails 2.3, GlassFish Gem 0.9.3, ActiveRecord JDBC Adapter 0.9.1 - can they work together ?


Oh, what a week for the JRuby, Rails, and GlassFish enthusiasts!

JRuby 1.2, Rails 2.3GlassFish Gem 0.9.3, and ActiveRecord JDBC Adapater 0.9.1 - all released earlier this week. This is an opportune moment to run the integration tests to ensure the latest JRuby and GlassFish versions work nicely with each other.

First, lets see whats there to get exicted in each release.

JRuby 1.2 introduces a new versioning scheme by jumping from 1.1.6 -> 1.2. JRUBY-3649 is an important fix for the Windows users. Improved Ruby 1.9 support, 3-6x faster parsing, and preliminary android support are some other highlights. 1052 revisions and 256 bugfixes since 1.1.6 (89 days ago) means close to 12 revisions / day and 3 bugfixes/day!

Rails 2.3 has a bunch of highlights ranging from Rack integration, nested forms, attributes, and transactions, reconnecting lost MySQL connections, Application controller renamed (make sure to "rake rails:update:action_controller" to update from an older version), faster boot time in dev mode using lazy loading, and many others. The Release Notes provide all the detailed information.

The GlassFish Gem with features like running as daemon,  rake-style configuration of JVM options, ability to "sudo install" gem and run as normal user and multi-level logging are all gearing towards adding more production-quality features. My favorite here is running as daemon since that brings the Gem one step closer to the Rails community.

Lets get back to running our tests #1, #2, #3, #4, and #5 for these released versions.

First, lets unzip JRuby 1.2 and install Rails 2.3, GlassFish Gem 0.9.3, and other gems as:

~/tools/jruby-1.2.0 >./bin/jruby -S gem install rails glassfish activerecord-jdbcmysql-adapter
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed activesupport-2.3.2
Successfully installed activerecord-2.3.2
Successfully installed actionpack-2.3.2
Successfully installed actionmailer-2.3.2
Successfully installed activeresource-2.3.2
Successfully installed rails-2.3.2
Successfully installed rack-0.9.1
Successfully installed glassfish-0.9.3-universal-java
Successfully installed activerecord-jdbc-adapter-0.9.1
Successfully installed jdbc-mysql-5.0.4
Successfully installed activerecord-jdbcmysql-adapter-0.9.1
11 gems installed
Installing ri documentation for activesupport-2.3.2...
Installing ri documentation for activerecord-2.3.2...
Installing ri documentation for actionpack-2.3.2...
Installing ri documentation for actionmailer-2.3.2...
Installing ri documentation for activeresource-2.3.2...
Installing ri documentation for rack-0.9.1...
Installing ri documentation for glassfish-0.9.3-universal-java...
Installing ri documentation for activerecord-jdbc-adapter-0.9.1...
Installing ri documentation for jdbc-mysql-5.0.4...
Installing ri documentation for activerecord-jdbcmysql-adapter-0.9.1...
Installing RDoc documentation for activesupport-2.3.2...
Installing RDoc documentation for activerecord-2.3.2...
Installing RDoc documentation for actionpack-2.3.2...
Installing RDoc documentation for actionmailer-2.3.2...
Installing RDoc documentation for activeresource-2.3.2...
Installing RDoc documentation for rack-0.9.1...
Installing RDoc documentation for glassfish-0.9.3-universal-java...
Installing RDoc documentation for activerecord-jdbc-adapter-0.9.1...
Installing RDoc documentation for jdbc-mysql-5.0.4...
Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.9.1...

If you have a previous version of GlassFish gem installed, then update it as:

~/tools/jruby-1.1.6 >./bin/jruby -S gem update glassfish
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Updating installed gems
Updating glassfish
Successfully installed glassfish-0.9.3-universal-java
Gems updated: glassfish

Similarly ActiveRecord gem can be updated as:

~/tools/jruby-1.1.6 >./bin/jruby -S gem update activerecord
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Updating installed gems
Updating activerecord-jdbc-adapter
Successfully installed activerecord-jdbc-adapter-0.9.1
Updating activerecord-jdbcmysql-adapter
Successfully installed activerecord-jdbcmysql-adapter-0.9.1
Updating activerecord-jdbcsqlite3-adapter
Successfully installed jdbc-sqlite3-3.6.3.054
Successfully installed activerecord-jdbcsqlite3-adapter-0.9.1
Updating merb_activerecord
Successfully installed merb_activerecord-1.0.0.1
Gems updated: activerecord-jdbc-adapter, activerecord-jdbcmysql-adapter, jdbc-sqlite3, activerecord-jdbcsqlite3-adapter, merb_activerecord

Running test #1 encounters JRUBY-3502, basically "db:create" is not working with JRuby 1.2.0, Rails 2.3.2 and MySQL ActiveRecord JDBC Adapter. However "db:create" works if JRuby 1.2.0 and Rails 2.2.2 are used. Alternatively SQLite3 ActiveRecord JDBC Adapter may be used. So first lets install SQLite3 JDBC adapter as:

~/tools/jruby-1.2.0 >./bin/jruby -S gem install activerecord-jdbcsqlite3-adapter
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed jdbc-sqlite3-3.6.3.054
Successfully installed activerecord-jdbcsqlite3-adapter-0.9.1
2 gems installed
Installing ri documentation for jdbc-sqlite3-3.6.3.054...
Installing ri documentation for activerecord-jdbcsqlite3-adapter-0.9.1...
Installing RDoc documentation for jdbc-sqlite3-3.6.3.054...
Installing RDoc documentation for activerecord-jdbcsqlite3-adapter-0.9.1...

Now lets recreate our application without specifying "-d mysql" switch as:

~/tools/jruby-1.2.0/samples/rails >../../bin/jruby -S rails runner
      create 
      create  app/controllers
      create  app/helpers
. . .
      create  log/production.log
      create  log/development.log
      create  log/test.log

In the generated "config/database.yml", change the database adapter from:

development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

to

development:
  adapter: jdbcsqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

The changes are highlighted in bold. Run the remainder of test #1.

The supported Rails version on GlassFish v3 Prelude is Rails 2.1 so we'll stick with running a Rails 2.1 (instead of Rails 2.3.2) simple scaffold application but will use the latest JRuby 1.2.0. Running a Rails 2.3.2 on GlassFish v3 Prelude will encounter issue #7384. Please add your comments to the bug report if you are running GlassFish v3 Prelude in production and would like this bug to be fixed!

Rails 2.3.2 require workaround for a WAR-based deployment of a Rails application as expained here. This workaround is required only if you are using JRuby-Rack 0.9.1 or lower. A newer version of JRuby-Rack may solve these problems making these steps optional. The steps are anyway outlined below for convenience:
  1. Uncomment the following line from "config/initializers/session_initializers.rb":

    ActionController::Base.session_store = :active_record_store
  2. Do "jruby -S warble config" to generate the template "config/warble.rb", edit it and add the following line:

    config.webxml.jruby.session_store = 'db'
  3. In "config/environment.rb", add the following code:

     if defined?(JRUBY_VERSION)
     # hack to fix jruby-rack's incompatibility with rails edge
     module ActionController
       module Session
         class JavaServletStore
           def initialize(app, options={}); end
           def call(env); end
         end
       end
     end
    end 

    just above the line "Rails::Initializer.run do |config|".
Always refer to JRuby/Rails 2.3.2 wiki for the latest information on these steps.

The deployment goes fine after making the changes but bringing up the scaffold page in the browser shows the following error message:


So commented the "jndi" and "driver" entry from "config/database.yml" such that the bundled MySQL JDBC Adapter is used instead. And then the test passes.

Here is a status report after running all the tests:

Test # Description Status
#1 Simple Scaffold using GlassFish Gem PASS (with workaround in JRUBY-3502)
#2 Simple Scaffold using GlassFish v3 Prelude PASS
#3 Simple Scaffold using GlassFish v3 FAIL (used workaround mentioned in JRUBY-3502,  issues #7266, #7270, #7271 still need to be fixed). PASS if the Application and Controller name are different.
#4 Simple Scaffold as WAR-based application on GlassFish v2.1 FAIL (issue #7385), PASS (with workaround in issue JRUBY-3515)
#5 Redmine using GlassFish Gem PASS

It's certainly exciting to know that @grantmichaels is already using the latest version of GlassFish Gem and Rails in production :)

JRuby/GlassFish Wiki provide a list of other known JRuby/Rails/GlassFish deployments in production. Leave a comment on this blog if you are using it as well and we'll be happy to add your name!

The complete set of tests are available using the tags rubyonrails+glassfish+integrationtest. So to answer the title of this blog - YES, JRuby 1.2.0, Rails 2.3.2, GlassFish Gem 0.9.3, ActiveRecord JDBC Adapater 0.9.1 all work together with the restrictions stated above. GlassFish v3 is a moving target and the bugs will be fixed soon. JRUBY-3515 is what delayed this entry otherwise would've posted it much earlier ;-)

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

Technorati: totd rubyonrails glassfish v3 gem jruby sampleapp activerrecord redmine integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090318 Wednesday March 18, 2009

TOTD #75: Getting Started with Grails using GlassFish v3 Embedded


For a change, this blog entry is talking about something that exists for a while now :)

Basically, I wanted to setup a demo environment for Grails and GlassFish v3 Prelude on my machine and so decided to dcument the steps along the process. More detailed steps with explanation are available on GlassFish/Grails Getting Started Wiki.

  1. Download and unzip GlassFish v3 Prelude.
  2. Run GlassFish Update Center to install the Grails module as shown:

    ~/demos/glassfishv3-prelude >./bin/updatetool

    The software needed for this command (updatetool) is not installed.

    If you choose to install Update Tool, your system will be automatically
    configured to periodically check for software updates. If you would like
    to configure the tool to not check for updates, you can override the
    default behavior via the tool's Preferences facility.

    When this tool interacts with package repositories, some system information
    such as your system's IP address and operating system type and version
    is sent to the repository server. For more information please see:

    http://wiki.updatecenter.java.net/Wiki.jsp?page=UsageMetricsUC2

    Once installation is complete you may re-run this command.

    Would you like to install Update Tool now (y/n): y

    Install image: /Users/arungupta/demos/glassfishv3-prelude/bin/..
    Installing pkg packages.
    Installing: [pkg:/pkg@1.0.7,0-15.1269:20081008T212532Z, pkg:/python2.4-minimal@2.4.5.0,0-15.1269:20081008T212544Z]
    Installing updatetool packages.
    Installing: [pkg:/updatetool@2.0.0,0-15.1269:20081008T212613Z, pkg:/wxpython2.8-minimal@2.8.8,0-15.1269:20081008T212630Z]
    Registering notifier: Already registered.
    Initialization complete.

    Software successfully installed. You may now re-run this command (updatetool).
  3. Now run the Update Center again to see a screen as shown below:


  4. Select "GlassFish support for Grails Framework" and click on "Install" to install the module locally. This creates a new directory "grails" in your GlassFish v3 Prelude directory and install Grails 1.0.4 there.
  5. Set environment variables as:

    ~/demos/glassfishv3-prelude/glassfish/grails >export GRAILS_HOME=~/demos/glassfishv3-prelude/glassfish/grails
    ~/demos/glassfishv3-prelude/glassfish/grails >export PATH=$GRAILS_HOME/bin:$PATH

  6. Create a template application as:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples >grails create-app bookstore

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/CreateApp.groovy
    Environment set to development
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/src
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/src/java
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/src/groovy
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/controllers
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/services
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/domain
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/taglib
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/utils
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/views
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/views/layouts
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/i18n
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/conf
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/unit
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/integration
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/scripts
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/js
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/css
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/images
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/META-INF
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/lib
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/conf/spring
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/conf/hibernate
    [propertyfile] Creating new property file: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/application.properties
         [copy] Copying 2 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copied 1 empty directory to 1 empty directory under /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 2 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/WEB-INF
         [copy] Copying 5 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/WEB-INF/tld
         [copy] Copying 28 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app
         [copy] Copying 18 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    [propertyfile] Updating property file: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/application.properties
    Created Grails Application at /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore

  7. Create a domain specific class as:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore >grails create-domain-class book

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/CreateDomainClass.groovy
    Environment set to development
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/domain
    Created Domain Class for Book
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/integration
    Created Tests for Book

  8. Add attributes to the domain class by editing "grails-app/domain/Book.groovy" such that it looks like:

    class Book {
      String title
      String author
    }

  9. Create a new controller as:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore >grails create-controller Book

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/CreateController.groovy
    Environment set to development
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/controllers
    Created Controller for Book
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/views/book
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/integration
    Created ControllerTests for Book
  10. Edit the generated controller in "grails-app/controller/BookController.groovy" to specify scaffold for the domain class. It looks like:

    class BookController {
        def scaffold = Book
    }
  11. Run the app as shown below:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore >grails run-app

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/RunApp.groovy
    Environment set to development
    Starting GlassFish embedded server...    [mkdir] Created dir: /Users/arungupta/.grails/1.0.4/projects/bookstore/classes
      [groovyc] Compiling 8 source files to /Users/arungupta/.grails/1.0.4/projects/bookstore/classes
        [mkdir] Created dir: /Users/arungupta/.grails/1.0.4/projects/bookstore/resources/grails-app/i18n
    [native2ascii] Converting 11 files from /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/i18n to /Users/arungupta/.grails/1.0.4/projects/bookstore/resources/grails-app/i18n
         [copy] Copying 1 file to /Users/arungupta/.grails/1.0.4/projects/bookstore/classes
         [copy] Copying 1 file to /Users/arungupta/.grails/1.0.4/projects/bookstore/resources
         [copy] Copying 1 file to /Users/arungupta/.grails/1.0.4/projects/bookstore
    Running Grails application..
    Application name : bookstore
    Web App Root :/Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app
    web.xml:/Users/arungupta/.grails/1.0.4/projects/bookstore/resources/web.xml
    Mar 18, 2009 10:19:09 PM CommonClassLoaderManager Skipping creation of CommonClassLoader as there are no libraries available
    INFO: urls = []
    no resource bundle found for version, using default GlassFish version
    Mar 18, 2009 10:19:09 PM AppServerStartup run
    INFO: [Thread[GlassFish Kernel Main Thread,5,main]] started
    Mar 18, 2009 10:19:09 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8080
    Mar 18, 2009 10:19:10 PM org.glassfish.admin.mbeanserver.ConnectorStartupService$ConnectorsStarterThread startConnector
    INFO: Started JMXConnector, JMXService URL = service:jmx:rmi:///jndi/rmi://192.168.1.145:8686/jmxrmi
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.v3.admin.adapter.AdminEndpointDecider setGuiContextRoot
    INFO: Admin Console Adapter: context root: /admin
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3 Prelude startup time : Embedded(418ms) startup services(887ms) total(1305ms)
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.web.WebContainer createHttpListener
    INFO: Created HTTP listener http-listener-1 on port 8080
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.web.WebContainer createHosts
    INFO: Created virtual server server
    Mar 18, 2009 10:19:11 PM org.apache.catalina.loader.WebappLoader setClassPath
    INFO: Unknown loader org.glassfish.grails.MaskingClassLoader@3b948e75 class org.glassfish.grails.MaskingClassLoader
    Mar 18, 2009 10:19:12 PM org.apache.catalina.loader.WebappLoader setClassPath
    INFO: Unknown loader org.glassfish.internal.api.DelegatingClassLoader@191fa2af class org.glassfish.internal.api.DelegatingClassLoader
    Mar 18, 2009 10:19:12 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Set web app root system property: 'bookstore-development-0.1' = [/Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/]
    Mar 18, 2009 10:19:12 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Initializing log4j from [file:/Users/arungupta/.grails/1.0.4/projects/bookstore/resources/log4j.properties]
    Mar 18, 2009 10:19:12 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Initializing Spring root WebApplicationContext
    [0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@430b4506: display name [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@430b4506]; startup date [Wed Mar 18 22:19:14 PDT 2009]; parent: org.springframework.web.context.support.XmlWebApplicationContext@6ceb51a8
    [0] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@430b4506]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1f43243e
    Mar 18, 2009 10:19:17 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Initializing Spring FrameworkServlet 'grails'
    Mar 18, 2009 10:19:17 PM com.sun.enterprise.web.WebApplication start
    INFO: Loading application bookstore at /bookstore
    Server running. Browse to http://localhost:8080/bookstore

    Notice, here GlassFish v3 Embedded Server is used for running the application. It is now accessible at "http://localhost:8080/bookstore" and looks like:



  12. Clicking on the "BookController" shows:


  13. Click on "New Book" to add a new book as:

  14. Each entry can be updated/deleted after clicking on "Create" ...



    or "Book List" as shown below:



In a matter of few minutes, we created a simple Grails scaffold that runs using GlassFish v3 Embedded Server.

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

Technorati: totd glassfish v3 grails embedded prelude

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090316 Monday March 16, 2009

TOTD # 74: JRuby and GlassFish Integration Test #5: JRuby 1.2.0 RC2 + Rails 2.x.x + GlassFish + Redmine


TOTD #70, #71, #72, #73 shows four integration tests that can ensure that the latest JRuby and GlassFish versions work nicely with each other.

#70 showed how to create a trivial Rails application and run it using GlassFish Gem#71 showed how the same application can be deployed on GlassFish v3 Prelude#72 showed how to deploy the same application on GlassFish v3. #73 showed how to deploy a Rails application as WAR file and use the JDBC connection pooling framework available in GlassFish.

The next set of tests ensure that some commonly used open source Rails applications can be easily run using this setup. The first one is Redmine - 0.8 is the stable release now. Redmine was first tried on GlassFish a few months ago. The steps have simplified since then :)

Lets begin integration test #5.

  1. Download Redmine 0.8 ...

    /samples/jruby/redmine >svn co http://redmine.rubyforge.org/svn/branches/0.8-stable redmine-0.8
    A    redmine-0.8/test
    A    redmine-0.8/test/unit
    A    redmine-0.8/test/unit/document_test.rb
    A    redmine-0.8/test/unit/token_test.rb
    . . .
    A    redmine-0.8/public/stylesheets/scm.css
    A    redmine-0.8/public/stylesheets/application.css
    A    redmine-0.8/public/favicon.ico
     U   redmine-0.8
    Checked out revision 2580.
  2. Copy "config/database.yml.example" to "config/database.yml" and then generate/migrate the database:

    ~/samples/jruby/redmine/redmine-0.8 >../jruby-1.2.0RC2/bin/jruby -S rake db:create
    (in /Users/arungupta/samples/jruby/redmine/redmine-0.8)
    ~/samples/jruby/redmine/redmine-0.8 >../jruby-1.2.0RC2/bin/jruby -S rake db:migrate
    (in /Users/arungupta/samples/jruby/redmine/redmine-0.8)
    == 1 Setup: migrating =========================================================
    -- create_table("attachments", {:force=>true})
       -> 0.0880s
    -- create_table("auth_sources", {:force=>true})
       -> 0.1430s
    . . .
    == 100 AddChangesetsUserId: migrating =========================================
    -- add_column(:changesets, :user_id, :integer, {:default=>nil})
       -> 0.0980s
    == 100 AddChangesetsUserId: migrated (0.0990s) ================================

    == 101 PopulateChangesetsUserId: migrating ====================================
    == 101 PopulateChangesetsUserId: migrated (0.0030s) ===========================

  3. Redmine is a Rails 2.1.x application so install Rails 2.1.x using JRuby 1.2 and run the application as:

    ~/samples/jruby/redmine/redmine-0.8 >../jruby-1.2.0RC2/bin/jruby -S glassfish
    Mar 13, 2009 11:14:59 AM com.sun.enterprise.glassfish.bootstrap.ASMainStatic findDerbyClient
    INFO: Cannot find javadb client jar file, jdbc driver not available
    Mar 13, 2009 11:14:59 AM APIClassLoaderService createAPIClassLoader
    INFO: APIClassLoader = java.net.URLClassLoader@59fb8de1
    . . .
    Mar 13, 2009 11:15:10 AM com.sun.grizzly.pool.DynamicPool$1 run
    INFO: New instance created in 10,175 milliseconds
    Mar 13, 2009 11:15:10 AM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3  startup time : Static(356ms) startup services(11456ms) total(11812ms)

    Very simple and seamless!
The application is now accessible at "http://locahost:3000". The following screen dumps are captured by traversing through different parts of the application:















The next blog will show the last test in this series. The current set of tests are available using the tags rubyonrails+glassfish+integrationtest.

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

Technorati: totd rubyonrails glassfish v3 gem jruby sampleapp redmine integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|
« Previous page | Main | Next page »

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.