Axis2(aar)+ spring,没有servletContext

时间:2013-09-20 13:58:49

标签: spring integration axis2 mainframe cics

亲爱的Stackoverflow用户,最近我对使用Spring框架的axis2 Web服务的一个特定问题感到非常痛苦。我已经阅读了很多不同的指南并阅读了不同的论坛,但发现人们有同样的问题,但没有解决方案。基本上最后用我的双手拿着显示器大喊“你发现了什么,找到了BudapestHacker938?”。无论如何,我的axis2 Web服务类需要Spring bean,因此它们在Web服务类中自动装配。在我有servletContext的jetty服务器里,一切都运行良好。只需在web.xml中定义所需的侦听器即可。这样的幸福。但不幸的是,在某些方面所有好事都落到了尽头,对我来说,魔鬼是大型机内部的CICS环境。在Jetty / Tomcat中没有servletcontext,幸运的是它仍然支持axis2。因此,根据不同的用户指南,我决定将我的网络服务存档到.aar并将其添加到services文件夹下。 Axis2文件夹结构如下:

  • 库/
    • 模块
    • 服务

当我构建这个.aar存档时,我也在生成我自己的wsdl,而不是使用axis2内置的wsdl生成器,根据services.xml生成给定类的服务(当我运行axis2server时,不使用因为据我所知,不喜欢JAX-WS注释。要初始化Spring框架,我需要编写初始化Spring bean的SpringInit类。不幸的是,由于某种原因它也会根据其注释初始化我的web服务类,然后占用主端口(怀疑SpringInit由其自己的Web服务类初始化,因为它也被定义为Spring bean而SpringInit扩展了Axis2类ServiceLifeCycle)我得到JVM BIND异常,它说明地址已被使用。我希望根据存储在WSDL内部的wsdl构建服务,而不是生成新服务,因为我有各种环境:1)本地机器 - Jetty 2)大型机。无论如何,我深入了解了我的services.xml:

<service name="Absence" class="org.services.SpringInit">
<description>
    random description
</description>
<parameter name="ServiceTCCL">composite</parameter>
<parameter name="useOriginalwsdl" locked="false">true</parameter>
<parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter>
<parameter name="ServiceClass">org.services.Absence</parameter>
<parameter name="SpringBeanName">absence</parameter>
<parameter name="SpringContextLocation">META-INF/applicationContextAar.xml</parameter>
</service>

Spring applicationContextAar.xml,为亲爱的Stack社区进行了一点点重构:

<beans>
<bean id="applicationContext" class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:tcp://localhost/~/devDb" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="absence" class="org.services.Absence"></bean>
<bean id="jtemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="ds"></constructor-arg>
</bean>
<bean id="datasetFactory" class="org.vsam.DataSetFactory"></bean>
<bean id="dataManagerFactory" class="org.datamanager.DataManagerFactory"></bean>
<bean id="absenceFactory" class="org.services.AbsenceFactory"></bean>
<bean id="h2Database" class="org.dataset.H2Database"><constructor-arg ref="jtemplate"></constructor-arg>
</bean>
<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"></bean>
</beans>

我的SpringInit类看起来像这样:

public class SpringInit implements ServiceLifeCycle {

public void startUp(ConfigurationContext ignore, AxisService service) {

    try {
        ClassLoader classLoader = service.getClassLoader();
        ClassPathXmlApplicationContext appCtx = new
        ClassPathXmlApplicationContext(new String[] {"applicationContextAar.xml"}, false);
            appCtx.setClassLoader(classLoader);
            appCtx.refresh();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public void shutDown(ConfigurationContext ctxIgnore, AxisService ignore) {}
}

现在我们转到org.services.Absence.class,它是一个普通的JAX-WS Web服务类,包含以下头文件(包含JAX-WS注释):

@WebService(name = "AbsenceService", serviceName = "Absence", portName = "Absence",
targetNamespace = "http://www.something.org/Absence")
public class Absence extends ServiceHandlerBase { 

    @Autowired
private AbsenceFactory absenceFactory;

@Autowired
private DataManagerFactory dataManagerFactory;

@Autowired
private DataSetFactory dataSetFactory;


... 

}

包含类似的方法:

@WebMethod
@WebResult(name = "AbsenceResponse")
public SearchAbsenceRecordsResponse invokeSearchAbsenceRecords(
        @WebParam ServiceRequest request,
        @WebParam SearchAbsenceRecordsRequest absenceRequest) {...}

另一种方法是将“servicejars”文件夹添加到“repository”文件夹中,并使用在子文件夹“lib”中具有所有依赖关系的absence.jar填充它。然后Axis2自动运行absense.jar,因为它具有JAX-WS注释。但是当我用SOAP-UI调用Web服务时,它没有初始化Spring,因为我不知道如何在该解决方案中初始化Spring。也许有人对此有任何专业知识。

TL; DR

如何按照不按照注释启动Web服务类中的服务的方式初始化我的Spring bean,而是根据wsdl构建服务?

欢迎您提问。

1 个答案:

答案 0 :(得分:2)

如何在没有servletcontext的情况下在CICS中初始化Spring?

基本上直到今天,SOAP Web服务已经通过servicejars发布了,这意味着在存储库文件夹中创建了“servicejars”文件夹,该文件夹包含了从Web服务类构建的jar文件夹。 “servicejars”子文件夹“lib”包含Web服务jar所需的所有依赖项。

首先,我从Web(Axis2主页,有关于axis2和spring集成的指令)中了解到,在Axis2 Web服务中初始化Spring我需要.aar archive和services.xml中定义的SpringInit服务。但是这带来了许多问题,因为在jaxws和jaxb上构建了旧架构,因此需要重构Web服务层。 Axis2仅使用“servicejars”解决方案容忍jaxws注释。使用SpringInit类进入Spring意味着它根据应用程序上下文初始化Spring bean。这现在运行web服务bean(在前一篇文章中的缺省bean)作为单独的Web服务并占用8080端口,当根据WSDL创建Web服务的时间到来时我收到错误“JVM绑定地址已在使用中”。所以在那之后我想我应该根据缺少的Spring bean创建服务,让axis2server生成WSDL,但是axis2server不喜欢jaxws注释,即使没有它们也不喜欢我的jaxb DTO。

因此,我决定放弃.aar架构并回到“servicejars”架构。不幸的是,在那里我没有service.xml支持,以定义潜在的SpringInit服务。

由于jaxws Web服务是唯一的入口点,所以我决定执行以下操作(在Web服务层初始化Spring bean):

@WebService(name = "AbsenceService", serviceName = "Absence", portName = "Absence",
targetNamespace = "http://www.something.org/Absence")
public class Absence extends ServiceHandlerBase { 

private static AbsenceFactory absenceFactory;

private static DataManagerFactory dataManagerFactory;

private static DataSetFactory dataSetFactory;

static {
    try {
        ClassPathXmlApplicationContext appCtx = new
        ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"}, false);
        appCtx.refresh();

        absenceFactory = (AbsenceFactory) appCtx.getBean("absenceFactory", AbsenceFactory.class);
        dataManagerFactory = (DataManagerFactory) appCtx.getBean("dataManagerFactory", DataManagerFactory.class);
        dataSetFactory = (DataSetFactory) appCtx.getBean("datasetFactory", DataSetFactory.class);

    } catch (Exception ex) {
        ex.printStackTrace();
    }

}


... 

}

正如您所看到的,当调用此类时,它将初始化applicationcontext并且因为它是静态的,所有spring bean将保留在内存中直到结束(当服务关闭时)。在其他类中,自动装配工作完美,无需手动连接这些bean。

最后,我没有找到像我希望通过.aar架构那样初始化Spring的可能性,但我找到了一位高级程序员的指导。非常感谢他!现在,所有StackOverFlow用户都可以看到可能的解决方案。

编辑:

在applicationContext.xml中我有:

<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"/>

尝试使用Absence.class(缺勤bean)创建Web服务。删除它,因为我可以在本地机器上使用预先生成的带有Jetty的WSDL(最初用于在本地机器中创建Web服务,就像我之前说过的,我有本地开发环境,它应该也与CICS兼容,现在它解决了。)