Archive

Archive for the ‘grails’ Category

Dissecting an Amazon Elastic Beanstalk instance

January 22nd, 2011 5 comments

Amazon Elastic Beanstalk provides a PaaS similar to Google AppEngine, bundling many of their existing offerings such as Elastic Compute Cloud (EC2), Simple Storage Service (S3), Simple Notification Service (SNS), Elastic Load Balancing, Auto Scaling, and monitoring using Cloud Watch into a simple to use service. Additionally, other Amazon services such as SimpleDB, Relational Database Service (RDS), Simple Queue Service (SQS) may be used as well.

Currently, Elastic Beanstalk provides a Java-based application container with Apache Tomcat as the work horse. All you have to do is to deploy a standard Java WAR file containing your web application.

Simply create a Java web application with Spring MVC, Grails, OSGi, Eclipse RAP, or any other of the numerous Java web frameworks and upload it using the AWS web console.

Additional containers for other platforms such as Ruby, Python or PHP may follow later, but as Tomcat hosts standard Java WAR files, anything with a Java implementation may be run. Ruby apps based on Rails or Rack using Warbler and JRuby, Python apps using Jython, even PHP apps can be made to run on Beanstalk.

In this blog post, I’ll dive into the inner workings of a Beanstalk server instance and poke around its internals. I invite you to come along for the ride.

Accessing your instance
The first step in dissecting a Beanstalk instance is getting access via SSH.
In order to acces your running instance(s), you first need to configure the SSH key pair to be used:

Configuration dialog in Elastic Beanstalk web console

Configuration dialog in Elastic Beanstalk web console

Enter the name of a key pair as configured in your EC2 web console. See the EC2 guide and the description in the Elastic Beanstalk guide for details on creating and configuring a key pair.

Setting the key pair requires a restart of your Beanstalk environment, which may take a couple of minutes.

Finally look up your instance id and get the instance’s hostname. Connecting to the server is now as simple as this:

ssh -i .ec2/mykeypair.pem ec2-user@ec2-184-72-134-2.compute-1.amazonaws.com

Please note, that you need to connect as user ec2-user, root access can be reached using the command

sudo su -

Getting around your instance
The first steps are to collect some interessting facts. The instance uses a Amazon Linux AMI (release 2010.11.1 (beta), README). The AMI id for the ElasticBeanstalk-Tomcat6-32bit is ami-7609f81f, the kernel id is aki-407d9529. The instance is EBS-based and there is no ephemeral storage. Currently, Beanstalk is only available in the US East zone.

Software
The process list reveals: along with Apache Tomcat, Beanstalk uses the venerable Apache Web Server. Additional software includes Bluepill for basic process monitoring, and Amazons own HostManager (see below), which is run within a Thin web server.

Network setup
Elastic Beanstalk scales EC2 instances as needed. Therefore the first target is a load balancer provided by Elastic Load Balancing. Each instance runs Apache as the front end on port 80, with web request being reverse proxied into Tomcat on port 8080. Requests for URI /_hostmanager are forwarded to HostManager on port 8999.

CloudWatch performs health checks by periodically requesting the root page (URI /) of your application. Both health check URI and frequency are configurable. If an instance is no longer available or the load changes, CloudWatch starts or stops instances.

Application stack
[Image from AWS Elastic Beanstalk Concepts blog post]

HostManager
Local instance management is performed by Amazons HostManager. HostManager is a Ruby application based on Rack and running in a Thin server on port 8999. It receives requests on URI /_hostmanager.

Some examples from the access log:

72.21.217.96 (72.21.217.96) - - [21/Jan/2011:22:00:45 +0000] "POST /_hostmanager/tasks HTTP/1.1" 200 368 "-" "AWS ElasticBeanstalk Health Check/1.0"
10.223.61.43 (10.223.61.43) - - [21/Jan/2011:22:01:05 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
10.122.19.154 (10.122.19.154) - - [21/Jan/2011:22:01:11 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
10.223.61.43 (10.223.61.43) - - [21/Jan/2011:22:01:36 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
10.122.19.154 (10.122.19.154) - - [21/Jan/2011:22:01:42 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
72.21.217.96 (72.21.217.96) - - [21/Jan/2011:22:01:46 +0000] "POST /_hostmanager/tasks HTTP/1.1" 200 368 "-" "AWS ElasticBeanstalk Health Check/1.0"
10.223.61.43 (10.223.61.43) - - [21/Jan/2011:22:02:07 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
10.122.19.154 (10.122.19.154) - - [21/Jan/2011:22:02:13 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
10.223.61.43 (10.223.61.43) - - [21/Jan/2011:22:02:38 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
10.122.19.154 (10.122.19.154) - - [21/Jan/2011:22:02:44 +0000] "GET /_hostmanager/healthcheck HTTP/1.1" 200 90 "-" "ELB-HealthChecker/1.0"
72.21.217.96 (72.21.217.96) - - [21/Jan/2011:22:02:47 +0000] "POST /_hostmanager/tasks HTTP/1.1" 200 368 "-" "AWS ElasticBeanstalk Health Check/1.0"

Files
HostManager is installed in /opt/elasticbeanstalk/srv/hostmanager. A file list can be found here. /opt/elasticbeanstalk/lib also contains a full Ruby 1.9.1 installation.

Some log files can be found at /opt/elasticbeanstalk/var/:

/opt/elasticbeanstalk
/opt/elasticbeanstalk/var
/opt/elasticbeanstalk/var/state
/opt/elasticbeanstalk/var/state/hostmanager.pid
/opt/elasticbeanstalk/var/state/healthcheck
/opt/elasticbeanstalk/var/tmp
/opt/elasticbeanstalk/var/log
/opt/elasticbeanstalk/var/log/LogDirectoryMonitor.log
/opt/elasticbeanstalk/var/log/DaemonManager.log
/opt/elasticbeanstalk/var/log/bluepill.log
/opt/elasticbeanstalk/var/log/hostmanager.log
/opt/elasticbeanstalk/var/log/ApplicationHealthcheck.log
/opt/elasticbeanstalk/var/log/CatalinaLogMonitor.log

Final words
That’s all for today’s blog post. Further posts will take a closer look at HostManager and deployment including the application setup sequence.

I’m looking forward to any feedback and additional information.

Maybe we can even hack HostManager to accept other application containers, e.g. for OSGi applications.

Fork me on GitHub

Released Grails Spy plugin 0.2

July 6th, 2010 No comments

I just released version 0.2 of my Grails Spy plugin.

About

The Grails Spy plugin provides some views to inspect Grails internals such as the Spring application context(s), artefacts, etc.

As most of the beans of the Grails WebApplicationContext are constructed at runtime with the help of a BeanBuilder, there is no Spring xml file with bean definitions.

In order to browse the dynamic bean definitions, Grails Spy can be used to watch into an application’s guts.

Installation

grails install-plugin spy

Usage

Simply install the plugin, enable the Spy controller for the dev environment and run grails run-app. Then browse to http://localhost:8080/yourapp/spy and enjoy.

Changes

  • For security reasons the Spy controller must now be enabled in Config.groovy:
    grails.plugins.spy.enabled = true
    

    The plugin can be enabled or disabled individually for each environment. Example:

    environments {
        production {
            grails.serverURL = "http://www.changeme.com"
        }
        development {
            grails.serverURL = "http://localhost:8080/${appName}"
    	grails.plugins.spy.enabled = true
        }
        test {
            grails.serverURL = "http://localhost:8080/${appName}"
        }
    }
    
  • 'inspect' is now the default action for the spy controller, so it can be called as http://localhost:8080/yourapp/spy instead of http://localhost:8080/yourapp/spy/inspect

License

The Spy plugin is released under the Apache License 2.0.

Source code and Issues

The source code is hosted at GitHub, issues can be reported here.

Screenshots

Eye-candy you say? See below:

GrailsSpy: GrailsApplication

GrailsSpy: ApplicationContext view

GrailsSpy: bean view

Categories: grails, plugin, spy Tags:

Released Grails spy plugin

January 6th, 2010 1 comment

While digging through the inner workings of Grails in order to improve my OSGi plugin, it is sometimes necessary to inspect the GrailsApplication object and its companion Spring ApplicationContext(s).

As most of the beans of the Grails WebApplicationContext are constructed at runtime with the help of a BeanBuilder, there is no Spring xml file with bean definitions.

Only the main application context can be inspected, e.g. by extracting it from the generated war file:

jinspect -a target/myapp-0.1.war

In order to browse the dynamic bean definitions I created a little plugin called Grails Spy, which can be used to watch into an application’s guts.

License

The Spy plugin is released under the Apache License 2.0.

Source code and Issues

The source code is hosted at GitHub, issues can be reported here.

Installation

As always, simply execute grails install-plugin spy.

Note: until the Grails plugin page is sync’ed, the plugin can also be installed using
grails install-pluginhttp://cloud.github.com/downloads/jetztgradnet/grails-spy-plugin/grails-spy-0.1.zip

Usage

Simply browse to http://localhost:8080/myapp/spy/ and have a closer look.

Note: this path is NOT PROTECTED, so don’t do this in a production environment! Or at least use one of the security plugins to protect this page.

Screenshots

Eye-candy you say? See below:

GrailsSpy: GrailsApplication

GrailsSpy: ApplicationContext view

GrailsSpy: bean view

Categories: grails, plugin, spy Tags:

Updated bash completion script for OSX and Grails 1.1 & 1.2

January 6th, 2010 5 comments

Fernando Takai wrote an excellent bash completion script (also available here, originally from Ted Naleid), which makes calling Grails commands much easier.

Some examples:

Within a Grails application directory, listing all available commands:

myapp> grails [tab][tab]
bootstrap create-integration-test generate-controller list-plugins_ set-version
bug-report create-plugin_ generate-views package shell
clean create-script help_ package-plugin_ stats
compile create-service init plugin-info_ test-app
console create-tag-lib install-dependency release-plugin tomcat
create-app_ create-unit-test install-plugin run-app uninstall-plugin
create-controller dependency-report install-templates run-war upgrade
create-domain-class doc integrate-with schema-export war
create-filters generate-all list-plugin-updates set-proxy_

Within a Grails application directory, completing a command:

myapp> grails run-[tab][tab]
run-app run-war

Outside of a Grails application directory, listing all available commands:

home> grails [tab][tab]
create-app create-plugin help list-plugins package-plugin plugin-info set-proxy

Changes

I updated the script to adapt it to new Grails versions and made some minor changes:

* works with plugin provided scripts in Grails version >= 1.1, were plugins are stored under $HOME/.grails/grailsversion/projects/appname/plugins.
* detects the Grails version from $GRAILS_HOME instead of choosing the latest version from $HOME/.grails.
* adapts to different locations of plugins-list.xml, which changed with newer Grails versions
* does not need gawk (which is not installed by default on OSX)

My version of the script was tested with Grails 1.2 and OSX Snow Leopard and can be found at GitHub or below.

Installation

Save the script to an appropriate path (e.g. ~/bin/grails-bash-completion.sh)
[ -r ~/bin/grails-bash-completion.sh ] && source ~/bin/grails-bash-completion.sh

The complete Script

Categories: grails, scripts Tags:

Script to inspect jar and war files, Grails applications and plugins

January 4th, 2010 No comments

I just wrote a little script to inspect jar and war files, Grails applications and plugins.

Installation

Simply copy the script to somewhere in your path (e.g. ~/bin) and make it executable using
chmod +x jinspect

I tested the script on OSX Snow Leopard, but it should run on other versions of OSX and Linux, too.

Examples:

List all files in a war/jar/zip:
jinspect -l myapp.war

Show contents of some files in a jar/war/zip:
jinspect myapp.war index.html another.txt

List gsp and jsp files in a war:
jinspect -JG myapp.war

Show contents of web.xml file in a war:
jinspect -w myapp.war

Extract and save web.xml file in a war:
jinspect -Xw myapp.war

Show contents of the Plugin class of a Grails plugin:
jinspect -P grails-osgi-0.1.zip

Available options:

jinspect [-hHvxXoawmISMWjJrgGcCpPlLZZZ] jarfile [filename ...]
Options:
-h show help
-v be more verbose
-X save specified files (including path) to the current directory instead of printing them
-l list war contents; specify again to include more information
-x list xml files
-o list properties files
-c list class files
-j list java files
-J list jsp files
-S list js files
-g list groovy files
-G list gsp files
-H list html files
-C list css files
-I list image files
-L list files in lib directory
-M list files in META-INF directory
-W list files in WEB-INF directory
-a show WEB-INF/applicationContext.xml
-w show WEB-INF/web.xml
-r show WEB-INF/grails.xml
-m show META-INF/MANIFEST.MF
-p show plugin.xml
-P show *GrailsPlugin.groovy
-d show manifest headers in nicely formatted way; implies -m
-D display named manifest header; can be used multiple times, implies -m

Script
(also available on GitHub)

Categories: grails, scripts Tags:

Grails on OSGi (3): Released Grails OSGi plugin 0.1

January 3rd, 2010 30 comments

The Grails OSGi plugin provides scripts to package a Grails application as an OSGi bundle. Additionally the bundle(s) may be run in an OSGi container assembled ad hoc by the excellent Pax Runner or deployed to a SpringSource DM Server.

License

The OSGi plugin is released under the Apache License 2.0.

Installation

Simply call grails install-plugin osgi to install the OSGi plugin.

Usage:

Creating an OSGi bundle from the Grails application

grails bundle
grails prod bundle

Running the bundle

grails run-bundle
grails prod run-bundle

The application can be accessed at http://localhost:8080/myapp/.

Note: at first start the OSGi runtime is assembled, which may take some time, while Maven is downloading the internet…

Creating a zipped OSGi runtime

grails assemble-osgi-runtime
grails prod assemble-osgi-runtime

Deploy bundle to DM Server

grails dmserver deploy (Not yet implemented)

Getting around the OSGi runtime

The OSGi runtime is based on the Equinox OSGi framework, Pax Web and some additional bundles.

Web Console

The Felix Web Management Console provides excellent insight into the inner workings (see Screenshots). It can be accessed at http://localhost:8080/system/console/ with user “admin” and password “admin”.

Shell Console

The command grails run-bundle drops the user in the Equinox Shell. Typing help shows the available commands.

How it works

In order to be a valid OSGi bundle, the application is war’ed and provided with the necessary bundle manifest headers (see scripts/_Event.groovy for details).
The bundle can be created using grails bundle.

The OSGi runtime is assembled in the target/osgi directory.

Source code and Issues

The source code is hosted at GitHub, issues can be reported here.

Roadmap

  • make bundle generation configurable (e.g. include/exclude dependencies, …)
  • make OSGi runtime created by grails run-bundle and grails assemble-osgi-runtime configurable
  • support auto-reloading of changed artifacts
  • use Spring DM instead of Pax Web as Web extender
  • remove dependencies from bundle and package them as their own plugins (re-using existing bundles from the SpringSource Enterprise Repository
  • export main Grails beans and application context as OSGi service
  • export services as OSGi service (via static expose = 'osgi')
  • provide access to OSGi BundleContext to artifacts (controllers, services, …)
  • implement deployment to DM Server
  • consider other deployment options: Apache Karaf, …
Categories: grails, osgi, plugin, release Tags:

Grails on OSGi (2): First steps

November 24th, 2009 7 comments

The first step on the road to running Grails applications in an OSGi environment is to get a simple application to run as a monolithic bundle (almost) without changes.


Test application

We create a simple Grails application (e.g. the one described in a article on developer works; the application has a single domain class Trip, the controller and all views are generated). A single domain class and the corresponding controller is all we need for a simple test.


Bundle 101

For the first attempt, the Grails application will be transformed, into a single, monolithic bundle (see part 1 for possible modularization levels) containing all dependencies like Grails, Groovy, Hibernate, Spring, …

A bundle is basically a JAR or WAR with some special headers in its manifest file. Required headers are Bundle-SymbolicName, which uniquely identifies the bundle, Bundle-Version, which specifies the bundle version (multiple versions of the bundle can run concurrently!) and Bundle-ClassPath, which specifies the classpath within the bundle. Other important headers are Import-Package and Export-Package, which are necessary when using code and resources from and providing classes to other bundles.


Preparing the bundle

In order to create a valid bundle manifest, $GRAILS_HOME/scripts/_GrailsWar.groovy must be patched with bundle-manifest.patch:

cd $GRAILS_HOME
patch -p0 < /pacth/to/bundle-manifest.patch

In the future, the changes could either be integrated into Grails directly or into a OSGi plugin.

Our Grails application will need to be transformed into a bundle, so we package it using grails war. The application and all dependencies are contained in the resulting WAR file.

The bundle manifest can now be inspected using the following command (on Linux or Mac OSX):

unzip -p target/trip-planner-0.1.war META-INF/MANIFEST.MF

The manifest now looks like this:


Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 14.1-b02-92 (Apple Inc.)
Bundle-ManifestVersion: 2
Bundle-Name: trip-planner
Bundle-SymbolicName: trip-planner
Bundle-Version: 0.1
Bundle-ClassPath: WEB-INF/classes,WEB-INF/lib/antlr-2.7.6.jar,WEB-INF/
lib/aopalliance-1.0.jar,WEB-INF/lib/aspectjrt-1.6.2.jar,WEB-INF/lib/a
spectjweaver-1.6.2.jar,WEB-INF/lib/cglib-nodep-2.1_3.jar,WEB-INF/lib/
commons-beanutils-1.8.0.jar,WEB-INF/lib/commons-codec-1.3.jar,WEB-INF
/lib/commons-collections-3.2.1.jar,WEB-INF/lib/commons-dbcp-1.2.2.jar
,WEB-INF/lib/commons-el-1.0.jar,WEB-INF/lib/commons-fileupload-1.2.1.
jar,WEB-INF/lib/commons-io-1.4.jar,WEB-INF/lib/commons-lang-2.4.jar,W
EB-INF/lib/commons-pool-1.5.3.jar,WEB-INF/lib/commons-validator-1.3.1
.jar,WEB-INF/lib/dom4j-1.6.1.jar,WEB-INF/lib/ehcache-1.6.1.jar,WEB-IN
F/lib/ejb3-persistence-1.0.2.GA.jar,WEB-INF/lib/grails-bootstrap-1.2-
M4.jar,WEB-INF/lib/grails-core-1.2-M4.jar,WEB-INF/lib/grails-crud-1.2
-M4.jar,WEB-INF/lib/grails-docs-1.2-M4.jar,WEB-INF/lib/grails-gorm-1.
2-M4.jar,WEB-INF/lib/grails-resources-1.2-M4.jar,WEB-INF/lib/grails-s
pring-1.2-M4.jar,WEB-INF/lib/grails-web-1.2-M4.jar,WEB-INF/lib/groovy
-all-1.6.5.jar,WEB-INF/lib/hibernate-annotations-3.4.0.GA.jar,WEB-INF
/lib/hibernate-commons-annotations-3.3.0.ga.jar,WEB-INF/lib/hibernate
-core-3.3.1.GA.jar,WEB-INF/lib/hibernate-ehcache-3.3.1.GA.jar,WEB-INF
/lib/hsqldb-1.8.0.10.jar,WEB-INF/lib/javassist-3.4.GA.jar,WEB-INF/lib
/jcl-over-slf4j-1.5.6.jar,WEB-INF/lib/jta-1.1.jar,WEB-INF/lib/jul-to-
slf4j-1.5.6.jar,WEB-INF/lib/log4j-1.2.15.jar,WEB-INF/lib/org.springfr
amework.aop-3.0.0.RC1.jar,WEB-INF/lib/org.springframework.asm-3.0.0.R
C1.jar,WEB-INF/lib/org.springframework.aspects-3.0.0.RC1.jar,WEB-INF/
lib/org.springframework.beans-3.0.0.RC1.jar,WEB-INF/lib/org.springfra
mework.context-3.0.0.RC1.jar,WEB-INF/lib/org.springframework.context.
support-3.0.0.RC1.jar,WEB-INF/lib/org.springframework.core-3.0.0.RC1.
jar,WEB-INF/lib/org.springframework.expression-3.0.0.RC1.jar,WEB-INF/
lib/org.springframework.instrument-3.0.0.RC1.jar,WEB-INF/lib/org.spri
ngframework.jdbc-3.0.0.RC1.jar,WEB-INF/lib/org.springframework.jms-3.
0.0.RC1.jar,WEB-INF/lib/org.springframework.orm-3.0.0.RC1.jar,WEB-INF
/lib/org.springframework.oxm-3.0.0.RC1.jar,WEB-INF/lib/org.springfram
ework.transaction-3.0.0.RC1.jar,WEB-INF/lib/org.springframework.web-3
.0.0.RC1.jar,WEB-INF/lib/org.springframework.web.servlet-3.0.0.RC1.ja
r,WEB-INF/lib/oro-2.0.8.jar,WEB-INF/lib/oscache-2.4.1.jar,WEB-INF/lib
/sitemesh-2.4.jar,WEB-INF/lib/slf4j-api-1.5.6.jar,WEB-INF/lib/slf4j-l
og4j12-1.5.6.jar,WEB-INF/lib/standard-1.1.2.jar,WEB-INF/lib/xpp3_min-
1.1.3.4.O.jar
Import-Package: javax.servlet,javax.servlet.http,javax.servlet.resourc
es,javax.servlet.jsp.resources;resolution:=optional,javax.xml.parsers
,org.w3c.dom,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers
Webapp-Context: trip-planner

Name: Grails Application
Implementation-Title: trip-planner
Implementation-Version: 0.1
Grails-Version: 1.2-M4

Note that Bundle-ClassPath contains all dependencies required by Grails, JAR files from the lib/ directory, and those contributed by installed Grails plugins.

The bundle imports some packages from the Servlet specification. This is to ensure, that the bundle uses the same classes as the web container, otherwise the classes would not be compatible, as they would be loaded by different class loaders.

BTW: if you need to have a look at the generated web.xml, you can achieve it like this:

unzip -p target/trip-planner-0.1.war WEB-INF/web.xml | xmllint --format -


Running the bundle

In order to run the bundle, it must be installed into an OSGi container like Equinox (the base for the Eclipse IDE), Apache Felix, or Knopflerfish. The test environment described below uses Equinox. Other frameworks could be used as well, but I haven't tested them yet.

Additionally we need a web container like Tomcat or Jetty. The web container needs also to be installed within the OSGi container, so we skip the download on the main site(s), but go looking for OSGI-fied versions. Jetty is OSGi-capable out of the box, an adapted Tomcat also used in Spring dm server can be found at the SpringSource Enterprise Bundle Repository. (Note: Tomcat does not yet work, so we currently use Jetty. I get no errors, but all requests seem to get silently ignored.)

The remaining part is a module usually called Web Extender, which bridges the gap between web applications and the web container. The web extender looks for bundles matching a certain criteria (e.g. existance of WEB-INF/web.xml or some bundle headers) and configures these as a web application. Candidates are Pax Web and Spring-DM.

As Pax Web is currently not able to configure a Grails applications because of PAXWEB-148, and Spring-DM will probably be required for other OSGi and Spring related stuff anyway, we use the latter as Web Extender.


Test environment

The test environment is made up of the excellent Pax Runner with a set of configuration files. Pax Runner is basically a starter for OSGi applications. It supports different OSGi frameworks and provisions both framework and bundles from sources like Maven repos, web servers, or directories.

The test environment loads the Equinox OSGi Framework (version 3.5.1), Spring-DM 2.0M1, Spring 3.0RC1, and Jetty (Tomcat doesn’t work right know). All configuration files be found on GitHub.

The test environment can be installed using the following commands:

Create a directory and change into it:

mkdir testenv; cd testenv

Download Pax Runner, extract it and create a version agnostic link:

curl -o pax-runner-assembly-1.3.0-jdk15.tar.gz http://repo1.maven.org/maven2/org/ops4j/pax/runner/pax-runner-assembly/1.3.0/pax-runner-assembly-1.3.0-jdk15.tar.gz

tar xzf pax-runner-assembly-1.3.0-jdk15.tar.gz

ln -s pax-runner-1.3.0 pax-runner

Get the example configuration:

git clone git://github.com/jetztgradnet/grails-osgi-testenv.git

The framework can be started with the following command:

cd grails-osgi-testenv
./pax-osgitest

After lots of log messages, we arrive at a prompt of the command shell. Help is available using help.

We now type ss to get an overview over all running bundles:


osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.1.R35x_v20090827
1 ACTIVE org.eclipse.osgi.util_3.2.0.v20090520-1800
2 ACTIVE org.eclipse.osgi.services_3.2.0.v20090520-1800
3 ACTIVE org.springframework.aop_3.0.0.RC1
4 ACTIVE org.springframework.asm_3.0.0.RC1
5 ACTIVE org.springframework.aspects_3.0.0.RC1
6 ACTIVE org.springframework.beans_3.0.0.RC1
7 ACTIVE org.springframework.context_3.0.0.RC1
8 ACTIVE org.springframework.context.support_3.0.0.RC1
9 ACTIVE org.springframework.core_3.0.0.RC1
10 ACTIVE org.springframework.expression_3.0.0.RC1
11 ACTIVE org.springframework.jdbc_3.0.0.RC1
12 INSTALLED org.springframework.jms_3.0.0.RC1
13 ACTIVE org.springframework.orm_3.0.0.RC1
14 ACTIVE org.springframework.transaction_3.0.0.RC1
15 ACTIVE org.springframework.web_3.0.0.RC1
16 ACTIVE org.springframework.web.servlet_3.0.0.RC1
17 ACTIVE com.springsource.org.aopalliance_1.0.0
18 ACTIVE com.springsource.org.objectweb.asm_2.2.3
19 ACTIVE com.springsource.net.sf.cglib_2.1.3
20 ACTIVE org.springframework.osgi.core_2.0.0.M1
21 ACTIVE org.springframework.osgi.extender_2.0.0.M1
22 ACTIVE org.springframework.osgi.io_2.0.0.M1
23 ACTIVE org.springframework.osgi.web_2.0.0.M1
24 ACTIVE org.springframework.osgi.web.extender_2.0.0.M1
Fragments=28
25 ACTIVE com.springsource.org.mortbay.jetty.server_6.1.9
26 ACTIVE com.springsource.org.mortbay.util_6.1.9
27 ACTIVE org.springframework.osgi.jetty.start.osgi_1.0.0
28 RESOLVED org.springframework.osgi.jetty.web.extender.fragment.osgi_1.0.1
Master=24
29 ACTIVE com.springsource.javax.activation_1.1.1
30 ACTIVE com.springsource.javax.annotation_1.0.0
31 ACTIVE com.springsource.javax.el_1.0.0
32 ACTIVE com.springsource.javax.ejb_3.0.0
33 ACTIVE com.springsource.javax.mail_1.4.1
34 ACTIVE com.springsource.javax.persistence_1.99.0
35 ACTIVE com.springsource.javax.transaction_1.1.0
36 ACTIVE com.springsource.javax.servlet_2.5.0
37 ACTIVE com.springsource.javax.servlet.jsp_2.1.0
38 ACTIVE com.springsource.javax.xml.bind_2.1.7
39 ACTIVE com.springsource.javax.xml.rpc_1.1.0
40 ACTIVE com.springsource.javax.xml.soap_1.3.0
41 ACTIVE com.springsource.javax.xml.stream_1.0.1
42 ACTIVE com.springsource.javax.xml.ws_2.1.1
43 ACTIVE org.apache.felix.webconsole_2.0.2
45 ACTIVE org.ops4j.pax.logging.pax-logging-api_1.4.0
46 ACTIVE org.ops4j.pax.logging.pax-logging-service_1.4.0
47 ACTIVE org.eclipse.equinox.util_1.0.100.v20090520-1800
48 ACTIVE org.eclipse.equinox.ds_1.1.1.R35x_v20090806
49 ACTIVE org.eclipse.equinox.cm_1.0.100.v20090520-1800
50 ACTIVE org.eclipse.equinox.supplement_1.1.0.v20080421-2006
51 ACTIVE org.eclipse.equinox.common_3.4.0.v20080421-2006
52 ACTIVE org.eclipse.equinox.preferences_3.2.201.R34x_v20080709
53 ACTIVE org.ops4j.pax.url.assembly_1.1.1
54 ACTIVE org.ops4j.pax.url.classpath_1.1.1
55 ACTIVE org.ops4j.pax.url.cache_1.1.1
56 ACTIVE org.ops4j.pax.url.mvn_1.1.1
57 ACTIVE org.ops4j.pax.url.link_1.1.1
58 ACTIVE org.ops4j.pax.url.war_1.1.1
59 ACTIVE org.ops4j.pax.url.wrap_1.1.1

We can now install our bundle:

install file:/path/to/trip-planner-0.1.war
Bundle id is 60

After installing we run ss again. Our bundle is now installed and in the RESOLVED state. With the id of our bundle (the number in the first column), we can now start it:

start 60

The application should now be reachable at http://localhost:8080/trip-planner-0.1/. If you get a 404 HTTP error, wait a moment, to give the web extender time to configure the bundle.

The system directory serves as the current directory of the OSGi container. The HSQLdb files from our test application will be created there, log messages of the container are written to the system/logs directory.

If our web bundle has been changed, we can simply update it using update 60. If this does not work, we can un- and reinstall it using uninstall 60 and the installation procedure described above.


Next steps

As outlined in part 1, the ultimate goal is to create modular Grails applications. The next step will be to extract the dependencies from the monolithic bundle and put them into their own bundles. Spring and Groovy are already available as bundles, other dependencies may need to be replaced with an OSGi-ready version, e.g. from the SpringSource Bundle Repository.

There will be some issues regarding singletons (e.g. ApplicationHolder, ConfigurationHolder) and class loading (Hibernate), but I think, they can be resolved with some work.

The findings may finally find their way into Grails or a Grails OSGi plugin.

Stay tuned...

Categories: grails, osgi Tags:

Grails on OSGi (1): Thoughts

November 16th, 2009 1 comment

What is OSGi

The OSGi Alliance (formerly known as the Open Services Gateway initiative) is a consortium of companies in the Java world, which develop the OSGi Service Platform, a framework for component-oriented software. Originally developed for embeded devices, OSGi frameworks can now also be found in enterprise, mobile, home, telematics and consumer products.

Applications in an OSGi environment are split into individual modules called bundles, which are usually provided as jar files. Each bundle provides a manifest file containing meta data, which describe its name, version, dependencies and offerings, i.e. code and services. An OSGi container can host multiple applications at once, each application can be started or stopped any time.

The OSGi specifications describe both the core framework and a set of standard services for common functionality such as logging, web access, declarative services, etc. A more detailed description can be found here.

There are multiple OSGi implementations available. Well-known open source implementations include Equinox, which is the base for the Eclipse IDE and eco system, Apache Felix and Knopflerfish.


Benefits

Running a Grails application in an OSGi environment would bring some benefits:

  • Support for modularization
  • Handling and versioning of components and dependencies (*)
  • Separation of applications
  • Dependencies and used libraries can be transferred independently to the application server, which makes for smaller application bundles and therefore faster transmission
  • Easy in-place update and reloading of individual components during runtime
  • Service-oriented architecture

(*) Alltough starting with version 1.2 Grails provides good support for versioning and dependency resolution with the integration of Ivy)


Progress so far

JIRA issue GRAILS-2221 for OSGi support for Grails exists for quite some time. Originally OSGi support was requested with an eye towards a plugin system. Grails now has its own plugin system, but OSGi support is on the roadmap for Grails 2.0, whenever that will be released ;-)

Update: Grails 1.2 will contain a valid OSGi bundle manifest, so the Grails jars may already be pulled out of a Grails application bundle and installed sepearately.


Possible implementation levels

There are several possibilities running a Grails application in an OSGi environment:

  • Monolithic application (Compatibility mode)
  • Modularized application
  • Fully componentized application


Monolithic application (Compatibility mode)

This can be seen as a first step of an OSGi-fied Grails application and should be already possible today with some manual steps.

The Grails application is packaged as a WAR file with the manifest file containing necessary OSGi headers, like Bundle-SymbolicName, Bundle-Version, Bundle-ClassPath, and Import-Package.

An OSGi framework providing a web service and corresponding web extender like Spring-DM or Pax Web can now run this application.

Advantages:

  • Already possible today
  • No classloading issues

Disadvantages:

  • No modularization
  • Big, monolithic bundle, slow upload to an application server


Modularized application

The next step will be splitting a Grails application into individual bundles. Ideally each of Grails’ and the application’s dependencies like Hibernate, Sitemesh, etc. would come as its own (set of) bundle(s).

Spring and Groovy already contain OSGi meta data and can be run unmodified in an OSGi environment, OSGi-fied bundles of some other dependencies can be found in the bundle repositories provided by SpringSource, Apache Felix, or Knopflerfish. Eclipse also hosts some third-party libraries, e.g. many commonly-used Apache jars, which were converted to OSGi bundles, in the Orbit project.

The Grails application itself would be another bundle. As it contains no dependencies, it would be quite small and can therefore easily be transferred to an application server.

Advantages:

  • Shared dependencies for all Grails applications
  • Small bundle for faster upload to an application server

Disadvantages:

  • Issues with Grails’ singletons, when running more than one Grails application in a single VM (*)
  • Classloading issues

(*) This is also the case when running more than one Grails application in a servlet container with shared jars, e.g. using grails war --nojars.


Fully componentized application

Many posts on the Grails mailing list ask for ways to modularize big web applications. The most common answer and approach is to split the application into multiple Grails plugins.

In an OSGi environment, the Grails application could be split into multiple bundles, each of which can be individually updated or reloaded. Each Grails plugin would compose a bundle of its own, which could be used and shared by multiple Grails applications.

A starting point for implementing this approach could be the newly created Spring Slices project.

Advantages:

  • Full modularization
  • Small bundles for fast uploads to an application server

Disadvantages:

  • Issues with Grails’ singletons, when running more than one Grails application in a single VM
  • Classloading issues


OSGi-fied Development mode

The Grails development mode (aka grails run-app) could also profit from OSGi support. With the OSGi framework constantly running, changes could be integrated by simply updating or reloading individual bundles. Even major changes would only mean reloading some bundles. This would reduce startup times, as the VM is always running and does not need to be stopped and restarted.

For extreme cases, each controller/domain class/Grails artefact could even be temporarily packaged in its own bundle.


Conclusion

Real OSGi support for Grails is still some time in the future. There is a lot to do and some issues regarding classloading and singletons to resolve. This series of blog posts will look at OSGi support from different angles and try to find solutions to emerging problems. Stay tuned…

Categories: grails, osgi Tags:

PlugRepo mentioned in Grails Podcast

September 14th, 2009 No comments

PlugRepo was mentioned in the most recent edition of Grails Podcast. Thanks, Glen and Sven!

Categories: grails Tags:

Started new offline Grails Plugin Repository

September 10th, 2009 6 comments

Plugrepo is an offline Grails (and maybe Griffon) plugin repository. It can be used as an offline proxy for the grails.org repository as well as a repository for internal plugins, which are not ment to be published.

The application is work in progress, see project page at http://github.com/jetztgradnet/plugrepo/

PlugRepo main screen

Categories: general, grails, plugin Tags: