HEADSTRONG

"I have no special talents. I am only passionately curious" - Albert Einstein.

Service Simulator for Oracle Composites

Mock Services has its serious uses.

During development phase, unavailability of third party systems, could be mitigated with Mock Services. During testing phase, Mock services can simulate Reference HTTP Services, in case of overriding Oracle SOA simulation.

Here, we will explore on One Page Mock Service Simulation program, which is simple to implement. The objective is to focus on fundamentals and extend the simulator as required.

Simulating External Systems.

The Simulator is constructed on these basic steps.


The Code Implementation for sending back the WSDL is as below.

 
 public class HTTPServer
{

    public static void main(String[] args) throws Exception
    {
		startServer();
    }

    public static void startServer() throws IOException
    {
        HttpServer server = HttpServer.create(new InetSocketAddress(11000), 0);
        server.createContext("/TestSimulator", new MyHandler());
        server.setExecutor(null);
        server.start();
    }

    static class MyHandler implements HttpHandler
    {
        @Override
        public void handle(HttpExchange t)
        {
            String url = t.getRequestURI().toString();
            String response = null;
            if (url.endsWith("WSDL") || url.endsWith("wsdl"))
            {
                String wsdlName = url.substring(url.indexOf("?") + 1);
                System.out.println(" wsdl" + wsdlName);
                try
                {
                    response = PropertyHelper.readFileasString("FilePath" + wsdlName);					
                } 
				catch (Exception ex)
                {
                    ex.printStackTrace();
                }
                try
                {
                    t.sendResponseHeaders(200, response.length());
                    OutputStream os = t.getResponseBody();
                    os.write(response.getBytes());
                    os.close();
                } 
				catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            } 
        }
}

 

In a similar fashion, we can send the responses relevant to Service in a series of if-else blocks. This completes the Service Simulation part.

Simulation of Unit Test Cases.

While Oracle SOA Suite provides the Service simulation as part of its Unit testing framework, it has limitations of supporting single request response per Service Operation (Meaning any subsequent same service operation calls from the BPEL will always return the first mock response.)

We can extend the Proxy Code above to resolve this case, wherein the HTTP Server parses the Unit Test Configuration ( The Unit Test part is detailed in this Post) and forms the sequence of wire request and responses to be sent back.

The above case is fairly straight forward for synchronous 2-way calls. However, for sending 1-way callback response we have to tweak the response SOAP Header and treat the response as separate invocation call.

The Code Snippet for simulating the Test Case Response is provided below.

 
 public class HTTPServer
{

    public static void main(String[] args) throws Exception
    {
        startServer();
    }

    public static void startServer() throws IOException
    {
        HttpServer server = HttpServer.create(new InetSocketAddress(11000), 0);
        server.createContext("/TestSimulator", new MyHandler());
        server.setExecutor(null);
        server.start();
    }

    static class MyHandler implements HttpHandler
    {
        static Map HTTPMockServices = new HashMap();

        @Override
        public void handle(HttpExchange t)
        {
            String url = t.getRequestURI().toString();
            String response = null;
            if (url.endsWith("WSDL") || url.endsWith("wsdl"))
            {
                String wsdlName = url.substring(url.indexOf("?") + 1);
                System.out.println(" wsdl" + wsdlName);
                try
                {
                    response = PropertyHelper.readFileasString("C:\\Tester\\resources\\wsdls\\" + wsdlName);
                } catch (Exception ex)
                {
                    ex.printStackTrace();
                }
                try
                {
                    t.sendResponseHeaders(200, response.length());
                    OutputStream os = t.getResponseBody();
                    os.write(response.getBytes());
                    os.close();
                } catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            } else
            {
                InputStream is = t.getRequestBody();
                Headers headers = t.getRequestHeaders();
                Set keySet = t.getRequestHeaders().keySet();
                Iterator iter = keySet.iterator();

                while (iter.hasNext())
                {
                    String key = iter.next();
                    List values = headers.get(key);
                    String s = key + " = " + values.toString() + "\n";
                    System.out.println(s);
                }

                //Print Request
                java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
                String req = s.hasNext() ? s.next() : "";
                if (null != req)
                {
                    //System.out.println("Request Received : " + req);
                }
                url = t.getRequestURI().toString();
                if (url.contains("START"))
                {
                    String testcase = url.substring(url.indexOf("=") + 1);
                    System.out.println(" Ready for TestCase  : " + testcase);

                    try
                    {
                        HTTPMockServices = populateHTTPMockServices(testcase);
                        System.out.println("Size : " + HTTPMockServices.size());
                        response = " Ready for TestCase " + testcase + " requests";
                        t.sendResponseHeaders(200, response.length());
                        OutputStream os = t.getResponseBody();
                        os.write(response.getBytes());
                        os.close();
                    } catch (Exception ex)
                    {
                        ex.printStackTrace();
                        response = " Could not retrieve TestCase " + testcase + " requests";
                    }

                } else
                {
                    try
                    {
                        System.out.println("In response loop");
                        MockServiceBean bean = selectMockService(req, HTTPMockServices);
                        System.out.println("Invocation type" + bean.getInvocationType());
                        if (null != bean.getInvocationType() && bean.getInvocationType().startsWith("1-way"))
                        {
                            sendCallBackResponse(req, bean);
                        } else
                        {
                            response = bean.getResponse();
                            if (response.contains("bpelFault"))
                            {
                                response = PropertyHelper.SOAP_FAULT_ENVELOPE_PREFIX + response + PropertyHelper.SOAP_FAULT_ENVELOPE_POSTFIX;
                                System.out.println("Response : " + response);
                                Headers h = t.getResponseHeaders();
                                h.set("Content-Type", "text/xml; charset=utf-8");
                                t.sendResponseHeaders(404, response.length());
                                OutputStream os = t.getResponseBody();
                                os.write(response.getBytes());
                                os.close();
                            } else
                            {
                                response = PropertyHelper.SOAP_ENVELOPE_PREFIX + response + PropertyHelper.SOAP_ENVELOPE_POSTFIX;
                                System.out.println("Response : " + response);
                                Headers h = t.getResponseHeaders();
                                h.set("Content-Type", "text/xml; charset=utf-8");
                                t.sendResponseHeaders(200, response.length());
                                OutputStream os = t.getResponseBody();
                                os.write(response.getBytes());
                                os.close();
                            }
                        }
                    } catch (Exception ex)
                    {
                        ex.printStackTrace();
                        response = "Error occurred while sending response";
                    }
                }
            }

        }

        private static Map populateHTTPMockServices(String testCaseName) throws IOException, SAXException
        {
            Map HTTPMockServices = new HashMap();
            GeneratorResponseBean responseBean = new GeneratorResponseBean("C:\\Tester\\output\\" + testCaseName + "_config.xml");
            List mockservices = responseBean.getMockServices();
            System.out.println("mockservices size :" + mockservices.size());
            for (MockServiceBean bean : mockservices)
            {
                System.out.println("service type :" + bean.getServiceType());
                if (bean.getServiceType().equalsIgnoreCase("HTTP"))
                {
                    HTTPMockServices.put(bean.getRequestPattern(), bean);
                }
            }
            System.out.println("HTTPMockServices Size " + HTTPMockServices.size());
            return HTTPMockServices;
        }

        private static MockServiceBean selectMockService(String req, Map map)
        {
            for (String key : map.keySet())
            {
                MockServiceBean bean = map.get(key);
                if (req.contains(key))
                {
                    return bean;
                }
            }
            return null;
        }

        private static void sendCallBackResponse(String req, MockServiceBean bean) throws MalformedURLException, IOException
        {
            System.out.println("callback request : " + req);
            int startIndex = req.indexOf(":ReplyTo>");
            String replyTo = req.substring(startIndex + 6, req.indexOf("ReplyTo>", startIndex + 8));

            int endPointIndex = replyTo.indexOf("Address>");
            String replyToEndpoint = replyTo.substring(endPointIndex + "Address>".length() , replyTo.indexOf("Address>", endPointIndex + "Address>".length() + 1));
            replyToEndpoint = replyToEndpoint.substring(0, replyToEndpoint.indexOf("<"));

            int messageIDIndex = req.indexOf("MessageID>");
            String messageID =
                req.substring((messageIDIndex + "MessageID>".length()), req.indexOf("MessageID>", messageIDIndex + "MessageID>".length() + 1));
            messageID = messageID.substring(0, messageID.indexOf("<"));
            
            StringBuffer response = new StringBuffer();
            response.append("");
            response.append("");
            response.append("" + replyToEndpoint + "");
            response.append("" + bean.getCallbackOperation() + "");
            response.append("" + messageID + "");
            response.append("" + messageID + "");
            response.append("");
            response.append("");
            response.append(bean.getResponse());
            response.append("");

            System.out.println( "Response" + response.toString() );
            SOAPClient.invoke(replyToEndpoint, response.toString(), bean.getCallbackOperation());

        }
    }
}

	 

The SOAP Client is bare bones code for sending the 1-way HTTP callbacks, as below.

 
	public static void invoke(String SOAPUrl, String request, String SOAPAction) throws MalformedURLException, IOException
    {
        /* Added for basic authentication  */
        final String username = "user";
        final String userpass = "pass";

        // Create the connection where we're going to send the file.
        URL url = new URL(SOAPUrl);
        URLConnection connection = url.openConnection();
        HttpURLConnection httpConn = (HttpURLConnection)connection;
        byte[] b = request.getBytes();

        Authenticator authenticator = new Authenticator()
        {
            public PasswordAuthentication getPasswordAuthentication()
            {
                return (new PasswordAuthentication(username, userpass.toCharArray()));
            }
        };

        Authenticator.setDefault(authenticator);
        // Set the appropriate HTTP parameters.
        httpConn.setRequestProperty("Content-Length", String.valueOf(b.length));
        httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
        httpConn.setRequestProperty("SOAPAction", SOAPAction);
        httpConn.setRequestMethod("POST");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        // Everything's set up; send the XML that was read in to b.
        OutputStream out = httpConn.getOutputStream();
        out.write(b);
        out.close();

        // Read the response and write it to standard out.
        InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
        BufferedReader in = new BufferedReader(isr);
        String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);
        in.close();

    }