1 2 3 4 Previous Next


47 posts

Java VM has a standard option called -verbose as shown by java -help:

                  enable verbose output

To diagnose class loading issues, you need to specify -verbose:class.  It's straight forward to use if you are launching the Java process  yourself. How does a GlassFish user use this?

Option #1: Using java command directly

If you (like me) are starting glassfish using java command directly,  then you could easily specify in your command output and you will see  each class loading getting logged with a source of the class (You would  like to redirect the output as there are just so much output that your  terminal buffer may not be sufficient to capture the entire output):

java -verbose:class -jar glassfish/modules/glassfish.jar

Option #2: Starting GlassFish in foreground using start-domain  command

Even if you are using start-domain command to start the server, I   recommend starting GlassFish in foreground using "-v"  option of start-domain so that the jvm log and  server log appear in  console output like option #1, thus allowing you to corelate them   better. You would like to redirect the output  just like previous case  as well. In this case, you just need the following setting in  domain.xml:


and start server like this:

asadmin start-domain -v

Option #3: Starting GlassFish in background using start-domain  command

If you are using asadmin start-domain command to start GlassFish in  background, then you have to add the following jvm options in  jvm-options section of your domain.xml:


In this case, the jvm.log will be next to server.log in logs  directory. You are relying on proprietary JVM options here.

Because I forget about these additional options, I decided to write  them down here.

Look at the code below where the main() loads a class whose name is specified by first argument. The second argument tells whether the class should be resolved or not. It also contains 5 test classes: A1, A2 and their dependencies: B, B1, B2. We will try to identify how early Bs are needed if I want to use As.

class Main {
  public static void main(String... args) throws Exception {
   Class c = Class.forName(args[0], Boolean.valueOf(args[1]), Main.class.getClassLoader());

abstract class B { public abstract void bar(); }

class B1 extends B { public void bar(){} }

class B2 extends B { public void bar(){} }

class A1 {
  void foo(boolean cond) {
   B b = cond ? new B1() : new B2();

class A2 {
  void foo(boolean cond) {
   B1 b = new B1();

After compilation, we shall delete all the B classes so that we can identify when B1.class and B2.class are required while loading A1 or A2.

$ javac Main.java

$ rm B[12].class

$ ls
A1.class  A2.class  A.class  B.class  Main.class  Main.java

$ java Main A1 false

$ java Main A2 false

$ java Main A2 true

$ java Main A1 true
Exception in thread "main" java.lang.NoClassDefFoundError: B1
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at Main.main(Main.java:3)
Caused by: java.lang.ClassNotFoundException: B1
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    ... 3 more

$ java -Xverify:none Main A1 true

This tells us that the byte code verification of A1.class caused some of the referencing classes (B1 in this case) to be loaded. Why did it then not fail when we tried to load A2? I turned to my long time friend and colleague Sundarajan, who works in Java SE group, to discuss this. He explained that since LHS and RHS used different types in the following line:

  B b = cond ? new B1() : new B2();

so, the byte code verifier had to load the types involved to ensure assignment compatibility.

Most developers don't care about this, but a few that do typically are writing some kind of lazily initialized systems where they probably don't want some dependencies to be loaded until the dependent service is actually invoked. Of course, frameworks like OSGi helps a long way in developing such systems. Even those developers have to pay attention to such details to get the desired lazy behavior. Some may say that reflection could avoid the problem, but that's not the point being made here.

I understand this behavior of bytecode verifier is probably implementation specific and can differ across implementations including implementation versions. For the record, my Java version is 1.6.0_21.

Actually I came across this in a much more coimplex scnerio while trying to investigate why certain modules in GlassFish are getting loaded at startup time contrary to my expectation, but basic test case remains same.

Sahoo Guest

OSGi/JMS/MDB Example Blog

Posted by Sahoo Guest Apr 21, 2010

Here is an example of yet another hybrid (OSGi + Java EE) application. This is a complete JMS consumer/producer example using OSGi and GlassFish. You can download the complete sample from here.

How to use the sample:

1. Download osgi-jms-mdb-1.zip and unzip it.

2. cd osgi-jms-mdb-1/

3. mvn clean install

4. Start GlassFish (something like "asadmin start-domain" or "java -jar glassfish.jar" will do)

5. Download OSGi/EJB container support bundle for GlassFish and 
install it by just copying to modules/autostart/:
wget http://download.java.net/maven/glassfish/org/glassfish/osgi-ejb-container/3.1-SNAPSHOT/osgi-ejb-container-3.1-SNAPSHOT.jar
cp osgi-ejb-container-3.1-SNAPSHOT.jar $glassfish/modules/autostart/

6. Create a couple of JMS resources by executing the following commands 
(you can use the admingui if you prefer GUI)

asadmin create-jms-resource --restype javax.jms.Topic jms/osgi.Topic1

asadmin create-jms-resource --restype javax.jms.ConnectionFactory jms/osgi.ConnectionFactory1

7.tail -f $glassfish/domains/domain1/logs/server.log.

8. Deploy the bundles and configure them as shown below 
(Although, you can copy them in any order you like, but I suggest you copy them 
in the following order to them in action and after each step, watch server.log).

cp ./message-consumer/target/osgijms1.consumer.jar $glassfish/domains/domain1/autodeploy/bundles/
cp ./message-producer/target/osgijms1.producer.jar $glassfish/domains/domain1/autodeploy/bundles/
cp ./osgijms1.producer.cfg $glassfish/domains/domain1/autodeploy/bundles/


Description of the sample 

As the diagram above shows, there are two bundles, viz:

a) A JMS message consumer bundle - This is also an OSGi bundle. It contains a single class which is the message consumer  or listener. It is implemented as a Message Driven Bean (MDB). There is nothing OSGi-specific in the bean. The jar file contains OSGi metadata and an additional GlassFish specific header called Export-EJB to indicate to the server that the OSGi bundle contains EJBs that need to be processed. Refer to my earlier blogs about deploying ejb jars as OSGi bundles in glassfish.

The relevant metadata for the EJB OSGi bundle looks like this:

[MANIFEST osgijms1.consumer.jar]

Export-EJB                              NONE                                                   
Bundle-ManifestVersion                  2                                                       Bundle-SymbolicName                     sahoo.osgijms1.consumer                              Bundle-Version                          1.0.0.SNAPSHOT                                          Import-Package                          javax.ejb,javax.jms                                     Manifest-Version                        1.0                                                 

The MDB looks like this:

@MessageDriven(mappedName = "jms/osgi.Topic1")

public class AnMDB implements MessageListener {
    public void onMessage(Message message) {
        String str = null;
        if (message instanceof TextMessage) {
            try {
                str = TextMessage.class.cast(message).getText();
            } catch (JMSException e) {
                // ignore
        if (str == null) str = message.toString();
        System.out.println("AnMDB Received: " + str);

b) A JMS message producer bundle - This contains a single class which is the the BundleActivator.  The bundle activator is configured about JMS destination via OSGi Config Admin service. Upon configured, it sends messages to the JMS destination. The complete source code for the message producer is given below:

public class Activator1 implements BundleActivator {

    public void start(BundleContext context) throws Exception {
        System.out.println("Message producer started - waiting to be configured with topic name");
        Properties props = new Properties();
        props.put(Constants.SERVICE_PID, "osgijms1.producer");
        context.registerService(ManagedService.class.getName(), new ManagedService() {
            public void updated(Dictionary properties) throws ConfigurationException {
                if (properties != null) {
                    String destinationName = (String) properties.get("osgijms1.Destination");
                    String connectionFactoryName = (String) properties.get("osgijms1.ConnectionFactory");
                    int noOfMsgs = Integer.valueOf((String) properties.get("osgijms1.NoOfMsgs"));
                    sendMessage(connectionFactoryName, destinationName, noOfMsgs);
        }, props);

    private void sendMessage(String connectionFactoryName, String destinationName, int noOfMsgs) {

        Connection connection = null;
        try {
            InitialContext ctx = new InitialContext();

            ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup(connectionFactoryName);

            connection = connectionFactory.createConnection();

            Session session = connection.createSession(

            Destination dest = (Destination) ctx.lookup(destinationName);
            MessageProducer producer = session.createProducer(dest);
            TextMessage message = session.createTextMessage();

            for (int i = 0; i < noOfMsgs; i++) {
                message.setText("This is message " + (i + 1));
                System.out.println("Sending message: " + message.getText());

             * Send a non-text control message indicating end of
             * messages.
        } catch (JMSException e) {
            System.err.println("Exception occurred: " + e.toString());
        } catch (NamingException e) {
            System.err.println("Exception occurred: " + e.toString());
        } finally {
            if (connection != null) {
                try {
                } catch (JMSException e) {

    public void stop(BundleContext context) throws Exception {

What's coming next

We will make the JMS resources available as OSGi services just like we make JDBC resources available as OSGi services. Once we do that, our message producer can track the service and send message once the resource is deployed.


As usual, if you have questions, please ask us in our forum or mailing lists.

Recently a user in GlassFish forum asked about developing JAX-WS web service in an OSGi bundle. Here is a complete sample demonstrating a JAX-WS web service invoking an OSGi service via OSGi service registry. You can download it from here. The diagram below hopefully explains the organisation of the sample:


As the above diagram shows, we have three components, viz:

1) osgi-service.jar: This is an OSGi bundle which provides a service to other bundles. It contains two POJOs, viz: a) an interface called sahoo.hybridapp.jaxws1.service.Watch, b) an implementation of the same interface called sahoo.hybridapp.jaxws1.service.WatchImpl.  This bundle also contains a bundle activator called sahoo.hybridapp.jaxws1.service.Activator, which is responsible for registering an instance of WatchImpl in OSGi service registry.

  2) web-service.war: This is a Web Application Bundle. A Web Application Bundle is a hybrid application - it's both a Java EE archive as well as an OSGi bundle. In this case, it is a war file as well as an OSGi bundle. It's a war file, because it contains a Servlet based JAX-WS end point. It's an OSGi bundle, because we want to make use of OSGi service in the implementation of our web service. It contains a single class called sahoo.hybridapp.jaxws1.webservice.WatchWebService which is defined like this:


package sahoo.hybridapp.jaxws1.webservice;

import sahoo.hybridapp.jaxws1.service.Watch;
import org.osgi.framework.*;
import javax.jws.*;

public class WatchWebService {
   @WebMethod public String currentTime() {
       Watch watch = getService(Watch.class);
       System.out.println("WatchService: OSGi service is: " + watch);
       if (watch == null) {
          return "I don't have a watch";
       } else {
          return watch.currentTime();

     * 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(WatchWebService.class.getClassLoader()).getBundle().getBundleContext();
       ServiceReference ref = ctx.getServiceReference(type.getName());
       return ref != null ? type.cast(ctx.getService(ref)) : null;

The MANIFEST.MF of web-service.war looks like this:

Bundle-ClassPath                        WEB-INF/classes/                       
Bundle-ManifestVersion                  2                                      
Bundle-SymbolicName                     sahoo.hybridapp.jaxws1.web-service     
Bundle-Version                          1.0.0.SNAPSHOT                         
Import-Package                          javax.jws;version="2.0",org.osgi.framework;version="1.5",sahoo.hybridapp.jaxws1.service;version="1.0"
Web-ContextPath                         /hybridapp.jaxws1.web-service        

3) web-service-client.jar: This is a plain jar file which makes use of JAX-WS stack of Java SE environment to invoke our web service. It has a single class called sahoo.hybridapp.jaxws1.webserviceclient.Main. The rest of the classes that are part of this jar are generated by wsdl compiler as part of build.

How to build, deploy and test:

Step 1: Start GlassFish

java -jar glassfish.jar

Step 2: Build and deploy the service bundles

cd hybridapp.jaxws1/

mvn clean install

This will produce two OSGi bundles called osgi-service/target/osgi-service.jar and web-service/target/web-service.war. Deploy these two OSGi bundles to GlassFish by simply copying them to domain1/autodeploy/bundles/ dir as shown below:

cp osgi-service/target/osgi-service.jar web-service/target/web-service.war $glassfish.home/domains/domain1/autodeploy/bundles/

GlassFish will automatically detect that web-service.war is a WAB and will perform necessary deployment of EE artifacts as a result of which a web service end point will be available. You can see something like this appearing in server.log:

WS00018: Webservice Endpoint deployed
 WatchWebService  listening at address at http://localhost:8080/hybridapp.jaxws1.web-service/WatchWebServiceService

Step 3: Build and run the client

Once the web service is available, run

mvn -f web-service-client/pom.xml

to build web-service-client.jar. This is because the WSDL url, as specified in web-service-client/pom.xml, is not available until the web service is deployed.

To test, simple run:

java -jar web-service-client.jar

You shall see it will print the current time as obtained from the web service which in turn obtrains it from the OSGi service.

Look at the source code and maven pom.xmls to see how various maven plugins help make life easier. This sample uses a WAB to develop web service. You can develop JAX-WS service end points as EJBs as well and in that case you can deploy them as OSGi/EJB bundle in GlassFish. Enjoy developing OSGi enabled Java EE applications in GlassFish!!! As usual,  feddback most welcome.

Typical users of GlassFish use GlassFish in a separate process and they start GlassFish by using commands like the following:

java -jar glassfish.jar
asadmin start-domain

The above commands first launch an OSGi framework and then deploy the necessary bundles. What if you want to embed GlassFish in an existing OSGi runtime? The bootstrapping code was slightly complicated IMO. Recently when Apache Camel committer Charles Moulliard asked me some questions around embedding GlassFish v3 in an OSGi runtime, I decided to revisit the bootstrap module in order to simplify it so that I had less explaining to do. I recently did exactly that. In this blog, I show how using a simple BundleActivator, one can embed GlassFish in an OSGi runtime. In the use case below, I first start an instance of Equinox (plain  vanilla Equinox runtime) and deploy a test bundle which controls life cycle of GlassFish. You can use other launchers like karaf as well.

/tmp/equinox-3.5.1$ java -jar org.eclipse.osgi_3.5.1.R35x_v20090827.jar -console

osgi> install file:///tmp/embeddedgf-1.0-SNAPSHOT.jar
Bundle id is 1

osgi> start 1 
// The above command will start glassfish. You shall some output indicating the same.
// After GlassFish is started, you can use all regular GlassFish commands.
// e.g., to deploy an app, you can run "asadmin deploy ..."

osgi> stop 1
// This will stop GlassFish server. To start again, "start bundle #1"

What is this embeddedgf-1.0-SNAPSHOT.jar?

That's a tiny sample bundle I developed to embed GlassFish. It has a single class called GFActivator. This bundle activator does the following in the start() method:

1. Goes through glassfish modules directory and installs all bundles.

2. It then configures a configuration object with service PID com.sun.enterprise.glassfish.bootstrap.GlassFish. This is the PID for the <strong>ManagedService</strong> registered by GlassFish.  The PID name is subject to change. It then updates the configuration object with the following properties:

com.sun.aas.installRoot = /space/ss141213/WS/gf/v3/publish/glassfishv3/glassfish/
com.sun.aas.instanceRoot =  /space/ss141213/WS/gf/v3/publish/glassfishv3/glassfish/domains/domain1/

These two properties are enough for GlassFish to start.

3. It then locates GlassFish main bundle and starts it.

When I stop this bundle, it stops GlassFish server by stopping the main GlassFish bundle. Of course, you can restart the bundle and GlassFish will be restarted. The java source and pom.xml are all part of this zip file.


package sahoo.embeddedgf;

import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.Configuration;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;

 * Activator that starts and stops GlassFish.
 * To start glassfish, it does the following:
 * 1. Installs all bundles located in glassfish modules directory.
 * 2. Creates a configuration with a couple of properties:
 * com.sun.aas.installRoot and com.sun.aas.instanceRoot.
 * The former one refers to the directory where glassfish is installed.
 * (e.g., /tmp/glassfishv3/glassfish)
 * The latter one refers to the domain directory - this is a directory containing
 * configuration information and deployed applications, etc.
 * 3. Starts the main bundle of GlassFish. Main bundle is identified by Bundle-SymbolicName
 * org.glassfish.core.glassfish. This main bundle then is used to start any necessary bundle.
 * In order to stop glassfish, we just stop the main bundle.
 * @author Sanjeeb.Sahoo@Sun.COM
public class GFActivator implements BundleActivator
    private BundleContext bundleContext;
    // I have hardcoded the glassfish path as this is just an example bundle.
    private String installRoot = "/space/ss141213/WS/gf/v3/publish/glassfishv3/glassfish/";
    private String instanceRoot = "/space/ss141213/WS/gf/v3/publish/glassfishv3/glassfish/domains/domain1/";
    private Bundle mainBundle;
    private static final String mainBundleName = "org.glassfish.core.glassfish";
    private static final String gfpid = "com.sun.enterprise.glassfish.bootstrap.GlassFish";
    private static final String JAR_EXT = ".jar";

    public void start(BundleContext bundleContext) throws Exception
        this.bundleContext = bundleContext;
        // Install all gf bundles

    public void stop(BundleContext bundleContext) throws Exception
        if (mainBundle != null) {

     * Install all bundles located in modules directory and subdirectories under that.
    private void installBundles() {
        for (File jar : findJars()) {
            try {
            } catch (BundleException e) {
                // continue processing after logging the exception

     * Returns a list of jar files found in modules directory and subdirectories under that.
     * Any file with extension .jar is considered as a jar file.
     * @return a list of jar files
    private List<File> findJars() {
        File modulesDir = new File(installRoot, "modules/");
        final List<File> jars = new ArrayList<File>();
        modulesDir.listFiles(new FileFilter(){
            public boolean accept(File pathname) {
                if (pathname.isDirectory()) {
                } else if (pathname.getName().endsWith(JAR_EXT)){
                return false;
        return jars;

    private void configureBundles() {
        final Properties props = new Properties();
        props.setProperty("com.sun.aas.installRoot", installRoot);
        props.setProperty("com.sun.aas.instanceRoot", instanceRoot);
        ServiceTracker tracker = new ServiceTracker(bundleContext, ConfigurationAdmin.class.getName(), null) {
            public Object addingService(ServiceReference reference) {
                ConfigurationAdmin ca = ConfigurationAdmin.class.cast(bundleContext.getService(reference));
                try {
                    Configuration c = ca.getConfiguration(gfpid, null);
                } catch (IOException e) {
                return super.addingService(reference); //TODO(Sahoo): Not Yet Implemented

     * Starts GlassFish primordial bundle
    private void startBundles() {
        for (Bundle b : bundleContext.getBundles()) {
            if (mainBundleName.equals(b.getSymbolicName())) {
                mainBundle = b;
                try {
                } catch (BundleException e) {

Happy GlassFish-ing.

Statutory Warning: The code shown here is all sample code.

Did you know javap ignores Class-Path manifest attribute where as javac honors it? I didn't. Now I know. I have a jar called foo.jar with following manifest entry:

Manifest-Version: 1.0
Class-Path: javax.ejb.jar
Created-By: 1.6.0_16 (Sun Microsystems Inc.)
javax.ejb.jar contains all the EJB APIs and it is in the same directory as foo.jar. Yet, this is what I see when I run javap:
javap -classpath foo.jar javax.ejb.EJB
ERROR:Could not find javax.ejb.EJB
On the other hand, javac works fine. e.g., I could successfully compile the following file:
public class A {}
like this:
javac -classpath foo.jar A.java
It definitely looks like a bug in javap. The situation that prompted me to this experiment is we are trying to create some empty jars in glassfish/lib directory which would have Class-Path manifest reference to glassfish/modules directory. We need those empty jars as we have advertised about them in previous versions of GlassFish and our users use them in classpath during compilation, so we don't want to break their build scripts. I was trying to find out what java commands can consume those empty jars. At this point, javap can't. I am using Sun JDK 1.6.0_16-b01. It's not that bad considering javac can consume them and that takes care of our existing users' need.
When my colleague Marina Vatkina sent me some code earlier today hoping a second pair of eyes would spot the obvious error, knowing how thorough Marina typically is, I knew there was no obvious error there. Simplified version of what was being attempted is shown below:
import java.io.*;
import java.util.*;
import java.util.jar.*;

public class CreateJarWithManifest {
    public static void main(String[] a) throws Exception {
        Manifest manifest = new Manifest();
        manifest.getMainAttributes().putValue("Foo", "Bar");
        FileOutputStream fo = new FileOutputStream(new File("foo.jar"));
        JarOutputStream jo = new JarOutputStream(fo, manifest);
        new JarFile("foo.jar").getManifest().write(System.out);
As you can see, the above code is creating a new Jar file with a manifest entry Foo: Bar and then reads the manifest from the jar and prints it to output for verification purpose. But, strangely this program prints an empty manifest. I vaguely remembered to have encountered this problem before, but never wrote it down anywhere. It took some time to figure out here and that's why I thought of putting it down here this time. The problem here is that if there is no attribute called Manifest-Version in the main section, the manifest is simply ignored. So, for the above code to work, we need something like this:
        manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
I don't understand why new Manifest() does not populate this attribute automatically. Even worse, why is there no warning or exception reported when such a manifest is used.

While evaluating a GlassFish bug, I discovered a discrepancy in behavior of Class.getAnnotations() between IBM JRE and Sun JRE. the complex GlassFish issue boiled down to a simple test case as discussed below. The question is what should be the behavior of Class.getAnnotations() if one or more annotation class is not available at runtime. Consider the following test case:

// Main.java

import java.lang.annotation.*;

@interface Bar {}

class Foo {}

class Main {
 public static void main(String[] args) throws Exception{
  Annotation[] as = Foo.class.getAnnotations();
  System.out.println("Found " + as.length + " no. of annotations");

When you compile this, you shall obviously get Main.class, Foo.class and Bar.class. Remove Bar.class and run:

java Main

On IBM JRE (I am using 1.6.0 SR5 on AIX platform), it results in

Exception in thread "main" java.lang.TypeNotPresentException: Type Bar not present
        at com.ibm.oti.reflect.AnnotationHelper.getAnnotation(AnnotationHelper.java:38)
        at com.ibm.oti.reflect.AnnotationHelper.getDeclaredAnnotations(AnnotationHelper.java:50)
        at java.lang.Class.getDeclaredAnnotations(Class.java:1628)
        at java.lang.Class.getAnnotations(Class.java:1589)
        at Main.main(Main.java:13)
Caused by: java.lang.ClassNotFoundException: Bar
        at java.lang.Class.forName(Class.java:169)
        at com.ibm.oti.reflect.AnnotationHelper.getAnnotation(AnnotationHelper.java:33)
        ... 4 more

where as while using Sun JRE (1.6.0_07), the program prints:

Found 0 no. of annotations


I believe it is a bug in IBM JRE. There used to be a similar bug in Sun JDK. See http://bugs.sun.com/view_bug.do?bug_id=6322301 for details. It says that Class.getAnnotations() is supposed to ignore when a annotation type can't be loaded. Sun JDK has been fixed. Now time for IBM JDK to be fixed.

autodpeloy-bundles directory has been moved to autodeploy/bundles. In my earlier blog titled Using filesystem operations to manage OSGi bundles in GlassFish, I had mentioned the directory name to be ${domain_dir}/autodeploy-bundles/. Based on feedback from co-developers and users, I have moved it to ${domain_dir}/autodeploy/bundles/. As you may be knowing, ${domain_dir}/autodeploy is already watched by GlassFish server for deployable artifacts. So, having a dedicated subdirectory for OSGi bundles under that directory makes a lot of sense. This change is effective from GlassFish v3 b67. It's just a change in directory name, everything else remains unchanged. So, you can use autodeploy/bundles just like you could use autodeploy-bundles.


By the way, in case you have not paid attention, we have also added a new directory under glassfish/modules called autostart where you can drop OSGi bundles to be automatically part of server runtime. This directory is also watched by Felix FileInstall. bundles from autostart directory are started after server is started. See this discussion for more details.



What are our options to administer OSGi runtime in GlassFish? We have already talked about

a) a command line tool, and

b) a web console.

We now have a third option. Recently I came across a REST based console being developed by Filippo Diotalevi. We already have all the necessary support in GlassFish - the REST console requires OSGi/HTTP Service and we have an implementation of the same in GlassFish. So,  I thought I would give it a try and I found it a smooth ride.

How to install the REST console:

Here are the simple steps to install them:

0. Start GlassFish (I usually run "java -jar glassfish/modules/glassfish.jar"). I suggest you use v3 build #62 or higher available at http://download.java.net/glassfish/v3/promoted

1. Download GlassFish OSGi/HTTP Service bundle and copy it to glassfish/domains/domain1/autodeploy-bundles/.

2. Download the REST Console bundle and copy it to the same directory (i.e., glassfish/domains/domain1/autodeploy-bundles/).

That's all. If you are watching the GlassFish logs, you can see GlassFish detecting the new OSGi bundles and starting them.

Using the REST console

I will show you a couple of commands here. To use the console, you need a HTTP client. You can refer to the usage page for more information. I am using cURL. It is installed by default in many OS.

To list all the bundles in the system, we can run:

curl http://localhost:8080/osgi/restconsole/bundles/.txt

To see the details of a particular bundle (let;'s say bundle with id 100), run:
curl http://localhost:8080/osgi/restconsole/bundles/100.txt


The above commands are requesting data in text format. You can get it in XML and have a style sheet to nicely present it in a suitable format.


If you refer to the usage page, you will find commands for installing new bundles, controlling life cycle of bundles and querying bundle headers, services, etc.




This is the true benefit of using OSGi. The bundles are very portable. REST console needs OSGi/HTTP service and GlassFish has one. As long as that requirement is met, it runs successfully. Good job Filippo! I look forward to a proper release of the REST console. Those who are interested in OSGi may like to subcribe to his blog the OSGi Look, where he not only aggregates interesting OSGi related articles but also makes available his own content.

Starting with build #56, GlassFish v3 now comes pre-installed with Apache Felix Service Component Runtime, which is an implementation of OSGi Declarative Service Specification. This bundle is located in modules/ directory and is started automatically when server starts.

Expect a detailed message from Sreeni and/or other monitoring folks of GlassFish, but I just came to know that BTrace has found its way into GlassFish v3. This project, which started as a one-man effort by Sundar, has been able to attract other open source developers' attention and is now a well established project. It is used by many of us to solve issues where debuggers can't be used efficiently. e.g., see Binod's use case. I am glad to see it being officially integrated in GlassFish v3. Many congratulations to Sundar and the rest of the BTrace team.

Filter Blog

By date: