The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


TOTD #36: Deploy OSGi bundles in GlassFish using maven-bundle-plugin

Posted by arungupta on June 26, 2008 at 6:15 AM PDT

GlassFish v3 is a modular (OSGi compliant), embeddable (runs in-VM) and extensible (supports non-Java apps) Application Server.

The extensible part is demonstrated by deployment of Rails and Grails applications. An example of embeddability is an in-VM Servlet. This blog demonstrates how a simple OSGi bundle can be easily created using Maven Bundle Plugin and deployed on v3 trunk.
  1. Generate a simple Maven project using the command as shown below:

    ~/samples/v3 >mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.samples.osgi.helloworld -DartifactId=helloworld
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'archetype'.
    [INFO] Ignoring available plugin update: 2.0-alpha-3 as it requires Maven version 2.0.7
    [INFO] Ignoring available plugin update: 2.0-alpha-2 as it requires Maven version 2.0.7
    [INFO] Ignoring available plugin update: 2.0-alpha-1 as it requires Maven version 2.0.7
    [INFO] ----------------------------------------------------------------------------
    [INFO] Building Maven Default Project
    [INFO]    task-segment: [archetype:create] (aggregator-style)
    [INFO] ----------------------------------------------------------------------------
    [INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
    [INFO] Setting property: velocimacro.messages.on => 'false'.
    [INFO] Setting property: resource.loader => 'classpath'.
    [INFO] Setting property: resource.manager.logwhenfound => 'false'.
    [INFO] **************************************************************
    [INFO] Starting Jakarta Velocity v1.4
    [INFO] RuntimeInstance initializing.
    [INFO] Default Properties File: org/apache/velocity/runtime/defaults/velocity.properties
    [INFO] Default ResourceManager initializing. (class org.apache.velocity.runtime.resource.ResourceManagerImpl)
    [INFO] Resource Loader Instantiated: org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader
    [INFO] ClasspathResourceLoader : initialization starting.
    [INFO] ClasspathResourceLoader : initialization complete.
    [INFO] ResourceCache : initialized. (class org.apache.velocity.runtime.resource.ResourceCacheImpl)
    [INFO] Default ResourceManager initialization complete.
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Literal
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Macro
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Parse
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Include
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Foreach
    [INFO] Created: 20 parsers.
    [INFO] Velocimacro : initialization starting.
    [INFO] Velocimacro : adding VMs from VM library template : VM_global_library.vm
    [ERROR] ResourceManager : unable to find resource 'VM_global_library.vm' in any resource loader.
    [INFO] Velocimacro : error using  VM library template VM_global_library.vm : org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'VM_global_library.vm'
    [INFO] Velocimacro :  VM library template macro registration complete.
    [INFO] Velocimacro : allowInline = true : VMs can be defined inline in templates
    [INFO] Velocimacro : allowInlineToOverride = false : VMs defined inline may NOT replace previous VM definitions
    [INFO] Velocimacro : allowInlineLocal = false : VMs defined inline will be  global in scope if allowed.
    [INFO] Velocimacro : initialization complete.
    [INFO] Velocity successfully started.
    [INFO] [archetype:create]
    [INFO] Defaulting package to group ID: org.glassfish.samples.osgi.helloworld
    [INFO] ----------------------------------------------------------------------------
    [INFO] Using following parameters for creating Archetype: maven-archetype-quickstart:RELEASE
    [INFO] ----------------------------------------------------------------------------
    [INFO] Parameter: groupId, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: packageName, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: basedir, Value: /Users/arungupta/samples/v3
    [INFO] Parameter: package, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] Parameter: artifactId, Value: helloworld
    [INFO] ********************* End of debug info from resources from generated POM ***********************
    [INFO] Archetype created in dir: /Users/arungupta/samples/v3/helloworld
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1 second
    [INFO] Finished at: Wed Jun 25 10:07:27 PDT 2008
    [INFO] Final Memory: 5M/10M
    [INFO] ------------------------------------------------------------------------
  2. Change the generated App class in "src/main/java/org/glassfish/samples/osgi/helloworld" folder so that it looks like:

    package org.glassfish.samples.osgi.helloworld;

    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;

    /**
     * Hello world!
     *
     */
    public class App implements BundleActivator {
        public void start(BundleContext context) throws Exception {
            System.out.println("Hey!");
        }
        public void stop(BundleContext context) throws Exception {
            System.out.println("Bye!");
        }
    }


    This is a trivial Activator class but sitll shows the key methods. The changes are highlighted in bold.
  3. Update "pom.xml" with the following changes:
    1. Change the <packaging> to "bundle" from the default value of "jar".
    2. Add the <dependency> on "org.osgi.core".
    3. Add the <plugin> maven-bundle-plugin and provide <instructions> to generate the appropriate MANIFEST.MF.

    The updated "pom.xml" with changes highlighted in bold are shown below:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.glassfish.samples.osgi.helloworld</groupId>
      <artifactId>helloworld</artifactId>
      <packaging>bundle</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>helloworld</name>
      <url>http://maven.apache.org</url>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.apache.felix</groupId>
          <artifactId>org.osgi.core</artifactId>
          <version>1.0.0</version>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
              <instructions>
                <Export-Package>${pom.groupId}</Export-Package>
                <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                <Bundle-Activator>${pom.groupId}.App</Bundle-Activator>
              </instructions>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
  4. Generate the OSGi bundle as shown below:

    ~/samples/v3/helloworld >mvn install
    [INFO] Scanning for projects...
    [INFO] ----------------------------------------------------------------------------
    [INFO] Building helloworld
    [INFO]    task-segment: [install]
    [INFO] ----------------------------------------------------------------------------
    [INFO] [resources:resources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Compiling 1 source file to /Users/arungupta/samples/v3/helloworld/target/classes
    [INFO] [resources:testResources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:testCompile]
    [INFO] Compiling 1 source file to /Users/arungupta/samples/v3/helloworld/target/test-classes
    [INFO] [surefire:test]
    [INFO] Surefire report directory: /Users/arungupta/samples/v3/helloworld/target/surefire-reports

    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.glassfish.samples.osgi.helloworld.AppTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 sec

    Results :

    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

    [INFO] [bundle:bundle]
    [INFO] [install:install]
    [INFO] Installing /Users/arungupta/samples/v3/helloworld/target/helloworld-1.0-SNAPSHOT.jar to /Users/arungupta/.m2/repository/org/glassfish/samples/osgi/helloworld/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
    [INFO] [bundle:install]
    [INFO] Parsing file:/Users/arungupta/.m2/repository/repository.xml
    [INFO] Installing org/glassfish/samples/osgi/helloworld/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
    [INFO] Writing OBR metadata
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 4 seconds
    [INFO] Finished at: Wed Jun 25 10:20:27 PDT 2008
    [INFO] Final Memory: 22M/54M
    [INFO] ------------------------------------------------------------------------

    The generated "target/helloworld-1.0-SNAPSHOT.jar" has the following contents:

    META-INF/MANIFEST.MF
    META-INF/
    META-INF/maven/
    META-INF/maven/org.glassfish.samples.osgi.helloworld/
    META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/
    META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/pom.properties
    META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/pom.xml
    org/
    org/glassfish/
    org/glassfish/samples/
    org/glassfish/samples/osgi/
    org/glassfish/samples/osgi/helloworld/
    org/glassfish/samples/osgi/helloworld/App.class

    And the generated "MANIFEST.MF" looks like:

    Manifest-Version: 1.0
    Export-Package: org.glassfish.samples.osgi.helloworld;uses:="org.osgi.
     framework"
    Built-By: arungupta
    Tool: Bnd-0.0.255
    Bundle-Name: helloworld
    Created-By: Apache Maven Bundle Plugin
    Bundle-Version: 1.0.0.SNAPSHOT
    Build-Jdk: 1.6.0_05
    Bnd-LastModified: 1214414426851
    Bundle-ManifestVersion: 2
    Bundle-Activator: org.glassfish.samples.osgi.helloworld.App
    Import-Package: org.glassfish.samples.osgi.helloworld,org.osgi.framewo
     rk;version="1.3"
    Bundle-SymbolicName: helloworld
Now let's install this newly created bundle using Felix shell in GlassFish v3. Check out and build GlassFish v3 workspace as explained in TOTD #33. Unzip "~/workspaces/glassfish/v3/distributions/web/target/web.zip" and enable Felix TUI as explained in TOTD #34.
  1. Start GlassFish v3 as:

    ~/testbed/glassfish/v3/snapshot/glassfish >java -jar modules/glassfish-10.0-SNAPSHOT.jar
    Jun 25, 2008 4:09:19 PM com.sun.enterprise.glassfish.bootstrap.ASMain main
    INFO: Launching GlassFish on Apache Felix OSGi platform
    Jun 25, 2008 4:09:19 PM com.sun.enterprise.glassfish.bootstrap.ASMainOSGi getSharedRepos
    INFO: /Users/arungupta/testbed/glassfish/v3/snapshot/glassfish/domains/domain1/lib does not exist

    Welcome to Felix.
    =================

    Jun 25, 2008 4:09:20 PM HK2Main start
    INFO: contextRootDir = /Users/arungupta/testbed/glassfish/v3/snapshot/glassfish/modules
    Jun 25, 2008 4:09:20 PM OSGiFactoryImpl initialize
    INFO: Singleton already initialized as com.sun.enterprise.module.impl.HK2Factory@3d44d0c6
    Jun 25, 2008 4:09:20 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.glassfish-mbeanserver [19]
    Jun 25, 2008 4:09:20 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.core.kernel [51]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.glassfish-naming [8]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.admin.config-api [43]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.internal-api [33]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.deployment.deployment-common [10]
    Jun 25, 2008 4:09:21 PM 
    INFO: JMXMP connector server URL = service:jmx:jmxmp://localhost:8888
    Jun 25, 2008 4:09:21 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8080
    Jun 25, 2008 4:09:21 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8181
    Jun 25, 2008 4:09:21 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 4848
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.container-common [21]
    Jun 25, 2008 4:09:22 PM com.sun.enterprise.v3.admin.adapter.AdminConsoleAdapter setContextRoot
    INFO: Admin Console Adapter: context root: /admin
    Jun 25, 2008 4:09:22 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: Glassfish v3 started in 1789 ms
    Jun 25, 2008 4:09:22 PM 
    INFO: ->
    Jun 25, 2008 4:09:22 PM com.sun.enterprise.glassfish.bootstrap.ASMainFelix launchOSGiFW
    INFO: Framework successfully started
  2. Install the Hello World bundle as:

    install file:///Users/arungupta/samples/v3/helloworld/target/helloworld-1.0-SNAP...
    Jun 25, 2008 4:10:19 PM 
    INFO: Bundle ID: 75
    Jun 25, 2008 4:10:19 PM 
    INFO: ->

    The command output shows "75" as the process id. This id is used to start/stop/uninstall the bundle later.
  3. Check the bundle status

    ps     
    Jun 25, 2008 4:10:27 PM 
    INFO: START LEVEL 1
    Jun 25, 2008 4:10:27 PM 
    INFO:    ID   State         Level  Name
    Jun 25, 2008 4:10:27 PM 
    INFO: [   0] [Active     ] [    0] System Bundle (1.0.4)
    Jun 25, 2008 4:10:27 PM 
    INFO: [   1] [Active     ] [    1] org.jvnet.tiger-types repackaged as module (0.3.2)
    Jun 25, 2008 4:10:27 PM 

    . . .

    INFO: [  71] [Installed  ] [    1] Web module command line interface (10.0.0.SNAPSHOT)
    Jun 25, 2008 4:10:27 PM 
    INFO: [  72] [Installed  ] [    1] Admin GUI Web Container Plugin (10.0.0.SNAPSHOT)
    Jun 25, 2008 4:10:27 PM 
    INFO: [  75] [Installed  ] [    1] helloworld (1.0.0.SNAPSHOT)
    Jun 25, 2008 4:10:27 PM 
    INFO: ->

    The last log output shows the newly added process.
  4. Start the bundle as:

    start 75
    Jun 25, 2008 4:10:32 PM 
    INFO: Hey!
    Jun 25, 2008 4:10:32 PM 
    INFO: ->

    This fragment shows "Hey!" output printed from the start method of Activator.
  5. Stop the bundle as:

    stop 75
    Jun 25, 2008 4:10:35 PM 
    INFO: Bye!
    Jun 25, 2008 4:10:35 PM 
    INFO: ->

    This fragment shows "Bye!" output printed from the stop method of Activator.
  6. And finally uninstall the bundle as:

    uninstall 75
    Jun 25, 2008 4:10:42 PM 
    INFO: ->
So following this blog you can deploy any of your OSGi bundles in GlassFish v3.

Technorati: glassfish v3 osgi maven mavenbundleplugin
Related Topics >> Glassfish      
Comments
Comments are listed in date ascending order (oldest first)

Hi Arun, Thanks for sharing this. However I do have one question. Does glasfish does have some sort of pickup folder, which will load a bundle into felix once in this folder? Thanks. Regards Vincent

Vincent, OSGi bundles can be dropped in "modules" directory and will automatically get loaded.

is it possible to start glassfish in one process and start a separate process to manage osgi bundles. I would like to start/stop the osgi felix cli without having to start/stop glassfish itself. thank you

Please post your question to users@glassfish.dev.java.net and somebody may know.

There is something missing between step 5 and step 6. I believe that step 6, 7, 8, 9, 10 are all Felix shell command. How do I start Felix shell after I start Glassfish? In Felix standalone environment, I can start Felix shell by "java -jar bin/felix.jar". If I do the same for Felix under Glassfish. I will be prompted with profile name: I am using glassfishv3-prelude instead of building myself.

Felix shell is started as part of v3 startup. v3 Prelude shows a message like: INFO: GlassFish v3 Prelude startup time : Felix(1732ms) startup services(1091ms) total(2823ms) It clearly shows how much time is taken to startup Felix. TOTD# 34 (http://blogs.sun.com/arungupta/entry/totd_34_using_felix_shell) shows how to start Felix shell. Are you looking for something else ?