org.springframework.integration.ws.SimpleWebServiceOutboundGateway.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.ws.SimpleWebServiceOutboundGateway.java

Source

/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.integration.ws;

import java.io.IOException;
import java.util.Iterator;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;

import org.w3c.dom.Document;

import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.SourceExtractor;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.support.destination.DestinationProvider;
import org.springframework.ws.mime.Attachment;
import org.springframework.ws.mime.MimeMessage;
import org.springframework.xml.transform.StringResult;
import org.springframework.xml.transform.StringSource;
import org.springframework.xml.transform.TransformerObjectSupport;

/**
 * An outbound Messaging Gateway for invoking a Web Service.
 *
 * @author Mark Fisher
 * @author Oleg Zhurakousky
 * @author Artem Bilan
 * @author Gary Russell
 */
public class SimpleWebServiceOutboundGateway extends AbstractWebServiceOutboundGateway {

    private final SourceExtractor<?> sourceExtractor;

    private volatile boolean extractPayload = true;

    public SimpleWebServiceOutboundGateway(DestinationProvider destinationProvider) {
        this(destinationProvider, null, null);
    }

    public SimpleWebServiceOutboundGateway(DestinationProvider destinationProvider,
            SourceExtractor<?> sourceExtractor) {
        this(destinationProvider, sourceExtractor, null);
    }

    public SimpleWebServiceOutboundGateway(DestinationProvider destinationProvider,
            SourceExtractor<?> sourceExtractor, WebServiceMessageFactory messageFactory) {
        super(destinationProvider, messageFactory);
        this.sourceExtractor = (sourceExtractor != null) ? sourceExtractor : new DefaultSourceExtractor();
    }

    public SimpleWebServiceOutboundGateway(String uri) {
        this(uri, null, null);
    }

    public SimpleWebServiceOutboundGateway(String uri, SourceExtractor<?> sourceExtractor) {
        this(uri, sourceExtractor, null);
    }

    public SimpleWebServiceOutboundGateway(String uri, SourceExtractor<?> sourceExtractor,
            WebServiceMessageFactory messageFactory) {
        super(uri, messageFactory);
        this.sourceExtractor = (sourceExtractor != null) ? sourceExtractor : new DefaultSourceExtractor();
    }

    /**
     * A flag to return the whole {@link WebServiceMessage} or build
     * {@code payload} based on {@link WebServiceMessage}
     * and populated headers according {@code headerMapper} configuration.
     * Defaults to extract payload.
     * @param extractPayload build payload or return a whole {@link WebServiceMessage}
     * @since 5.0
     */
    public void setExtractPayload(boolean extractPayload) {
        this.extractPayload = extractPayload;
    }

    @Override
    public String getComponentType() {
        return "ws:outbound-gateway(simple)";
    }

    @Override
    protected Object doHandle(String uri, final Message<?> requestMessage,
            final WebServiceMessageCallback requestCallback) {
        Object requestPayload = requestMessage.getPayload();
        Result responseResultInstance = null;
        if (requestPayload instanceof String) {
            responseResultInstance = new StringResult();
        } else if (requestPayload instanceof Document) {
            responseResultInstance = new DOMResult();
        }
        return getWebServiceTemplate().sendAndReceive(uri,
                new SimpleRequestMessageCallback(requestCallback, requestMessage),
                new SimpleResponseMessageExtractor(responseResultInstance));
    }

    private final class SimpleRequestMessageCallback extends RequestMessageCallback {

        SimpleRequestMessageCallback(WebServiceMessageCallback requestCallback, Message<?> requestMessage) {
            super(requestCallback, requestMessage);
        }

        @Override
        public void doWithMessageInternal(WebServiceMessage message, Object payload)
                throws IOException, TransformerException {
            Source source = this.extractSource(payload);
            transform(source, message.getPayloadResult());
            if (message instanceof MimeMessage && payload instanceof MimeMessage) {
                copyAttachments((MimeMessage) payload, (MimeMessage) message);
            }
        }

        private Source extractSource(Object requestPayload) throws IOException, TransformerException {
            Source source = null;

            if (requestPayload instanceof Source) {
                source = (Source) requestPayload;
                Object o = SimpleWebServiceOutboundGateway.this.sourceExtractor.extractData(source);
                Assert.isInstanceOf(Source.class, o);
                source = (Source) o;
            } else if (requestPayload instanceof String) {
                source = new StringSource((String) requestPayload);
            } else if (requestPayload instanceof Document) {
                source = new DOMSource((Document) requestPayload);
            } else if (requestPayload instanceof WebServiceMessage) {
                source = ((WebServiceMessage) requestPayload).getPayloadSource();
            } else {
                throw new MessagingException("Unsupported payload type '" + requestPayload.getClass() + "'. "
                        + this.getClass().getName() + " only supports 'java.lang.String', '"
                        + Source.class.getName() + "', '" + Document.class.getName() + "' and '"
                        + WebServiceMessage.class.getName() + "'. " + "Consider either using the '"
                        + MarshallingWebServiceOutboundGateway.class.getName() + "' or a Message Transformer.");
            }

            return source;
        }

        private void copyAttachments(MimeMessage source, MimeMessage target) {
            for (Iterator<Attachment> attachments = source.getAttachments(); attachments.hasNext();) {
                Attachment attachment = attachments.next();
                target.addAttachment(attachment.getContentId(), attachment.getDataHandler());
            }
        }

    }

    private final class SimpleResponseMessageExtractor extends ResponseMessageExtractor {

        private final Result result;

        SimpleResponseMessageExtractor(Result result) {
            super();
            this.result = result;
        }

        @Override
        public Object doExtractData(WebServiceMessage message) throws IOException, TransformerException {
            if (!SimpleWebServiceOutboundGateway.this.extractPayload) {
                return message;
            } else {
                Source payloadSource = message.getPayloadSource();

                if (payloadSource != null && this.result != null) {
                    this.transform(payloadSource, this.result);
                    if (this.result instanceof StringResult) {
                        return this.result.toString();
                    } else if (this.result instanceof DOMResult) {
                        return ((DOMResult) this.result).getNode();
                    } else {
                        return this.result;
                    }
                }

                return payloadSource;
            }
        }

    }

    private static class DefaultSourceExtractor extends TransformerObjectSupport
            implements SourceExtractor<DOMSource> {

        DefaultSourceExtractor() {
            super();
        }

        @Override
        public DOMSource extractData(Source source) throws IOException, TransformerException {
            if (source instanceof DOMSource) {
                return (DOMSource) source;
            }
            DOMResult result = new DOMResult();
            this.transform(source, result);
            return new DOMSource(result.getNode());
        }

    }

}