【问题标题】:Axis2(aar) + spring, without a servletContextAxis2(aar) + spring,没有 servletContext
【发布时间】:2013-09-25 22:49:45
【问题描述】:

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

  • 存储库/
    • 模块
    • 服务

当我构建这个 .aar 存档时,我也在生成自己的 wsdl,而不是使用根据 services.xml 生成给定类的服务的axis2内置wsdl生成器(当我运行axis2server时,不使用因为据我所知不喜欢 JAX-WS 注释)。为了初始化 Spring 框架,我需要编写一个小的 SpringInit 类来初始化 Spring bean。不幸的是,它也出于某种原因根据其注释初始化了我的 Web 服务类,然后占用了主端口(怀疑 SpringInit 自己初始化 Web 服务类,因为它也被定义为 Spring bean 并且 SpringInit 扩展了 Axis2 类 ServiceLifeCycle)我得到 JVM BIND 异常,它表明该地址已在使用中。我想根据存储在 WSDL 中的 wsdl 建立服务,而不是生成新的服务,因为我有各种环境:1)本地机器 - 码头 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”文件夹中,并使用absence.jar 填充它,该jar 的所有依赖项都位于子文件夹“lib”中。 Axis2 然后自动运行 absense.jar,因为它具有 JAX-WS 注释。但是在那里,当我使用 SOAP-UI 调用 Web 服务时,它没有初始化 Spring,因为我不知道如何在该解决方案中初始化 Spring。也许有人对此有任何专长。

TL;DR

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

欢迎提问。

【问题讨论】:

    标签: spring integration axis2 mainframe cics


    【解决方案1】:

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

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

    一开始我从网上得知(Axis2主页,有关于axis2和spring集成的说明)在Axis2 web服务中初始化Spring我需要.aar存档和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”架构。不幸的是,我没有 services.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(absence bean) 创建 Web 服务。删除它,因为我也可以在本地机器上使用预先生成的 WSDL 和 Jetty(最初是用于在本地机器上创建 Web 服务,就像我之前说的,我有本地开发环境,它也应该与 CICS 兼容,现在解决了)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 2020-01-30
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多