Thursday, August 28, 2014

iOS - short note, how to change view of tabs in UiTabBarController

for (UINavigationController * nav in self.tabBarController.viewControllers) {


        [nav.tabBarItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:


                                                [UIColor grayColor],


                                                NSForegroundColorAttributeName,


                                                [UIFont systemFontOfSize:12], NSFontAttributeName,


                                                nil]


                                      forState:UIControlStateNormal];


        [nav.tabBarItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:


                                                [UIColor colorWithRed:0.0 green:122/255.0 blue:1.0 alpha:1], NSForegroundColorAttributeName,


                                                [UIFont systemFontOfSize:14], NSFontAttributeName,


                                                nil]


                                      forState:UIControlStateSelected];



    }

Monday, August 4, 2014

How to force change jboss class loader method 2

In my previous post there is the first method where you can force jboss to isolate class loader of your web app from server class loader. Here what happen is before adding jars in server classpath, jboss will search jars in your web app classpath. If matching jars or duplicating jars found jboss will give priority to the jars found in your web app’s classpath.


So to achieve this the first method is create an entry in jboss-web.xml which is the jboss specific deployment descriptor. The second method is creating a separate xml file “jboss-classloading.xml” in your app’s “WEB-INF” folder and add the class loading instructions in that file. An example is given below.


<classloading xmlns=”urn:jboss:classloading:1.0”
            name=”MyAPP.war”
            domain=”MyAPP_domain”
            parent-domain=”this is optional”
            parent-first=”false”
            export-all=”NON_EMPTY”
            import-all=”true”>
</classloading>


***** parent daomain is optional.

JBOSS EAP 5.1.2 & Sun Metro JAX-WS

Jboss does have their own web service implementation which is JBossWS-CXF, based out of Apache CXF. But if you are into JAX-WS metro stack you can simply use it with jboss.


1. Overide the class loader to load SUN Metro stack instead jboss supplied jax-ws version.


create “jboss-web.xml” file in “WEB-INF” folder with following content.


<?xml version=”1.0” encoding=”UTF-8”?>
<jboss-web>
    <context-root>/MyApp</context-root>
    <class-loading java2ClassLoadingCompliance=”false”>
        <loader-repository>
            org.myapp:loader=MyApp.war
            <loader-repository-config>
                java2ParentDelegation=false
            </loader-repository-config>
        </loader-repository>
    </class-loading>
</jboss-web>



2. Add WSServletContextListener listner to web.xml file


<listener>
       <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
  </listener>



3. Add servlet and servlet mapping for WSServlet


<servlet>
    <servlet-name>WSServlet</servlet-name>
    <servlet-class>
            com.sun.xml.ws.transport.http.servlet.WSServlet
        </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>WSServlet</servlet-name>
    <url-pattern>/*</url-pattern>
   <!—  <url-pattern>/services/*</url-pattern> —>
  </servlet-mapping>



You may now get your web service not only work but dynamic WSDL creation also working.

Wednesday, July 23, 2014

WSO2 IS SAML SSO using openSAML java library

In this blog post i will explain how to write a sample SSO service provider code using wso2is as the identity provider and openSAML as the supporting library to create SAML request.


First download the wso2IS from [1] and openSAML release from [2]. Then startup the wso2is. Create a new java web application project and import below jars from opensaml lib and lib/endorsed folders.


    serializer-2.10.0
    xalan-2.7.1
    xercesImpl-2.10.0
    xml-apis-2.10.0
    xmltooling-1.4.1
    xmlsec-1.5.6
    slf4j-api-1.7.5
    openws-1.5.1
    opensaml-2.6.1
    joda-time-2.2
    esapi-2.0.1
    commons-lang-2.6


Also include “axiom-api.jar” from apache axis project which has the UIDGenerator.java class.


Lets take our service provider name is “test.com” & our consumer landing page is “http://localhost:8080/test.com/home.jsp”. (You have to register a new service provider with above fields in wso2 identity server. To do so please refer [3] )


You can use below code to sent login & logout saml requests.




import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.common.SAMLVersion;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.LogoutRequest;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.NameIDPolicy;
import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.saml2.core.RequestedAuthnContext;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.SessionIndex;
import org.opensaml.saml2.core.impl.AuthnContextClassRefBuilder;
import org.opensaml.saml2.core.impl.AuthnRequestBuilder;
import org.opensaml.saml2.core.impl.IssuerBuilder;
import org.opensaml.saml2.core.impl.LogoutRequestBuilder;
import org.opensaml.saml2.core.impl.NameIDBuilder;
import org.opensaml.saml2.core.impl.NameIDPolicyBuilder;
import org.opensaml.saml2.core.impl.RequestedAuthnContextBuilder;
import org.opensaml.saml2.core.impl.SessionIndexBuilder;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.XMLObjectBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.io.UnmarshallingException;
import org.opensaml.xml.util.Base64;
import org.opensaml.xml.util.XMLHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

public class SAMLConsumer {
    
    private static final Logger logger = LoggerFactory.getLogger(SAMLConsumer.class);
    private static boolean isBootstraped = false;

    private static final String ISSUER_URL = “test.com”;
    private static final String CONSUMER_URL = “http://localhost:8080/test.com/home.jsp”;

    private static final String NAME_SPACE_URI_ISSUER = “urn:oasis:names:tc:SAML:2.0:assertion”;
    private static final String NAME_SPACE_URI_AUTH = “urn:oasis:names:tc:SAML:2.0:protocol”;
    private static final String SAML_TRANSPORT_TYPE_PWD_PROTECTED = “urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport”;
    private static final String SAML_TRANSPORT_PROTOCOL_BINDING = “urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST”;
    
    private static final String LOCAL_NAME_ISSUER = “Issuer”;
    private static final String LOCAL_NAME_AUTHRQ = “AuthnRequest”;
    private static final String NAME_SPACE_PREFIX = “samlp”;
    private static final String AUTH_CNTXT_REF = “AuthnContextClassRef”;
    private static final String SAML = “saml”;
    
    public static String buildLoginRequest() throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException, MarshallingException, IOException  {
        logger.info(“started”);

        IssuerBuilder issuerBuilder = new IssuerBuilder();
        Issuer issuer = issuerBuilder.buildObject(NAME_SPACE_URI_ISSUER, LOCAL_NAME_ISSUER, “samlp”);
        issuer.setValue(ISSUER_URL);
        
        NameIDPolicyBuilder nameIdPolicyBuilder = new NameIDPolicyBuilder();
        NameIDPolicy nameIdPolicy = nameIdPolicyBuilder.buildObject();
        nameIdPolicy.setFormat(“urn:oasis:names:tc:SAML:2.0:nameid-format:persistent”);
        nameIdPolicy.setSPNameQualifier(“Isser”);
        nameIdPolicy.setAllowCreate(new Boolean(true));
        
        AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder();
        AuthnContextClassRef authnContextClassRef =
                                                    authnContextClassRefBuilder.buildObject(NAME_SPACE_URI_ISSUER,
                                                            AUTH_CNTXT_REF, SAML);
        authnContextClassRef.setAuthnContextClassRef(SAML_TRANSPORT_TYPE_PWD_PROTECTED);
        
        RequestedAuthnContextBuilder requestedAuthnContextBuilder =
                                                        new RequestedAuthnContextBuilder();
        RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject();
        requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
        requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef);
        
        DateTime issueInstant = new DateTime();
        AuthnRequestBuilder authnRequestBuilder = new AuthnRequestBuilder();
        AuthnRequest authnRequest = authnRequestBuilder.buildObject(NAME_SPACE_URI_AUTH, LOCAL_NAME_AUTHRQ, NAME_SPACE_PREFIX);
        authnRequest.setForceAuthn(new Boolean(false));
        authnRequest.setIsPassive(new Boolean(false));
        authnRequest.setIssueInstant(issueInstant);
        authnRequest.setProtocolBinding(SAML_TRANSPORT_PROTOCOL_BINDING);
        authnRequest.setAssertionConsumerServiceURL(CONSUMER_URL);
        authnRequest.setIssuer(issuer);
        authnRequest.setNameIDPolicy(nameIdPolicy);
        authnRequest.setRequestedAuthnContext(requestedAuthnContext);
        
        String authReqRandomId = Integer.toHexString(new Double(Math.random()).intValue());
        
        authnRequest.setID(authReqRandomId);
        authnRequest.setVersion(SAMLVersion.VERSION_20);
                
        return marshall(authnRequest);
        
    }
    
    public static String buildLogoutRequest(String user) throws MarshallingException, IOException {

        LogoutRequest logoutReq = new LogoutRequestBuilder().buildObject();

        logoutReq.setID(createID());

        DateTime issueInstant = new DateTime();
        logoutReq.setIssueInstant(issueInstant);
        logoutReq.setNotOnOrAfter(new DateTime(issueInstant.getMillis() + 5 * 60 * 1000));

        IssuerBuilder issuerBuilder = new IssuerBuilder();
        Issuer issuer = issuerBuilder.buildObject();
        issuer.setValue(ISSUER_URL);
        logoutReq.setIssuer(issuer);

        NameID nameId = new NameIDBuilder().buildObject();
        nameId.setFormat(“urn:oasis:names:tc:SAML:2.0:nameid-format:entity”);
        nameId.setValue(user);
        logoutReq.setNameID(nameId);

        SessionIndex sessionIndex = new SessionIndexBuilder().buildObject();
        sessionIndex.setSessionIndex(UIDGenerator.generateUID());
        logoutReq.getSessionIndexes().add(sessionIndex);

        logoutReq.setReason(“Single Logout”);

        return marshall(logoutReq);
    }
    
    private static String marshall(RequestAbstractType authnRequest) throws MarshallingException, IOException {
        doBootstrap();
        Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(authnRequest);
        Element authDOM = marshaller.marshall(authnRequest);
        
        
        StringWriter rspWrt = new StringWriter();
        XMLHelper.writeNode(authDOM, rspWrt);
        String requestMessage = rspWrt.toString();
        
        System.out.println(requestMessage);
                 
        Deflater deflater = new Deflater(Deflater.DEFLATED, true);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
        deflaterOutputStream.write(requestMessage.getBytes());
        deflaterOutputStream.close();
                 
        /* Encoding the compressed message */
        String encodedRequestMessage = Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES);
        String encodedAuthnRequest = URLEncoder.encode(encodedRequestMessage,”UTF-8”).trim();;
        
        return encodedAuthnRequest;
    }
    
    
    public static <T> T createSAMLObject(final Class<T> clazz) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
         XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
        
         QName defaultElementName = (QName)clazz.getDeclaredField(“DEFAULT_ELEMENT_NAME”).get(null);
         Map<QName, XMLObjectBuilder> builderMap= builderFactory.getBuilders();
         System.out.println(“is nul “  + builderMap.get(defaultElementName));
        
        return null;
    }
    
    private static void doBootstrap() {
        if(!isBootstraped) {
            try {
                DefaultBootstrap.bootstrap();
                isBootstraped = true;
            } catch (ConfigurationException e) {
                logger.error(“Error calling bootstrap”, e);
            }
        }
    }
    
    public static Map<String, String> processResponse(String response) {

        XMLObject resp = null;
        
        try {
            resp = unmarshall(response);
        } catch (ConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnmarshallingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return getResult(resp);
        
    }
    
    private static XMLObject unmarshall(String responseMessage) throws ConfigurationException,
                            ParserConfigurationException, SAXException, IOException, UnmarshallingException {
        
        doBootstrap();
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
        
        byte[] base64DecodedResponse = Base64.decode(responseMessage.trim());
        
        System.out.println(new String(base64DecodedResponse));
        
        ByteArrayInputStream is = new ByteArrayInputStream(base64DecodedResponse);
        
        Document document = docBuilder.parse(is);
        Element element = document.getDocumentElement();
        UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
        Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(element);
        return unmarshaller.unmarshall(element);
        
    }
    
    private static Map<String, String> getResult(XMLObject responseXmlObj) {

        if (responseXmlObj.getDOM().getNodeName().equals(“saml2p:LogoutResponse”)) {
            logger.error(“user logout”);
            return null;
        }

        Response response = (Response) responseXmlObj;
        logger.info(“SAML resp” + response);

        Assertion assertion = response.getAssertions().get(0);
        Map<String, String> resutls = new HashMap<String, String>();

        /*
         * If the request has failed, the IDP shouldn’t send an assertion.
         * SSO profile spec 4.1.4.2 <Response> Usage
         */
        if (assertion != null) {

            String subject = assertion.getSubject().getNameID().getValue();
            resutls.put(“Subject”, subject); // get the subject

            List<AttributeStatement> attributeStatementList = assertion.getAttributeStatements();

            if (attributeStatementList != null) {
                // we have received attributes of user
                Iterator<AttributeStatement> attribStatIter = attributeStatementList.iterator();
                while (attribStatIter.hasNext()) {
                    AttributeStatement statment = attribStatIter.next();
                    List<Attribute> attributesList = statment.getAttributes();
                    Iterator<Attribute> attributesIter = attributesList.iterator();
                    while (attributesIter.hasNext()) {
                        Attribute attrib = attributesIter.next();
                        Element value = attrib.getAttributeValues().get(0).getDOM();
                        String attribValue = value.getTextContent();
                        resutls.put(attrib.getName(), attribValue);
                    }
                }
            }
        }
        return resutls;
    }
    
    public static String createID() {

        byte[] bytes = new byte[20]; // 160 bit
        
        new Random().nextBytes(bytes);
        
        char[] charMapping = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’, ‘p’};

        char[] chars = new char[40];

        for (int i = 0; i < bytes.length; i++) {
            int left = (bytes[i] » 4) & 0x0f;
            int right = bytes[i] & 0x0f;
            chars[i * 2] = charMapping[left];
            chars[i * 2 + 1] = charMapping[right];
        }

        return String.valueOf(chars);
    }
    
}




[1] http://wso2.com/products/identity-server/


[2] https://wiki.shibboleth.net/confluence/display/OpenSAML/Home


[3] http://pavithramadurangi.blogspot.com/2013/09/saml-20-sso-with-wso2-is-450.html

Wednesday, March 19, 2014

WSO2 esb JSON proxy REST API SAMPLE

<?xml version=”1.0” encoding=”UTF-8”?>
<api xmlns=”http://ws.apache.org/ns/synapse”
     name=”SelfcareMobile”
     context=”/a/b”>
   <resource methods=”POST” url-mapping=”/c/*”>
      <inSequence>
         <property name=”messageType”
                   value=”application/json”
                   scope=”axis2”
                   type=”STRING”/>
         <property name=”contentType”
                   value=”application/json”
                   scope=”axis2”
                   type=”STRING”/>
         <log level=”full”/>
         <send>
            <endpoint>
               <http format=”rest”
                     method=”post”
                     uri-template=”YOUR_BACK_END_URL”/>
            </endpoint>
         </send>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
   </resource>


</api>



*** URL-mapping


Lets say our external url (which we give to outside )will be “http://www.mysite.com/a/b/c/someservice” and back end service will be “http://yourip:port/something/c/someservice" .


Then our url context for the api will be “/a/b”. Which means what has the url pattern of “/a/b” should go into this API.


url-mapping will be “/c/*” which meas what ever has “/c” and after what ever string should use the given resource.


Last not least, our endpoint address should be like below. (note “uri-template” which is the back end address of the real REST service.



<http format=”rest”
                     method=”post”
                     uri-template=”http://yourip:port/something”/>


Yeah you see it right, we ommit the “/c/someservice" part from real back end url because when we tell to url-mapping in the resource tag it will put that part and append it to the uri-template to determine the final destination.

Tuesday, December 17, 2013

WSO2 ESB - sample REST to REST API configuration

<api xmlns=”http://ws.apache.org/ns/synapse” name=”TestApi” context=”/helloWorld”>
   <resource methods=”GET” url-mapping=”/hello”>
      <inSequence>
         <property name=”ContentType” value=”text/xml” scope=”axis2” type=”STRING”/>
         <switch source=”$axis2:HTTP_METHOD”>
            <case regex=”GET”>
               <property name=”HTTP_METHOD” value=”GET” scope=”axis2” type=”STRING”/>
            </case>
            <case regex=”POST”>
               <property name=”HTTP_METHOD” value=”POST” scope=”axis2” type=”STRING”/>
            </case>
            <default/>
         </switch>
         <log/>
         <send>
            <endpoint>
               <address uri=”http://localhost:8080/HelloRestFul” format=”pox”/>
            </endpoint>
         </send>
      </inSequence>
      <outSequence>
         <log/>
         <send/>
      </outSequence>
   </resource>
</api>
                       

Thursday, December 5, 2013

WSO2 ESB exposing Web Service Proxy to a TCP client PART 2 : Sending batch responses from ESB to TCP server

In my last post regarding how to expose a web service for a TCP client we have discussed about retrieving a request in plain text format from a TCP client, convert it to SOAP message and send to the back end webservice.


In that post I have mentioned that according to our implementation we did not need to send the response back to the TCP client immediately due to that our responses are not synchronous.


So what we did to achieve this asynchronous status is converting the ESB it self to a TCP client and send the responses as batches to a TCP server.


So in this article I am going to explain how to use the WSO2 ESB as a TCP client where we needed to convert the XML responses to delimited string sequences before sending to TCP server.



To convert the XML file to delimited string sequence we have used the smooks mediator. (Refer the smooks configuration below)


In above example we are converting a xml file that has an entity called “Login”. Each login element has three child elements.


Freemarker tool has been used to convert the XML elements to text fields and delimit two values.


<smooks-resource-list xmlns=”http://www.milyn.org/xsd/smooks-1.1.xsd” xmlns:ftl=”http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd” xmlns:core=”http://www.milyn.org/xsd/smooks/smooks-core-1.3.xsd” xmlns:file=”http://www.milyn.org/xsd/smooks/file-routing-1.1.xsd”>
      <core:filterSettings type=”SAX” defaultSerialization=”false”/>
      <resource-config selector=”//batchTransfer/returnVal/login”>
         <resource>org.milyn.delivery.DomModelCreator</resource>
      </resource-config>
      <ftl:freemarker applyOnElement=”login”>
         <ftl:template>${.vars[“login”].id},${.vars[“login”].password},${.vars[“login”].userName}
           </ftl:template>
      </ftl:freemarker>
   </smooks-resource-list>


Save above smooks configuration as a Local XML entry.


Then to send a batch of responses to ESB from our back end, we have created a dummy web service proxy inside ESB. This dummy web service connect to the TCP server, thus the TCP server now acts as the back end. Also we have hand written a WSDL and expose that hand written WSDL through the ESB. This way we can configure what kind or SOAP structure accept by this dummy proxy web service and then convert the XML resides within that proxy and then send those converted text to the back end TCP server.


Below is the WSDL which we hand written for the above “Login batch response” example.


<wsdl:definitions xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/” xmlns:tns=”com.mobitel.test” name=”test” targetNamespace=”com.mobitel.test”>
      <wsdl:types>
         <xsd:schema targetNamespace=”com.mobitel.test”>
            <xsd:element name=”batchTransfer” type=”tns:batchTransfer”/>
            <xsd:element name=”batchTransferResponse” type=”tns:batchTransferResponse”/>
            <xsd:complexType name=”batchTransfer”>
               <xsd:sequence>
                  <xsd:element name=”returnVal” type=”tns:logins”/>
               </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name=”logins”>
               <xsd:sequence>
                  <xsd:element name=”login” type=”tns:login” nillable=”true” minOccurs=”0” maxOccurs=”unbounded”/>
               </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name=”login”>
               <xsd:sequence>
                  <xsd:element name=”id” type=”xsd:int”/>
                  <xsd:element name=”password” type=”xsd:string”/>
                  <xsd:element name=”userName” type=”xsd:string”/>
               </xsd:sequence>
            </xsd:complexType>
            <xsd:complexType name=”batchTransferResponse”/>
         </xsd:schema>
      </wsdl:types>
      <wsdl:message name=”batchTransferRequest”>
         <wsdl:part element=”tns:batchTransfer” name=”parameters”/>
      </wsdl:message>
      <wsdl:message name=”batchTransferResponse”>
         <wsdl:part element=”tns:batchTransferResponse” name=”parameters”/>
      </wsdl:message>
      <wsdl:portType name=”test”>
         <wsdl:operation name=”batchTransfer”>
            <wsdl:input message=”tns:batchTransferRequest”/>
            <wsdl:output message=”tns:batchTransferResponse”/>
         </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name=”testSOAP” type=”tns:test”>
         <soap:binding style=”document” transport=”http://schemas.xmlsoap.org/soap/http”/>
         <wsdl:operation name=”batchTransfer”>
            <soap:operation soapAction=”com.mobitel.test/NewOperation”/>
            <wsdl:input>
               <soap:body use=”literal”/>
            </wsdl:input>
            <wsdl:output>
               <soap:body use=”literal”/>
            </wsdl:output>
         </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name=”test”>
         <wsdl:port binding=”tns:testSOAP” name=”testSOAP”>
            <soap:address location=”http://localhost:8282/services/TcpOutput”/>
         </wsdl:port>
      </wsdl:service>
   </wsdl:definitions>


This way the user of this dummy web service can create a web service client by using the above WSDl expose from WSO2 ESB’s dummy proxy service. Also the details such as back end is TCP can be hidden from the user.


Below is the dummy proxy for the “Login batch response” example.


<?xml version=”1.0” encoding=”UTF-8”?>
<proxy xmlns=”http://ws.apache.org/ns/synapse”
       name=”TcpOutput”
       transports=”https,http,tcp”
       statistics=”disable”
       trace=”disable”
       startOnLoad=”true”>
   <target>
      <inSequence>
         <log level=”full”/>
         <smooks config-key=”smooksXMLToText”>
            <input type=”xml”/>
            <output type=”text”/>
         </smooks>
         <log level=”full”/>
         <property name=”CONTENT_TYPE”
                   value=”text/plain”
                   scope=”axis2”
                   type=”STRING”/>
         <property name=”OUT_ONLY” value=”true” scope=”default” type=”STRING”/>
         <send>
            <endpoint>
               <address uri=”tcp://localhost:9448”/>
            </endpoint>
         </send>
         <property name=”FORCE_SC_ACCEPTED”
                   value=”true”
                   scope=”axis2”
                   type=”STRING”/>
      </inSequence>
      <outSequence>
         <send>
            <endpoint>
               <default/>
            </endpoint>
         </send>
      </outSequence>
   </target>
   <publishWSDL key=”testOutPutWsdl”/>
   <description/>
</proxy>
                               


Here we have used 3 properties ( please refer the proxy xml above)


1. <property name=”CONTENT_TYPE” value=”text/plain”               scope=”axis2” type=”STRING”/>   


This will tell ESB that the output to back end will be “text/plain”. We needed this because our TCP server accept only text formate.


2. <property name=”OUT_ONLY” value=”true” scope=”default” type=”STRING”/>


This will tell ESB that this proxy does not send a response or simply do not need a out sequence. Though we defined empty outsequance tag we does not expect web service client to wait for a response from back end TCP server.


3. <property name=”FORCE_SC_ACCEPTED” value=”true”                 scope=”axis2” type=”STRING”/>


Add this property just after the SEND mediator. We use this property to send a HTTP 202 ( no content ) response to the web service client to avoid it wait for response.


Also please note that in our dummy proxy web service we have enabled all the http,https,tcp transport types because in our proxy we retrieve the “batch response” request via HTTP or HTTPS and we use TCP to transport that “batch response” request to TCP server.



(Special thanks goes to Lalaji Sureshika from WSO2)