1

I am trying to do something which may be against J2EE specification. I have different jars containing cxf end points respectively.

I created a web project with CXFServlet and deployed it on JBoss 7 server. When i deploy other jars, they are unable to register their CXF endpoints in the CXFServlet, as it is not accessible for them.

I want to somehow provision the CXFServlet as a service so that when the route gets loaded for other jars while deployment, automatically the CXF endpoints should be able to register to this CXFServlet.

I know about crossContext, RequestDispatcher concepts but they are driven by the individual projects when we trigger the servlet of those projects. But in my case, as soon as the project gets deployed, the CXF route gets loaded and the endpoint searches for any CXFServlet and if not found, it doesn't get registered.

Sunil Dabburi
  • 1,442
  • 12
  • 18

1 Answers1

0

I assume you meant separate WARs deployed standalone or within different EARs.

Please remember that CXF is built into JBoss so maybe you don't need such dynamic registering - if it's just about configuration.

Unfortunately you cannot do such dynamic registering easily with separate WARs. I did some research.

First of all, in order to make this work, the CXF library would have to be loaded from JBoss libs, not from your web-app's lib directory. It is because WARs have separate classloaders. When loading classes these classloaders consult their parent but never other WAR classloader. Even if both WARs had CXF jars embedded, resulting classes would be incompatible - CXFServlet class loaded by classloader A is something different than CXFServlet class loaded by classloader B, even though both classes are loaded from same JAR.

To use JBoss embedded CXF you need to add jboss-deployment-structure.xml to WEB-INF with the following content:

<jboss-deployment-structure>
 <deployment>
  <dependencies>
   <module name="org.apache.cxf" services="import">
    <imports>
     <include path="**" />
    </imports>
   </module>
  </dependencies>
 </deployment>
</jboss-deployment-structure>

To run CXFServlet, which requires spring framework, you also need to add spring jars to JBoss installation and define them as modules, like described here: How can I use the external jars on JBoss 7?. Also dependency in jboss-deployment-structure.xml needs to be added.

If you get this running (congratulations, I was not able to do it :/ ) then you can try playing with default Bus, returned by org.apache.cxf.BusFactory.getDefaultBus(). For instance your main WAR with CXFServlet might set this default bus and other modules might be able to retrieve this. But I'm 99% sure that instead of getting BusFactory from CXF you'll get some org.jboss.wsf.stack.cxf.client.configuration.JBossWSBusFactory. This one is "strengthened" by JBoss so you won't be able to retrieve shared Bus object but different one for each thread. To change this you should create in each WAR the following file: META-INF/services/org.apache.cxf.bus.factory with content: org.apache.cxf.BusFactory. This should be able to overwrite JBoss bus factory with default's CXF one.

OK, so now we should be able to retrieve common Bus. I have not tested that but with Bus you should be able to add new services. There is no obvious API for this, but maybe something like this would work: bus.getExtension(WSDLManager.class).addDefinition(implementor, definition);.

Uhh, as you see this is just a sketch of potential solution. There are too many things that can go wrong. The task is not easy and is definitely painful.

Alternatively you can try using OSGi, which is supported by JBoss 7. You install bundles, they publish some endpoints. Some introduction to OSGi on JBoss can be found here. And here is some hint how to start with CXF and OSGi on JBoss. But again, this is not very popular way of using JBoss so don't expect much support.


EDIT: It might be also interesting for you why automatic discovery of cxf.xml files does not work. CXFServlet is using currentClassloader.getResourceAsStream(..) to check whether cxf.xml exists. If cxf.xml is in different WAR then current classloader is not able to find it.

Community
  • 1
  • 1
Dawid Pytel
  • 2,750
  • 1
  • 23
  • 30