Search code examples
javaxsltxsdjax-rpc

ur-type with JAX-RPC or XSLT-ing the response via a Handler


So we've got ourselves a lovely vintage PHP WS we must integrate via JAX-RPC and this WS delivers some responses as follows:

 <return SOAP-ENC:arrayType="SOAP-ENC:Array[1]" xsi:type="SOAP-ENC:Array">
    <item SOAP-ENC:arrayType="xsd:ur-type[3]" xsi:type="SOAP-ENC:Array">
       <item xsi:type="xsd:string">...</item>
       <item xsi:type="xsd:float">...</item>
       <item xsi:type="xsd:int">...</item>
    </item>
 </return>

Now the problem is, JAX-RPC doesn't seem to know about ur-type

We thought about using a Handler for doing a search and replace on the the responses' XML or transforming it via XSLT so that ur-type => anyType but we can't seem to figure it out how to do it. Specifically what OutputStream / StreamResult could we use for the transformation?

Any other suggestion is more than welcomed :)


Solution

  • So if the end we gave up with our idea of using a XSLT or doing a search and replace on the raw XML.

    We're using SOAPBody to manipulate the responses' DOM and replace ur-type with anyType and everything works out just fine. Nonetheless, if you have any better idea, please do post it.

    Edit: here's how we basically did it.

    This goes in the class where you get the port, you need to register the handler where you do your search and replace:

    private TestSOAPPort getPort() {
        TestSOAPService service = new TestSOAPServiceImpl();
        try {
            registerResponseHandler(service);
            TestSOAPPort port = service.getTestSOAPPort();
            ((TestSOAPPortStub) port)._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, TestConstants.ENDPOINT_URL);
            return port;
        } catch (Exception e) {
            // ...
        }
    
        return null;
    }
    
    private void registerResponseHandler(TestSOAPService service) {
        HandlerRegistry hr = service.getHandlerRegistry();
        QName portName = new QName(TestConstants.NAMESPACE_URI, TestConstants.PORT_NAME);
        List handlerChain = hr.getHandlerChain(portName);
        HandlerInfo hi = new HandlerInfo();
        hi.setHandlerClass(TestResponseHandler.class);
        handlerChain.add(hi);
    }
    

    And this is how the handler looks like:

    import javax.xml.rpc.handler.GenericHandler;
    
    public class TestResponseHandler extends GenericHandler {
        private static final String XSD_UR_TYPE = "xsd:ur-type";
        private static final String XSD_ANY_TYPE = "xsd:anyType";
        private static final String XSD_INT_ARRAY = "xsd:int[";
        private static final String XSD_ANY_TYPE_ARRAY = "xsd:anyType[";
    
        @Override
        public boolean handleResponse(MessageContext context) {
            SOAPMessageContext smc = (SOAPMessageContext) context;
            SOAPMessage sm = smc.getMessage();
            try {
                SOAPBody sb = sm.getSOAPBody();
                handleNodes(sb.getElementsByTagName("problemTag"));
                sm.saveChanges();
            } catch (Exception e) {
                // ...
            }
    
            return super.handleResponse(context);
        }
    
        private void handleNodes(NodeList nodes) {
            // do your search and replace here
            if (nodes == null) {
                return;
            }
            for (int i = 0; i < nodes.getLength(); i++) {
                Node node = nodes.item(i);
                NamedNodeMap attributes = node.getAttributes();
                for (int j = 0; j < attributes.getLength(); j++) {
                    Node attribute = attributes.item(j);
                    if (attribute.getNodeValue().startsWith(XSD_UR_TYPE)) {
                        attribute.setNodeValue(attribute.getNodeValue().replace(XSD_UR_TYPE, XSD_ANY_TYPE));
                    } else if (attribute.getNodeValue().startsWith(XSD_INT_ARRAY)) {
                        attribute.setNodeValue(attribute.getNodeValue().replace(XSD_INT_ARRAY, XSD_ANY_TYPE_ARRAY));
                    }
                }
            }
        }
    
    }