Mark Czubin created CXF-7669:
--------------------------------

             Summary: Cxf encodes escape caracters twice in JDK9.0.5 and 
JDK8_161
                 Key: CXF-7669
                 URL: https://issues.apache.org/jira/browse/CXF-7669
             Project: CXF
          Issue Type: Bug
    Affects Versions: 3.2.2
            Reporter: Mark Czubin
         Attachments: ExampleService.wsdl

When our response text contains escape characters then those will be encoded 
twice. 

For example when I return "hello > world". Cxf will encode this as "hello 
> world".

Below a test with all the interceptors used in our setup on production: 
{code:java}
package be.vlaanderen.omgeving.rest.controller.parameter.v1;

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.binding.Binding;
import org.apache.cxf.binding.BindingFactory;
import org.apache.cxf.binding.BindingFactoryManager;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.endpoint.EndpointException;
import org.apache.cxf.endpoint.EndpointImpl;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.ExchangeImpl;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.wsdl.interceptors.BareOutInterceptor;
import org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor;
import org.apache.cxf.wsdl11.WSDLServiceFactory;
import org.junit.Test;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.TreeSet;

import static java.util.Collections.emptyList;
import static 
org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor.OUT_BUFFERING;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

public class CxfIsUnstable {
    CxfFacade cxf = new CxfFacade();

    @Test
    public void 
givenAResponseWithAmpersans_whenMarshallingToXml_theAmpersandAreEncoded_onlyOnce()
 throws Exception {
        cxf.setupExampleService();

        String request = cxf.demarshallRequest("<request>hello &amp; 
world</request>");
        assertThat(request).isEqualTo("hello & world");

        String responseXml = cxf.marshallResponse("hello & world");
        assertThat(responseXml).isEqualTo("<response>hello &amp; 
world<</response>");
    }

    static class CxfFacade {
        private final SAAJOutInterceptor saajOutInterceptor = new 
SAAJOutInterceptor();
        private final BareOutInterceptor outInterceptor = new 
BareOutInterceptor();
        private final DocLiteralInInterceptor inInterceptor = new 
DocLiteralInInterceptor();
        private SoapMessage message;

        private List<Object> messageContents;

        public String demarshallRequest(String input) throws XMLStreamException 
{
            message.setContent(XMLStreamReader.class, 
XMLInputFactory.newInstance().createXMLStreamReader(new 
ByteArrayInputStream(input.getBytes())));
            
StaxUtils.skipToStartOfElement(message.getContent(XMLStreamReader.class));

            inInterceptor.handleMessage(message);

            assertThat(message.getContent(Exception.class)).isNull();
            messageContents = message.getContent(List.class);
            String requestContent = (String) messageContents.get(0);

            saajOutInterceptor.handleMessage(message);
            return requestContent;
        }

        public String marshallResponse(String responseBody) throws Exception {
            messageContents.set(0, responseBody);

            ByteArrayOutputStream boas = new ByteArrayOutputStream();
            XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
            XMLStreamWriter output = 
xmlOutputFactory.createXMLStreamWriter(boas);
            message.setContent(XMLStreamWriter.class, output);
            message.put(OUT_BUFFERING, "true");
            outInterceptor.handleMessage(message);
            output.flush();
            boas.flush();

            return boas.toString();
        }

        public void setupExampleService() throws JAXBException, 
EndpointException {
            Bus bus = BusFactory.newInstance().createBus();
            BindingFactoryManager bfm = 
bus.getExtension(BindingFactoryManager.class);
            BindingFactory bf = mock(BindingFactory.class);
            Binding binding = mock(Binding.class);

            given(bf.createBinding(null)).willReturn(binding);
            given(binding.getInFaultInterceptors()).willReturn(emptyList());
            given(binding.getOutFaultInterceptors()).willReturn(emptyList());

            bfm.registerBindingFactory("http://schemas.xmlsoap.org/wsdl/soap/";, 
bf);
            String ns = "http://webservice.example-V1.vlaanderen.be";;

            WSDLServiceFactory factory = new WSDLServiceFactory(bus, 
"classpath:/files/ExampleService.wsdl");

            Service service = factory.create();
            service.setDataBinding(new 
JAXBDataBinding(JAXBContext.newInstance()));

            EndpointInfo endpointInfo = service.getEndpointInfo(new QName(ns, 
"exampleServicePort"));
            EndpointImpl endpoint = new EndpointImpl(bus, service, 
endpointInfo);

            BindingOperationInfo operation = 
endpointInfo.getBinding().getOperation(new QName(ns, "example"));
            
operation.getOperationInfo().getInput().getMessagePartByIndex(0).setTypeClass(String.class);

            message = new SoapMessage(new MessageImpl());
            Exchange exchange = new ExchangeImpl();
            message.setExchange(exchange);
            message.setInterceptorChain(new PhaseInterceptorChain(new 
TreeSet<>()));

            exchange.put(Service.class, service);
            exchange.put(Endpoint.class, endpoint);
            exchange.put(Binding.class, endpoint.getBinding());
        }
    }
}
{code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to