Thursday, June 23, 2011

Hot Deploy & F5/Refresh-Driven Web Application Development Are Ancient Compared to Eclipse RAP!

Eclipse-rap-riena-hot-deploy-w

Most web applications developer would be very familiar with F5/Refresh-Driven development. You know, make a little change and press F5 in the web browser and you can view the updated page. This was the good old PHP days.

Java EE web application developers used to not that lucky. While some changes like JSP pages, JSF facelets, etc. take effect immediately (and thus, "refresh-driven"), in some cases they have to "redeploy". This usually means developer changes a Java class backing bean or an "important" file like web.xml. Redeploy means undeploying the web app from the Java EE container or application server, then redeploying the web app or WAR again. IDEs like the excellent Eclipse IDE Indigo (yay!) automate this but a redeploy can take anything between a few seconds to... minutes! I think typical web apps would deploy in about 20-30 seconds so that is painful.

JRebel from ZeroTurnaround (which just won the Most Innovative Java Technology in JAX Innovation Awards 2011, congratulations guys!) really helps here, by allowing most common changes to not cause a full redeploy, but just... hot deploy! It's like JSP/JSF but for the rest of Java app, Spring beans, etc. JRebel is a commercial plug-in but is definitely worth it.

But I'd argue Eclipse RAP should won the Most Innovative Java Technology title... Here's why!

(Eclipse Rich Ajax Platform/RAP is framework to develop AJAX-powered web applications easily based on Eclipse RCP programming model, see Eclipse Rich Client Platform (2nd Edition) for more information.)

I've just noticed something today. I know I should've noticed this long ago, but when you launch an Eclipse RAP rich internet application from Eclipse IDE using Debug (F11 key), ALL your code changes take effect immediately! No exceptions!

No need to even refresh the web browser!

Change the code for a menu item or a view or an action, save the .java file, go to the browser and click it... your new code is there!

"No refresh? But how can it be!"

Part of the magic is due to OSGi Dynamic Module System, that is brilliantly integrated as part of the Eclipse platform itself.

So when you save a Java file, Eclipse IDE will compile your class (and only your class, due to incremental builder feature, so it's very fast!), then update the OSGi bundle or Eclipse plug-in in the Eclipse RAP application. And only your bundle/plug-in is updated/refreshed in the application, so again, even if it's a different process it's also very fast. The whole process typically takes less than a second on a typical developer workstation, even on moderately complex apps! Most of the time the process is already done before you have a chance to hit Alt+Tab. ;-)

The other part of the magic is even though Eclipse RAP application comes with full AJAX features by default (it's not an option, it's actually a requirement), most of the business logic is server-side Java. So even if the most of the render JavaScript/HTML presentation layer in the web browser, when you perform an action for example by clicking a menu item, this will trigger a server request...

Which means your updated code! Yay! :)

Also important feature of Eclipse RAP is that for background/long-running jobs or "server push" operations, Eclipse RAP supports several approaches: Eclipse Jobs API or session-long UICallback.

This is pretty much automatic if you're already an Eclipse RCP programmer utilizing Jobs API. There's no need to do workarounds and hacks like traditional AJAX web development or learn yet another new API (and programming model) just for server push.

To learn more about Eclipse platform programming, I highly recommend Eclipse Rich Client Platform (2nd Edition). It's really good for learning Eclipse RCP/RAP development, most of the things that apply to RCP also applies to RAP. In fact, you can single-source an application to two target platforms (RCP for desktop, RAP for web) simultaneously. :-)

Eclipse Virgo IDE Tooling 1.0.0.M01 Released

Martin Lippert from SpringSource announced:

I am happy to announce that we released the first milestone build of the Virgo IDE tooling. For installation instructions, please take a look at the this wiki page:
http://wiki.eclipse.org/Virgo/Tooling

This is the first milestone build after the code contribution from SpringSource and there aren't that much changes with regards to features or bugs in there compared to the latest dm server tooling releases. But this will change from now on... :-)

Enjoy!

Eclipse Virgo Web Server / Kernel is an Enterprise OSGi web server, capable of serving dynamic OSGi web applications via OSGi Web Bundles (WABs). It works with Eclipse Gemini project to provide Java EE 6 capabilities to server-side OSGi applications.

For more in-depth explanation on using OSGi for enterprise applications, I highly recommend OSGi in Action: Creating Modular Applications in Java.

Thursday, June 16, 2011

How to Create Felix GoGo Commands with OSGi Blueprint in Eclipse Virgo Kernel / Web Server

Felix GoGo aka OSGi RFC-147 is a standard-based way to implement modular CLI (command-line interface / console / shell) commands in Java.

Apache Karaf supports Felix GoGo console out-of-the box, along with MINA SSH server integration. This blog post's focus would be Eclipse Virgo Web Server (Eclipse Virgo Kernel), and how we can leverage the same CLI support, along with SSH, in Eclipse Virgo. Now this article would be very short if I were using Apache Karaf, because it already had the right ingredients built-in and well-integrated: Felix GoGo, SSH server, Apache Aries as OSGi Blueprint implementation. I hope these features will also be in Eclipse Virgo soon (here's hoping)! :-)

Modular Java programming uses OSGi technology, if you aren't yet familiar with OSGi I recommend reading OSGi in Action: Creating Modular Applications in Java.

Enhancing Eclipse Virgo with Felix GoGo and SSH

I hope Virgo will soon have built-in support for Felix GoGo and SSH server, but for now, we must do this ourselves.

Hristo Iliev from SAP has written an excellent tutorial on how to enable Felix GoGo and SSH support in Eclipse Virgo, so I'll pretty much just paste it here :-)

Step 1: Download Gogo shell

To run the Gogo you will need three bundles from Apache Felix downloads:

Step 2: Equinox and RFC-147

To enable  RFC-147 integration in Equinox you will need some console supportability features that are provided by the Console supportability project in Equinox Incubator.

20110611 build is fine for me. Download the Incubator build that includes the bundle we'll need. Extract only the supportability JAR (org.eclipse.equinox.console.supportability) from plugins folder.

Step 3: Enabling SSH Support

First download Apache Mina's binary distribution for SSHD, and then from the lib directory of the archive extract these two bundles:

  • sshd-core

  • mina-core

Step 4: Setting up Virgo

  • Copy the console supportability bundle (org.eclipse.equinox.console.supportability) in lib directory

  • Place the rest of the bundles (3xGogo, SSHD and Mina) in lib/kernel directory

  • Edit config/org.eclipse.virgo.kernel.userregion.properties file and add the bundles to base bundles list:

baseBundles = \
 file:lib/kernel/org.eclipse.virgo.kernel.userregion-3.0.0.M05.jar@start,\
 file:lib/kernel/org.eclipse.virgo.kernel.osgicommand-3.0.0.M05.jar@start,\
 file:lib/kernel/mina-core-2.0.1.jar@start,\
 file:lib/kernel/org.apache.felix.gogo.command-0.8.0.jar@start,\
 file:lib/kernel/org.apache.felix.gogo.runtime-0.8.0.jar@start,\
 file:lib/kernel/org.apache.felix.gogo.shell-0.8.0.jar@start,\
 file:lib/org.eclipse.equinox.console.supportability_1.0.0.N20110608-2000.jar@start,\
 file:lib/kernel/sshd-core-0.5.0.jar@start
  • In lib/org.eclipse.virgo.kernel.launch.properties remove the old Virgo shell  by deleting the line org.eclipse.virgo.osgi.console.telnet.hook.TelnetHookConfigurator. The hooks entry should look like this afterwards:

    osgi.hook.configurators.include=\
     org.eclipse.virgo.osgi.extensions.equinox.hooks.ExtensionsHookConfigurator

  • Delete (or move outside lib) the bundle lib/org.eclipse.virgo.osgi.console-3.0.0.M05.jar

Step 5: Configuring Virgo

  • Comment or delete osgi.console property in lib/org.eclipse.virgo.kernel.launch.properties: (should already be commented)

#osgi.console=2401
  • Add the following property entries to lib/org.eclipse.virgo.kernel.launch.properties:

osgi.console.ssh=2422
osgi.console.enable.builtin=false
osgi.console.ssh.useDefaultSecureStorage=true
  • Add in config/org.eclipse.virgo.kernel.authentication.config file JAAS configuration for the SSH:

equinox_console { 
    org.eclipse.equinox.console.jaas.SecureStorageLoginModule REQUIRED; 
};
  • Edit the bin/dmk.bat file to add org.eclipse.equinox.console.jaas.file and ssh.server.keystore VM system properties. After the changes the file should look as follows: 

set KERNEL_JAVA_PARMS=%KERNEL_JAVA_PARMS% -Dorg.eclipse.virgo.kernel.authentication.file="%CONFIG_DIR%\org.eclipse.virgo.kernel.users.properties"
set KERNEL_JAVA_PARMS=%KERNEL_JAVA_PARMS% -Dorg.eclipse.equinox.console.jaas.file="%CONFIG_DIR%/store"
set KERNEL_JAVA_PARMS=%KERNEL_JAVA_PARMS% -Dssh.server.keystore="%CONFIG_DIR%/hostkey.ser"
set KERNEL_JAVA_PARMS=%KERNEL_JAVA_PARMS% -Djava.io.tmpdir="%TMP_DIR%"  
  • Edit bin/dmk.sh as follows: (following is in diff format)

diff --git a/bin/dmk.sh b/bin/dmk.sh index 5f8112b..4122d55 100755 --- a/bin/dmk.sh +++ b/bin/dmk.sh @@ -174,6 +174,8 @@ then -XX:HeapDumpPath=$KERNEL_HOME/serviceability/heap_dump.hprof \ -Djava.security.auth.login.config=$CONFIG_DIR/org.eclipse.virgo.ker -Dorg.eclipse.virgo.kernel.authentication.file=$CONFIG_DIR/org.ecli + -Dorg.eclipse.equinox.console.jaas.file=$CONFIG_DIR/store \ + -Dssh.server.keystore=$CONFIG_DIR/hostkey.ser \ -Djava.io.tmpdir=$TMP_DIR \ -Dorg.eclipse.virgo.kernel.home=$KERNEL_HOME \ -classpath $CLASSPATH \

Step 6: Connecting to Virgo

Fire your favourite SSH client on the specified port (2422 for instance).

$ ssh -p2422 equinox@localhost

  • Login with the default user and password (equinox/equinox) 

  • Create a new user and password (roles are optional)

Step 7: Fun with Gogo

Check the features provided by GoGo and Equinox Console Supportability:

  • Tab Completion (...doesn't yet work for me... any suggestions?) / Line editing

  • Built-in commands like lb, ls, cat to name a few

  • Create some scripts

  • Create some commands using RFC-147

Step 8: Disconnecting

Do not use "exit" since this will exit Virgo/OSGi framework. To end the session you'll have to close the console/SSH window. There is no command to close the session currently.


Create the Felix GoGo Command Implementation Project

You'll need Eclipse IDE for RCP Development distribution or PDE plug-in for this. Create a new Eclipse PDE Plug-in project with the following class:

package gogosimple1;

public class SimpleCommand {

    public void walk() {
        System.out.println("walking");
    }
   
    public void talk() {
        System.out.println("talking");
    }
}

Simple isn't it? And no external dependency on Felix GoGo API whatsoever (at this point).

I will use OSGi Blueprint to publish that class as a service and register a command scope to Felix GoGo. Create src/OSGI-INF/blueprint/gogosimple1.xml file with the following:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <bean id="simpleCommand" class="gogosimple1.SimpleCommand" />
    <service ref="simpleCommand" auto-export="all-classes">
        <service-properties>
            <entry key="osgi.command.scope"><value>simple</value></entry>
            <entry key="osgi.command.function">
                <array value-type="java.lang.String">
                    <value>walk</value>
                    <value>talk</value>
                </array>
            </entry>
        </service-properties>
    </service>

</blueprint>

For your convenience, the gogosimple1 example project is available on GitHub.

Installing Eclipse Gemini Blueprint on Virgo Web Server

Virgo 3.0 milestones shipped with (and unfortunately, will still ship) the ancient Spring-DM 1.2.1, so to enable OSGi Blueprint we need to install a OSGi Blueprint implementation by ourselves.

Fortunately Eclipse Gemini Blueprint seems to work just fine.

Download Eclipse Gemini Blueprint.

Copy the following files to Virgo's pickup/ folder: (in order)

  1. gemini-blueprint-core-1.0.0.M1.jar

  2. gemini-blueprint-extender-1.0.0.M1.jar

  3. gemini-blueprint-io-1.0.0.M1.jar

Alternative: Apache Aries Blueprint

Actually, I originally used Apache Aries Blueprint implementation for this experiment.

Download Apache Aries Blueprint.

Put these bundles in pickup/ folder: (in order)

  1. com.springsource.org.objectweb.asm-3.1.0.jar

  2. com.springsource.org.objectweb.asm.commons-3.1.0.jar

  3. com.springsource.org.objectweb.asm.tree-3.1.0.jar

  4. org.apache.aries.util-0.3.jar

  5. org.apache.aries.proxy-0.3.jar

  6. org.apache.aries.blueprint-0.3.jar

Trying the Commands

Build the simplegogo1 project (right click the project > Export... > Deployable plug-ins and fragments), and copy the resulting bundle JAR to Virgo's pickup/ folder.
If you don't feel like compiling, you can download prebuilt gogosimple1 JAR here (hint: it's very small, just 12 KB).
Virgo should install it, and Blueprint should register SimpleCommand bean as OSGi service:

g! lb | grep -i gogo
   44|Active     |    1|Apache Felix Gogo Command (0.8.0)
   45|Active     |    1|Apache Felix Gogo Runtime (0.8.0)
   46|Active     |    1|Apache Felix Gogo Shell (0.8.0)
  128|Active     |    1|Gogosimple1 (1.0.0.qualifier)
true

g! b 128
gogosimple1_1.0.0.qualifier [128]
  Id=128, Status=ACTIVE      Data Root=/home/ceefour/project/Soluvas/web-as/virgo-tomcat-server-3.0.0.M05/work/osgi/configuration/org.eclipse.osgi/bundles/128/data
  "Registered Services"
    {gogosimple1.SimpleCommand}={osgi.command.scope=simple, osgi.command.function=[walk,talk], org.eclipse.gemini.blueprint.bean.name=simpleCommand, osgi.service.blueprint.compname=simpleCommand, Bundle-SymbolicName=gogosimple1, Bundle-Version=1.0.0.qualifier, service.id=269}
    {org.osgi.service.blueprint.container.BlueprintContainer}={Bundle-SymbolicName=gogosimple1, Bundle-Version=1.0.0.qualifier, osgi.blueprint.container.version=1.0.0.qualifier, osgi.blueprint.container.symbolicname=gogosimple1, service.id=270}
    {org.eclipse.gemini.blueprint.context.DelegatedExecutionOsgiBundleApplicationContext, org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext, org.springframework.context.ConfigurableApplicationContext, org.springframework.context.ApplicationContext, org.springframework.context.Lifecycle, org.springframework.beans.factory.ListableBeanFactory, org.springframework.beans.factory.HierarchicalBeanFactory, org.springframework.context.MessageSource, org.springframework.context.ApplicationEventPublisher, org.springframework.core.io.support.ResourcePatternResolver, org.springframework.beans.factory.BeanFactory, org.springframework.core.io.ResourceLoader, org.springframework.beans.factory.DisposableBean}={org.springframework.context.service.name=gogosimple1, Bundle-SymbolicName=gogosimple1, Bundle-Version=1.0.0.qualifier, service.id=271}
  Services in use:
    {org.xml.sax.EntityResolver}={spring.osgi.core.bundle.id=130, spring.osgi.core.bundle.timestamp=1308232521056, service.id=249}
    {org.springframework.beans.factory.xml.NamespaceHandlerResolver}={spring.osgi.core.bundle.id=130, spring.osgi.core.bundle.timestamp=1308232521056, service.id=248}
    {org.osgi.service.packageadmin.PackageAdmin}={service.ranking=2147483647, service.pid=0.org.eclipse.osgi.framework.internal.core.PackageAdminImpl, service.vendor=Eclipse.org - Equinox, service.id=1}
  No exported packages
  Imported packages
    org.osgi.framework; version="1.6.0"<org.eclipse.osgi_3.7.0.v20110224 [0]>
  No fragment bundles
  Named class space
    gogosimple1; bundle-version="1.0.0.qualifier"[provided]
  No required bundles

You can try GoGo commands you just installed:

g! simple:walk
walking
g! simple:talk
talking

"help" command is also available to list all available commands:

g! help
equinox:addRoles
equinox:addUser
equinox:b
equinox:bundle
equinox:bundles
equinox:classSpaces
equinox:close
equinox:deleteUser
equinox:exec
equinox:exit
equinox:fork
equinox:gc
equinox:getPackages
equinox:getprop
equinox:h
equinox:headers
equinox:help
equinox:i
equinox:init
equinox:install
equinox:listUsers
equinox:p
equinox:packages
equinox:pr
equinox:profilelog
equinox:props
equinox:r
equinox:refresh
equinox:removeRoles
equinox:requiredBundles
equinox:resetPassword
equinox:s
equinox:se
equinox:services
equinox:setPassword
equinox:setbsl
equinox:setfwsl
equinox:setibsl
equinox:setp
equinox:setprop
equinox:shutdown
equinox:sl
equinox:ss
equinox:ssh
equinox:sta
equinox:start
equinox:status
equinox:sto
equinox:stop
equinox:t
equinox:telnet
equinox:threads
equinox:un
equinox:uninstall
equinox:up
equinox:update
felix:bundlelevel
felix:cd
felix:frameworklevel
felix:headers
felix:help
felix:inspect
felix:install
felix:lb
felix:log
felix:ls
felix:refresh
felix:resolve
felix:start
felix:stop
felix:uninstall
felix:update
felix:which
gogo:cat
gogo:each
gogo:echo
gogo:format
gogo:getopt
gogo:gosh
gogo:grep
gogo:not
gogo:set
gogo:sh
gogo:source
gogo:tac
gogo:telnetd
gogo:type
gogo:until
obr:deploy
obr:info
obr:javadoc
obr:list
obr:repos
obr:source
simple:talk
simple:walk

Using Virgo Tools Eclipse IDE Plugin to Launch Eclipse Virgo Web Server

Building project and manually copying the JAR is boring, not to mention it's not helpful during development/debugging.
Thankfully there is Virgo Tools, which has been part of SpringSource Tool Suite. You can install it in your Eclipse IDE using one of the following update sites (depending on your preference of stability, I use the "milestone" one, and I am not having problems):

Choose: Core / dm Server Tools (as of Virgo Tools 2.7.0-M2)

Open the Servers view (Shift+Alt+Q Q, choose Servers), then add a new server, pick Eclipse Virgo Web Server.

Before launching, you need to edit the launch configuration to enable SSH server.
Double-click Eclipse Virgo Web Server in the Servers view, then click "Edit launch configuration".

On Arguments > VM arguments, add the following:

-Dorg.eclipse.equinox.console.jaas.file="$CONFIG_DIR/store" -Dssh.server.keystore="$CONFIG_DIR/hostkey.ser"

You need to manually replace $CONFIG_DIR above with the Virgo Web Server's config folder.

Now you can launch Eclipse Virgo Web Server from Eclipse IDE, develop & debug, inspect its configuration, deploy artifacts, etc. right inside the Eclipse IDE.

Deploying PDE Plug-in Projects into Eclipse Virgo Web Server

Currently Virgo Tools is integrated with WTP, but not with PDE.  Which means:

  • Eclipse plugin projects cannot be deployed straightforwardly into Virgo Web Server using Virgo Tools plugin

  • What can be deployed are VWS-specific OSGi Plan project and OSGi Bundle project. You can right click a "plain" Eclipse plugin project > Spring Tools > Add OSGi Bundle project nature to convert it to VWS OSGi Bundle project.

  • OSGi Bundle nature has its own way of generating MANIFEST.MF, it doesn't use Eclipse PDE's META-INF/MANIFEST.MF file.

State as of 13 June 2011: (source)

Unfortunately there is no integration of STS and PDE. The Libra project is doing a great job at integrating WTP and PDE and looks like a great way of developing OSGi standard bundles, although it doesn't yet have a way to launch Virgo. The Virgo tooling, contributed to Eclipse from STS, is also developing, is able to launch Virgo (of course), and we hope to align it with Libra in due course.

For now, why not ditch the PDE manifest and run with STS and Maven? That's the approach we took in the Greenpages sample application which you may like to refer to. See also "Creating an Application with Virgo" which goes through the Greenpages sample in some detail.

Better tooling for OSGi, Eclipse Virgo, Eclipse Gemini, and integration with PDE are goals of Eclipse Libra project. Maybe you can help? :-)

To deploy gogosimple1 using Virgo Tools, first you need to enable the OSGi bundle project nature: right-click on the project, click Spring Tools > Add OSGi Bundle project nature.

Then right-click on the Virgo Web Server in Servers view, click Add and Remove, now you can choose gogosimple1 to deploy the project as artifact to Virgo.

By doing the steps above, the development cycle with Virgo and Eclipse IDE becomes very convenient, anytime you change the project's source code, resource files, etc. Virgo will immediately pick it up. You can also launch Eclipse Virgo in debug mode and have all Eclipse IDE debugging tools at your fingertips!

Recommended Resources

For more in-depth explanation on OSGi, I highly recommend OSGi in Action: Creating Modular Applications in Java.