How to avoid web application deployment faliures due to deployment listener class loading issue. - WSO2 Application Server

WSO2 Application server can be use to deploy web applications and services. For some advance use cases we might need to handle deployment tasks and post deployment tasks. There can be listeners defined globally in repository/conf/tomcat/web.xml to achieve this as follows.

<listener>
  <listener-class>com.test.task.handler.DeployEventGenerator</listener-class>
</listener>



When we deploy web application to WSO2 Application Server sometimes class loading environment can be changed. To fix this we can deploy the webapp with "Carbon" class loading environment. For some use cases we are shipping CXF/Spring dependencies within the web application so any class loader environment other than "CXF" might fail. 

To fix this we need to add file named webapp-classloading.xml to META-INF. Then content should be as follows.

<Classloading xmlns="http://wso2.org/projects/as/classloading">
   <Environments>Carbon</Environments>
</Classloading>

How to avoid dipatching Admin service calls to ELB services - WSO2 ELB

We can front WSO2 services by WSO2 ELB. If we have this kind of deployment all requests to services should route through WSO2 ELB. Some scenarios we might need to invoke admin services deployed in servers through ELB. If you send request to some of back end servers admin service load balancer will try to find that service it self. To avoid that we need to define different service path. So admin services in ELB can access through defined service path and other services will not mix up with it.

For this Then we can change ELB's service context to /elbservices/. Edit  servicePath property in axis2.xml as follows.

<parameter name="servicePath">elbservices</parameter>

How to retrive property and process/iterate them in synapse using xpath and script mediator - WSO2 ESB

Sometimes we need to retrieve properties and manipulate them according to custom requirement. For this i can suggest you two approaches.



01. Retrieve roles list and fetch them using script mediator.
//Store Roles into message context
 <property name="ComingRoles" expression="get-property('transport','ROLES')"/>

//Or you can you following if property is already set to default message context
 <property name="ComingRoles" expression="get-property(''ROLES')"/>


//process them inside script mediator
<script language="js">
            var rolelist = mc.getProperty('ComingRoles');
//Process rolelist and set roles or required data to message context as follows. Here we set same role set
            mc.setProperty('processedRoles',rolelist);
</script>
 <log>
            <property name="Processed Roles List" expression="get-property('processedRoles')"/>
</log>





02. Retrieve roles list and fetch them using xpath support provided.
//Retrive incoming role list
  <property name="ComingRoles" expression="get-property('transport','ROLES')"/>

//Or you can you following if property is already set to default message context
 <property name="ComingRoles" expression="get-property(''ROLES')"/>

//Fetch roles one by one using xpath operations
         <property name="Role1"
                   expression="fn:substring-before(get-property('ComingRoles'),',')"/>
         <property name="RemainingRoles"
                   expression="fn:substring-after(get-property('transport','ROLES'),',')"/>

//Fetch roles one by one using xpath operations
         <property name="Role2"
                   expression="fn:substring-before(get-property('RemainingRoles'),',')"/>
         <property name="RemainingRoles"
                   expression="fn:substring-after(get-property('RemainingRoles'),',')"/>

//Fetch roles one by one using xpath operations
         <property name="Role3" expression="(get-property('RemainingRoles'))"/>

//Then log all properties using log mediator
         <log>
            <property name="testing" expression="get-property('Role1')"/>
         </log>
         <log>
            <property name="testing" expression="get-property('Role2')"/>
         </log>
         <log>
            <property name="testing" expression="get-property('Role3')"/>
         </log>

//Check whether roles list having String "sanjeewa". If so we will set isRolesListHavingSanjeewa as true else its false.
         <log>
            <property name="isRolesListHavingSanjeewa"
                      expression="fn:contains(get-property('transport','ROLES'),'sanjeewa')"/>
         </log>


You will find xpath expressions and sample here(http://www.w3schools.com/xpath/xpath_functions.asp)

Trust all hosts when send https request – How to avoid SSL error when we connect https service

Sometimes when we write client applications we might need to communicate with services exposed over SSL. Some scenarios we might need to skip certificate check from client side. This is bit risky but if we know server and we can trust it we can skip certificate check. Also we can skip host name verification. So basically we are going to trust all certs. See following sample code.

//Connect to Https service     
HttpsURLConnection  conHttps = (HttpsURLConnection) new URL(urlVal).openConnection();
                conHttps.setRequestMethod("HEAD");
                //We will skip host name verification as this is just testing endpoint. This verification skip
                //will be limited only for this connection
                conHttps.setHostnameVerifier(DO_NOT_VERIFY);
                //call trust all hosts method then we will trust all certs
                trustAllHosts();
                if (conHttps.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    return "success";

               }
//Required utility methods
static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

private static void trustAllHosts() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

        public void checkClientTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
    } };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

How to skip Host name verification when we do http request over SSL

 

Sometimes we need to skip host name verification when we do Https call to external server. Most of the cases you will get error saying host name verification failed. In such cases we should implement host name verifier and  return true from verify method.  See following sample code.

HttpsURLConnection conHttps = (HttpsURLConnection) new URL(urlVal).openConnection();

conHttps.setRequestMethod("HEAD");

//We will skip host name verification as this is just testing endpoint. This verification skip

//will be limited only for this connection

conHttps.setHostnameVerifier(DO_NOT_VERIFY);

if (conHttps.getResponseCode() == HttpURLConnection.HTTP_OK) {

//Connection was successful

}

static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {

public boolean verify(String hostname, SSLSession session) {

            return true;

        }

  };

How to build and access message body from custom handler – WSO2 API Manager

From API Manager 1.3.0 onward we will be using pass-through transport inside API Manager. Normally in passthrough we do not build message body. When we use pass-through you need to build message inside handler to access message body. But please note that this is bit costly operations when we compare it with the default mediation. Actually we introduced pass-through transport to improve performance of gateway. There we do not build or touch message body. Add followings to your handler to see message body.

 

Add following dependency to your handler implementation project


       <dependency>
           <groupId>org.apache.synapse</groupId>
           <artifactId>synapse-nhttp-transport</artifactId>
           <version>2.1.2-wso2v5</version>
       </dependency>


Then import RelayUtils to handler as follows.
import org.apache.synapse.transport.passthru.util.RelayUtils;

Then build message before process message body as follows(add try catch blocks when needed).
RelayUtils.buildMessage(((Axis2MessageContext)messageContext).getAxis2MessageContext());


Then you will be able to access message body as follows.
<soapenv:Body><test>sanjeewa</test></soapenv:Body>

How to clear token cache in gateway nodes – API Manager 1.7.0 distributed deployment

 

In API Manager deployments we need to clear gateway cache when we regenerate application tokens from API store user interface(or calling revoke API).  So we added new configuration for that in API Manager 1.7.0. Lets see how we can apply it and use.

01. If we generate new application access token from ui old tokens remain as active in gateway cache.

02. If we use revoke API deployed in gateway it will clear only super tenants cache.

To address these issues recently we introduced new parameter named RevokeAPIURL. In distributed deployment we need to configure this parameter in API key manager node. Then it will call API pointed by RevokeAPIURL parameter. RevokeAPIURL parameter should be pointed to revoke API deployed API gateway node. If it is gateway clustered we can point to one node. So from this release(1.7.0) on ward all revoke requests will route to oauth service through revoke API deployed in API manager. When revoke response route through revoke API cache clear handler will invoke. Then it will extract relevant information form transport headers and clear associated cache entries. In distributed deployment we should configure followings.

01. In key manager node, point gateway API revoke end point as follows.

<!-- This the API URL for revoke API. When we revoke tokens revoke requests should go through this

             API deployed in API gateway. Then it will do cache invalidations related to revoked tokens.

    In distributed deployment we should configure this property in key manager node by pointing

    gateway https url. Also please note that we should point gateway revoke service to key manager-->

<RevokeAPIURL>https://${carbon.local.ip}:${https.nio.port}/revoke</RevokeAPIURL>

02. In API gateway revoke API should be pointed to oauth application deployed in key manager node.

  <api name="_WSO2AMRevokeAPI_" context="/revoke">

        <resource methods="POST" url-mapping="/*" faultSequence="_token_fault_">

            <inSequence>

                <send>

                    <endpoint>

                        <address uri="https://keymgt.wso2.com:9445/oauth2/revoke"/>

                    </endpoint>

                </send>

            </inSequence>

            <outSequence>

                <send/>

            </outSequence>

        </resource>

        <handlers>

            <handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerCacheExtensionHandler"/>

        </handlers>

    </api>

Empowering the Future of API Management: Unveiling the Journey of WSO2 API Platform for Kubernetes (APK) Project and the Anticipated Alpha Release

  Introduction In the ever-evolving realm of API management, our journey embarked on the APK project eight months ago, and now, with great a...