[WARNING: Much rambling follows.] Daniel Kulp <[EMAIL PROTECTED]> writes:
> Basically, in the servlet, we need to have some objects that the > Servlet provides set into the bus that spring creates. Those > objects aren't created by any spring xml or anything like that. A bus is first created by Spring, without these Servlet-related objects wired in, but when the CXFServlet gets created, it needs to add things to the bus already created and held by Spring. One of the things that the CXFServlet adds is a special Resource resolver that uses the ServletContext to find things. It also creates a child ApplicationContext to hold objects loaded from the "post-Servlet-initialization" configuration file. Is that correct? > There may be some way to pre-initialize the context with those > objects such that they could be built right into the bus > immediately. I really don't know. If so, that could solve the > problem and we could just do everything all at once and be done with > it. Well, why not ask Servlet users to specify a parameter to Spring's ContextLoaderListener telling it which kind of ApplicationContext to create? Right now, it defaults to XmlWebApplicationContext. However, it will honor a "contextClass" parameter and load the specified class instead. You could load BusApplicationContext right from the start. Actually, that's probably not the right idea; the Spring WebApplicationContext variants already take the hierarchy of a Web application into account, with a root context and various per-Servlet child contexts. It just looks to me like there's an extra context for the CXFServlet: one BusApplicationContext, created by SpringBusFactory.createBus(), and a GenericApplicationContext if the Servlet-specific user-provided CXF configuration file is found. Maybe the documentation has been too liberal with prescribing Spring-based configuration for the CXFServlet. It looks like there should be no CXFServlet-dependent configuration in the root application context, as the Servlet hasn't been loaded yet when those definitions are processed. As endpoints depend upon the Servlet -- or maybe they only sometimes depend upon the Servlet -- the example shown here looks wrong: Declaring your server beans http://cwiki.apache.org/CXF20DOC/writing-a-service-with-spring.html The META-INF/cxf/cxf-servlet.xml file doesn't need to be loaded there, or at least it shouldn't be necessary; it should be loaded by CXFServlet no matter what, rather than conditionally as it is now in loadSpringBus(): ,---- | if (ctx == null) { | bus = new SpringBusFactory().createBus("/META-INF/cxf/cxf-servlet.xml"); | } else { | bus = new SpringBusFactory(ctx).createBus(); | } `---- The jaxws:endpoint definition should be moved into a user-provided cxf-servlet.xml file, or whatever is designated by the Servlet's "config-location" parameter. That would mimic Spring's existing setup: a root context for the whole Web application, with "namespace"-specific contexts for individual Servlets, or at least like Spring's DispatcherServlet. Change BusApplicationContext to accept not just one configuration file parameter, but an array of them. Then have CXFServlet pass its own configuration file -- /META-INF/cxf/cxf-servlet.xml -- and the user-provided file (if it exists) to a new SpringBusFactory.createBus() overload that also takes an array of configuration files. That would help get rid of the second-stage configuration done by loadAdditionalConfig(). Well, maybe there's still too much work done in between when the Bus is created and when the system is ready to process user-provided Spring definitions such as jaxws:endpoint. Those ideas won't work. Digging through the code, I see one point that looks like it should be addressed: SpringBusFactory.createBus() should not be used as it is by CXFServlet. Three cases are possible: Either the user already initialized CXF in some parent ApplicationContext before CXFServlet got loaded, or the user has not, and there is no bean called "cxf" in the Servlet's parent ApplicationContext. There's the third case that there is no parent ApplicationContext at all, such as when the user has not employed Spring's ContextLoaderListener. If there is no existing parent ApplicaitonContext, call on SpringBusFactory.createBus("/META-INF/cxf/cxf-servlet.xml"), as we do now. Configure the Servlet-Bus interaction. Later proceed to check for a user-provided Servlet-specific configuration file and create a child GenericApplicationContext if such a file is present. If there is no existing "cxf" bean in an existing parent ApplicationContext, again, like above, call on SpringBusFactory.createBus("/META-INF/cxf/cxf-servlet.xml"), as we do now. Configure the Servlet-Bus interaction. Later proceed to check for a user-provided Servlet-specific configuration file and create a child GenericApplicationContext if such a file is present. However, if there is an existing "cxf" bean, SpringBusFactory.createBus() should /not/ be used, as it creates a new BusApplicationContext each time, in this case unnecessarily. It does avoid reloading the default configuration files, but it still creates an extra ApplicationContext. Instead, call something like SpringBusFactory.getBus(), which would just return (Bus)context.getBean(DEFAULT_BUS_ID); Carry on setting up the Servlet-Bus interaction, then check if there's a user-provided CXFServlet configuration file and create a child GenericApplicationContext if such a file is present. That eliminates creating an extra BusApplicationContext just to gain access to an existing bus instance. I see that SpringBusFactory just extends BusFactory, so its interface wouldn't be as flexible as I thought. This has been a lot of rambling, but the I do now agree that the Servlet-dependent Spring beans need to be in a separate configuration file from the root ApplicationContext's configuration files. It looks like the CXFServlet-SpringBusFactory interaction could be cleaned up some to avoid spurious creation of extra ApplicationContexts. Finally, the documentation should clarify which CXF Spring configuration directives depend on CXFServlet and hence need to live in a separate configuration file. -- Steven E. Harris
