Integrating Togglz in OSGi applications

240 views
Skip to first unread message

SV

unread,
Apr 27, 2015, 12:29:46 PM4/27/15
to togglz...@googlegroups.com
Hello,
            I am trying to integrate Togglz framework within an OSGi bundle and I encountered the exception as detailed below. I am using WebSphere 8.5 as the deployment container. Any help in resolving this is highly appreciated.
             
              1.  Imported the Togglz library as a contained bundle in the EBA manifest.
              2.  In another Bundle (that is also a contained bundle in the EBA )
                   2.1 Implemented an Enum type for Features.
public enum MyFeatures implements Feature {
@EnabledByDefault
    @Label("First Feature")
    FEATURE_ONE,
    
    @Label("Second Feature")
    FEATURE_TWO;

    public boolean isActive() {
        return FeatureContext.getFeatureManager().isActive(this);
    }
}
                   2.2 Implemented FeatureManagerProvider interface as below:
public class SingletonFeatureManagerProvider implements FeatureManagerProvider {
private static FeatureManager featureManager;
@Override
public int priority() {
return 30;
}

@Override
public FeatureManager getFeatureManager() {
if (featureManager == null) {
            featureManager = new FeatureManagerBuilder()
                    .featureClass(MyFeatures.class)
                    .stateRepository(new InMemoryStateRepository())
                    .userProvider(new NoOpUserProvider())
                    .build();
        }

        return featureManager;
}

}
  
            3. When my OSGi client application invokes method MyFeatures.FEATURE_ONE.isActive(), it fails with an exception as below.
       BlueprintCont E org.apache.aries.blueprint.container.BlueprintContainerImpl doRun Unable to start blueprint container for bundle com.ibm.ws.eba.helloWorld.client
                                 org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to initialize bean HelloWorldClientBean
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:714)
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:824)
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:787)
at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:82)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
at java.util.concurrent.FutureTask.run(FutureTask.java:149)
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:91)
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:245)
at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:183)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:672)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:369)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:261)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:450)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
at java.util.concurrent.FutureTask.run(FutureTask.java:149)
at org.apache.aries.blueprint.container.ExecutorServiceWrapper.run(ExecutorServiceWrapper.java:106)
at org.apache.aries.blueprint.utils.threading.impl.DiscardableRunnable.run(DiscardableRunnable.java:48)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:450)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
at java.util.concurrent.FutureTask.run(FutureTask.java:149)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:109)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:217)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:784)
Caused by: java.lang.ExceptionInInitializerError
at java.lang.J9VMInternals.initialize(J9VMInternals.java:259)
at com.svaid.togglz.config.MyFeatures.isActive(MyFeatures.java:17)
at com.ibm.ws.eba.helloWorld.service.HelloWorldService.hello(HelloWorldService.java:10)
at Proxyad3dca20_1f2d_486b_b5e6_f1458220b90e.hello(Unknown Source)
at Proxyad3dca20_1f2d_486b_b5e6_f1458220b90e.hello(Unknown Source)
at Proxyd652bb9d_ce6b_4dcc_abde_0942e7a41992.hello(Unknown Source)
at com.ibm.ws.eba.helloWorld.client.HelloWorldClient.refHello(HelloWorldClient.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.apache.aries.blueprint.utils.ReflectionUtils.invoke(ReflectionUtils.java:297)
at org.apache.aries.blueprint.container.BeanRecipe.invoke(BeanRecipe.java:958)
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:712)
... 24 more
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:356)
at org.togglz.core.logging.LogFactory.getLogProvider(LogFactory.java:37)
at org.togglz.core.logging.LogFactory.getLog(LogFactory.java:27)
at org.togglz.core.logging.LogFactory.getLog(LogFactory.java:23)
at org.togglz.core.context.FeatureContext.<clinit>(FeatureContext.java:26)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:237)
 

Christian Kaltepoth

unread,
Apr 28, 2015, 1:42:38 AM4/28/15
to togglz...@googlegroups.com
Hey,

it looks like Togglz is unable to find the LogProvider implementations shipping with Togglz by default. Togglz is using the JDK's ServiceLoader mechanism for discovering all kinds of implementations. Not sure why this doesn't work for you. Any idea?

Christian

Christian Kaltepoth

unread,
Apr 28, 2015, 1:43:58 AM4/28/15
to togglz...@googlegroups.com
Looks like getting ServiceLoader to work correctly in OSGI is a known problem!?!?

SV

unread,
Apr 29, 2015, 5:01:10 PM4/29/15
to togglz...@googlegroups.com
Is there a work around to get Togglz frameworking in OSGi? The solution mentioned as described in the article mentioned in the earlier blog post does not help for OSGi implementations for version earlier than OSGi enterprise 5. Websphere 8.5 implements OSGi version 4.2.

Thanks,
SV

Christian Kaltepoth

unread,
Apr 30, 2015, 11:13:20 AM4/30/15
to togglz...@googlegroups.com
I'm not very familiar with OSGi. But Togglz heavily relies on the standard Java ServiceLoader mechanism. If this doesn't work in OSGi environments, this would be a real problem.

You should have a look at the OSGi related issues resolved in the past:


AFAIK there are some comments regarding ServiceLoader.

Christian

Ian Page

unread,
Jan 21, 2016, 9:48:26 AM1/21/16
to togglz-users
To get it working in OSGi (Apache Karaf) I added the following to the Togglz MANIFEST.MF:

Require-Capability: osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)",osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)",osgi.serviceloader;filter:="(osgi.serviceloader=org.togglz.core.spi.LogProvider)";cardinality:=multiple
Provide-Capability: osgi.serviceloader;osgi.serviceloader=org.togglz.core.spi.ActivationStrategy,osgi.serviceloader;osgi.serviceloader=org.togglz.core.spi.FeatureManagerProvider,osgi.serviceloader;osgi.serviceloader=org.togglz.core.spi.LogProvider


I also added the following to the MANIFEST.MF in my bundle that uses Togglz:

Require-Capability: osgi.extender;filter:="(osgi.extender=osgi.serviceloader.processor)",osgi.serviceloader;filter:="(osgi.serviceloader=org.togglz.core.spi.LogProvider)";cardinality:=multiple


Depending on the use of Togglz, it may be ncessary to add the following to the above line:

osgi.serviceloader;filter:="(osgi.serviceloader=org.togglz.core.spi.FeatureManagerProvider)";cardinality:=multiple


I used dynamic weaving so I added the following bundles to my container:

org.apache.aries.spifly.core-internal-1.0.8.jar
org.apache.aries.spifly.dynamic.bundle-1.0.8.jar
asm-all-5.0.4.jar


As a side note, the Togglz MANIFEST.MF in togglz-core-2.2.0.Final.jar states that the versions of the packages it exports are all 2.1.0 - it looks like a mis-match between the artifact version and the osgi.bundles.version property in the POM.

Christian Kaltepoth

unread,
Jan 21, 2016, 12:27:36 PM1/21/16
to togglz...@googlegroups.com
Thanks for sharing these details. I hope these will be helpful for others.

Is there any way to get this into the default Togglz manifest in an automated way? Togglz uses bundlor for the OSGi related packaging.

Thanks for the hint regarding the incorrect version number. I just fixed that and added a note to the Release docs.

Christian

Ian

unread,
Jan 22, 2016, 4:12:53 AM1/22/16
to togglz-users
No problem.

I use the maven-bundle-plugin which is based on BND.  This allows you to configure the Provide-capability and Require-Capability parameters in the POM, so that they get added to the manifest at build time.  I'm not familiar with Bundlor but it may have something similar.

Christian Kaltepoth

unread,
Jan 23, 2016, 10:12:31 AM1/23/16
to togglz...@googlegroups.com
Hey,

thanks for the info. I was wondering whether these is some way to auto-generate the required manifest entries from the META-INF/services/ files. I'm asking because many classes in Togglz use the JDK ServiceLoader API and I would like to make sure that the manifest gets generated correctly even if new SPIs gets added.

Any idea?

Christian

Ian

unread,
Jan 25, 2016, 5:33:07 AM1/25/16
to togglz-users
Unfortunately I'm not aware of any tools that allow you to do that automatically.  It might be possible to write something that reads the file names from the META-INF/service directory and creates the appropriate OSGi references.  However as there are currently only three SPIs it's probably not worth the effort.

Christian Kaltepoth

unread,
Jan 26, 2016, 11:33:02 AM1/26/16
to togglz...@googlegroups.com
Hmmm. Too bad.

I was hoping that there is some tooling support for keeping this metadata up to date. Togglz relies on many different SPIs and I guess the number will even grow in the future.

BTW: Is this metadata specific to Karaf or is this a standard OSGi metadata attribute? Sorry for the dump question. I'm really not very familiar with OSGi. :)

Christian

Ian

unread,
Jan 27, 2016, 5:11:44 AM1/27/16
to togglz-users
Not a dumb question at all - I didn't know anything about OSGi until 18 months ago when I had to start using it!

This is part of the OSGi specification, however the only implementation of the spec that I'm aware of is that provided by the SPI Fly module (http://aries.apache.org/modules/spi-fly.html) which is part of the Apache Aries  project.  That module works in Apache Karaf, and I would imagine that it would work in other containers too (but I haven't tested it anywhere else).

Christian Kaltepoth

unread,
Jan 28, 2016, 1:50:54 AM1/28/16
to togglz...@googlegroups.com
Hey,

thanks for the info. I just checked the Togglz code to see which SPIs actually exists and are loaded via the ServiceLoader mechanism. There a 7 SPIs:

org.togglz.console.RequestHandler
org.togglz.core.spi.ActivationStrategy
org.togglz.core.spi.BeanFinder
org.togglz.core.spi.FeatureManagerProvider
org.togglz.core.spi.LogProvider
org.togglz.servlet.spi.CSRFTokenProvider
org.togglz.servlet.spi.RequestListener

Just to confirm I understand everything correctly. You wrote that you added some of the entries to Togglz' MANIFEST file. Which one? Only the MANIFEST of togglz-core? Do you just use togglz-core?

If I understand all of this correctly, all of the ~22 Togglz modules would need to declare which service are provided and consumed correct? Many of the modules provided for example an implementation of FeatureManagerProvider. All these modules would need to declare that they provide this service?

Thanks for your help with this. 

Christian 




Ian

unread,
Jan 29, 2016, 10:11:11 AM1/29/16
to togglz-users
Yes, we just use togglz-core.  I didn't think about the other parts of the project, which yes, would make things more complicated.

You're right with your understanding - anything that provides an implementation of one of the service interfaces will need to declare it as a provided capability, and anything that consumes a service will need to declare it as a required capability.

...

Christian Kaltepoth

unread,
Jan 29, 2016, 11:46:32 AM1/29/16
to togglz...@googlegroups.com
Thanks a lot for your help.

I just committed a change which adds the config from your original mail to the togglz-core manifest. I think this is a good first step.


We can extend this to other modules later.

Thanks

Christian

Ian

unread,
Feb 2, 2016, 12:09:42 PM2/2/16
to togglz-users
Cool - I'll see if I can test it at some point (although I'm tied up on something else right now).

...
Reply all
Reply to author
Forward
0 new messages