如何使用jaxws向soap请求添加soap标头

时间:2015-08-10 20:51:09

标签: spring web-services soap jax-ws soap-client

我们需要使用其他团队开发的Web服务。使用JAX-WS生成Web服务。我们使用wsimport生成客户端存根。

问题是我需要将以下信息作为标题与肥皂体一起传递。

<soapenv:Header>
    <ns1:HeaderData xmlns:wsse="http:///wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
                    xmlns:ns1="http:///esb/data_type/HeaderData/v1">
        <ChannelIdentifier>ABC</ChannelIdentifier>
    </ns1:HeaderData>
</soapenv:Header>

<execution>
                            <id>wsimport-profile</id>
                            <goals>
                                <goal>wsimport</goal>
                            </goals>
                            <configuration>
                                <wsdlDirectory>src/main/resources/wsdl/GPP</wsdlDirectory>
                                <wsdlFiles>
                                    <wsdlFile>LoadProfileService.wsdl</wsdlFile>
                                </wsdlFiles>
                                <packageName>com.soapbinding.service</packageName>
                                 <extension>true</extension>
                                <protocol>Xsoap1.2</protocol>
                                <xadditionalHeaders>true</xadditionalHeaders>
                            </configuration>
                        </execution>

我尝试使用JAX-WS。它几乎相同,修改标题以添加用户凭据:

public class LoadProfileSOAPHandler implements SOAPHandler<SOAPMessageContext> {

    @Log
    private Logger LOGGER;
    private String username;

    /**
     * Handles SOAP message. If SOAP header does not already exist, then method will created new SOAP header. The
     * username  is added to the header as the credentials to authenticate user. If no user credentials is
     * specified every call to web service will fail.
     *
     * @param context SOAP message context to get SOAP message from
     * @return true
     */

    @Override
    public boolean handleMessage(SOAPMessageContext context) {       

            try {
                String uri = "http:/SCL/CommonTypes";
                String prefix = "q2";
                SOAPMessage message = context.getMessage();
                SOAPHeader header = message.getSOAPHeader();
                SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
                if (header == null) {
                    header = envelope.addHeader();
                }


                QName qNameFndtHeader = new QName(uri,prefix, "FndtHeader");
                SOAPHeaderElement fndtHeader = header.addHeaderElement(qNameFndtHeader);

                QName qNamecredentials = new QName(prefix, "credentials");

                QName qNameuser = new QName(prefix, "UserID");
                SOAPHeaderElement userHeader = header.addHeaderElement(qNameuser);
                userHeader.addTextNode(this.username);

                fndtHeader.addChildElement(qNameFndtHeader);
                fndtHeader.addChildElement(qNamecredentials);
                fndtHeader.addChildElement(userHeader );
                message.saveChanges();
                //TODO: remove this writer when the testing is finished
                StringWriter writer = new StringWriter();
                message.writeTo(new StringOutputStream(writer));
                LOGGER.debug("SOAP message: \n" + writer.toString());
            } catch (SOAPException e) {
                LOGGER.error("Error occurred while adding credentials to SOAP header.", e.getMessage());
            } catch (IOException e) {
                LOGGER.error("Error occurred while writing message to output stream.", e.getMessage());
            }
            return true;            

    }

    //TODO: remove this class after testing is finished
    private static class StringOutputStream extends OutputStream {

        private StringWriter writer;

        public StringOutputStream(StringWriter writer) {
            this.writer = writer;
        }

        @Override
        public void write(int b) throws IOException {
            writer.write(b);
        }
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        LOGGER.debug("handleFault has been invoked.");
        return true;
    }

    @Override
    public void close(MessageContext context) {
        LOGGER.debug("close has been invoked.");
    }

    @Override
    public Set<QName> getHeaders() {
        LOGGER.debug("getHeaders has been invoked.");
        return null;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

@Component("loadProfileHandlerResolver")

/**
 * Overrode in order to load custom handlers.
 * @see javax.xml.ws.handler.HandlerResolver#getHandlerChain(javax.xml.ws.handler.PortInfo)
 */
public class LoadProfileHandlerResolver implements org.springframework.context.ApplicationContextAware, HandlerResolver  {

    /*@Autowired
    LoadProfileSOAPHandler loadProfileSOAPHandler;
    */
    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        ListableBeanFactory lb = (ListableBeanFactory) arg0;
        System.out.println(Arrays.toString(lb.getBeanDefinitionNames()));
    }

    public LoadProfileHandlerResolver() {
        // TODO Auto-generated constructor stub
        System.out.println("");
    }

    @Override
    public List<Handler> getHandlerChain(PortInfo arg0) {
        List<Handler> handlerChain = new ArrayList<Handler>();
        LoadProfileSOAPHandler loadProfileSOAPHandler =new LoadProfileSOAPHandler();
        handlerChain.add(loadProfileSOAPHandler);
        return handlerChain;
    }

还在应用程序配置文件中添加了依赖性。我在Spring配置中定义了这个处理程序,如上所述

<bean id="loadProfilePortProxy"
    class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
    <property name="serviceInterface"
        value="com.soapbinding.gpppservice.LoadProfileServicePortType" />

    <property name="wsdlDocumentUrl" value="classpath:wsdl/GPP/LoadProfileService.wsdl" />
    <property name="namespaceUri" value="http://SCL/LoadProfileService" />
    <property name="serviceName" value="LoadProfileService" />
    <property name="endpointAddress" value="${service.loadCalenderdata}" />
    <property name="handlerResolver" ref="loadProfileHandlerResolver"/> 
</bean>

我正在解决以下问题:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadProfilePortProxy' defined in class path resource [application-config.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException

由于spring application.xml中的property name="handlerResolver" ref="loadProfileHandlerResolver"

并且还让我知道为什么我的wsimport没有使用xadditionalHeaders,因为它没有给我带有soap标头的存根类,这可能会以其他方式解决问题。

<xadditionalHeaders>true</xadditionalHeaders>

1 个答案:

答案 0 :(得分:0)

解决了这个问题,我们在春天注入属性ref loadProfileHandlerResolver

时得到一些null

...谢谢