Saturday, March 28, 2015

Logging for Jax-RS webapps.

1. Add logs to custom log file using java logging API.

i) Define a logging.peroperties file (sample file in webapp https://github.com/ajithnv/blog_resources/blob/master/webapp-logging/jaxrs_basic/src/main/conf/logging.properties) property description http://developer.classpath.org/doc/java/util/logging/FileHandler.html

handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
#Log file name in home directory(GNU)
java.util.logging.FileHandler.pattern=%h/jaxrs_basic%u.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

#Size of the log file
java.util.logging.FileHandler.limit=500000

#Number of log file
java.util.logging.FileHandler.count=1

#Append logs to original file without creating new one
java.util.logging.FileHandler.append=true

ii. You need to add this file (logging.peroperties) to WEB-INF/classes location inside the war file.(This is configured in pom.xml file in sample webapp https://github.com/ajithnv/blog_resources/blob/master/webapp-logging/jaxrs_basic/pom.xml )

2. Add logs to wso2carbon.log file (If deployed on WSO2  Server ).

i. Copy the log4j.properties file to war file (WEB-INF/classes) which can be found in <server_home>repository/conf

3.  Initialize the logger.
//This it to write to logs to external file
 private static Logger customLog = Logger.getLogger(CustomerService.class.getName());
//This us to write to logs to wso2carbon.log file
private static final Log wso2Log = LogFactory.getLog(CustomerService.class);
4. Java Imports required.
import java.util.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 @GET
    @Path("/customers/{id}/")
    public Customer getCustomer(@PathParam("id") String id) {
        System.out.println("----invoking getCustomer, Customer id is: " + id);

        customLog.info("get customer information for " + id);
        wso2Log.info("get customer information for "+ id);

        long idNumber = Long.parseLong(id);
        Customer c = customers.get(idNumber);
        return c;
    } 
(https://github.com/ajithnv/blog_resources/blob/master/webapp-logging/jaxrs_basic/src/main/java/demo/jaxrs/server/CustomerService.java)

5. Build the war file using maven and deploy. (Eg: WSO2 Application Server).

6. Invoke the sample REST service using curl
curl -X  GET "http://localhost:9763/jaxrs_basic/services/customers/customerservice/customers/123"
7. You can find the logs in following locations.

i) wso2carbon.log (wso2_server/repository/log/wso2carbon.log)
ii) jaxrs_basic0.log (created in home dir)
iii) Start up console





Thursday, March 26, 2015

Connect WSO2 server to PostgreSQL

I'm going to install PostgreSQL in Ubuntu machine and connect WSO2 API manager 1.8.0.

1. Install PostgreSQL.
sudo apt-get install -y postgresql postgresql-contrib
2. Open the postgresql.conf  file (/etc/postgresql/9.3/main/postgresql.conf ) and change the listen_addresses.
listen_addresses = 'localhost'
3. Logged to the  PostgreSQL.
sudo -u postgres psql
4. Create a user(eg : vajira/vajira123).
CREATE USER <user_name> WITH PASSWORD '<password>';
5. Create a database (eg: wso2carbon_db).
CREATE DATABASE <database_name>;
6. Grant permission to for user for that database.
GRANT ALL PRIVILEGES ON DATABASE <database_name> to <user_name>;
7. Open the pg_hba.conf file (/etc/postgresql/9.3/main/pg_hba.conf) and change the peer authentication to md5. (using the peer authentication only the operating system user can login to the database)
# TYPE     DATABASE USER ADDRESS METHOD

    local      all                all                        peer
8.  Restart the PostgreSQL.
sudo service postgresql restart
9. Run the script to create registry and user manager database.
psql -U vajira -d wso2carbon_db -a -f wso2am-1.8.0/dbscripts/postgresql.sql
7. Logged in to the database.
psql -U <user_name> -d <database_name> -h 127.0.0.1
8. Use the following command to view the table list of wso2carbon_db.
\dt
8. Download the jdbc driver https://jdbc.postgresql.org/download.html and copy to <server_home>/repository/components/lib.

9. Open the master-datasources.xml  file (server_home/repository/conf/datasources/master-datasources.xml) and the change the data source configuration as bellow.
<datasource>
            <name>WSO2_CARBON_DB</name>
            <description>The datasource used for registry and user manager</description>
            <jndiConfig>
                <name>jdbc/WSO2CarbonDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:postgresql://localhost:5432/wso2carbon_db</url>
                    <username>vajira</username>
                    <password>vajira123</password>
                    <driverClassName>org.postgresql.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource> 

9. Start the server.
10. Using same steps you can create other databases in   PostgreSQL.

11. You can use pgAdmin PostgreSQL tool to connect to databse.



Friday, March 13, 2015

Add registry permisson for roles using admin service - WSO2 products.

You can use the ResourceAdminService to perform that task.

i) Open the carbon.xml and enable the WSDL view for admin services.
 <HideAdminServiceWSDLs>false</HideAdminServiceWSDLs>
ii) Use the following WSDL endpoint to generate the SoapUI project.

 https://localhost:9443/services/ResourceAdminService?wsdl

Select the "addRolePermission" request.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://services.resource.registry.carbon.wso2.org">
   <soap:Header/>
   <soap:Body>
      <ser:addRolePermission>
         <!--Optional:-->
         <ser:pathToAuthorize>?</ser:pathToAuthorize>
         <!--Optional:-->
         <ser:roleToAuthorize>?</ser:roleToAuthorize>
         <!--Optional:-->
         <ser:actionToAuthorize>?</ser:actionToAuthorize>
         <!--Optional:-->
         <ser:permissionType>?</ser:permissionType>
      </ser:addRolePermission>
   </soap:Body>
</soap:Envelope> 

pathToAuthorize    - The registry path that need to set permissions.
roleToAuthorize     - Role name that need to authorize
actionToAuthorize - This can be following values

 2 - READ
 3 - WRITE
 4 - DELETE
 5 - AUTHORIZE

permissionType - This can be following valies

 1 - Allowed
 2 - Denied




[WSO2 ESB] Aggregate two REST responses

There are two mock APIs (ListUsersAPI and UserRolesAPI).

 1. ListUsersAPI
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse" name="ListUsersAPI" context="/services/users">
   <resource methods="GET" url-mapping="/*">
      <inSequence>
         <payloadFactory media-type="json">
            <format>{     "persons":{        "person":[           {              "Id":"1",            "givenName":"ajith",            "lastName":"vitharana",            "age":"25",            "contactInfos":[                 {                    "InfoId":"1",                  "department":"1",                  "contactType":"email",                  "value":"ajith@abc.org"               },               {                    "InfoId":"2",                  "department":"1",                  "contactType":"mobile",                  "value":"111111111"               },               {                    "InfoId":"3",                  "department":"1",                  "contactType":"home",                  "value":"Magic Dr,USA"               }            ]         },         {              "Id":"2",            "givenName":"shammi",            "lastName":"jagasingha",            "age":"30",            "contactInfos":[                 {                    "InfoId":"1",                  "department":"1",                  "contactType":"email",                  "value":"shammi@abc.org"               },               {                  "InfoId":"2",                  "department":"1",                  "contactType":"mobile",                  "value":"2222222222"               },               {                    "InfoId":"3",                  "department":"1",                  "contactType":"home",                  "value":"Magic Dr,USA"               }            ]         }      ]   }}</format>
            <args />
         </payloadFactory>
         <property name="NO_ENTITY_BODY" scope="axis2" action="remove" />
         <property name="messageType" value="application/json" scope="axis2" type="STRING" />
         <respond />
      </inSequence>
   </resource>
</api>
Sample output.
curl -X GET  http://localhost:8280/services/users
{  
   "persons":{  
      "person":[  
         {  
            "Id":"1",
            "givenName":"ajith",
            "lastName":"vitharana",
            "age":"25",
            "contactInfos":[  
               {  
                  "InfoId":"1",
                  "department":"1",
                  "contactType":"email",
                  "value":"ajith@abc.org"
               },
               {  
                  "InfoId":"2",
                  "department":"1",
                  "contactType":"mobile",
                  "value":"111111111"
               },
               {  
                  "InfoId":"3",
                  "department":"1",
                  "contactType":"home",
                  "value":"Magic Dr,USA"
               }
            ]
         },
         {  
            "Id":"2",
            "givenName":"shammi",
            "lastName":"jagasingha",
            "age":"30",
            "contactInfos":[  
               {  
                  "InfoId":"1",
                  "department":"1",
                  "contactType":"email",
                  "value":"shammi@abc.org"
               },
               {  
                  "InfoId":"2",
                  "department":"1",
                  "contactType":"mobile",
                  "value":"2222222222"
               },
               {  
                  "InfoId":"3",
                  "department":"1",
                  "contactType":"home",
                  "value":"Magic Dr,USA"
               }
            ]
         }
      ]
   }
}
2. UserRolesAPI
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse"
     name="UserRolesAPI"
     context="/services/roles">
   <resource methods="GET" uri-template="/{personid}">
      <inSequence>
         <filter source="get-property('uri.var.personid')" regex="1">
            <then>
               <payloadFactory media-type="json">
                  <format>{     "Id":1,   "roles":[        {           "roleId":1,         "personKey":1,         "role":"Deverloper"      },      {           "roleId":2,         "personKey":1,         "role":"Engineer"      }   ]}</format>
                  <args/>
               </payloadFactory>
               <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
               <property name="messageType"
                         value="application/json"
                         scope="axis2"
                         type="STRING"/>
               <respond/>
            </then>
         </filter>
         <filter source="get-property('uri.var.personid')" regex="2">
            <then>
               <payloadFactory media-type="json">
                  <format>{"personId": 2,"roles": [{ "personRoleId": 1, "personKey": 2, "role": "Manager" },{ "personRoleId": 2, "personKey": 2, "role": "QA" }]}</format>
                  <args/>
               </payloadFactory>
               <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
               <property name="messageType"
                         value="application/json"
                         scope="axis2"
                         type="STRING"/>
               <respond/>
            </then>
         </filter>
      </inSequence>
   </resource>
</api>
Sample output.
curl -X GET  http://localhost:8280/services/roles/1 
{  
   "Id":1,
   "roles":[  
      {  
         "roleId":1,
         "personKey":1,
         "role":"Deverloper"
      },
      {  
         "roleId":2,
         "personKey":1,
         "role":"Engineer"
      }
   ]
}

3. UserDetailsAPI is the aggregated API
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse"
     name="UserDetailsAPI"
     context="/userdetails">
   <resource methods="GET">
      <inSequence>
         <call>
            <endpoint>
               <http method="get" uri-template="http://localhost:8280/services/users"/>
            </endpoint>
         </call>
         <iterate xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  id="it1"
                  preservePayload="true"
                  attachPath="//jsonObject/persons"
                  expression="//jsonObject/persons/person">
            <target>
               <sequence>
                  <property xmlns:ns="http://org.apache.synapse/xsd"
                            name="uri.var.Id"
                            expression="$body/jsonObject/persons/person/Id"
                            scope="default"
                            type="STRING"/>
                  <property xmlns:ns="http://org.apache.synapse/xsd"
                            name="response1"
                            expression="$body//jsonObject//person"
                            scope="default"
                            type="STRING"/>
                  <call>
                     <endpoint>
                        <http method="get"
                              uri-template="http://localhost:8280/services/roles/{uri.var.Id}"/>
                     </endpoint>
                  </call>
                  <payloadFactory media-type="xml">
                     <format>
                        <combined xmlns="">                        $1$2                        </combined>
                     </format>
                     <args>
                        <arg xmlns:ns="http://org.apache.synapse/xsd"
                             evaluator="xml"
                             expression="get-property('response1')"/>
                        <arg xmlns:ns="http://org.apache.synapse/xsd"
                             evaluator="xml"
                             expression="$body//jsonObject/roles"/>
                     </args>
                  </payloadFactory>
                  <loopback/>
               </sequence>
            </target>
         </iterate>
      </inSequence>
      <outSequence>
         <property name="ECNCLOSING_ELEMENT" scope="default">
            <wrapper xmlns=""/>
         </property>
         <aggregate id="it1">
            <completeCondition>
               <messageCount min="2" max="-1"/>
            </completeCondition>
            <onComplete xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                        xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                        expression="//combined"
                        enclosingElementProperty="ECNCLOSING_ELEMENT">
               <property name="messageType"
                         value="application/json"
                         scope="axis2"
                         type="STRING"/>
               <send/>
            </onComplete>
         </aggregate>
      </outSequence>
   </resource>
</api>
Sample output
curl -X GET  http://localhost:8280/userdetails
{  
   "wrapper":{  
      "combined":[  
         {  
            "person":{  
               "Id":1,
               "givenName":"ajith",
               "lastName":"vitharana",
               "age":25,
               "contactInfos":[  
                  {  
                     "InfoId":1,
                     "department":1,
                     "contactType":"email",
                     "value":"ajith@abc.org"
                  },
                  {  
                     "InfoId":2,
                     "department":1,
                     "contactType":"mobile",
                     "value":111111111
                  },
                  {  
                     "InfoId":3,
                     "department":1,
                     "contactType":"home",
                     "value":"Magic Dr,USA"
                  }
               ]
            },
            "roles":[  
               {  
                  "roleId":1,
                  "personKey":1,
                  "role":"Deverloper"
               },
               {  
                  "roleId":2,
                  "personKey":1,
                  "role":"Engineer"
               }
            ]
         },
         {  
            "person":{  
               "Id":2,
               "givenName":"shammi",
               "lastName":"jagasingha",
               "age":30,
               "contactInfos":[  
                  {  
                     "InfoId":1,
                     "department":1,
                     "contactType":"email",
                     "value":"shammi@abc.org"
                  },
                  {  
                     "InfoId":2,
                     "department":1,
                     "contactType":"mobile",
                     "value":2222222222
                  },
                  {  
                     "InfoId":3,
                     "department":1,
                     "contactType":"home",
                     "value":"Magic Dr,USA"
                  }
               ]
            },
            "roles":[  
               {  
                  "personRoleId":1,
                  "personKey":2,
                  "role":"Manager"
               },
               {  
                  "personRoleId":2,
                  "personKey":2,
                  "role":"QA"
               }
            ]
         }
      ]
   }
}