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



19 comments:

  1. Hello,

    I tried this example but get many errors, I think because of missing dependencies. Could you please upload or send me a working example?

    Thank you :)

    ReplyDelete
    Replies
    1. Hi
      You can find all dependency jars from $CARBON_HOME/repository/components/plugins as well. Add this folder to class path if you have not got the dependency jars from online maven repo

      Thanks

      Delete
  2. I am having an issue creating the AuthenticationAdminStub as it requires an org.apache.axis2.context.ConfigurationContext as a parameter. How do you instantiate the config context?

    ReplyDelete
    Replies
    1. You can set a null value for ConfigurationContext. Please note that There should be a constructor without ConfigurationContext parameter too.

      Delete
  3. How can I secure a thrift service using Identity server and then authenticate a user using RemoteUserStoreManagerServiceStub. After authenticating a user i wish to use the given session id for corresponding access.

    ReplyDelete
  4. AuthenticationAdmin service is not listed by getting a list of services in Wso2 DAS (by giving listAdminServices command in osgi console). But still I can use that service and I can't understand why. If that service is available, why is it not listed there?

    ReplyDelete
  5. Thanks Nuwan, it's interesting example how to invoke services from java client. I have few questions, the dependencies you mentioned doesn't exist in maven repo. I added the jars from /repository/components/plugins folder and tried running the client but haven't succeeded. It's a jar version conflict I believe, I added axiom-api and axiom-impl dependencies but no luck still getting below error. I would appreciate your help

    Exception in thread "main" java.lang.NoSuchMethodError: org.apache.axiom.om.OMXMLBuilderFactory.createSOAPModelBuilder(Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/axiom/om/OMXMLParserWrapper;

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Hi Biniam,

    Adding below repositories will resolve the dependencies.

    http://maven.wso2.org/nexus/content/repositories/releases/
    http://maven.wso2.org/nexus/content/groups/wso2-public/

    I have already updated the repository in pom file in this post. Please refer the pom file configuration

    Thanks,
    Nuwanw

    ReplyDelete
    Replies
    1. Hi Nuwan, thanks for a quick reply. The dependency issue is resolved and I am able to login and get the session cookie, but can not get the list of service names because of data binding issues (Caused by: org.apache.axis2.databinding.ADBException: Unexpected subelement). I have been researching about it, it seems a common problem. I have tried different things like changing parameter order of serviceAdminStub.listServices("ALL", "*", 0) because some posts suggested that but no luck yet.

      Login Successful
      JSESSIONID=98BADD187A3E72E7A927CA42C581946B; Path=/; Secure=null; HttpOnly=null
      org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement {http://mgt.service.carbon.wso2.org/xsd}CAppArtifact
      at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430)
      at org.wso2.carbon.service.mgt.stub.ServiceAdminStub.fromOM(ServiceAdminStub.java:12981)
      at org.wso2.carbon.service.mgt.stub.ServiceAdminStub.listServices(ServiceAdminStub.java:8219)
      at com.test.dss.JavaClient.ServiceAdminClient.listServices(ServiceAdminClient.java:36)
      at com.test.dss.JavaClient.ListServices.main(ListServices.java:24)
      Caused by: java.lang.Exception: org.apache.axis2.databinding.ADBException: Unexpected subelement {http://mgt.service.carbon.wso2.org/xsd}CAppArtifact
      at org.wso2.carbon.service.mgt.stub.types.carbon.ServiceMetaData$Factory.parse(ServiceMetaData.java:2857)
      at org.wso2.carbon.service.mgt.stub.types.carbon.ServiceMetaDataWrapper$Factory.parse(ServiceMetaDataWrapper.java:1053)
      at org.wso2.carbon.service.mgt.stub.types.axis2.ListServicesResponse$Factory.parse(ListServicesResponse.java:417)
      at org.wso2.carbon.service.mgt.stub.ServiceAdminStub.fromOM(ServiceAdminStub.java:12898)
      ... 3 more
      Caused by: org.apache.axis2.databinding.ADBException: Unexpected subelement {http://mgt.service.carbon.wso2.org/xsd}CAppArtifact
      at org.wso2.carbon.service.mgt.stub.types.carbon.ServiceMetaData$Factory.parse(ServiceMetaData.java:2851)
      ... 6 more

      Thanks,
      Biniam

      Delete
    2. HI Biniam,

      What is the WSO2 ESB version you are trying out?
      Please check the org.wso2.carbon.service.mgt.stub version in $ESB_HOME/repository/components/plugins directory to make sure that version is the same. if not you have to use same stub version in your client

      Thanks,
      Nuwanw

      Delete
  8. Hi Nuwan,

    I am using WSO2 version 3.5.0 (wso2dss-3.5.0) and it comes with org.wso2.carbon.authenticator.stub.4.4.2, org.wso2.carbon.service.mgt.stub_4.5.3.jar and 1.6.1.wso2v15. I couldn't find the org.wso2.carbon.service.mgt.stub_4.5.3, the latest version in nexus is 4.2.0, so I manually added it in the class path from $ESB_HOME/repository/components/plugins and it worked. Thanks for your help.

    I am trying to use java client to create data service by just passing the required parameters, like sql query, input mapping, output mapping and so on.. the DataServiceAdminStub has methods to save/edit dataservice. But I don't know how to pass the input/output parameters.

    saveDataService(String serviceName, String serviceGroup, String serviceContents)

    Is it possible to use java client, instead of the UI console? Is there a sample code that I can look into?


    Thanks,
    Biniam

    ReplyDelete
  9. Hi Nuwan,

    So I was able to create data services from java client using org.wso2.carbon.dataservices.ui.beans.* and to generate org.wso2.carbon.dataservices.ui.DataServiceAdminClient the dbs file. now I am working on retrieving the datasources using org.wso2.carbon.ndatasource.ui.NDataSourceAdminServiceClient but again there is jar conflict the nexus repository doesn't seem to have the latest dependencies that are part of wso2dss-3.5.0. I am manually adding in the class path, I would want to add them as maven dependencies like below but the latest dependency is 4.2.3.


    org.wso2.carbon
    org.wso2.carbon.ndatasource.ui
    4.4.8


    Thanks,
    Biniam

    ReplyDelete
  10. Hi Biniam

    Great to hear that you have solved your issue.

    We have changed the groupId in ndatasource.ui from org.wso2.carbon to org.wso2.carbon.commons. Please use the org.wso2.carbon.commons as the maven dependency groupId as bellow. It will get resolved.

    org.wso2.carbon.commons
    org.wso2.carbon.ndatasource.ui
    4.4.8

    Thanks,
    Nuwanw

    ReplyDelete
  11. Hi Nuwan,

    I changed the group id and it worked, how about service.mgt.stub did it get moved too? I can't find it in commons or just in org.wso2.carbon?


    org.wso2.carbon
    org.wso2.carbon.service.mgt.stub
    4.5.3


    Thanks,
    Biniam

    ReplyDelete
  12. Hi Nuwan,

    So the groupId for org.wso2.carbon.service.mgt.stub I believe is also changed to org.wso2.carbon.deployment, I was able to resolve the dependency issues for service management.


    org.wso2.carbon.deployment
    org.wso2.carbon.service.mgt.stub
    4.5.3


    But I still cant figure out a way to list all data services, as serviceAdminStub.listServices("ALL", serviceFileName, 0) will list only the first page or page number you provided.

    Thanks,
    Biniam

    ReplyDelete
  13. Hi,
    Im following a tutorial from this site http://wso2.com/library/articles/2015/02/how-to-write-a-web-application-backed-by-wso2-middleware-part-2/ im stuck. I got an error saying

    java.lang.NoSuchMethodError: org.wso2.carbon.um.ws.api.stub.RemoteUserStoreManagerServiceStub.addAnonymousOperations()

    i'm using the latest .jar file version. My jar file version is 5.2.0 and my WSO2 identity server version is 5.2.0 they are the same but still im getting this error. i can't continue to other tutorials because i dont know what will i do with this error..

    ReplyDelete
  14. Hi Nuwan,

    I couldn't find anything on WSO2 dss batching query result. I want to ideally batch into a file if the result set is huge, 100s of millions records. Is there any feature out of the box dss feature to handle big data?

    Thanks,
    Biniam

    ReplyDelete
  15. When I tried as a stand-alone java program it is working. If I use same for my web-application it is giving an error as follows:

    org.apache.axis2.AxisFault: Transport error: 302 Error: Moved Temporarily
    at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:308)
    at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:194)
    at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:451)
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:278)
    at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
    at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:398)
    at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:224)
    at org.apache.axis2.client.OperationClient.execute(OperationClient.java:149)
    at org.wso2.carbon.authenticator.stub.AuthenticationAdminStub.getAuthenticatorName(AuthenticationAdminStub.java:934)

    ReplyDelete