第一台服务器会覆盖多个CXF服务器绑定

时间:2013-04-18 12:53:41

标签: spring osgi cxf

我有多个WAR,它们都使用CXFServlet来处理所有请求和Spring配置。

他们所有人都有类似的web.xml(是的,它也在OSGi上):

<web-app id="app1">
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:META-INF/spring/*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>app1</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>app1</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

所有人都共享一个共同的Spring配置(common-rest.xml):

<beans>
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <!-- For brevity I left out jaxRSProviders and jaxRSInInterceptors lists definitions -->    
    <bean id="baseJaxRSServer"
        abstract="true"
        lazy-init="false"
        class="org.apache.cxf.jaxrs.spring.JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean"
        init-method="create"
        p:address="${http.server}/"
        p:providers-ref="jaxRSProviders"
        p:inInterceptors-ref="jaxRSInInterceptors" />
</beans>

所有这些都有类似的特定Spring配置:

<beans>
    <import resource="classpath:META-INF/app/common-rest.xml" />
    <!-- For brevity I left out app1ServiceBeans list definition -->    
    <bean id="app1JaxRSServer"
        parent="baseJaxRSServer"
        p:serviceBeans-ref="app1ServiceBeans" />
</beans>

问题是,当我现在部署第一个应用程序时,它似乎相当不错,但其他所有应用程序绑定基本上都看不到。似乎尽管所有应用都有separete Spring上下文和单独的CXF服务器以及单独的CXF总线,但它们仍然会以某种方式混淆,并为每个应用分配一个org.apache.cxf.transport.Destination - 来自第一捆的那个。有谁知道这怎么可能?

CXF:2.6.2,Spring:3.1.4,Karaf:2.3.1

2 个答案:

答案 0 :(得分:1)

如果您在Karaf内部运行,我建议先安装cxf功能,之后只需通过蓝图注册您的cxf端点,就像使用Apache Camel一样。据我所知,CXF确实在cxf上下文中注册了一个“主”servlet,从中可以访问所有Web服务。 此时你不需要任何战争。除了你没有显示关于Web-ContextPath的清单条目之外,Web容器需要在可服务的上下文之间有所不同,所以如果它们都具有相同的上下文,那么第一个获胜!

答案 1 :(得分:0)

原来这是DestinationRegistry的问题。默认情况下,CXF会注册使用DestinationFactory的单个实例的单个DestinationRegistry。这就是为什么每个Server被分配给单个Destination的原因,因为/字段值定义了所有这些address,因为WAR字段值定义了所有这些common-rest.xml

对我有用的解决方案是为每个<beans> <import resource="classpath:META-INF/cxf/cxf.xml" /> <bean id="httpDestinationRegistry" class="org.apache.cxf.transport.http.DestinationRegistryImpl" /> <!-- For brevity I left out jaxRSProviders and jaxRSInInterceptors lists definitions --> <bean id="baseJaxRSServer" abstract="true" lazy-init="false" class="org.apache.cxf.jaxrs.spring.JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean" init-method="create" p:address="${http.server}/" p:providers-ref="jaxRSProviders" p:inInterceptors-ref="jaxRSInInterceptors" /> </beans> 捆绑包添加一个单独的目标注册表。所以我的{{1}}现在看起来像这样:

{{1}}

以上配置与SpringBeanLocator使用的SpringBus结合为ConfiguredBeanLocator会导致每个WAR捆绑包的单独的Spring托管HTTP DestinationRegistry实例依次生成允许在每个捆绑包中配置CXF服务器,并导致正确完成应用程序。