简体   繁体   中英

Spring web service client XwsSecurityInterceptor afterCompletion exception

I've implemented a Spring Web Service Server and Client with the configuration enclosed below.

I have opted to use simplePasswordSecurity mechanism and both sides have been fitted to handle this. So far I can send my request from client to server, server will process the request and send the response back.

In my terminal log, I can see that client receives the response but out of nowhere I get this exception:

java.lang.AbstractMethodError: org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor.afterCompletion(Lorg/springframework/ws/context/MessageContext;Ljava/lang/Exception;)V
at org.springframework.ws.client.core.WebServiceTemplate.triggerAfterCompletion(WebServiceTemplate.java:806)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:615)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)

....

Any ideas why I get this exception?


Server

spring-config.xml

<bean id="FinancialService" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition" lazy-init="true">
    <property name="schemaCollection">
        <bean class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
            <property name="inline" value="true" />
            <property name="xsds">
                <list>
                    <value>schemas/FinancialServiceOperations.xsd</value>
                </list>
            </property>
        </bean>
    </property>

    <property name="portTypeName" value="FinancialService" />
    <property name="serviceName" value="FinancialService" />
    <property name="locationUri" value="/endpoints" />
</bean>

<sws:interceptors>
    <bean id="authenticationInterceptor" class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
        <property name="policyConfiguration" value="/WEB-INF/spring-security.xml" />
        <property name="callbackHandlers">
            <list>
                <bean id="passwordValidationHandler" class="org.springframework.ws.soap.security.xwss.callback.SimplePasswordValidationCallbackHandler">          
                    <property name="users">  
                        <props>  
                            <prop key="myUser">myPassword</prop>
                        </props>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
</sws:interceptors>

spring-security.xml

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config" dumpMessages="true">  
    <xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/>  
</xwss:SecurityConfiguration>

pom.xml

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-security</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>


Client

spring-config.xml

<bean id="soapMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
    <property name="soapVersion">
        <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11" />
    </property>
</bean>

<oxm:jaxb2-marshaller id="marshaller" context-path="com.example.domain.service.financial.stub" />

<bean id="financialWebServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    <constructor-arg ref="soapMessageFactory" />
    <property name="marshaller" ref="marshaller" />
    <property name="unmarshaller" ref="marshaller" />
    <property name="defaultUri" value="http://localhost:8080/financial/FinancialService.wsdl" />
    <property name="messageSender" ref="xwsSecurityMessageSender" />
    <property name="interceptors">
        <list>
            <ref bean="xwsSecurityInterceptor" />
        </list>
    </property>
</bean>
<bean id="xwsSecurityMessageSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender" />
<bean id="xwsSecurityInterceptor" class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
    <property name="policyConfiguration" value="/WEB-INF/spring-ws-security.xml" />
    <property name="callbackHandlers">
        <list>
            <ref bean="xwsSecurityCallbackHandler" />
        </list>
    </property>
</bean>
<bean id="xwsSecurityCallbackHandler" class="org.springframework.ws.soap.security.xwss.callback.MockValidationCallbackHandler" />

spring-security.xml

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config" dumpMessages="true">
     <xwss:UsernameToken name="myUser" password="myPassword" digestPassword="false" useNonce="false"/>
</xwss:SecurityConfiguration>

pom.xml

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-security</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>


Terminal Log

INFO: ==== Sending Message Start ====
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="XWSSGID-140733907019228719200">
<wsse:Username>willapweb</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">****</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns2:OnlinePaymentFormRequest xmlns:ns2="http://com/example/ws">
<ns2:serial>c3hqvk9dejps923m01qrpqrh6f</ns2:serial>
<ns2:amount>200000</ns2:amount>
</ns2:OnlinePaymentFormRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
==== Sending Message End  ====

INFO: ==== Received Message Start ====
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="XWSSGID-140733907019228719200">
<wsse:Username>willapweb</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">****</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns2:OnlinePaymentFormRequest xmlns:ns2="http://com/example/ws">
<ns2:serial>c3hqvk9dejps923m01qrpqrh6f</ns2:serial>
<ns2:amount>200000</ns2:amount>
</ns2:OnlinePaymentFormRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
==== Received Message End  ====

INFO: ==== Sending Message Start ====
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:OnlinePaymentFormResponse xmlns:ns2="http://com/example/ws">
<ns2:message>{"form":"&lt;form action='https://bank.om/Payment.aspx' method='post' id='bank-form'&gt;&lt;input type='hidden' name='Amount' value='200000'/&gt;&lt;input type='hidden' name='MID' value='12'/&gt;&lt;input type='hidden' name='ResNum' value='c3hqvk9dejps923m01qrpqrh6f'/&gt;&lt;input type='hidden' name='RedirectURL' value='http://130.185.73.133/payment/verification'/&gt;&lt;\/form&gt;","successful":true}</ns2:message>
</ns2:OnlinePaymentFormResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
==== Sending Message End  ====

INFO: ==== Received Message Start ====
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:OnlinePaymentFormResponse xmlns:ns2="http://com/example/ws">
<ns2:message>{"form":"&lt;form action='https://bank.com/Payment.aspx' method='post' id='bank-form'&gt;&lt;input type='hidden' name='Amount' value='200000'/&gt;&lt;input type='hidden' name='MID' value='12'/&gt;&lt;input type='hidden' name='ResNum' value='c3hqvk9dejps923m01qrpqrh6f'/&gt;&lt;input type='hidden' name='RedirectURL' value='http://130.185.73.133/payment/verification'/&gt;&lt;\/form&gt;","successful":true}</ns2:message>
</ns2:OnlinePaymentFormResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
==== Received Message End  ====

You most likely have incompatible JARs in your classpath.

AbstractMethodError

AbstractMethodError is a runtime error that is thrown by the JVM when a method that should exist, actually does not.

This should not happen in your own code : the compiler prevents you from calling methods that do not exist.

However, when using external JARs (that depend upon other external JARs), the compiler can not warn you.

Say I have A-1.0.jar, which contains class A, that has a method doStuffV1() .
Then, A-2.0.jar, which contains an update to the class A, which adds another method doStuffV2() . Finally, say I have B-2.0.jar, which is compiled with A-2.0.jar, with class B that extends A.

In you project, if you import B-2.0.jar only, and you use class B and call doStuffV2 , the compiler will not complain : you are using a class that's working.

But if, at runtime, you throw in your classpath A-1.0.jar and B-2.0.jar, when your code executes, you will get AbstractMethodError : what existed when B-2.0.jar was compiled, does not exist at runtime. This is a crash.

Applied to Spring WS Jars 2.0.0 to 2.2.0

In Spring WS, if you look at Spring WS 2.0.0 Javadoc, which your are referencing, you can see here ( http://docs.spring.io/spring-ws/sites/2.0/apidocs/index.html ) the afterCompletion signature :

public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex)

But if you look at the 2.2.0 api ( http://docs.spring.io/spring-ws/docs/2.2.0.RELEASE/api/ ) the same method does exist, only with a different signature. To the Java compiler and runtime, this is NOT the same method :

public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException

Informations from your stacktrace

Your stack trace indicates that the runtime, from the WSTemplate class, tries to call the later version (see the first line).

java.lang.AbstractMethodError: ...XwsSecurityInterceptor.afterCompletion(Lorg/springframework/ws/context/MessageContext;Ljava/lang/Exception;)V at org...WebServiceTemplate.triggerAfterCompletion(WebServiceTemplate.java:806)

Which suggests to me that

  1. you have a Spring-WS-Core (WebServiceTemplate.class) that is a 2.2.0 version
  2. with a Spring WS Security (XwsSecurityInterceptor) which is a 2.1.0 version (or something in between).

That is not compatible. You should keep both versions in sync.

EDIT : with your POM, this seems confirmed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM