Tuesday, October 30, 2012

WSO2 Ant Application Deployer

Note :  You would be able to achieve most the requirements described here using puppet scripts, which would be the ideal way of doing it. Anyway, if you are still interested, you can continue reading.

Ant application deployer is a custom deployer written to deploy an Ant script in a WSO2 Carbon based server, which will then get executed automatically. Using Ant deployer, you can deploy any artifact/jar/configuration into a carbon server using a single file.

Along with the Ant deployer, following custom tasks are also included.
  1. server
    • This can be used to shutdown/restart a local/remote Carbon Server
  2. registry
    • This can be used to insert metadata into a local/remote registry of a WSO2 server
Note : Ant application deployer should be used if and only if, Ant applications are deployed by trusted parties. Also, this shouldn't be used in a cloud environment.

Why Ant application deployer


Lets assume you have a requirement to configure an WSO2 ESB server as below.
  1. Install a set of custom mediators
  2. Deploy a set of carbon applications with sequences/registry resources which uses those custom mediators
  3. Deploy APIs and templates which cannot be included in car file at the moment
  4. Add metadata like properties, associations along with the registry resources.
Notes :  Support for APIs and templates would be added in the future, but at the moment it is not supported.

If you want to do above configurations, then you might need to follow below steps.
  1. Copy jar files
  2. Restart the server
  3. Copy carbon applications
  4. Copy APIs and templates
  5. Manually add metadata
But, using Ant deployer with its custom tasks mentioned above, you can create a single deployable artifact which does everything mentioned above using ant. Only step that you will need to do is, just to copy the all in one zip file into the relevant location. Then the Ant script in the zip file will be automatically executed and above steps would be executed.

Although above is a simple usecase, you would be able to do more cool stuff such as to configure/patch/migrate a whole carbon installation with a proper ant script.

 

Installation

  1. Copy the jar named org.wso2.carbon.extensions.antdeployer-1.0.0.jar into repository/components/dropins directory of the carbon 4.0.x based server.
  2. Restart the server

Using Ant Deployer

 

Properties


Following properties can be used within the Ant script to get the information about the server being runing.

Property Example Value
carbon.home /home/ruchira/wso2esb-4.5.0
carbon.conf /home/ruchira/wso2esb-4.5.0/repository/conf
carbon.logs /home/ruchira/wso2esb-4.5.0/repository/logs
carbon.dropins /home/ruchira/wso2esb-4.5.0/repository/components/dropins
carbon.lib /home/ruchira/wso2esb-4.5.0/repository/components/libs
carbon.repo /home/ruchira/wso2esb-4.5.0/repository/deployment/server/
carbon.tenants /home/ruchira/wso2esb-4.5.0/repository/tenants
carbon.components /home/ruchira/wso2esb-4.5.0/repository/components/plugins
carbon.tmp /home/ruchira/wso2esb-4.5.0/tmp
carbon.catalina /home/ruchira/wso2esb-4.5.0/lib/tomcat/work/Catalina

Custom Ant Tasks


server

This Ant task can be used to restart/shutdown a local/remote carbon server.
<server
        url="https://serverhost:port/services"
        username="user"
        password="pass"
        action="restart|shutdown|gracerestart|graceshutdown"
        target="t1"/>
For the action, you need to specify one of the followings
  1. shutdown
    • Discard any requests currently being processed and immediately shutdown the server.
  2. restart
    • Discard any requests currently being processed and immediately restart the server.
  3. graceshutdown
    • Stop accepting new requests, continue to process already received requests, and then shutdown the server.
  4. gracerestart
    • Stop accepting new requests, continue to process already received requests, and then restart the server.

Shutdown/restart different server
<server
        url="https://serverhost:port/services"
        username="user"
        password="pass"
        action="restart|shutdown|gracerestart|graceshutdown"/>

Shutdown/restart same server
<server target="t1" action="restart|shutdown|gracerestart|graceshutdown"/>
When the same server is being restarted/shutdown, then everything that you need to execute after restart/shutdown, should be defined as a separate task/tasks and specify first task with "target" attribute.

If the server is just shutdown, then "target" attribute can be omitted.  But if you have specified a “target” attribute even for shutdown action, then that target will be executed whenever the server is being restarted.

registry

Registry metadata can be added by specifying  the paths to metadata files as below.
<registry password="pass" url="https://serverhost:port/registry" username="user">
    <metadata path="registry-meta/meta1.xml"/>
    <metadata path="registry-meta/meta2.xml"/>
</registry>
Further, if the metadata is added to the resources which are being deployed by the *.car files in the same Ant application, then there is a possibility of executing metadata task before the resources get added to the registry.

As a solution for this, registry Ant task waits and retries several times until resources get deployed.  Default value for wait is 10s and retry count is 5.

Anyway, these wait and retry times can be overridden by specifying following properties in the build.xml.
<property name="registry.retries" value="4"/>
<property name="registry.sleep" value="20000"/>

Using your own custom tasks

If any additional custom tasks are required depending on your environment, those jars can be added either into repository/components/dropins (OSGI bundles) or repository/components/lib (Non-OSGI jars).

Then, above custom tasks can be used in your ant scripts as below by defining the task class in every script.
<target name="use" description="Use the Task" depends="jar">
    <taskdef name="helloworld" classname="com.mycompany.HelloWorld"/>
    <helloworld/>
</target>
Adding task definitions in each script can be avoided by defining them in repository/conf/ant-deployer.xml as below.
<AntDeployer xmlns="http://wso2.org/carbon/antdeployer">
    <Tasks>
        <Task name="helloworld" classname="com.mycompany.HelloWorld"/>
        <Task name="hellouniverse" classname="com.mycompany.HelloUniverse"/>
    </Tasks>
</AntDeployer>
Then, tasks can be used directly without defining them in the scripts.

Metadata Configuration

Adding metadata

Following is an example metadata file. When there are multi-valued properties, “append” attribute need to be specified.
<metadata xmlns="http://wso2.org/carbon/registry/metadata">
    <resource path="/_system/config/resource1">
        <associations>
            <association path="/_system/governance/resource2"
                         type="depends"/>
            <association path="/_system/governance/resource3"
                         type="depends"/>
        </associations>
        <properties>
            <property name="p1" append=”true”>v1</property>
            <property name="p2">v2</property>
        </properties>
        <tags>
            <tag>t1</tag>
            <tag>t2</tag>
        </tags>
    </resource>
</metadata>

Removing resources/metadata from Registry

By defining an attribute named “remove” within each resource, association, property and tag elements,  you can instruct to remove those resources/metadata from the registry.
<metadata xmlns="http://wso2.org/carbon/registry/metadata">
    <resource path="/_system/config/resource1" remove="true"/>
    <resource path="/_system/config/resource2">
        <associations>
            <association path="/_system/governance/resource3"
                         type="depends" remove="true"/>
        </associations>
        <properties>
            <property name="p1" append=”true” remove="true">v1</property>
            <property name="p2" remove="true"/>
        </properties>
        <tags>
            <tag remove="true"/>
        </tags>
    </resource>
</metadata>

Trying it out

 

The source code, the pre-build jar and a sample Ant application written for WSO2 ESB server can be found at [1]. This sample Ant application will do the following steps.
  1. Copying the mysql driver
  2. Restarting the server
  3. Deploying ESB sequence template named template1
  4. Deploying ESB API named api1
  5. Deploying the carbon application named sample-antapp_1.0.0.car which includes
    • A proxy service named SampleProxy
    • Registry resources named endpoint1.xml and endpoint2.xml which will be deployed at /_system/antapp-sample/endpoints
  6. Creating a set of associations between /_system/antapp-sample and above endpoint1.xml, endpoint2.xml resources
  7. Adding a set properties named p1, p2 etc. and tags named t1, t2 etc into the collection /_system/antapp-sample and endpoint1.xml, endpoint2.xml resources

In order to try it out,
  1. Install the Ant deployer into WSO2 ESB 4.5.0 server following the above installation steps
    • Pre-built jar can be found in lib directory at [1]
  2. Create a directory at <cabon_home>/repository/deployment/server/antapps
    • e.g. wso2esb-4.5.0/repository/deployment/server/antapps
  3. Copy the sample-antapp.zip file into the antapps directory
    • Pre-build antapp can be found in lib directory at [1]
  4. Restarting logs should be able to notice either in the console or  server logs within a few seconds

Resources

[1] https://svn.wso2.org/repos/wso2/people/ruchira/ant-deployer
[2] build.xml in the sample antapp
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="sample-antapp" basedir="." default="t0">
    <target name="t0" description="Copy jars into Carbon Server and restart">
        <copy file="jars/mysql-connector-java-5.1.22-bin.jar"
              todir="${carbon.lib}"/>
        <server target="t1"/>
    </target>
    <target name="t1" description="Copy artifacts">
        <copy file="templates/template1.xml"
              todir="${carbon.repo}/synapse-configs/default/templates"/>
        <copy file="apis/api1.xml"
              todir="${carbon.repo}/synapse-configs/default/api"/>
        <copy file="carbonapps/sample-antapp_1.0.0.car"
              todir="${carbon.home}/repository/carbonapps/0"/>
        <registry url="https://localhost:9443/registry"
                  username="admin" password="admin">
            <metadata path="registry-meta/*"/>
        </registry>
    </target>
    <target name="t2" description="Create ruchira directory">
        <mkdir dir="${carbon.home}/ruchira"/>
    </target>
</project>
[3]  Registy metadata xml in the sample antapp
<metadata xmlns="http://wso2.org/carbon/registry/metadata">
    <resource path="/_system/antapp-sample">
        <associations>
            <association path="/_system/antapp-sample/endpoints/endpoint1.xml"
                         type="depends"/>
            <association path="/_system/antapp-sample/endpoints/endpoint2.xml"
                         type="depends"/>
        </associations>
        <properties>
            <property name="p1">v1</property>
            <property name="p2">v2</property>
        </properties>
        <tags>
            <tag>t1</tag>
            <tag>t2</tag>
        </tags>
    </resource>
    <resource path="/_system/antapp-sample/endpoints/endpoint1.xml">
        <associations>
            <association path="/_system/antapp-sample/endpoints/endpoint2.xml"
                         type="sibling"/>
        </associations>
        <properties>
            <property name="p1">e1v1</property>
            <property name="p2">e1v2</property>
        </properties>
        <tags>
            <tag>e1t1</tag>
            <tag>e1t2</tag>
        </tags>
    </resource>
    <resource path="/_system/antapp-sample/endpoints/endpoint2.xml">
        <associations>
            <association path="/_system/antapp-sample/endpoints/endpoint1.xml"
                         type="sibling"/>
        </associations>
        <properties>
            <property name="p1">e2v1</property>
            <property name="p2">e2v2</property>
        </properties>
        <tags>
            <tag>e2t1</tag>
            <tag>e2t2</tag>
        </tags>
    </resource>
</metadata>

Wednesday, October 3, 2012

How to Specify Default Message Builder and Message Formatter in Axis2

By default Axis2 message builders and formatters are registered against a content type. But there might be situations that you might need to specify a default message builder/formatter in Axis2.

This can be achieved by specifying a regular expression as the contentType. Then, Axis2 will first try to find a matching message builder/formatter for your content type and when it couldn't find a match, it will try to match against the regular expressions which we have specified.

Using this functionality, you can either register a default builder/formatter or one builder/formatter pair for a set of content types which matches to the given regular expression.

Further, if you are using binary relay feature of WSO2 ESB or WSO2 ELB(Elasting Load Balancer), then you will feel the ease of using regular expressions to specify BinaryRelayBuilder and ExpandingMessageFormatter.
<messageBuilder contentType=".*" class="org.wso2.carbon.relay.BinaryRelayBuilder"/>

<messageFormatter contentType=".*" class="org.wso2.carbon.relay.ExpandingMessageFormatter"/>

Thursday, July 5, 2012

WSO2 ESB - Error Codes

Following is the list of error codes used in WSO2 ESB and a brief description about them.

Code Description
101000 Receiver IO error sending
101001 Receiver IO error receiving
101500 Sender IO error sending
101501 Sender IO error receiving
101503 Connection failed
101504 Connection timed out
101505 Connection closed
101506 HTTP protocol violation
101507 Connect cancel
101508 Connect timeout
101509 Send abort

Error Handling in WSO2 ESB

When a Proxy Service or a Sequence which mediate messages, is considered, error handling would be a key concern. Depending on the error type, we might need to send a fault message, custom response etc.

WSO2 ESB makes our life easier by allowing us to specify a custom fault sequence for error handling. i.e. It gives the flexibility to use mediator and do various tasks even when an error occurred.

Following is a sample sequence which logs the error details and sends a custom message to the client when an error occurs. Further, if you need to send a SOAP Fault, then Fault mediator can be used instead of Payload Factory mediator.
<sequence name="myErrorSequence">
    <header name="To" action="remove"/>
    <property name="RESPONSE" value="true"/>
    <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>

    <log level="custom">
        <property name="error-message" expression="get-property('ERROR_MESSAGE')"/>
        <property name="error-code" expression="get-property('ERROR_CODE')"/>
        <property name="error-detail" expression="get-property('ERROR_DETAIL')"/>
        <property name="error-exception" expression="get-property('ERROR_EXCEPTION')"/>
    </log>

    <payloadFactory>
        <format>
            <ns:MyResponse xmlns:ns="http://services.samples">
                <ns:Error/>
            </ns:MyResponse>
        </format>
    </payloadFactory>
    <send/>
</sequence> 

As response might be sending even without going to the outSequence, we need to remove the To header and specify the other two properties named RESPONSE and NO_ENTITY_BODY.

You can also get the details of the error occurred using properties named ERROR_MESSAGE, ERROR_CODE, ERROR_DETAIL and ERROR_EXCEPTION.

After you added the above sequence into the configuration, you can refer it as below from a Proxy or a Sequence.

For a Sequence :
<sequence name="mySequence" onerror="myErrorSequence">
.......
</sequence>
For a Proxy Service :
<proxy name="MyProxy" xmlns="http://ws.apache.org/ns/synapse">
    <target faultSequence="myErrorSequence">
    ......
    </target>
</proxy>

Wednesday, July 4, 2012

Enable Wire Level Logs in WSO2 ESB

When you work with WSO2 ESB, you might need to monitor the wire level data which go through the server. Then, you can simply do that by adding the following entry into the log4j.properties file which can be found at lib/log4j.properties

log4j.category.org.apache.synapse.transport.nhttp.wire=DEBUG

Fixing REST URLs in Send Mediator of WSO2 ESB

There might be situations, that you would need to do REST calls using the send mediator of WSO2 ESB. Then, you might have noticed the endpoint url that you specified in the endpoint configuration, gets suffixed by a url fragment.

This happens when ever you do a REST call using the send mediator. In order to get rid of it, please specify the following property before the send mediator.
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>

Sending a Dummy Response from WSO2 ESB

When you play with WSO2 ESB, you might need to send some dummy data as the response of a proxy service or an REST API. In order to do that you will need to specify To, RESPONSE and NO_ENTITY_BODY properties in the inSequence. If the sequence doesn't get called via an HTTP GET, then the property NO_ENTITY_BODY can be removed from the sequence.

Then, the sequence will directly send the response to the client even without going through the outSequence. Using either Enrich or Payload Factory mediator, you can create the response massage manually.

Following is a sample inSequence.
<inSequence>
    <header name="To" action="remove"/>
    <property name="RESPONSE" value="true"/>
    <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
    <payloadFactory>
        <format>
            <ns:getQuoteResponse xmlns:ns="http://services.samples">
                <ns:return xmlns:ax21="http://services.samples/xsd">
                    <ax21:change>4.212070096051944</ax21:change>
                    <ax21:earnings>-9.567415587431361</ax21:earnings>
                    <ax21:high>-148.1740146577308</ax21:high>
                    <ax21:symbol>IBM</ax21:symbol>
                </ns:return>
            </ns:getQuoteResponse>
        </format>
    </payloadFactory>
    <send/>
</inSequence>