JBoss.orgCommunity Documentation

Chapter 5. Developer Documentation

5.1. Service Provider Interface
5.2. Management View
5.3. Writing Test Cases
5.3.1. Simple Test Case
5.3.2. Simple Husky Test Case

The JBoss OSGi Service Provider Interface (SPI) is the integration point for:

The latest version of the JBoss OSGi SPI.

Bootstrapping JBoss OSGi

The OSGiBootstrap provides an OSGiFramework through a OSGiBootstrapProvider.

A OSGiBootstrapProvider is discovered in two stages

  1. Read the bootstrap provider class name from a system property
  2. Read the bootstrap provider class name from a resource file

In both cases the key is the fully qalified name of the org.jboss.osgi.spi.framework.OSGiBootstrapProvider interface.

The following code shows how to get the default OSGiFramework from the OSGiBootstrapProvider.



    OSGiBootstrapProvider bootProvider = OSGiBootstrap.getBootstrapProvider();
    OSGiFramework framework = bootProvider.getFramework();
    Bundle bundle = framework.getSystemBundle();
    

The OSGiBootstrapProvider can also be configured explicitly. The OSGiFramework is a named object from the configuration.



    OSGiBootstrapProvider bootProvider = OSGiBootstrap.getBootstrapProvider();
    bootProvider.configure(configURL);
    
    OSGiFramework framework = bootProvider.getFramework("AnotherOSGiFramework");
    Bundle bundle = framework.getSystemBundle();
    

The JBoss OSGi SPI comes with two bootstrap providers:

OSGiBootstrapProvider implementations that read their configurtation from some other source are possible, but currently not part of the JBoss OSGi SPI.

Using the SPI from within JBossAS deployed components

If you need access to the OSGi Framework from within an JBossAS deployed component (e.g. servlet, ejb, mbean) you would not bootstrap JBoss OSGi through the SPI. Instead, you would inject the already bootstrapped OSGi Framework instance into your component.

JBoss OSGi registers the Framework and every deployed Bundle with the JMX MBeanServer.

The ManagedFramework

The ManagedFramework gives you access to the MBean views of the deployed Bundles. It is registerd under the name:

  • jboss.osgi:service=ManagedFramework
The ManagedBundle

The ManagedBundle gives you access to the MBean views of a deployed Bundle. It is registerd under the name:

  • jboss.osgi:bundle=[SymbolicName],id=[BundleId]
Accessing the Management Objects

If you work with the JBoss OSGi Testsuite you get access to the Managed Objects through the JBoss OSGi SPI provided JUnit support package org.jboss.osgi.spi.testing.

If you install JBoss OSGi in an already existing JBossAS instance you also get access to the Managed Objects through the JBoss provided JMX Console (http://localhost:8080/jmx-console).

Note

The JMX Console is not part of the JBoss OSGi Runtime.

JBoss OSGi comes with JUnit test support as part of the SPI provided org.jboss.osgi.spi.testing package. There are two distinct test scenarios that we support:

  • Embedded OSGi Framework
  • Remote OSGi Framework

The remote scenario can actually be separated again in:

  • Standalone JBoss OSGi Runtime
  • JBoss OSGi Runtime running in JBossAS

A test case that takes advantage of the SPI provided OSGi runtime abstration would transparently handle these scenarios.

The test case bootstraps the OSGi Runtime, installes/starts the bundle, asserts the bundle state and finally shuts down the runtime again. Please note, this is a plain JUnit4 test case that transparently handles embedded/remote nature of the runtime.



      public class SimpleTestCase
      {
         @Test
         public void testSimpleBundle() throws Exception
         {
            // Get the default runtime
            OSGiRuntime runtime = new OSGiTestHelper().getDefaultRuntime();
            
            // Install the bundle
            OSGiBundle bundle = runtime.installBundle("example-simple.jar");
            assertEquals("Bundle installed", Bundle.INSTALLED, bundle.getState());
  
            // Start the bundle
            bundle.start();
            assertEquals("Bundle active", Bundle.ACTIVE, bundle.getState());
  
            // Uninstall the bundle
            bundle.uninstall();
           
            // Shutdown the runtime 
            runtime.shutdown();
         }
      }
      

To run the test in embedded mode (which is the default) you would execute your test runner like this



      [tdiesler@tddell example]$ mvn -Dtest=SimpleTestCase test
      ...
      Running org.jboss.test.osgi.example.simple.SimpleTestCase
      Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.361 sec
      

To run the test against the remote JBoss OSGi Runtime you would execute your test runner like this



      [tdiesler@tddell example]$ mvn -Dtarget.container=runtime -Dtest=SimpleTestCase test
      ...
      Running org.jboss.test.osgi.example.simple.SimpleTestCase
      Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.303 sec
     

In the runtime console you should see



      12:44:30,960 INFO  [jboss-osgi-common] Installed: example-simple [8]
      12:44:31,081 INFO  [example-simple] Start: example-simple [8]
      12:44:31,089 INFO  [example-simple] Stop: example-simple [8]
      12:44:31,095 INFO  [jboss-osgi-common] Uninstalled: example-simple [8]
     

Due to classloading restrictions it is not possible to interact with the services that get registered in the OSGi Framework directly. Instead, there must be some means for the bundle under test to communicate with the test case that lives outside the Framework. The approach of OSGi testing based on remote log messages is covered in Non intrusive OSGi Bundle Testing.

The next section explains how to write a plain JUnit test that is then executed within the OSGi Runtime.

The test case does everthing identical to SimpleTestCase (setUp and tearDown not shown again), but only executes the code in the test method when Husky injected the BundleContext.



      public class SimpleHuskyTestCase
      {
         @ProvideContext
         public BundleContext context;
         ...
         @Test
         public void testSimpleBundle() throws Exception
         {
            // Tell Husky to run this test method within the OSGi Runtime
            if (context == null)
               BridgeFactory.getBridge().run();
            
            // Stop here if the context is not injected
            assumeNotNull(context);
            
            // Get the SimpleService reference
            ServiceReference sref = context.getServiceReference(SimpleService.class.getName());
            assertNotNull("SimpleService Not Null", sref);
            
            // Access the SimpleService 
            SimpleService service = (SimpleService)context.getService(sref);
            assertEquals("hello", service.echo("hello"));
         }
      }
      

Running this test is also no different from SimpleTestCase.

In the runtime console you should see



      13:29:15,924 INFO  [jboss-osgi-common] Installed: example-simple-husky [16]
      13:29:15,972 INFO  [example-simple-husky] Start: example-simple-husky [16]
      13:29:15,981 INFO  [jboss-osgi-husky] Test-Package [org.jboss.test.osgi.example.simple] in bundle: example-simple-husky [16]
      13:29:16,160 INFO  [example-simple-husky] echo: hello
      13:29:16,191 INFO  [example-simple-husky] Stop: example-simple-husky [16]
      13:29:16,196 INFO  [jboss-osgi-common] Uninstalled: example-simple-husky [16]
     

To learn more about the magic of the BridgeFactory have a look at Husky Test Framework which comes next.