Sunday, February 17, 2013

How to send http messages to jms endpoint using WSO2 ESB

WSO2 ESB can route incomming messages to various endpoint type. This blog shows how to configure esb http proxy service to send incomming messages to jms queue.

Download WSO2 ESB and  ActiveMQ.  ActiveMQ is used as the jms broker.

Uncomment following configuration from axis2.xml to enable jms transport in WSO2 ESB. axis2.xml can be found in $WSO2_ESB_HOME/repository/axis2.aml or repository/axis2/axis2.xml

Copy below jars

activemq-core-5.7.0.jar
geronimo-j2ee-management_1.1_spec-1.0.1.jar
geronimo-jms_1.1_spec-1.1.1.jar

to $WSO2_ESB_HOME/repository/components/lib. Those jar file can be found from $ActiveMQ_HOME/lib directory

<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">  
     <parameter name="myTopicConnectionFactory" locked="false">  
          <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>  
          <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>  
          <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">TopicConnectionFactory</parameter>  
           <parameter name="transport.jms.ConnectionFactoryType" locked="false">topic</parameter>  
     </parameter>  
     <parameter name="myQueueConnectionFactory" locked="false">  
          <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>  
          <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>  
          <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>  
           <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>  
     </parameter>  
     <parameter name="default" locked="false">  
          <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>  
          <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>  
          <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>  
           <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>  
     </parameter>  
   </transportReceiver>  

 <transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender"/>

Start jms broker(./activemq console) and create  a queue named TestQueue(go to http://0.0.0.0:8161/admin/).

Then Start WSO2 ESB Server(./wso2server.sh) and create a proxy service and a endpoint from bellow configuration

<proxy name="proxyWithJmsEndpoint" transports="https http" startOnLoad="true" trace="disable">  
     <target endpoint="jmsEndpoint">  
       <inSequence>  
         <property name="OUT_ONLY" value="true"/>  
         <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>  
       </inSequence>  
       <outSequence>  
         <drop/>  
       </outSequence>  
     </target>  
   </proxy>  


<endpoint name="jmsEndpoint">  
     <address uri="jms:/TestQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&amp;java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&amp;java.naming.provider.url=tcp://127.0.0.1:61616&amp;transport.jms.DestinationType=queue" format="pox"/>  
   </endpoint>  

In endpoint, uri format is pox. so it remove the soap envelop and send actual payload. It is useful for REST Services. If you want to send SOAP messages to queue remove format.

Now We have finished the configuration. Since this is a one-way message, the property “OUT_ONLY” is set to true and “FORCE_SC_ACCEPTED” property is defined to send a 202 response to the client who invokes this proxy.

 once you send a SOAP messages via http transport to above proxy service, It will send the messages to TestQueue. 



Sunday, February 10, 2013

How to remove or set empty value to HTTP header SOAPAction on outgoing message in WSO2 ESB

When you invoke a web service, there is a HTTP header called SOAPAction which keeps the value of service operation name. if you want to remove or set empty value for SOAPAction within your proxy service, following configuration in your proxy configuration can do it. Both header and property mediators are required.

To set empty string to SOAPAction


<header name="Action" value="" />  
<property name="SOAPAction" scope="transport" value="" /> 

Then out put will be:
 POST /services/SimpleStockQuoteService HTTP/1.1  
 Content-Type: text/xml; charset=UTF-8  
 Accept-Encoding: gzip,deflate  
 SOAPAction:   
 TransformationSequence: s1  
 Transfer-Encoding: chunked  
 Host: 127.0.0.1:9000 

To remove SOAPAction

<header name="Action" action="remove" />  
<property name="SOAPAction" scope="transport" action="remove" />  

Then out put will be:

 POST /services/SimpleStockQuoteService HTTP/1.1  
 Content-Type: text/xml; charset=UTF-8  
 Accept-Encoding: gzip,deflate  
 TransformationSequence: s1  
 Transfer-Encoding: chunked  
 Host: 127.0.0.1:9000 

if you want to change the SOAPAction value, header mediator can do this.

<header name="Action" value="newAction" /> 

Then out put will be:

 POST /services/SimpleStockQuoteService HTTP/1.1  
 Content-Type: text/xml; charset=UTF-8  
 Accept-Encoding: gzip,deflate  
 TransformationSequence: s1  
 SOAPAction: "newAction"  
 Transfer-Encoding: chunked  
 Host: 127.0.0.1:9000  





Saturday, February 2, 2013

Invoking WSO2 Carbon Admin Services using Service Stub

This blog will help you to understand you how to invoke a WSO2 Carbon product functionality from your own client.

In WSO2 products we use client server architecture within our servers.
Any functionality available to you via WSO2 Carbon management console can also be invoked via a web service call.Those calls are called Admin Services calls.

There are three component we can see in our products to provides a particular service.

1) Service component - which provide actual service
2) UI Component  - which provide the web user interface to provide the service
3) Service Stub  -  Interface to invoke the service generated from the service WSDL.

You can find those component in $CARBON_HOME/repository/components/plugins folder

 In this example,  see how to list the deployed services in wso2esb-4.6.0.















To invoke an admin service you have to authenticate user first. then get the session cookie and invoke the services you want.

for this example we have to use two service stub classes for authentication and service listing. the relevant service stubs components as bellow.

You can resolve all the dependency by adding following maven dependency or by adding class path to plugins directory

  <dependencies>  
     <dependency>  
       <groupId>org.wso2.carbon</groupId>  
       <artifactId>org.wso2.carbon.authenticator.stub</artifactId>  
       <version>4.0.0</version>    
     </dependency>  
     <dependency>  
       <groupId>org.wso2.carbon</groupId>  
       <artifactId>org.wso2.carbon.service.mgt.stub</artifactId>  
       <version>4.0.0</version>  
     </dependency>  
     <dependency>  
       <groupId>org.apache.axis2.wso2</groupId>  
       <artifactId>axis2-client</artifactId>  
       <version>1.6.1.wso2v5</version>  
     </dependency>  
   </dependencies> 
 
<repositories>
        <repository>
            <id>wso2.releases</id>
            <name>WSO2 internal Repository</name>
            <url>http://maven.wso2.org/nexus/content/repositories/releases/</url>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>daily</updatePolicy>
                <checksumPolicy>ignore</checksumPolicy>
            </releases>
        </repository>
        <repository>
            <id>wso2-nexus</id>
            <name>WSO2 internal Repository</name>
            <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
            <releases>
                <enabled>true</enabled>
                <updatePolicy>daily</updatePolicy>
                <checksumPolicy>ignore</checksumPolicy>
            </releases>
        </repository>
    </repositories> 


Client code for Authenticate user and get the session cookie

import org.apache.axis2.AxisFault;  
 import org.apache.axis2.transport.http.HTTPConstants;  
 import org.wso2.carbon.authenticator.stub.AuthenticationAdminStub;  
 import org.wso2.carbon.authenticator.stub.LoginAuthenticationExceptionException;  
 import org.wso2.carbon.authenticator.stub.LogoutAuthenticationExceptionException;  
 import org.apache.axis2.context.ServiceContext;  
 import java.rmi.RemoteException;  
   
 public class LoginAdminServiceClient {  
   private final String serviceName = "AuthenticationAdmin";  
     private AuthenticationAdminStub authenticationAdminStub;  
     private String endPoint;  
   
     public LoginAdminServiceClient(String backEndUrl) throws AxisFault {  
       this.endPoint = backEndUrl + "/services/" + serviceName;  
       authenticationAdminStub = new AuthenticationAdminStub(endPoint);  
     }  
   
     public String authenticate(String userName, String password) throws RemoteException,  
                                       LoginAuthenticationExceptionException {  
   
       String sessionCookie = null;  
   
       if (authenticationAdminStub.login(userName, password, "localhost")) {  
         System.out.println("Login Successful");  
   
         ServiceContext serviceContext = authenticationAdminStub.  
             _getServiceClient().getLastOperationContext().getServiceContext();  
         sessionCookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);  
         System.out.println(sessionCookie);  
       }  
   
       return sessionCookie;  
     }  
   
     public void logOut() throws RemoteException, LogoutAuthenticationExceptionException {  
       authenticationAdminStub.logout();  
     }  
 }  


One of the important this is that you need to figure out the service end point url that you wish to invoke. Service management service name is "ServiceAdmin". to get the service name, find the service component in plugins directory and there is a file named service.xml in META-INF directory in the bundle. It contains the service information

service end point url is like , https://localhost:9443/services/ServiceAdmin

import org.apache.axis2.AxisFault;  
 import org.apache.axis2.client.Options;  
 import org.apache.axis2.client.ServiceClient;  
 import org.wso2.carbon.service.mgt.stub.ServiceAdminStub;  
 import org.wso2.carbon.service.mgt.stub.types.carbon.ServiceMetaDataWrapper;  
 import java.rmi.RemoteException;  
   
 public class ServiceAdminClient {  
   private final String serviceName = "ServiceAdmin";  
   private ServiceAdminStub serviceAdminStub;  
   private String endPoint;  
   
   public ServiceAdminClient(String backEndUrl, String sessionCookie) throws AxisFault {  
     this.endPoint = backEndUrl + "/services/" + serviceName;  
     serviceAdminStub = new ServiceAdminStub(endPoint);  
     //Authenticate Your stub from sessionCooke  
     ServiceClient serviceClient;  
     Options option;  
   
     serviceClient = serviceAdminStub._getServiceClient();  
     option = serviceClient.getOptions();  
     option.setManageSession(true);  
     option.setProperty(org.apache.axis2.transport.http.HTTPConstants.COOKIE_STRING, sessionCookie);  
   }  
   
   public void deleteService(String[] serviceGroup) throws RemoteException {  
     serviceAdminStub.deleteServiceGroups(serviceGroup);  
   
   }  
   
   public ServiceMetaDataWrapper listServices() throws RemoteException {  
     return serviceAdminStub.listServices("ALL", "*", 0);  
   }  
 }  


to list services


import org.wso2.carbon.authenticator.stub.LoginAuthenticationExceptionException;  
 import org.wso2.carbon.authenticator.stub.LogoutAuthenticationExceptionException;  
 import org.wso2.carbon.service.mgt.stub.types.carbon.ServiceMetaData;  
 import org.wso2.carbon.service.mgt.stub.types.carbon.ServiceMetaDataWrapper;  
   
 import java.rmi.RemoteException;  
   
 public class ListServices {  
   public static void main(String[] args)  
       throws RemoteException, LoginAuthenticationExceptionException,  
           LogoutAuthenticationExceptionException {  
     System.setProperty("javax.net.ssl.trustStore", "$ESB_HOME/repository/resources/security/wso2carbon.jks");  
     System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");  
     System.setProperty("javax.net.ssl.trustStoreType", "JKS");  
     String backEndUrl = "https://localhost:9443";  
   
     LoginAdminServiceClient login = new LoginAdminServiceClient(backEndUrl);  
     String session = login.authenticate("admin", "admin");  
     ServiceAdminClient serviceAdminClient = new ServiceAdminClient(backEndUrl, session);  
     ServiceMetaDataWrapper serviceList = serviceAdminClient.listServices();  
     System.out.println("Service Names:");  
     for (ServiceMetaData serviceData : serviceList.getServices()) {  
       System.out.println(serviceData.getName());  
     }  
   
     login.logOut();  
   }  
 }  

out put will be
Login Successful  
 JSESSIONID=64F29C9EE6ACEA2A0DA596FB97DCC278; Path=/; Secure=null; HttpOnly=null  
 Service Names:  
 echo  
 Version  
 wso2carbon-sts  

like this example , any admin service can be invoked using service stub