Search code examples
web-servicesproxyoracle11goracle-adfjdeveloper

How to prevent < converted to &lt; when using web service proxy class in JDeveloper


I am calling a BPM web service that sends HTML email. I generated a web service proxy in JDeveloper 11.1.1.7. The type of the body of the email is xsd:string which should map to java String. I understand that certain characters, for example < > &, are reserved and converted during the xml document creation during the proxy operation.

Using SOAPUI to call the service, I can pass the body as <h1>My Heading</h1> and service responds correctly, sending the email with HTML as expected. When doing the same from a POJO that calls the proxy, <h1> is converted to &lt;h1&gt;My heading&lt;/h1&gt;.

I have tried passing the body as a CDATA section but this makes no difference. I have tried converting the body to bytes then back to a UTF-8 string before the call but still no difference. I have access to the BPM service code. Is there a way I can send html to the service from a proxy, that retains the special characters?


Solution

  • I figured this out finally. While the JDeveloper web service proxy generator is useful most of the time, in this case it was not since I needed to send xml special characters to the service. Perhaps there is a way to manipulate the proxy code to do what you want but I couldn't figure it out.

    Of particular help was this AMIS blog entry. And if you ever need to handle special characters during JAXB marshalling, this entry will help you too. A great summary of the steps to use the java URLConnection class is here and that answer points to a library that would probably make life even easier.

    So here is the raw wrapper code below. The particular BPM email service we wrote also writes to a log and that explains the complex types in the raw xml input. Naturally I will populate the email values from a passed in POJO object in the main sendMail wrapper method.

    package com.yourdomain.sendmail.methods;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLConnection;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Scanner;
    
    import oracle.adf.model.connection.url.URLConnectionProxy;
    import oracle.adf.share.ADFContext;
    
    
    public class SendMailWrapper {
    
    public SendMailWrapper() {
        super();
    }
    
    public static void main(String[] args) throws MalformedURLException, IOException {
        SendMailWrapper w = new SendMailWrapper();
        w.sendMail();
    }
    
    public void sendMail() throws MalformedURLException, IOException {
        String xmlInput =
            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
            "xmlns:sen=\"http://xmlns.oracle.com/bpmn/bpmnProcess/SendEmailProcess\" " +
            "xmlns:ema=\"http://www.wft.com/BPM/SendEmail/Email\">\n" +
            "<soapenv:Header/>" +
            "<soapenv:Body>\n" +
            "<sen:start>\n" +
                "<ema:emailInput>\n" +
                    "<ema:emailContent>\n" +
                        "<ema:toAddr>your.name@yourdomain.com</ema:toAddr>\n" +
                        "<ema:fromAddr></ema:fromAddr>\n" +
                        "<ema:ccAddr></ema:ccAddr>\n" +
                        "<ema:bccAddr></ema:bccAddr>\n" +
                        "<ema:subject>SendMail HTML</ema:subject>\n" +
                        "<ema:body><h1>My Heading</h1><p>Text</p></ema:body>\n" +
                        "<ema:contentType>text/html</ema:contentType>\n" +
                    "</ema:emailContent>\n" +
                    "<ema:emailHistory>\n" +
                        "<ema:projectName>Soap Test</ema:projectName>\n" +
                        "<ema:reqID></ema:reqID>\n" +
                        "<ema:compositeID></ema:compositeID>\n" +
                        "<ema:processID></ema:processID>\n" +
                        "<ema:processName></ema:processName>\n" +
                        "<ema:activityName></ema:activityName>\n" +
                        "<ema:insertDate></ema:insertDate>\n" +
                        "<ema:insertByID></ema:insertByID>\n" +
                        "<ema:insertByName></ema:insertByName>\n" +
                        "<ema:commentType></ema:commentType>\n" +
                        "<ema:commentInfo></ema:commentInfo>\n" +
                    "</ema:emailHistory>\n" +
                 "</ema:emailInput>\n" +
            "</sen:start>\n" +
            "</soapenv:Body>\n" +
            "</soapenv:Envelope>\n";
    
        System.out.println(xmlInput);
    
        String wsURL = getWsdlUrl();
        URL url = new URL(wsURL);
        URLConnection connection = url.openConnection();
        HttpURLConnection httpConn = (HttpURLConnection)connection;
    
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] buffer = new byte[xmlInput.length()];
        buffer = xmlInput.getBytes();
        bout.write(buffer);
        byte[] b = bout.toByteArray();
        String SOAPAction = "start"; //this is the method in the service
        httpConn.setRequestProperty("Content-Length", String.valueOf(b.length));
        httpConn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
    
        //some other props available but don't need to be set...
        //httpConn.setRequestProperty("Accept-Encoding", "gzip,deflate");
        //httpConn.setRequestProperty("Host", "your.host.com:80");
        //httpConn.setRequestProperty("Connection", "Keep-Alive");
        //httpConn.setRequestProperty("User-Agent", "Apache-HttpClient/4.1.1 (java 1.5)");
    
        httpConn.setRequestProperty("SOAPAction", SOAPAction);
        httpConn.setRequestMethod("POST");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);
    
        OutputStream out = httpConn.getOutputStream();
        out.write(b);
        out.close();
    
        //check response code...
        int status = httpConn.getResponseCode();
        String respMessage = httpConn.getResponseMessage();
        System.out.println("RESPONSE CODE: " + status + " RESPONSE MESSAGE: " + respMessage);
    
        //check response headers...
        for (Map.Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
            System.out.println(header.getKey() + "=" + header.getValue());
        }
    
        //check error stream - this helps alot when debugging...
        InputStream errorStream = ((HttpURLConnection)connection).getErrorStream();
        if (errorStream != null) {
            System.out.println("Error Stream: " + convertStreamToString(errorStream));
        }
    
        //if there was an expected response, you need to parse it...
        /* String responseString = "";
        String outputString = "";
        InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
        BufferedReader in = new BufferedReader(isr);
        while ((responseString = in.readLine()) != null) {
            outputString = outputString + responseString;
        }
        isr.close();
        System.out.println("OUT: " + outputString); */
    }
    
    static String convertStreamToString(InputStream is) {
        Scanner s = new Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
    
    private static String getWsdlUrl() {
        String result = null;
    
        try {
            URLConnectionProxy wsConnection = (URLConnectionProxy)ADFContext.getCurrent().getConnectionsContext().lookup("SendMailProxyConnection");
            result = wsConnection.getURL().toExternalForm();
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return result;
    }
    

    }

    Happy coding.