Monday Apr 26, 2010

TOTD #130: Invoking a OSGi service from a JAX-WS Endpoint - OSGi and Enterprise Java

Sahoo blogged about JAX-WS Web service in an OSGi bundle. This Tip Of The Day (TOTD) provides complete steps to create such an application from scratch.

We will create an OSGi service, a JAX-WS compliant Web service as hybrid application, and a JAX-WS Web service client.

Lets create an OSGi service first.

  1. Create a simple OSGi service as explained in TOTD #36. Generate the maven project as:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes \\
    -DgroupId=org.glassfish.samples.osgi.hello.service -DartifactId=osgi-pure
    


    The updated directory structure looks like:

    osgi-pure
    osgi-pure/pom.xml
    osgi-pure/src
    osgi-pure/src/main
    osgi-pure/src/main/java
    osgi-pure/src/main/java/org
    osgi-pure/src/main/java/org/glassfish
    osgi-pure/src/main/java/org/glassfish/samples
    osgi-pure/src/main/java/org/glassfish/samples/osgi
    osgi-pure/src/main/java/org/glassfish/samples/osgi/hello
    osgi-pure/src/main/java/org/glassfish/samples/osgi/hello/service
    osgi-pure/src/main/java/org/glassfish/samples/osgi/hello/service/Hello.java
    osgi-pure/src/main/java/org/glassfish/samples/osgi/hello/service/impl
    osgi-pure/src/main/java/org/glassfish/samples/osgi/hello/service/impl/App.java
    osgi-pure/src/main/java/org/glassfish/samples/osgi/hello/service/impl/HelloImpl.java
    


    "Hello.java" is the OSGi service interface and looks like:

    public interface Hello {
        public String sayHello(String name);
    }
    


    "HelloImpl.java" is a trivial implementation of the service and looks like:

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


    "App.java" is the Bundle Activator and looks like:

    import org.glassfish.samples.osgi.hello.service.impl.HelloImpl;
    import java.util.Properties;
    import org.glassfish.samples.osgi.hello.service.Hello;
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    
    /\*\*
     \* Hello world!
     \*/
    public class App implements BundleActivator {
    
        public void start(BundleContext bc) throws Exception {
            bc.registerService(Hello.class.getName(), new HelloImpl(), new Properties());
        }
    
        public void stop(BundleContext bc) throws Exception {
            bc.ungetService(bc.getServiceReference(Hello.class.getName()));
        }
    }
    

    The "start" method registers the OSGi service using the name "Hello" and "stop" method un-registers the service.

  2. The updated "maven-bundle-plugin" from TOTD #36 looks like:

    <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-bundle-plugin</artifactId>
      <extensions>true</extensions>
      <configuration>
        <instructions>
          <Export-Package>${pom.groupId}</Export-Package>
          <Bundle-Activator>${pom.groupId}.impl.App</Bundle-Activator>
        </instructions>
      </configuration>
    </plugin>
    

    Notice, only the package that contains the service interface, i.e. "org.glassfish.samples.osgi.hello.service", is exported and the activator and service implementation are in a different package.

  3. Create the OSGi service bundle as:

    mvn install
    

    This also installs the OSGi bundle in the local maven repository. Deploy this bundle in GlassFish v3 by copying to "glassfish/domains/domain1/autodeploy/bundles" directory. Make sure GlassFish is running or start it as:

    asadmin start-domain --verbose
    

Lets create a hybrid application that consists of a JAX-WS compliant Web service, queries the OSGi service registry, invokes the OSGi service and return a response to the client.

  1. Create the Maven project as:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes \\
    -DgroupId=org.glassfish.samples.osgi.jaxws.webservice -DartifactId=helloservice
    
    
  2. Change the generated "src/main/java/org/glassfish/samples/osgi/jaxws/webservice/App.java" such that it looks like:

    import javax.jws.WebService;
    import org.glassfish.samples.osgi.hello.service.Hello;
    import org.osgi.framework.BundleContext;
    import org.osgi.framework.BundleReference;
    import org.osgi.framework.ServiceReference;
    
    /\*\*
     \* Hello world!
     \*/
    @WebService
    public class App {
        public String sayHello(String name) {
            Hello service = getService(Hello.class);
            return service.sayHello(name);
        }
    
    
        /\*\*
         \* This method looks up service of given type in OSGi service registry and returns if found.
         \* Returns null if no such service is available,
         \*/
       private static <T> T getService(Class<T> type) 
           BundleContext ctx = BundleReference.class.cast(
               App.class.getClassLoader()).getBundle().getBundleContext();
           ServiceReference ref = ctx.getServiceReference(type.getName());
           return ref != null ? type.cast(ctx.getService(ref)) : null;
       }
    }
    

    The "getService" method queries the OSGI service registry and returns the service reference. The "sayHello" method looks for the "Hello" service and invokes a method on it. The name "Hello" is the same as registered during the OSGi bundle creation earlier.

  3. In the generated "pom.xml":
    1. Change the packaging to "war".
    2. Add the following repository:

      <repositories>
        <repository>
          <id>java.net</id>
          <name>GlassFish Maven Repository</name>
          <url>http://maven.glassfish.org/content/groups/glassfish</url>
        </repository>
      </repositories>
      

      so that Java EE API dependency can be resolved.

    3. Add the following dependencies in "provided" scope:

      <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>6.0</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.core</artifactId>
        <version>4.2.0</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>org.glassfish.samples.osgi.hello.service</groupId>
        <artifactId>osgi-pure</artifactId>
        <version>1.0-SNAPSHOT</version>
        <scope>provided</scope>
      </dependency>
      

      Notice "osgi-pure" bundle is specified as dependency as that is used to invoke the service.
    4. Add the following plugins to "pom.xml" to create the hybrid application:

      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.0.2</version>
          <configuration>
            <source>1.5</source>
            <target>1.5</target>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <configuration>
            <supportedProjectTypes>
              <supportedProjectType>war</supportedProjectType>
              <supportedProjectType>bundle</supportedProjectType>
              <supportedProjectType>jar</supportedProjectType>
            </supportedProjectTypes>
            <instructions>
              <Import-Package>javax.jws; version=2.0, \*</Import-Package>
              <Web-ContextPath>${pom.artifactId}</Web-ContextPath>
            </instructions>
          </configuration>
          <executions>
            <execution>
              <id>bundle-manifest</id>
              <phase>process-classes</phase>
              <goals>
                <goal>manifest</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
        <plugin> <!-- Need to use this plugin to build war files -->
          <artifactId>maven-war-plugin</artifactId>
          <version>2.1-beta-1</version>
          <configuration>
            <archive>
              <!-- add bundle plugin generated manifest to the war -->
              <manifestFile>
                ${project.build.outputDirectory}/META-INF/MANIFEST.MF
              </manifestFile>
              <!-- For some reason, adding Bundle-ClassPath in maven-bundle-plugin
                   confuses that plugin and it generates wrong Import-Package, etc.
                   So, we generate it here.
              -->
              <manifestEntries>
                <Bundle-ClassPath>WEB-INF/classes/</Bundle-ClassPath>
              </manifestEntries>
            </archive>
            <failOnMissingWebXml>false</failOnMissingWebXml>
          </configuration>
        </plugin>
      </plugins>
      

      The "maven-bundle-plugin" is used to generate the appropriate OSGi metadata and "maven-war-plugin" is used to bundle the WAR file.

  4. Generate the deployable archive as:

    mvn clean package
    

    This generates "target/helloservice-1.0-SNAPSHOT.war". The generated manifest in "target/helloservice-1.0-SNAPSHOT/WEB-INF/classes/META-INF/MANIFEST.MF" looks like:

    Manifest-Version: 1.0
    Export-Package: org.glassfish.samples.osgi.jaxws.webservice;uses:="org
     .glassfish.samples.osgi.hello.service,javax.jws,org.osgi.framework";v
     ersion="1.0.0.SNAPSHOT"
    Bundle-Version: 1.0.0.SNAPSHOT
    Tool: Bnd-0.0.357
    Bundle-Name: helloservice
    Bnd-LastModified: 1272315464139
    Created-By: 1.6.0_17 (Apple Inc.)
    Bundle-ManifestVersion: 2
    Bundle-SymbolicName: org.glassfish.samples.osgi.jaxws.webservice.hello
     service
    Web-ContextPath: helloservice
    Import-Package: javax.jws;version="2.0",org.glassfish.samples.osgi.hel
     lo.service,org.glassfish.samples.osgi.jaxws.webservice;version="1.0",
     org.osgi.framework;version="1.5"
    
  5. Now this archive is a hybrid application, i.e. its a WAR file and an OSGi bundle. So lets deploy this file by copying the file to "domains/domain1/autodeploy/bundles" and see a message like:

    WS00018: Webservice Endpoint deployed App listening at address at http://localhost:8080/helloservice/AppService
    
  6. Accessing "http://localhost:8080/helloservice/AppService" in a browser window shows the following page:

Lets create the client project now to invoke this Web service.

  1. Create a new directory "client" and invoke the following command to generate the client-side artifacts:
    wsimport -keep http://localhost:8080/helloservice/AppService?wsdl
    
  2. Create a new directory "client" and a new file "HelloClient" in that directory as:
    package client;
    
    import org.glassfish.samples.osgi.jaxws.webservice.\*
    
    public class HelloClient {
            public static void main(String[] args) throws Exception {
                    App port = new AppService().getAppPort();
                    System.out.println(port.sayHello("Duke"));
            }
    }
    
    
    This "main" method gets a reference to the generated service class, gets the port from it, and then invokes the method by passing an argument.
  3. Compile the client code as:
    javac -d . -cp . client/HelloClient.java
    
  4. Invoke the client as:
    java -cp . client.HelloClient
    

    to see the result as:
    Hello Duke

    This result is coming from the OSGi service implementation.

All the three projects explained above are available in this download.

Using similar concept, a pure OSGi client can invoke a pure OSGi service which can then delegate the actual business method implementation to a JAX-WS endpoint and then use all the goodness of the underlying stack. This way, the benefits of JAX-WS are extended to a pure OSGi client and vice versa.

Also see other OSGi entries on this blog.

Technorati: totd jaxws osgi glassfish v3 webservice

Monday Apr 12, 2010

TOTD #127: Embedding GlassFish in an existing OSGi runtime - Eclipse Equinox

GlassFish has a modular architecture based upon OSGi and bundles Apache Felix as the OSGi runtime. TOTD #103 explains how to run GlassFish with two other OSGi runtimes (Equinox and Knopflerfish). However you may already have an OSGi runtime in your environment and like to run GlassFish within it. Sahoo blogged about how to embed GlassFish in Equinox.

This Tip Of The Day (TOTD) provides complete set of steps with Equinox and the different download options.

  1. There are two download options for Equinox - SDK or Framework. The framework is an easier option to start with as its just a single JAR. So create a top-level directory as "equinox-3.5.2" and download the latest framework JAR from here. Complete details about the starting and configuring the framework are described here.
  2. Start the framework and check its status as:
    ~/tools/equinox-3.5.2 >java -jar org.eclipse.osgi_3.5.2.R35x_v20100126.jar -console
    
    osgi> ss
    
    Framework is launched.
    
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.5.2.R35x_v20100126
    
    
    Notice only one bundle, i.e. Equinox main bundle, is currently active.
  3. Download and unzip the latest GlassFish 3.1 nightly build.
  4. Shutdown the framework by typing "exit" on the console or Ctrl+C. Copy "glassfish/osgi/equinox/configuration/config.ini" to "equinox-3.5.2/configuration" directory. This is required because the version number of some packages exported by JRE is not uniform across frameworks. This will hopefully be fixed in future versions of the frameworks.
  5. Sahoo's blog describes an OSGi bundle that controls the lifecycle of GlassFish. Download and unzip the OSGi bundle's Maven project.
  6. Edit "src/main/java/sahoo/embeddedgf/GFActivator.java" file and change the value of "installRoot" and "instanceRoot" on line 73 and 74 to match the location of your GlassFish install. Build the bundle as:
    mvn package
    

    which generates "target/embeddedgf-1.0-SNAPSHOT.jar". The bundle performs three tasks:
    1. Install all the bundles from "glassfish/modules" directory.
    2. Creates a configuration with "com.sun.aas.installRoot" and "com.sun.aas.instanceRoot" properties.
    3. Starts the main GlassFish bundle.
  7. Start the framework again, install the bundle, and check its status as:
    osgi> install file:///Users/arungupta/samples/v3/osgi/embeddedgf/target/embeddedgf-1.0-SNAPSHOT.jar
    Bundle id is 1
    
    osgi> ss
    
    Framework is launched.
    
    id      State       Bundle
    0       ACTIVE      org.eclipse.osgi_3.5.2.R35x_v20100126
    1       INSTALLED   sahoo.embeddedgf_1.0.0.SNAPSHOT
    

    Now GlassFish bundle is installed but not started. Optionally, the framework may be started with "-clean" switch that clears out the cache and starts with a clean slate.
  8. Start the newly installed bundle and see the log messages as:
    osgi> start 1
    
    osgi> [#|2010-04-10T10:46:04.616-0700|INFO|glassfishv3.0|com.sun.grizzly.config.GrizzlyServiceListener|_ThreadID=10;_ThreadName=Configuration Updater;|Perform lazy SSL initialization for the listener 'http-listener-2'|#]
    
    [#|2010-04-10T10:46:04.700-0700|INFO|glassfishv3.0|null|_ThreadID=11;_ThreadName=Thread-13;|Grizzly Framework 1.9.19-beta1 started in: 26ms listening on port 4848|#]
    
    [#|2010-04-10T10:46:04.700-0700|INFO|glassfishv3.0|null|_ThreadID=12;_ThreadName=Thread-9;|Grizzly Framework 1.9.19-beta1 started in: 50ms listening on port 8181|#]
    
    [#|2010-04-10T10:46:04.709-0700|INFO|glassfishv3.0|null|_ThreadID=13;_ThreadName=Thread-8;|Grizzly Framework 1.9.19-beta1 started in: 135ms listening on port 8080|#]
    
    . . .
    
    [#|2010-04-10T10:46:11.625-0700|INFO|glassfishv3.0|null|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, service.pid=org.apache.felix.fileinstall.76a03b47-814c-4359-ad37-f5d12e752a6f, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/3.1/apr9/glassfishv3/glassfish/domains/domain1/autodeploy/bundles/, felix.fileinstall.filename=org.apache.felix.fileinstall-autodeploy-bundles.cfg, service.factorypid=org.apache.felix.fileinstall, felix.fileinstall.debug=1};|{felix.fileinstall.poll (ms) = 5000, felix.fileinstall.dir = /Users/arungupta/tools/glassfish/3.1/apr9/glassfishv3/glassfish/domains/domain1/autodeploy/bundles, felix.fileinstall.debug = 1, felix.fileinstall.bundles.new.start = true, felix.fileinstall.tmpdir = /var/folders/+E/+E6YtSvGGEKNwOA77I-9Fk+++TI/-Tmp-/fileinstall--1798045578591636699, felix.fileinstall.filter = null}|#]
    
  9. Check the status of installed bundle as:
    osgi> ss
    
    Framework is launched.
    
    id      State       Bundle
    0       ACTIVE      org.eclipse.osgi_3.5.2.R35x_v20100126
                        Fragments=89, 106, 109
    1       ACTIVE      sahoo.embeddedgf_1.0.0.SNAPSHOT
    2       RESOLVED    org.glassfish.appclient.acc-config_3.1.0.SNAPSHOT
    3       RESOLVED    org.glassfish.admin.cli_3.1.0.SNAPSHOT
    4       RESOLVED    org.glassfish.admin.core_3.1.0.SNAPSHOT
    5       RESOLVED    org.glassfish.admin.util_3.1.0.SNAPSHOT
    
    . . .
    
    220     ACTIVE      org.glassfish.web.weld-integration_3.1.0.SNAPSHOT
    221     RESOLVED    org.jboss.weld.osgi-bundle_1.0.1.SP1
    222     RESOLVED    com.ctc.wstx_0.0.0
    223     RESOLVED    org.glassfish.connectors.work-management_3.1.0.SNAPSHOT
    
    osgi>
    

    So now all the GlassFish modules are installed and the required ones are started. "http://localhost:8080" shows the default web page and "asadmin" can be used to issue the standard commands.

If you downloaded Eclipsed SDK, then the framework needs to be started as:

java -jar plugins/org.eclipse.osgi_3.5.2.R35x_v20100126.jar -console

and the configuration file needs to be copied to "plugins/configuration" directory.

A future blog will show how to run GlassFish inside Eclipse as an RCP, however this requires issue #11782 to be fixed.

There are several other OSGi entries on this blog or on Sahoo's blog.

How are you using GlassFish's OSGi capabilities ?

Technorati: glassfish osgi embedded eclipse equinox

Thursday Apr 08, 2010

TOTD #126: Creating an OSGi bundles using Eclipse and deploying in GlassFish

TOTD #125 showed how to create an OSGi bundle using NetBeans and deploy in GlassFish. This Tip Of The Day (TOTD) shows how to do the same using Eclipse. OSGi replaced the plug-in technologies starting with Eclipse 3.0 and Equinox is used for all the modularity in Eclipse now.

Anyway, lets get started!

  1. In Eclipse 3.5.1, create a new Plug-in project by right-clicking in Package Explorer, selecting "New", Project ..." as shown below:



    and choose the "Plug-in Project":

  2. Enter the project name as "HelloOSGi"



    and take all other defaults. Make sure "Generate an activator ..." checkbox is selected and click on "Next >".
  3. Pick a project template as shown below:



    This creates a template "Activator" class that prints the messages when the bundle is started / stopped. Click on "Next >".
  4. Take the default start and stop message as:



    and click on "Finish".
  5. The generated directory structure looks like:



    and the generated source code looks like:

    package helloosgi;
    
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    
    public class Activator implements BundleActivator {
    
        /\*
         \* (non-Javadoc)
         \* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
         \*/
        public void start(BundleContext context) throws Exception {
            System.out.println("Hello World!!");
        }
        
        /\*
         \* (non-Javadoc)
         \* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
         \*/
        public void stop(BundleContext context) throws Exception {
            System.out.println("Goodbye World!!");
        }
    
    }
    
    
    Notice the imports are from standard org.osgi.framework.\* package. The generated manifest looks like:

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: HelloOSGi
    Bundle-SymbolicName: HelloOSGi
    Bundle-Version: 1.0.0.qualifier
    Bundle-Activator: helloosgi.Activator
    Import-Package: org.osgi.framework;version="1.3.0"
    Bundle-RequiredExecutionEnvironment: J2SE-1.5
    

  6. Right-click on your project, select "Run As", "OSGi Framework" as shown below:



    This launches the OSGi concole within Eclipse, starts the bundle, and prints the "Hello World!!" message from our Activator class in the console:



    This runs our newly created OSGi bundle using the Equinox framework within Eclipse. Our goal however is to run this bundle in GlassFish and so lets do that.
  7. Select "File", "Export ...", "Plug-in Development", and select "Deployable Plug-ins and fragments":



    and click on "Next >".
  8. Make sure "HelloOSGi" bundle is selected and specify the "domains/domain/autodeploy/bundles" directory of your GlassFish installation as specified below:



    GlassFish can be downloaded from here, unzipped, and started as "asadmin start-domain". And then you see the following message in your GlassFish logs:

    [#|2010-04-08T10:25:10.895-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=24;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, service.pid=org.apache.felix.fileinstall.b3dcd962-8b41-4669-858b-7c2e7d32d5c8, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/final/glassfishv3/glassfish/domains/domain1/autodeploy/bundles/, felix.fileinstall.filename=org.apache.felix.fileinstall-autodeploy-bundles.cfg, service.factorypid=org.apache.felix.fileinstall, felix.fileinstall.debug=1};|Hello World!!|#]

    Again, the same message from Activator class.

TOTD #118 shows other ways to manage OSGi bundles in GlassFish.

This blog showed how to create an OSGi bundle using Eclipse and deployed in GlassFish v3.

Also read other OSGi entries on this blog.

Technorati: totd eclipse glassfish osgi equinox

Wednesday Apr 07, 2010

Java EE 6, GlassFish, NetBeans, Eclipse, OSGi at Über Conf: Jun 14-17, Denver

Über Conf is a conference by No Fluff Just Stuff gang and plans to blow the minds of attendees with over 100 in-depth sessions (90 minutes each) from over 40 world class speakers on the Java platform and pragmatic Agile practices targeted at developers, architects, and technical managers.

Get your hands dirty and learn from the industry leaders in an intimate setting where the attendance is capped at 500 and in the beautiful city of Denver.

I'll be speaking on:

  • Java EE 6 & GlassFish v3: Paving the path for the future
  • Getting the best of both worlds: OSGi & Java together

The talks will start with an introduction of key concepts and then provide a detailed overview of the technology. The talks will be interspersed with multiple demos to leave you feel empowered. There will be NetBeans and Eclipse (hopefully IDEA too) showing the simplicity, ease-of-use, and increased productivity with Java EE 6. There will be multiple demos showing OSGi application development and how OSGi + Java EE leverage the best of both worlds.

Keeping with the spirit of "No Fluff Just Stuff", the material presented will be purely technical :-)

Hear Jay Zimmerman (Über Conf Director) talk about the event. My first engagement with NFJS was Rich Web Experience 2007 and that was a great experience, truly "rich". This is my first speaking engagement with NFJS and looking forward to a long term relationship :-)

On a personal front, I never ran in Denver so looking forward to some nice runs in the mile high city! Any recommendations ?

Technorati: conf nofluffjuststuff uberconf denver glassfish javaee netbeans eclipse intellij osgi

Monday Apr 05, 2010

TOTD #125: Creating an OSGi bundles using NetBeans and deploying in GlassFish

NetBeans has a modular architecture where each module is created as an NBM. OSGi is another popular modular system for Java applications and used by GlassFish to provide a light-weight Java EE 6 compliant application server.

There are a lot of similarities between NBM and OSGi:

  • Runtime container manages lifecycle and dependencies of modules
  • Both are packaged as JAR, metadata stored in META-INF/MANIFEST.MF and some other information
  • Runtime starts up, read meta information and sets up dependencies
  • Every module has its own class loader loading explicitly declared dependencies only

The following presentation explain the similarities and differences between NBM and OSGi very clearly:

Netigso provides a bridge between NBM and OSGi bundles. Using Netigso, NetBeans 6.9 allows you to choose between creating a NBM or an OSGi bundle.

This Tip Of The Day (TOTD) shows how to create an OSGi bundle using NetBeans and deploy in GlassFish.

  1. Download and Install NetBeans 6.9 latest nightly build from here.
  2. Create a new NetBeans module by selecting "New Project..." and picking the values as shown in the image below:



    and click on "Next >".
  3. The module can be created either stand-alone or added to a suite (more on this later). For now, lets create a stand-alone module as shown below:



    and click on "Next >".
  4. On the bundle configuration page, specify the options as shown below:



    and click on "Finish". "Code Name Base" is name of the base package. Notice "Generate OSGi Bundle" is selected which is what will generate the OSGi bundle instead of NBM. The generated directory structure looks like:



    The "manifest.mf" looks like:

    Manifest-Version: 1.0
    Bundle-Localization: hello/Bundle
    Bundle-Name: %OpenIDE-Module-Name
    Bundle-SymbolicName: hello
    Bundle-Version: 1.0
  5. Right-click on "Source Packages", select "New", "Installer / Activator ..." as shown below:




    Take the default values as shown below:



    and click on "Finish". The generated source code looks like:

    /\*
     \* To change this template, choose Tools | Templates
     \* and open the template in the editor.
     \*/
    package hello;
    
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    
    /\*\*
     \* Manages a bundle's lifecycle. Remember that an activator is optional and
     \* often not needed at all.
     \*/
    public class Installer implements BundleActivator {
    
     public void start(BundleContext c) throws Exception {
     }
    
     public void stop(BundleContext c) throws Exception {
     }
    }
    

    The code that needs to be executed during starting and stopping this OSGi bundle can now be added to "start" and "stop" methods respectively. To keep it simple, add the following line to "start" method:
    System.out.println("OSGi Bundle from NetBeans: Started");
    

    and the following to "stop" method:
    System.out.println("OSGi Bundle from NetBeans: Stopped");
    
  6. Right-click on the project and select "Create NBM" as shown below:



    This creates "hello.jar" in the "build" directory of project.
  7. Fire up your GlassFish as "asadmin start-domain" and copy "hello.jar" to "glassfishv3/glassfish/domains/domain1/autodeploy/bundles" directory to deploy the bundle. It shows a log statement as:


    [#|2010-04-02T18:37:07.001-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=24;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, service.pid=org.apache.felix.fileinstall.b3dcd962-8b41-4669-858b-7c2e7d32d5c8, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/final/glassfishv3/glassfish/domains/domain1/autodeploy/bundles/, felix.fileinstall.filename=org.apache.felix.fileinstall-autodeploy-bundles.cfg, service.factorypid=org.apache.felix.fileinstall, felix.fileinstall.debug=1};|OSGi Bundle from NetBeans: Started|#]

    The message printed from our generated bundle is highlighted in the bold. TOTD #118 shows other ways to manage OSGi bundles in GlassFish.

If you'd like to create multiple OSGi bundles that are related to each other then you create a "Module Suite" as shown below:

Multiple modules can be added by right-clicking on "Modules"



and either creating a new module or adding an existing one. Make sure to check "Generate OSGi Bundle" for the newly created bundle as well. Once the modules are added, then you can right-click on the suite, select "OSGi" and build all the modules in the suite together by selecting "Build Bundles" as shown below:

All the modules are now created in "/build/cluster/modules" directory of your suite.

Clicking on "Build Bundle Repository" creates an OSGi Bundle Repository (a federated repository of bundles).

UPDATED (Apr 8, 2010): Adding Maven-based OSGi functionality from NetBeans based upon a user comment, thanks Petr!

NetBeans also allows Maven-based OSGi projects to be easily created. This allows you to create pure-OSGi bundles without any NBM "fluff".

  1. Create a new Maven project and select "Maven OSGi Bundle":



    and click on "Next >".
  2. Enter the project details as:



    and click on "Finish".
  3. Expand "Source Packages", right click on the generated package and select "New", "Bundle Activator ...":



    Take the defaults as shown below:



    and click on "Finish".
  4. The generated code looks like:
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    
    /\*\*
     \*
     \* @author arungupta
     \*/
    public class NewActivator implements BundleActivator {
    
        public void start(BundleContext context) throws Exception {
            //TODO add activation code here
        }
    
        public void stop(BundleContext context) throws Exception {
            //TODO add deactivation code here
        }
    
    }
    

    Add add the following line to "start" method:
    System.out.println("OSGi Bundle from NetBeans/Maven: Started");
    

    and the following to "stop" method:
    System.out.println("OSGi Bundle from NetBeans/Maven: Stopped");
    
    
  5. Right-click the project and select "Clean and Build" to build "target/maven-osgi-1.0-SNAPSHOT.jar" in your project directory. This bundle can now be dropped in "glassfish/domains/domain1/autodeploy/bundles" to see a message like:

    [#|2010-04-08T11:54:09.721-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=24;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, service.pid=org.apache.felix.fileinstall.b3dcd962-8b41-4669-858b-7c2e7d32d5c8, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/final/glassfishv3/glassfish/domains/domain1/autodeploy/bundles/, felix.fileinstall.filename=org.apache.felix.fileinstall-autodeploy-bundles.cfg, service.factorypid=org.apache.felix.fileinstall, felix.fileinstall.debug=1};|OSGi Bundle from NetBeans/Maven: Started|#]

    And the generated manifest looks like:
    Manifest-Version: 1.0
    Export-Package: org.example.mavenosgi;uses:="org.osgi.framework"
    Built-By: arungupta
    Tool: Bnd-0.0.357
    Bundle-Name: maven-osgi OSGi Bundle
    Created-By: Apache Maven Bundle Plugin
    Bundle-Version: 1.0.0.SNAPSHOT
    Build-Jdk: 1.6.0_17
    Bnd-LastModified: 1270752743664
    Bundle-ManifestVersion: 2
    Bundle-Activator: org.example.mavenosgi.NewActivator
    Import-Package: org.example.mavenosgi,org.osgi.framework;version="1.5"
    Bundle-SymbolicName: org.example.maven-osgi
    

Technorati: totd netbeans glassfish osgi nbm module

Sunday Mar 14, 2010

TOTD #124: OSGi Declarative Services in GlassFish - Accessed from a Java EE client

The OSGi R4 compendium specification enables declaration of "Declarative Services" in configuration files. The specification says:

The service component model uses a declarative model for publishing, finding and binding to OSGi services. This model simplifies the task of authoring OSGi services by performing the work of registering the service and handling service dependencies.

There are several advantages of OSGi declarative services and they are well defined in the specification.

Neil Bartlett provided history and introduction to Declarative Services. Jerome blogged about OSGi Declarative Services in GlassFish v3 a while back. As mentioned in his post, this "curious reader" decided to experiment with adding more than one service implementation.

This Tip Of The Day shows how to use Maven Bundle Plugin and Maven SCR Plugin to create an OSGi bundle with two declarative services. Then it shows how to create a Java EE client, inject the declared services, and invoke them.

Lets get started!

For those who want want to see the results first:

  • Download service project and build as "mvn clean install". Install the service as "cp target/helloservice-1.0-SNAPSHOT.jar" to "domains/domain1/autodeploy/bundles".
  • Download client project and build as "mvn clean package"
  • Deploy the client to GlassFish v3 as "asadmin deploy target/helloclient-1.0-SNAPSHOT.war"
  • Invoke the client as "curl http://localhost:8080/helloclient-1.0-SNAPSHOT/HelloClient"

Now lets try to understand and create the projects from scratch.

First, create the service project as:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes 
     -DgroupId=org.glassfish.samples.osgi.helloservice -DartifactId=helloservice

Lets first look at the completed project structure:

pom.xml
src
src/main
src/main/java
src/main/java/org
src/main/java/org/glassfish
src/main/java/org/glassfish/samples
src/main/java/org/glassfish/samples/osgi
src/main/java/org/glassfish/samples/osgi/helloservice
src/main/java/org/glassfish/samples/osgi/helloservice/api
src/main/java/org/glassfish/samples/osgi/helloservice/api/HelloService.java
src/main/java/org/glassfish/samples/osgi/helloservice/impl
src/main/java/org/glassfish/samples/osgi/helloservice/impl/HelloImpl.java
src/main/java/org/glassfish/samples/osgi/helloservice/impl/HowdyImpl.java

The three source files are one service API and two implementations.

HelloService.java

package org.glassfish.samples.osgi.helloservice.api;

/\*\*
 \* @author arungupta
 \*/
public interface HelloService {
  public String sayHello(String name);
}

A very simple interface with one method that takes a String parameter and returns a String response.

HelloImpl.java

package org.glassfish.samples.osgi.helloservice.impl;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.glassfish.samples.osgi.helloservice.api.HelloService;

/\*\*
 \* @author arungupta
 \*/
@Component(name="hello-service")
@Service
public class HelloImpl implements HelloService {

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

This class is an implementation of the service interface. Notice this class is in "impl" package, different from the "api" package where interface was defined.

The business method implementation appends the greeting "Hello " to name parameter and generates the response message. The @Component and @Service annotations help in generation of the component descriptors as defined by the Maven SCR Plugin. This plugin provides many other annotations to customize the generation of metadata in "OSGI-INF/servicesComponent.xml". The "name" attribute will be used later by the Java EE client to access this service.

HowdyImpl.java

package org.glassfish.samples.osgi.helloservice.impl;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.glassfish.samples.osgi.helloservice.api.HelloService;

/\*\*
 \* @author arungupta
 \*/
@Component(name="howdy-service")
@Service
public class HowdyImpl implements HelloService {

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

Another implementation of HelloService interface and uses "Howdy " for the greeting. Notice the name attribute has a different value.

Here is the complete pom.xml:

<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.helloservice</groupId>
  <artifactId>helloservice</artifactId>
  <packaging>bundle</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>helloservice</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.apache.felix.scr.annotations</artifactId>
      <version>1.2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>2.0.1</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Export-Package>${pom.groupId}.api</Export-Package>
            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
          </instructions>
        </configuration>
      </plugin>
    <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-scr-plugin</artifactId>
      <executions>
        <execution>
          <id>generate-scr-scrdescriptor</id>
          <goals>
            <goal>scr</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
 </build>
</project>

Maven SCR Plugin generates the descriptor file using the metadata specified by the @Component and @Service annotation in service implementations. If this plugin is used with Maven Bundle Plugin then it also adds the generated descriptor (OSGI-INF/serviceComponents.xml) to the bundle and set the required "Service-Component" manifest header.

Giving "mvn clean install" generates "target/helloservice-1.0-SNAPSHOT.jar" and installs the bundle in the local repository. This JAR is used later in the client project for importing the service API definition. The generated JAR has the following manifest:

Manifest-Version: 1.0
Export-Package: org.glassfish.samples.osgi.helloservice.api
Service-Component: OSGI-INF/serviceComponents.xml
Built-By: arungupta
Tool: Bnd-0.0.357
Bundle-Name: helloservice
Created-By: Apache Maven Bundle Plugin
Build-Jdk: 1.6.0_17
Bundle-Version: 1.0.0.SNAPSHOT
Bnd-LastModified: 1268374529666
Bundle-ManifestVersion: 2
Import-Package: org.glassfish.samples.osgi.helloservice.api
Bundle-SymbolicName: helloservice

The key thing to notice is that only "api" package is exported. The generated component descriptor in "OSGI-INF/serviceComponents.xml" looks like:

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0">
  <scr:component enabled="true" name="hello-service">
    <implementation class="org.glassfish.samples.osgi.helloservice.impl.HelloImpl"/>
    <service servicefactory="false">
      <provide interface="org.glassfish.samples.osgi.helloservice.api.HelloService"/>
    </service>
    <property name="service.pid" value="hello-service"/>
  </scr:component>
  <scr:component enabled="true" name="howdy-service">
    <implementation class="org.glassfish.samples.osgi.helloservice.impl.HowdyImpl"/>
    <service servicefactory="false">
     <provide interface="org.glassfish.samples.osgi.helloservice.api.HelloService"/>
    </service>
    <property name="service.pid" value="howdy-service"/>
  </scr:component>
</components>

Notice that the "Service-Component" manifest header is pointing to this generated descriptor. And so the two declared services "hello-service" and "howdy-service" are available for consumption by other clients.

There are several ways to manage OSGi runtime bundle in GlassFish as described in TOTD #118. Simply copying the bundle to "glassfish/domains/domain1/autodeploy/bundles" is sufficient in this case, so lets do that.

The remote telnet shell (accessible using "telnet localhst 6666") shows status of the deployed bundle and associated service as:

-> find hello
START LEVEL 1
 ID State Level Name
[ 221] [Active ] [ 1] helloservice (1.0.0.SNAPSHOT)
-> scr list 221
 Id State Name
[ 2] [active ] hello-service
[ 3] [active ] howdy-service
-> scr info 2
ID: 2
Name: hello-service
Bundle: helloservice (221)
State: active
Default State: enabled
Activation: delayed
Services: org.glassfish.samples.osgi.helloservice.api.HelloService
Service Type: service
Properties:
 component.id = 2
 component.name = hello-service
 service.pid = hello-service
-> scr info 3
ID: 3
Name: howdy-service
Bundle: helloservice (221)
State: active
Default State: enabled
Activation: delayed
Services: org.glassfish.samples.osgi.helloservice.api.HelloService
Service Type: service
Properties:
 component.id = 3
 component.name = howdy-service
 service.pid = howdy-service

Maven SCR Plugin provides several other annotations to change the default value for each service.

Now create a Java EE client project to invoke the service as:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes 
       -DgroupId=org.glassfish.samples.osgi -DartifactId=helloclient

Lets look at the completed project structure:

pom.xml
src
src/main
src/main/java
src/main/java/org
src/main/java/org/glassfish
src/main/java/org/glassfish/samples
src/main/java/org/glassfish/samples/osgi
src/main/java/org/glassfish/samples/osgi/HelloClient.java

There is only one source file which is the Servlet client and looks like:

package org.glassfish.samples.osgi;

import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.glassfish.samples.osgi.helloservice.api.HelloService;

/\*\*
 \* Hello world!
 \*/
@WebServlet(urlPatterns={"/HelloClient"})
public class HelloClient extends HttpServlet {

  @Resource(mappedName="hello-service")
  HelloService helloService;

  @Resource(mappedName="howdy-service")
  HelloService howdyService;

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException {
    PrintWriter out = response.getWriter();
    out.println(helloService.sayHello("Duke"));
    out.println(howdyService.sayHello("Duke"));
  }
}

This is a Java EE 6-style Servlet, using @WebServlet annotation, and will be accessible at "/HelloClient". The two OSGi services are injected using @Resource annotation and using the name specified in the "OSGI-INF/serviceComponents.xml" descriptor earlier.

pom.xml

<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</groupId>
  <artifactId>helloclient</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>helloclient</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.glassfish.samples.osgi.helloservice</groupId>
      <artifactId>helloservice</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <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>
</project>

Note that the previously generated service bundle is added as a dependency in the "provided" scope as its already deployed to GlassFish.

"mvn clean package" generates "target/helloclient-1.0-SNAPSHOT.war" Deploy this WAR file to GlassFish as:

asadmin deploy target/helloclient-1.0-SNAPSHOT.war

And finally invoke the client as:

curl http://localhost:8080/helloclient-1.0-SNAPSHOT/HelloClient

to see the output as:

Hello Duke
Howdy Duke

This is the expected output after invoking the two services.

So there you go, this blog demonstrated how to access a OSGi declarative service from a Java EE client - both deployed on GlassFish v3.

Are you using OSGi Declarative Services ? How ?

Technorati: totd osgi glassfish javaee declarative service maven bundle bnd scr component dependencyinjection

Thursday Jan 21, 2010

TOTD #119: Telnet to GlassFish v3 with NetBeans 6.8 - "Could not open connection to the host"

As explained in TOTD #118, one of the ways to manage OSGi bundles in GlassFish is by giving the command "telnet localhost 6666".

This straight forward command works fine if you installed either the Sun GlassFish Enterprise Server or the GlassFish community bits. The "domain.xml" in both of them is pre-configured for the telnet port to 6666 using the "jvm-options" as shown below:

<jvm-options>-Dosgi.shell.telnet.port=6666</jvm-options>

However if you installed GlassFish as part of NetBeans 6.8, then you might see an error message as shown below:

C:\\Users\\Arun>telnet localhost 6666
Connecting To localhost...Could not open connection to the host, on
port 6666: Connect failed

This error is more prominent in Windows Vista / 7 because of the Windows User Account Control (UAC). Or anywhere where GlassFish is installed in a directory that require root/administrator/sudo access to read/write. This Tip Of The Day will explain how to workaround this issue.

The default NetBeans installation directory is "C:\\Program Files\\NetBeans 6.8" and GlassFish goes in "C:\\Program Files\\sges-v3". At first start of NetBeans (typically as a non-Administrator), it tries to register the pre-configured domain in GlassFish installed in "C:\\Program Files". But the non-Adminstrator user do not have read/write access to "C:\\Program Files" and any sub-directories. So NetBeans create a new "personal" domain and assign a random port available at that moment for telnet. It shows all the ports assigned during the domain creation as shown below:

The image shows the port number "22007" for OSGI_SHELL.

How do you find that port later ? - Go to "Services" tab, expand "Servers", right-click on "Personal GlassFish v3 Domain", select "Properties" from the popup menu to see the following window:

The "Domains folder" shows the directory location of newly created domain and "Domain Name" has the domain name. The exact assigned port can be found by looking at "Domains folder"\\"Domain Name"\\config\\domain.xml. On my Windows7, it showed the following line:

<jvm-options>-Dosgi.shell.telnet.port=22007</jvm-options>


So I tried "telnet localhost 22007" and voila, it worked!

Some other possible solutions that will work:

  1. Delete ".netbeans" directory and restart NetBeans by right-clicking on selecting "Run as administrator". This will provide the required rights for NetBeans to read/write "C:\\Program Files\\sges-v3\\glassfish\\domains\\domain1" directory. And so instead of creating a new "personal" domain, it'll register the existing domain in "\\Program Files\\sges-v3\\glassfish". Then "telnet localhost 6666" will work as expected.
  2. During NetBeans installation, specify GlassFish installation directory in a user directory such as:



    This will ensure that NetBeans will have required privileges to read/write the "domains\\domain1" directory.
  3. Delete the "Personal GlassFish v3 Domain" and register a new instance that is already installed in a user directory.
  4. Disable UAC.

A complete archive of all the TOTDs is available here.

Technorati: totd netbeans glassfish v3 felix osgi telnet

Wednesday Jan 20, 2010

TOTD #118: Managing OSGi bundles in GlassFish v3 - asadmin, filesystem, telnet console, web browser, REST, osgish

GlassFish v3 and OSGi integration is now known for almost two years. Several blogs have been published on this topic and googling on "glassfish osgi" shows 817,000 results. This blog has published four entries on the topic so far.

This Tip Of The Day (TOTD) will show the different ways you can manage OSGi bundles in GlassFish v3.

The first part is to create a trivial OSGi bundle as explained in TOTD #36.

  1. Create a simple Maven project using the command as shown below:
    ~/samples/v3/osgi >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] ------------------------------------------------------------------------
    [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] [archetype:create]
    [WARNING] This goal is deprecated. Please use mvn archetype:generate instead
    [INFO] Defaulting package to group ID: org.glassfish.samples.osgi.helloworld
    [INFO] artifact org.apache.maven.archetypes:maven-archetype-quickstart: checking for updates from central
    [INFO] ----------------------------------------------------------------------------
    [INFO] Using following parameters for creating OldArchetype: 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: package, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: artifactId, Value: helloworld
    [INFO] Parameter: basedir, Value: /Users/arungupta/samples/v3/osgi
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* End of debug info from resources from generated POM \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
    [INFO] OldArchetype created in dir: /Users/arungupta/samples/v3/osgi/helloworld
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 11 seconds
    [INFO] Finished at: Wed Jan 20 14:12:41 PST 2010
    [INFO] Final Memory: 12M/80M
    [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 <packaging> to "bundle" from the default value of "jar".
    2. Add <dependency> on "org.osgi.core".
    3. Add the <plugin> maven-bundle-plugin and provide <instructions> to generate the appropriate MANIFEST.MF.
      <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/osgi/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/osgi/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/osgi/helloworld/target/test-classes
    [INFO] [surefire:test]
    [INFO] Surefire report directory: /Users/arungupta/samples/v3/osgi/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.06 sec
    
    Results :
    
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO] [bundle:bundle]
    [INFO] [install:install]
    [INFO] Installing /Users/arungupta/samples/v3/osgi/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: 8 seconds
    [INFO] Finished at: Wed Jan 20 14:18:31 PST 2010
    [INFO] Final Memory: 20M/80M
    [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.357
    Bundle-Name: helloworld
    Created-By: Apache Maven Bundle Plugin
    Bundle-Version: 1.0.0.SNAPSHOT
    Build-Jdk: 1.6.0_17
    Bnd-LastModified: 1264025910352
    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
    

Lets install this newly created OSGi bundle in GlassFish v3. First, fire up GlassFish as:

~/tools/glassfish/v3/74b/glassfishv3/glassfish >./bin/asadmin start-domain -v
Jan 20, 2010 2:30:39 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: JVM invocation command line:
/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java
-cp
/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/glassfish.jar
-XX:+UnlockDiagnosticVMOptions
-XX:MaxPermSize=192m
-XX:NewRatio=2
-XX:+LogVMOutput

. . .

Jan 20, 2010 2:30:40 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: Successfully launched in 52 msec.
Jan 20, 2010 2:30:40 PM com.sun.enterprise.glassfish.bootstrap.ASMain main
INFO: Launching GlassFish on Felix platform

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

[#|2010-01-20T14:30:49.437-0800|INFO|glassfishv3.0|com.sun.grizzly.config.GrizzlyServiceListener|_ThreadID=11;_ThreadName=FelixStartLevel;|Perform lazy SSL initialization for the listener 'http-listener-2'|#]

[#|2010-01-20T14:30:49.527-0800|INFO|glassfishv3.0|com.sun.grizzly.config.GrizzlyServiceListener|_ThreadID=12;_ThreadName=Thread-11;|Starting Grizzly Framework 1.9.18-k - Wed Jan 20 14:30:49 PST 2010|#]

. . .

[#|2010-01-20T14:30:58.668-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/, felix.fileinstall.debug=1};|Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/org.apache.felix.scr.jar|#]

[#|2010-01-20T14:30:58.786-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/, felix.fileinstall.debug=1};|Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/osgi-web-container.jar|#]

[#|2010-01-20T14:31:00.436-0800|INFO|glassfishv3.0|null|_ThreadID=23;_ThreadName=ping;|Total number of available updates : 0|#]

There are several ways to manage the OSGi bundles in GlassFish v3:

  1. The "asadmin" command (explained here)
  2. Filesystem operations using the pre-installed Apache Felix File Install bundle (explained here)
  3. A Telnet shell using pre-installed Apache Felix Remote Shell (explained here and TOTD #103)
  4. A Web browser using the Apache Felix Web Console (needs to be installed separately and more details below)
  5. A RESTful client by installing the REST console (need to be installed separately and more details below)


Lets explore each option in detail now.

Option 1: Manage the OSGi bundle using the "asadmin" command

  1. Deploy the generated OSGi bundle using asadmin command:
    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin deploy --type osgi helloworld-1.0-SNAPSHOT.jar 
    Application deployed successfully with name helloworld-1.0-SNAPSHOT.
    
    
    Command deploy executed successfully.
    
    The server log shows the following output:
    [#|2010-01-20T16:15:10.553-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=36;_ThreadName=http-thread-pool-4848-(2);
    |Hey!|#]
    
    
    Notice "Hey!" message in the server log as the bundle gets started.
  2. Verify the installed bundle as:
    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin list-applications
    helloworld-1.0-SNAPSHOT 
    
    Command list-applications executed successfully.
    

    Or if there are multiple applications deployed then only the OSGi bundles can be queried as:

    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin list-applications --type osgi
    helloworld-1.0-SNAPSHOT 
    
    Command list-applications executed successfully.
    
  3. The bundle can be undeployed as:

    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin undeploy helloworld-1.0-SNAPSHOT 
    
    Command undeploy executed successfully.
    
    
    And then the following message is shown on the console:
    [#|2010-01-20T16:22:19.554-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=37;_ThreadName=http-thread-pool-4848-(1);
    |Bye!|#]
    
    
    Notice "Bye!" message in second line of the log output indicating the bundle is stopped.

Option 2: Manage the OSGi bundle using file system operations

  1. Copy the generated jar (target/helloworld-1.0-SNAPSHOT.jar) in "modules/autostart" directory as:
    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >cp ~/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar modules/autostart/
    
    
    and that shows the log output as:
    [#|2010-01-20T16:29:04.625-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Installed /Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/
    helloworld-1.0-SNAPSHOT.jar|#]
    
    [#|2010-01-20T16:29:04.635-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Hey!|#]
    
    [#|2010-01-20T16:29:04.636-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart
    /helloworld-1.0-SNAPSHOT.jar|#]
    
    
    Notice "Hey!" message in the second line of log output as the bundle gets started.
  2. The bundle can be undeployed by removing the JAR file from "modules/autostart" directory as:

    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >rm modules/autostart/helloworld-1.0-SNAPSHOT.jar
    
    
    that shows the following output:
    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >[#|2010-01-20T16:32:04.677-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Uninstalling bundle 224 (helloworld)|#]
    
    [#|2010-01-20T16:32:04.679-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Bye!|#]
    
    [#|2010-01-20T16:32:04.682-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Uninstalled /Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart
    /helloworld-1.0-SNAPSHOT.jar|#]
    
    
    Notice "Bye!" message in second line of the log output indicating the bundle is stopped.

Option 3: Manage the OSGi bundle using a remote Telnet Shell

  1. Connecting to the Felix Remote Shell as:
    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >telnet localhost 6666
    Trying ::1...
    telnet: connect to address ::1: Connection refused
    Trying fe80::1...
    telnet: connect to address fe80::1: Connection refused
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '\^]'.
    
    Felix Remote Shell Console:
    ============================
    
    ->
    
  2. Install the bundle as:
    -> install file:///Users/arungupta/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar
    Bundle ID: 225
    
    The command output shows "225" as the bundle id. This id is used to start / stop / uninstall the bundle.
  3. Check the bundle status as:
    -> find hello
    START LEVEL 1
       ID   State         Level  Name
    [ 225] [Installed  ] [    1] helloworld (1.0.0.SNAPSHOT)
    
    
    and then start, stop, and uninstall the bundle as:
    -> start 225
    -> stop 225
    -> uninstall 225
    -> find hello
    No matching bundles found
    
    
    which shows following output in the logs:
    [#|2010-01-20T16:43:45.399-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=38;_ThreadName=telnetconsole.shell remote=/127.0.0.1:4894;|Hey!|#]
    
    [#|2010-01-20T16:43:58.516-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=38;_ThreadName=telnetconsole.shell remote=/127.0.0.1:4894;|Bye!|#]
    

    Notice "Hey!" and "Bye!" messages in the log output as the bundle is started and stopped.


Option 4 - Manage the OSGi bundle using a Web browser

Lets see how the OSGi bundles in GlassFish can be managed using Apache Felix Web Console. This is originally explained in Sahoo's blog.

  1. Copy GlassFish OSGi HTTP Service bundle from here (latest) and save it in the "modules/autostart" directory.

  2. Copy Apache Felix Web Console bundle from here (latest) and save it in the "modules/autostart" directory.

  3. Ignore the "NoClassDefFoundError" in the server log. The key is to look for the following message in server log:

    Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/org.apache.felix.webconsole-2.0.4.jar|#]
    
  4. Open the URL "http://localhost:8080/osgi/system/console/bundles" in a browser and use "admin" as the username and "admin" as the password as shown below:



    I had to enter the credentials couple of times for the login to work but finally the following window showed up:



    It shows a complete summary of all the OSGi bundles available/installed/active etc in GlassFish v3. A new OSGi bundle can be installed by clicking on "Choose File" button. Several administration commands such as Start/Stop, Update, Uninstall, Refresh Import Packages can be issued for each bundle by clicking on associated buttons.

  5. Install the OSGi bundle by clicking on "Choose File" and selecting "helloworld-1.0.-SNAPSHOT.jar" and then click on "Install or Update" button. The following message is shown in the server log:

    [#|2010-01-20T17:04:46.654-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=39;_ThreadName=Background Install /var/folders/+E/+E6YtSvGGEKNwOA77I-9Fk+++TI/-Tmp-/install1657418488877506078.tmp;
    |Hey!|#]
    

    The bundle gets installed and started as identified by "Hey!" message.
    The recently installed "HelloWorld" bundle looks like:

    Clicking on "helloworld" shows the complete status about the bundle as shown below:

     

  6. The bundle can be stopped by clicking on the Stopped, Refreshed Package Imports, Updated, and Uninstalled by clicking on the respective buttons in the "Actions" column. Clicking on the Stop button shows the following message:

    [#|2010-01-20T17:10:56.359-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com
    .sun.enterprise.v3.services.impl|_ThreadID=25;_ThreadName=http-thread-pool-8080-(2);
    |Bye!|#]
    
    
    Notice "Bye!" message indicating the bundle has stopped.

Option 5: Manage the OSGi bundle using a REST console

  1. If not done already, copy GlassFish OSGi HTTP Service bundle from here (latest) and save it in the "modules/autostart" directory.
  2. Download the REST console bundle (latest) in "modules/autostart" directory.
  3. The complete list of bundles is available in Text or XML format by accessing the URL "http://localhost:8080/osgi/restconsole/bundles/.txt" or "http://localhost:8080/osgi/restconsole/bundles" respectively. Here is how the text output looks like:
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 16198    0 16198    0     0  1173k      0 --:--:-- --:--:-- --:--:-- 1173kbundles 
         bundle 
              id 
                   0 
              symbolic-name 
                   org.apache.felix.framework 
    
    . . .
    
              description 
                   Generated using Pax-Construct 
              vendor 
              version 
                   1.0.0.SNAPSHOT 
              location 
                   file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/
    com.knokode.osgi.restconsole.main-1.0-PREVIEW01.jar 
              state 
                   ACTIVE
    
  4. The OSGi bundle should be installed by issuing the following command:
    curl -X PUT file:///Users/arungupta/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar http://localhost:8080/osgi/restconsole/bundles
    
    but it's giving a "Segmentation fault". Am following with @fdiotalevi.

    Anyway, the complete usage information of the REST console is described here.

So how do you manage OSGi bundles in GlassFish v3 - asadmin, file system operations, telnet console, web browser, or REST ?

UPDATE: Osgish is a command-line shell for OSGi and implemented in Perl. See the complete installation instructions and it can be used to manage OSGi runtime in GlassFish as well.

A complete archive of all the TOTDs is available here.

Technorati: totd glassfish v3 osgi apache felix bundles maven

Monday Sep 14, 2009

TOTD #103: GlassFish v3 with different OSGi runtimes – Felix, Equinox, and Knoplerfish

GlassFish v3 uses standard OSGi APIs to achieve modularity. It bundles Apache Felix 2.0 as the OSGi runtime and can run on any other OSGi R4.1 compliant runtimes as well. This blog will use previously described instructions and show how to run GlassFish v3 on Eclipse Equinox and Knoplerfish. The complete details about different OSGi runtimes is described here, this TOTD provide detailed steps and overrides the instructions defined here (and here and here).

This blog is using a CI build from last week but you should try the instructions on a promoted build.

GlassFish with Felix - Felix 2.0.0 is bundled with GlassFish v3 and requires no additional configurations.

  1. Start GlassFish as:
    ~/tools/glassfish/v3/2269/glassfishv3/glassfish >./bin/asadmin start-domain --verbose
    

    and see the following messages in the log:
    Sep 11, 2009 4:41:16 PM com.sun.enterprise.glassfish.bootstrap.ASMain main
    INFO: Launching GlassFish on Felix platform
    
    Welcome to Felix
    ================
    
    . . .
    
    Sep 11, 2009 4:41:30 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3  startup time : Felix(9669ms) startup services(4453ms) total(14122ms)
    
    
  2. Optionally, connect to Felix runtime using Apache Felix Remote Shell (described here) as:

    ~/tools/glassfish/v3/2269/glassfishv3 >telnet localhost 6666
    Trying ::1...
    telnet: connect to address ::1: Connection refused
    Trying fe80::1...
    telnet: connect to address fe80::1: Connection refused
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '\^]'.
    
    Felix Remote Shell Console:
    ============================
    
    ->
    


    and type "help" to see the list of commands available as:

    -> help
    bundlelevel
    cd
    find
    headers
    help
    inspect
    install
    log
    ps
    refresh
    resolve
    shutdown
    start
    startlevel
    stop
    uninstall
    update
    version
    
    Use 'help ' for more information.
    
  3. See the list of OSGi modules installed as:
    -> ps
    START LEVEL 1
       ID   State         Level  Name
    [   0] [Active     ] [    0] System Bundle (2.0.0)
    [   1] [Active     ] [    1] HK2 OSGi Main Bundle (0.3.91)
    [   2] [Installed  ] [    1] EclipseLink Core (2.0.0.v20090821-r4934)
    [   3] [Resolved   ] [    1] Hibernate validator library and Validation API (JSR 303) repackaged as OSGi and HK2 bundle (3.0.0.JBoss-400Beta3)
    [   4] [Installed  ] [    1] Connector (gluecode) for GlassFish Java EE Connector Architecture Runtime (3.0.0.SNAPSHOT)
    [   5] [Active     ] [    1] GlassFish Flashlight Framework (3.0.0.SNAPSHOT)
    
    . . .
    
    [ 201] [Resolved   ] [    1] glassfish-corba-asm (3.0.0.b024)
    [ 202] [Resolved   ] [    1] MIME streaming extension (1.4)
    [ 203] [Installed  ] [    1] Admin Console Connectors Plugin (3.0.0.SNAPSHOT)
    [ 204] [Installed  ] [    1] Apache Felix Shell TUI (1.4.0)
    [ 205] [Resolved   ] [    1] org.glassfish.core.glassfish-extra-jre-packages
    
  4. Use "headers" command to display the bundle header properties for any bundle. "help <command>" shows more information about each command displayed in the output of "help". Finally type "exit" to quit the shell.

GlassFish on Equinox

  1. Download Equinox latest release from http://www.eclipse.org/equinox/ (3.5 as of this writing).
  2. Unzip the contents and copy the Equinox jar file to "osgi/equinox" directory of GlassFish as shown below:
    ~/tools/glassfish/v3/2269/glassfishv3/glassfish >unzip ~/Downloads/equinox-SDK-3.5.zip -d ~/tools/equinox-3.5
    ~/tools/glassfish/v3/2269/glassfishv3/glassfish >cp ~/tools/equinox-3.5/plugins/org.eclipse.osgi_3.5.0.v20090520.jar ./osgi/equinox
    
    
  3. Start GlassFish as:
    ~/tools/glassfish/v3/2269/glassfishv3 >GlassFish_Platform=Equinox ./bin/asadmin start-domain --verbose
    

    and see the following messages in the log:
    Sep 11, 2009 5:11:13 PM com.sun.enterprise.glassfish.bootstrap.ASMain main
    INFO: Launching GlassFish on Equinox platform
    Listening on port 6667 ...
    
    . . .
    
    Sep 11, 2009 5:11:19 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3  startup time : Equinox(3649ms) startup services(1843ms) total(5492ms)
    


    Note, Equinox platform started on port 6667 for remote management.
  4. Optionally, connect to Equinox runtime as:

    ~/tools/glassfish/v3/2269/glassfishv3/glassfish >telnet localhost 6667
    Trying ::1...
    Connected to localhost.
    Escape character is '\^]'.
    
    osgi>
    
    

    Make sure to use the port number specified during the startup. Type "help" to see the list of commands available as:
    osgi> help
    ---Controlling the OSGi framework---
            launch - start the OSGi Framework
            shutdown - shutdown the OSGi Framework
            close - shutdown and exit
            exit - exit immediately (System.exit)
            init - uninstall all bundles
            setprop = - set the OSGi property
    ---Controlling Bundles---
    
    . . . 
    
    ---Controlling the Console---
            more - More prompt for console output
            disconnect - Disconnects from telnet session
    
  5. See the list of OSGi modules installed as:
    osgi> ss
    
    Framework is launched.
    
    id      State       Bundle
    0       ACTIVE      org.eclipse.osgi_3.5.0.v20090520
                        Fragments=62, 128, 205
    1       ACTIVE      com.sun.enterprise.osgi-main_0.3.91
    2       RESOLVED    org.eclipse.persistence.core_2.0.0.v20090821-r4934
                        Fragments=136
    
    . . . 
    
    203     RESOLVED    org.glassfish.admingui.console-jca-plugin_3.0.0.SNAPSHOT
    204     RESOLVED    org.apache.felix.shell.tui_1.4.0
    205     RESOLVED    org.glassfish.core.glassfish-extra-jre-packages_0.0.0
                        Master=0
    

    Typing "help" shows a comprehensive list of commands. Finally type "disconnect" to terminate the shell. Do not type "exit" as it terminates the Equinox shell and killing the GlassFish process as well.

GlassFish with Knoplerfish - As mentioned here, GlassFish v3 requires at least R4.1 APIs. All Knopflerfish releases prior to 3.0.0 are R4 compliant and so will not work with the GlassFish v3 latest builds. Knopflerfish 3.0.0 beta1 is the first build that is R4.2 compliant but it does not start on Mac OS X 10.5.8 as described in issue #2858798. So until then, you you can follow the instructions documented at  GlassFish v3 on OSGi KnopflerFish and Using KnopflerFish Desktop in GlassFish v3 to get them running on GlassFish v3 TP2 or Prelude.

Some additional details missing form the entries above

  1. Download Knoplerfish 2.3.3 and install.
  2. In "knopflerfish_osgi_2.3.3/knopflerfish.org/osgi", copy "props.xargs" to "gf.xargs" and add the lines mentioned here. Make sure to copy the Knopflerfish related files to the modules directory and change the location accordingly.
  3. Create "gfpackages.txt" by copying "felix/conf/config.properties" from the GlassFish directory. List each package specified in the "gf-packages" property on a single line. There should be no other character such as ";" or "," or "/" on a line, only the package name.
  4. Start GlassFish as:
    ~/tools/glassfish/v3/2269/glassfishv3/glassfish >KNOPFLERFISH_HOME=/Users/arungupta/tools/knopflerfish_osgi_2.3.3/knopflerfish.org/osgi GlassFish_Platform=Knopflerfish ./bin/asadmin start-domain --verbose
    
    
    and see the following messages in the log:
    Knopflerfish OSGi framework, version 4.1.10
    Copyright 2003-2009 Knopflerfish. All Rights Reserved.
    
    See http://www.knopflerfish.org for more information.
    Loading xargs url file:/Users/arungupta/tools/knopflerfish_osgi_2.3.3/knopflerfish.org/osgi/gf.xargs
    Removed existing fwdir /Users/arungupta/tools/knopflerfish_osgi_2.3.3/knopflerfish.org/osgi/fwdir
    Installed: file:/Users/arungupta/tools/glassfish/v3/glassfishv3-tp2/glassfish/modules/tiger-types-osgi-0.2.1.jar (id#1)
    Installed: file:/Users/arungupta/tools/glassfish/v3/glassfishv3-tp2/glassfish/modules/auto-depends-0.2.1.jar (id#2)
    Installed: file:/Users/arungupta/tools/glassfish/v3/glassfishv3-tp2/glassfish/modules/config-0.2.1.jar (id#3)
    
    . . .
    
    Started: file:/Users/arungupta/tools/glassfish/v3/glassfishv3-tp2/glassfish/modules/cm_all-2.0.1.jar (id#7)
    Started: file:/Users/arungupta/tools/glassfish/v3/glassfishv3-tp2/glassfish/modules/console_all-2.0.1.jar (id#8)
    Started: file:/Users/arungupta/tools/glassfish/v3/glassfishv3-tp2/glassfish/modules/desktop_all-2.3.11.jar (id#11)
    


    and finally see the Knopflerfish console as:



The instructions will be updated after a more stable release of Knopflerfish is available.

A complete archive of all the tips is available here.

Technorati: totd glassfish v3 osgi apache felix eclipse equinox knopflerfish

Wednesday Jun 25, 2008

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


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-SNAPSHOT.jar
    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
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today