OSGI CXF singleton classloading issues - singleton

This question is now up for Bounty! First answer that solves this problem wins.
So I've recently discovered that bundles in OSGI are not 100% isolated from each other, especially when your bundles share a common bundle that has a singleton in it, which can result in two unrelated bundles overwritting the singleton. This issue has manifested itself with the CXF libraries. Let me give a detailed example of what is happening:
We have bundle A, B and the shared bundle CXF all in a FuseESB ServiceMix (An osgi platform). CXF's Bus class is a singleton and because of how OSGI has a single classloader per bundle it will share this singleton with every other bundle that uses CXF. So I seem to be unable to create different buses for bundle A and bundle B, which is important that I do because bundle A should be using SSL and bundle B should not be using SSL. This is even more frustrating given that bundle A and bundle B have nothing to do with each other at all other than that they must be deployed together on the same ServiceMix.
Now I've been at this problem for a while now (1-2 months) and I've read up a lot of different solutions. The problem however is that a lot of the solutions require me to have complete control over the source code and in this case I do not. Bundle A that I'm creating is using some proprietary third-party non-osgi library, called Xenara, which uses CXF. For business reasons beyond my control I MUST use this third-party library. Fortunately I do have access to the CXF spring bean file that this library uses.
My guess for solving this problem is that I need to some how make it so that bundle A can use its own personal instance of CXF or at least make it instantiate its CXF Bus that isn't shared with other bundles. Here are the methods I've tried or considered:
I embedded CXF into bundle A but unfortunately the classloader kept fetching CXF from outside of bundle A instead of looking on the classpath. Never figured out how to force it to search for CXF in bundle A first before searching outside of bundle A.
Suggestions were made to make bundle A into a service. I think there were some misunderstandings and people thought that the singleton was in A and not in CXF. Regardless I tried it and it didn't solve the problem. The CXF bus was still shared between bundle A and B.
Override the classloading so that bundle A uses a different classloader for loading the CXF classes. I don't fully understand the logic for this but I'm sure it will be very tricky given that a spring bean is being used to create the CXF bus and http-conduit. See (4) below to get a better idea.
In CXF there is a way to set the CXF bus and http-conduit for a given thread context. I really want to use this solution, but I can't figure out how to translate the CXF bean file into equivalent java code. The CXF spring bean file is provided below. Note I don't have access to the source code using this http-conduit, which is why I haven't used examples show in this link here at "Using Java Code" because I don't have access to the SOAPService, the wsdl, etc...
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchSystemEnvironment" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<cxf:bus>
<cxf:outInterceptors>
<bean class="com.xenara.messaging.security.IdentityAssertingOutInterceptor"
scope="singleton" />
</cxf:outInterceptors>
<cxf:features>
<wsa:addressing xmlns:wsa="http://cxf.apache.org/ws/addressing"/>
</cxf:features>
</cxf:bus>
<http-conf:conduit name="*.http-conduit">
<http-conf:client AllowChunking="false" Connection="Keep-Alive" />
<http-conf:tlsClientParameters disableCNCheck="true" secureSocketProtocol="TLS">
<sec:keyManagers keyPassword="${javax.net.ssl.keyStorePassword}">
<sec:keyStore type="JKS" password="${javax.net.ssl.keyStorePassword}"
file="${javax.net.ssl.keyStore}" />
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="${javax.net.ssl.trustStorePassword}" file="${javax.net.ssl.trustStore}" />
</sec:trustManagers>
<sec:cipherSuitesFilter>
<sec:include>SSL_RSA_WITH_3DES_EDE_CBC_SHA</sec:include>
...
</sec:cipherSuitesFilter>
</http-conf:tlsClientParameters>
</http-conf:conduit>

This sounds like the basic premisse of OSGi to me: isolation is provided, but you can do a lot of what you can in regular OSGi; such as, modify static members of a class, and since you all share that class (A presumably exports it, B and C import it), others will notice.
In most situations, I would advise you to not use static class state, since it is bound to mess something up for other bundles.
In your situation, it seems to me that bundle A is a library that has no real use being shared in the framework. I would package the library inside both of the using bundles, if you need real isolation, and not worry about the overhead too much.
For the record: this situation has nothing to do with Servicemix, it's basic Java: if we're talking about the same class, and someone changes a static property, others will notice. If this situation confuses you, you could read up a bit about the class loading and sharing mechanisms in OSGi.

The problem you are facing is fairly essential and basic. You have a static state in a supporting library CXF, while you still want shared instances of the libraries using CXF. You cannot modify the shared libraries (due to the sheer size), nor can you modify CXF (closed-source?). Let's call these shared libraries Foo and Bar.
Suppose you have the following classes:
CXF#1
Foo#1, using CXF#1
Bar#1, using CXF#1
WebApp#1, using Foo#1 and Bar#1
If I understand correctly, you now want another application to use the same instances of Foo and Bar, without using the same underlying library CXF#1. This amounts to the following situation.
CXF#2
CXF#1
Foo#1, using CXF#1 when called by App#1, using CXF#2 when called by App#2
Bar#1, using CXF#1 when called by App#1, using CXF#2 when called by App#2
WebApp#1, using Foo#1 and Bar#1
WebApp#2, using Foo#1 and Bar#1
This is just not possible; not in OSGi and not in any Java framework. An existing class cannot dynamically bind to another class, making the choice based on the calling Bundle. The only way to do this without modifying the libraries, is to duplicate the supporting libraries:
CXF#2
CXF#1
Foo#1, using CXF#1
Bar#1, using CXF#1
Foo#2, using CXF#2
Bar#2, using CXF#2
WebApp#1, using Foo#1 and Bar#1
WebApp#2, using Foo#2 and Bar#2
Indeed, this is a lot of effort and will explode the number of packages on disk and in memory. If the CXF package can only be used by a single application, the most logical solution is to duplicate the package and embed it everywhere you use it. Yes, this includes any and all libraries the package depends on.
A hacky/risky way to resolve this is as follows. You should be able to decompile the CXF class. This will allow you to modify the class as follows:
class CXF {
[...]
public static CXF getInstance() {
// based on the current Stack frame, determine which instance to return. Remember, the instance should be based on the WebApp bundle (while you still have shared libraries in between!)
}
}
This is not foolproof. Suppose your WebApp starts a callback thread originating from library A. This thread calls CXF.getInstance() -> The getInstance() method has no way of determining which WebApp started the callback thread.
The correct solution is to modify all libraries not to use the Singleton pattern. You can probably hack your way around the problem by implementing a special classloader, but this opens a whole other can of worms.
-- EDIT --
After reading up on CXF, it seems very strange that CXF exposes a Singleton class. The thing is made for OSGi! You are probably better off asking the question on the CXF mailing list; they will know all of the special sugar and reasons for making a singleton instance, and probably already thought about this usecase.

Related

How can I configure JAX-RS endpoints programmaticaly?

I'm trying to get rid of XML in my project.
I already tried to add this:
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setAddress("http://localhost:9000/");
sf.create();
to my Activator class, but my bundle wont start with this.
So, how usually people configuring endpoints?
(Sorry, no code, just some high level insights from my experience/projects)
I use jersey and its integration into the OSGi environment. I.e. org.glassfish.jersey.servlet.ServletContainer to which I register all jax-rs resources. This way, I can use whatever HTTP server implementation is available (for example, jetty) and configure it via the OSGi system environment properties.
For simplicity, I re-register annotated OSGi (declarative) services as singleton resources/endpoints into that ServletContainer.
Maybe, CXF has also a similar approach.

How to use a CXF ResourceComparator with Openliberty

is it possible to use a CXF ResourceComparator in OpenLiberty or WASLiberty?
http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Customselectionbetweenmultipleresourcesoroperations
Must the cxf dependencies be supplied in the WEB-INF/lib or is enough to modify the apiVisibility of the app? And how can be declared to CXF? with a cxf.xml?
TIA
PacoG
There are multiple ways to use CXF in OpenLiberty/WebSphere Liberty:
* You can use the built-in jaxrs-2.0 feature, or
* You can package the CXF modules you need with your app (or in a shared library associated with your app)
If you use the first approach (jaxrs-2.0 feature), then you will only have the JAX-RS 2.0 APIs available - which does not include CXF ResourceComparators. There are a few IBM-specific APIs that go above and beyond the spec (for example, integration with CDI, security, attachment processing, etc.) - you can find more information on those APIs at:
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/twlp_dep_jaxrs.html
If you use the second approach, then you have the full feature set of the CXF modules in your application, but they will not be fully integrated with other Liberty features like the jaxrs-2.0 feature is. For usage instructions, I would suggest the Apache CXF documentation - like the page you referenced in the initial question.
Hope this helps, Andy

MobileFirst 8 javascript adapters and messages

i have some questions about MobileFirst Adapters:
We are implementing javascript adapters on a MobileFirst 8 server.
Where is the best place to write javascript utils functions?
I also have some utils on java classes (called from javascript adapters) and i need to use the ConfigurationAPI class to get properties. The problem is that the configurationAPI variable (instantiated with the #Context annotation) is always null. Why? How can i get properties values from Java code?
I have a lot of properties (for example low-level backend endpoints) that should be shared between all the adapters. At the moment i used the <property name="" displayName="" defaultValue="" /> syntax, should i copy and paste them in all adapters?! Or where should i put them?
Thank you
We are implementing javascript adapters on a MobileFirst 8 server.
Where is the best place to write javascript utils functions?
JavaScript adapters allow for a single .js file, so your best place for any adapters JavaScript code is the same .js file...
I have a lot of properties (for example low-level backend endpoints)
that should be shared between all the adapters. At the moment i used
the <property name="" displayName="" defaultValue="" /> syntax, should
i copy and paste them in all adapters?! Or where should i put them?
See my answer to the following question. Once you add custom properties you should be able to handle them in the same way I mention handling other values from the adapter.xml file: Unable to build adapters using profiles and properties in Maven
I also have some utils on java classes (called from javascript
adapters) and i need to use the ConfigurationAPI class to get
properties. The problem is that the configurationAPI variable
(instantiated with the #Context annotation) is always null. Why? How
can i get properties values from Java code?
I've sent a question internally and will let you know once I get an answer.

how to configure the external properfiles into the OSGI

we are using the Jboss fuse 6.2 along with technical stack blueprint,camel ,activeMQ and Mybatis.
We need to know about how to configure the property files in OSGI ,
as per my knowledge we could configure .cfg files, but is there any simplest way to use like spring configuring the configuring.
In Our code we are reading from property files . using namespace ext:proeprtyplaceHolder giving that bean id and values we are giving .
Help to provide is there any simplest way to read the property files
There is several ways to add configuration, because OSGi services can access configuration via ConfigurationAdmin service. The blueprint also can access property values over it.
JBoss fuse using karaf, so you can use the following methods.
(There is some quotes from http://www.liquid-reality.de/display/liquid/2011/09/23/Karaf+Tutorial+Part+2+-+Using+the+Configuration+Admin+Service)
Configuration with Blueprint
The integration with our bean class is mostly a simple bean definition where we define the title property and assign the placeholder which will be resolved using the config admin service. The only special thing is the init-method. This is used to give us the chance to react after all changes were made like in the pure OSGi example.
For blueprint we do not need any maven dependencies as our Java Code is a pure Java bean. The blueprint context is simply activated by putting it in the OSGI-INF/blueprint directory and by having the blueprint extender loaded. As blueprint is always loaded in Karaf we do not need anything else.
<cm:property-placeholder persistent-id="ConfigApp" update-strategy="reload" >
<cm:default-properties>
<cm:property name="title" value="Default Title"/>
</cm:default-properties>
</cm:property-placeholder>
<bean id="myApp" init-method="refresh">
<property name="title" value="${title}"></property>
</bean>
After you can put a cfg file (which is a standard java property file) to
karaf's etc or deploy directory with the name of of the given persistent-id which is MyApp in our example. (For example: /etc/ConfigApp.cfg)
title=Configured title

Servlet 3.0 and JAX-RS

I've found conflicting answers to this question and I've failed to successfully run an example.
Can JAX-RS be implemented using Servlet 3.0 (in particular, Tomcat 7) with annotations, only, without having to implement another Servlet Container?
If no, please explain why the following quote from this book is either, incorrect or I'm interpreting it, wrong.
Because this example deploys within a Java EE application server or
standalone Servlet 3.x container, all we need is an empty web.xml
file. The server will detect that an Application class is within your
WAR and automatically deploy it. (RESTful Java with JAX-RS 2.0, Bill Burke)
To clarify what I don't need help with... I've, successfully, implemented JAX-RS in Tomcat 7 with Jersey using a web.xml, so, I don't need any explanation of how to do so. Also, I'm fully aware that other Java EE/Servlet Containers (TomEE, Glassfish, Jersey, Websphere, etc...) are all JAX-RS aware out of the box. I just need to know if I'm chasing my tail trying to get Tomcat 7 (Servlet 3.0) to work with JAX-RS without adding a Servlet Container and without web.xml entries.
In a Servlet environment, Jersey runs as a servlet or servlet filter. No way around that. So how does it work without declaring it in the web.xml? Two main components to this functionality
Programmatic registration of Servlet components (i.e. servlets and fitlers). You can do a Google search, and you should find some hits of examples.
Servlet pluggability introduced in Servlet 3.x. How it works is you implement a ServletContainerInitializer, list that implementation in a file named javax.servlet.ServletContainerInitializer, and put that file in the META-INF/services directory of the jar. The servlet container should scan jars looking for this file. When it finds on, it sees the implementation, finds the implementation, instantiates it, then calls it onStartup method.
Jersey has such an implementation of the SevletContainerInitializer in the JerseyServletContainerInitializer. This class is located in the jersey-container-servlet jar. So you need this jar for this to work. If you look at this method, this is where you will see the programmatic registration of the ServletContainer (the same one that yo would declare in the web.xml
But that's not all. We still need some way of configuring our application, at the least declare the servlet mapping. That's where the Application class and the #ApplicationPath annotation come in. We would extend the Application class and and annotate the #ApplicationPath("/path") where "path" is the same as the servlet mapping in the web.xml
#ApplicationPath("/api")
public class MyApplication extends Application {}
This is standard JAX-RS. With Jersey normally instead of an Application class, we use a ResourceConfig class (which is a subclass of Application)
#ApplicationPath("/api")
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("package.to.scan");
}
}
You can see more about Jersey deployment options in a Servlet 3.x environment, here.
It should also be noted, that a Java EE server has the JAX-RS implementation, so we only need to add the javaee-api jar to our application as provided dependency. But in a servlet container, we need to provide our own implementation, Jersey being such an implementation.
If you are using Maven, the main dependency you'll need is this one
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
This will pull a bunch of other jars in. You you aren't using Maven, then you can download all the jars here (the JAX-RS 2.0 RI bundle), and put all those into your application.
See Also:
How to use Jersey as JAX-RS implementation without web.xml?