Here's another example that I'm not sure what the outcome would look like or how the architecture would handle it. Suppose bundle A modifies the CXF bus in the following manner through spring,
Then bundle B instantiates classes in bundle A that use the cxf bus. Will there be two different buses or will there be a single bus between bundle A and bundle B?
The next questions then are,
a) If there are two different buses between A and B, how can I set it up so that there is only one?
b) If there is only one bus between A and B, how can I set it up so that there are two different buses, one for A and one only for B?
So I tested some of this theory out a bit and this is what I discovered:
- Bundle A has a bean file that instantiates a cxf http-conduit with name="*.http-conduit" that uses ssl and imports META-INF/cxf and so on forth.
- Bundle A also exports a new Camel Endpoint called FOO_A that needs ssl to work.
- Bundle B has a bean file that creates a camel route using FOO_A from Bundle A.
Everything works fine and the FOO_A endpoint is able to connect using SSL.
This is as expected but I did this to make sure everything was working properly first.
- Same setup as in Test 1 except bundle B's bean also imports the cxf resources (i.e. classpath:META-INF/cxf/cxf.xml and so on forth) on top of creating a camel route with FOO_A.
The FOO_A endpoint throws an ssl hand_shake failure because the http-conduit is being setup as plain http, which means the endpoint used Bundle B's cxf-bus.
I thought that this meant the cxf architecture was setup so that the parent bundle B would override the cxf bus of dependency bundle A... but the next test case proved this to be false.
So this is where things get interesting
- Same setup as Test 1, except we now have a bundle C that is an EXACT copy of bundle A, except Bundle C's http-conduit has no tlsClientParameters.
- Bundle B also now has two camel routes. One with FOO_A Endpoints and one with FOO_C Endpoints.
The result is either both FOO_A and FOO_C connect properly OR they both throw a hand_shake failure. Which of these two scenarios happens is random, which would imply a race condition of which http-conduit (or I guess cxf-bus) is loaded in which order.
Based on all three test cases, does this mean that there can only be a SINGLE cxf context between depending bundles? I find that hard to believe and very troubling!
I'll keep testing and checking to make sure I didn't make a mistake because if this is true it is a major problem for us because we want to create many bundles that are all used by one bundle and each of these bundles will need a different cxf-bus/http-conduit.
Edited by: marc.blomquist on Feb 10, 2012 12:43 AM
If you want to share the http-conduit across bundles, you need to make sure that these two bundles are using same cxf bus.
You can define a service in your bundle A to export the bus for the other bundle to use.
To answer the question of Bus.
There are some tricks of the CXF bus which is used in container like Services.
As the JAXWS API doesn't has the concept of Bus, CXF need to get the bus from thread local variable.
If you are using spring-dm to initialize the bundle context(A, B, C), it is hard to tell which bus is used. So you need to manage the bus yourself, and using the bus setting API of CXF to setup the bus.
Thanks for the answers so far! I have a few more questions based on what you said.
So if I understood it correctly, I can have only one CXF bus between bundle B, A and C unless I turn the CXF buses into OSGI services?
If this is true, what would happen if 1 year from now I need to include two other thirdparty bundles D and E that also have a cxf bus? Would this mean that I have to modify their cxf code/bean to get it to work with our bundle?
This sounds like a lot of work just to get CXF to work with other bundles that have CXF : ( but if this is the only solution then I must use it. I'll research exactly how to go about doing this and post how things turn out.
Edited by: marc.blomquist on Feb 10, 2012 5:05 PM
If you want to use the same bus across the bundle, you need to use the setBus API which is provided from the CXF API instead of JAXWS-API to set the bus explicitly.
You can use some factorybean class to wrap the bus setting work if you don't want other bundle to be effected.