I forgot to mention one other huge advantage to all of this...
One of the issues I keep having when deeling with customers and new users and
such, expecially of some of the advanced things, is the question of "what
META-INF/cxf/ files do I need to import for my application?" We've done a
pretty poor job of documenting exactly what you need and when. For
example, I know when Dennis was writing his dev works articles, he sent me a
couple test cases that were not working, but adding additional imports in (for
things like ws-a and such) just made them work.
Now they are all gone. :-) Just import cxf.xml and, if in a servlet
environment, cxf-servlet.xml (for now, I want to get rid of that next).
Done. Everything just works. :-)
A techical/code solution to a documentation problem. That's kind of
backwords. :-)
Dan
On Friday 04 March 2011 3:47:55 PM Daniel Kulp wrote:
> I just committed the gigantic refactoring of the Spring bus stuff to base
> it on the ExtensionManagerBus. I'll describe it in a minute, but first
> the performanc result on my test case:
>
> Running test - 2.4.0-SNAPSHOT
> Setup: 29105 51/sec
> Invoke: 38174 39/sec
> Setup config: 39026 38/sec
>
> Compared to the 2.3.3:
> > Running test - 2.3.3
> > Setup: 49732 30/sec
> > Invoke: 62276 24/sec
> > Setup config: 56164 26/sec
>
> As you can see, it's quite a bit faster across the board now. That's
> great. The code is also (IMO) a LOT simpler now. We no longer have to
> modify both bus-extension.xml and cxf-extension-blah.xml files. The
> extension loading is more unified. The extension retrieval from the Bus
> is simpler and, for the most part, identical between the Spring and
> Non-Spring cases. And the performance rocks. :-)
>
> For the most part, it's simple to modify existing applications to work.
> Just remove all the imports for everything except META-INF/cxf/cxf.xml
> and META- INF/cxf/cxf-servlet.xml if you use a servlet. However, there
> are a couple of other "gotchas" that I encountered:
>
> 1) We had several files that did something like:
>
> <bean id="cxf" class=".... CXFBusImpl>
> ... conifure some interceptors....
> </bean>
>
> That no longer works. The proper way to do that has been to use the
> <cxf:bus> namespaced object. It's been that way for a while. Creating
> separate Bus's like that is just asking for having things become confused.
> I converted all the tests to do that properly. You COULD potentially
> change that to:
> <bean id="cxf" class="org.apache.cxf.bus.spring.SpringBus">
> but using cxf:bus is definitely the better way to go. Directly
> instantiating and depending on internal "impl" classes and such is
> generally a bad idea.
>
> 2) depends-on and injections - since almost none of the CXF internal beans
> are now defined in the Spring context, you cannot really depend on them
> directly. That's not a normal thing anyway. The Bus is really the
> only thing that is in the context.
>
> In anycase, the rest was fairly simple. If you do define beans in the
> spring config, they will override/replace the auto loaded stuff (just like
> before), the configurations stuff remains the same, etc.... It just
> starts up a ton faster and uses a bit less memory. :-)
>
> I definitely have some more testing to do, but I think it's a good start.
>
> Dan
>
> On Thursday 03 March 2011 5:01:58 PM Daniel Kulp wrote:
> > I've done quite a bit of work now on trunk to speed up the "normal" use
> > cases. With what's on trunk now, a normal JAX-WS client that doesn't
> > include any spring config will get the extension bus instead. With my
> > lastest set of changes, a default extension bus now starts up without
> > ANY XML parsing and very few beans and such created. This is MUCH
> > faster now. I wrote a little benchmark based on the java-first-jaxws
> > example (to avoid any WSDL related things) and depending on cxf-bundle
> > to make
> >
> > sure we get EVERYTHING and then does:
> > public static void doIteration(boolean invoke) {
> >
> > BusFactory.setThreadDefaultBus(null);
> > BusFactory.setDefaultBus(null);
> >
> > Service service = Service.create(SERVICE_NAME);
> > String endpointAddress = "http://localhost:9000/helloWorld";
> > service.addPort(PORT_NAME,
> >
> > SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
> >
> > if (invoke) {
> >
> > service.getPort(HelloWorld.class).sayHi("Hello");
> >
> > } else {
> >
> > service.getPort(HelloWorld.class);
> >
> > }
> >
> > }
> >
> > in a loop under 3 conditions:
> > 1) First is with invoke=false to basically time all the upfront setup
> > costs. That includes creating the Bus, creating the Service, and then
> > creating the Proxy.
> >
> > 2) Then with invoke=true to include the additional stuff of creating the
> > interceptor chains and conduits and doing a real invoke.
> >
> > 3) Again with invoke=false, but this time with specifying a spring config
> > file (cxf.xml). This basically is the same as (1), but involves the
> > spring Bus now.
> >
> > I then ran this with several versions of CXF. Results are below.
> > (first number is the # of ms for 1500 iterations, then it's
> > iterations/sec)
> >
> > Basically, the Extension bus stuff is now a TON faster. For 80% of the
> > use cases, it's much faster. I'm definitely excited about that. The
> > spring case slowed down a bit. I'm not sure why. I'll need to profile
> > that a bit to figure it out. In anycase, for standalone applications
> > and cases where config is done through API's, this is quite a bit
> > faster. As we start thinking about Blueprint and such, this can be
> > important. Right now, the server side parts are all very spring based
> > and thus won't benefit from this.
> >
> > :-(
> >
> > One thing I'm going to try next is making META-INF/cxf/cxf.xml just have
> > a single bean (the ExtensionBus) and removing all the
> > cxf-extension-*.xml files (except for the HTTP things, more in a sec on
> > that) and seeing what happens.
> >
> > The HTTP stuff on the server side becomes a "challenge". Right now, we
> > have basically 3 implementations of the HTTPDestinationFactory: jetty,
> > servlet, and OSGi. The user pretty much selects the one they want by
> > importing the appropriate cxf-extension file and not the others in their
> > spring config. While it works, there is a down side: you can only have
> > one implementation in you application. Normally not a problem, but
> > there IS the use case of a Servlet based application that may also want a
> > service or two exposed on a specific jetty port (like maybe for a
> > decoupled client) that isn't under the servlet containers control.
> >
> > My proposal for that would be to put a single HTTPDestinationFactory in
> > the http module that would hold onto a DestinationRegistry. The OSGi
> > and Servlet based things would just grab that DestinationRegistry for
> > their dispatching. However, when the HTTPDestinationFactory is asked to
> > create a destination for a "full" URL (like
> > "http://localhost:8080/blah") instead of a path (like "/blah"), it would
> > call on a delegate that the Jetty stuff would provide to it. I need to
> > think about this a bit more, but I think it would work fairly well.
> >
> >
> > Dan
> >
> >
> >
> >
> > Running test - 2.4.0-SNAPSHOT
> > Setup: 29086 51/sec
> > Invoke: 42558 35/sec
> > Setup config: 69839 21/sec
> >
> >
> > Running test - 2.3.3
> > Setup: 49732 30/sec
> > Invoke: 62276 24/sec
> > Setup config: 56164 26/sec
> >
> > Running test - 2.3.0
> > Setup: 44233 33/sec
> > Invoke: 56496 26/sec
> > Setup config: 55305 27/sec
> >
> > Running test - 2.2.12
> > Setup: 48193 31/sec
> > Invoke: 55737 26/sec
> > Setup config: 50582 29/sec
> >
> >
> > Running test - 2.1.9
> > Setup: 43944 34/sec
> > Invoke: 47652 31/sec
> > Setup config: 44550 33/sec
> >
> >
> > Running test - 2.1.1
> > Setup: 47335 31/sec
> > Invoke: 48871 30/sec
> > Setup config: 49255 30/sec
--
Daniel Kulp
[email protected]
http://dankulp.com/blog
Talend - http://www.talend.com