[ https://issues.apache.org/jira/browse/CXF-7669?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16394876#comment-16394876 ]
Freeman Fang commented on CXF-7669: ----------------------------------- Hi Mark, Please ensure the way you create JAXBDatabinding in your testcase should be {code} JAXBDataBinding databinding = new JAXBDataBinding(JAXBContext.newInstance()); databinding.setEscapeHandler(null); service.setDataBinding(databinding); {code} The JAXB impl in JDK9 and latest JDK8 version introduce an EscapeHandler in com.sun.xml.internal.bind.v2.runtime.output.XMLStreamWriterOutput.text which break for your testcase. It should be the NoEscapeHandler used here. Freeman > 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 > Assignee: Freeman Fang > Priority: Critical > 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" > {code:java} > hello &> world{code} > > 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 & > world</request>"); > assertThat(request).isEqualTo("hello & world"); > String responseXml = cxf.marshallResponse("hello & world"); > assertThat(responseXml).isEqualTo("<response>hello & > 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)