5

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

  • 存储库/
    • 模块
    • 服务

当我构建这个 .aar 存档时,我也在生成自己的 wsdl,而不是使用axis2内置的wsdl生成器,它根据services.xml从给定的类中生成服务(当我运行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;博士

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

欢迎您提出问题。

4

1 回答 1

2

我如何在没有 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 绑定地址已在使用中”。

因此,我决定放弃 .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 兼容,现在解决了)。

于 2013-09-24T16:05:15.067 回答