Saturday, November 8, 2014

[WSO2 ESB] [4.8.1] How to Convert XML to JSON Array

Following API Demonstrate this functionality.

<api xmlns="http://ws.apache.org/ns/synapse" name="Transform" context="/Transform">
<resource methods="POST">
<inSequence>
<property name="messageType" value="application/json" scope="axis2"></property>
<log level="custom">
<property name="Status" expression="json-eval($.StockQuotes.Stock)"></property>
</log>
<filter source="json-eval($.StockQuotes.Stock.Symbol)" regex="null">
<then>
<payloadFactory media-type="json">
<format>{ "StockQuotes": { "Stock": $1 } }</format>
<args>
<arg evaluator="json" expression="$.StockQuotes.Stock"></arg>
</args>
</payloadFactory>
</then>
<else>
<payloadFactory media-type="json">
<format>{ "StockQuotes": { "Stock": [ $1 ] } }</format>
<args>
<arg evaluator="json" expression="$.StockQuotes.Stock"></arg>
</args>
</payloadFactory>
</else>
</filter>
<respond></respond>
</inSequence>
</resource>
</api>
view raw Transform.xml hosted with ❤ by GitHub
Try above api with a rest client with following sample requests.

1)Multiple Stocks.
XML request:
<StockQuotes>
<Stock>
<Symbol>IBM</Symbol>
<Last>0.00</Last>
<Date>N/A</Date>
<Time>N/A</Time>
<Change>N/A</Change>
<Open>N/A</Open>
<High>N/A</High>
<Low>N/A</Low>
<Volume>N/A</Volume>
<MktCap>N/A</MktCap>
<PreviousClose>N/A</PreviousClose>
<PercentageChange>N/A</PercentageChange>
<AnnRange>N/A - N/A</AnnRange>
<Earns>N/A</Earns>
<P-E>N/A</P-E>
<Name>IBM</Name>
</Stock>
<Stock>
<Symbol>WSO2</Symbol>
<Last>0.00</Last>
<Date>N/A</Date>
<Time>N/A</Time>
<Change>N/A</Change>
<Open>N/A</Open>
<High>N/A</High>
<Low>N/A</Low>
<Volume>N/A</Volume>
<MktCap>N/A</MktCap>
<PreviousClose>N/A</PreviousClose>
<PercentageChange>N/A</PercentageChange>
<AnnRange>N/A - N/A</AnnRange>
<Earns>N/A</Earns>
<P-E>N/A</P-E>
<Name>WSO2</Name>
</Stock>
</StockQuotes>
JSON response :
{
"StockQuotes":{
"Stock":[
{
"Name":"IBM",
"PercentageChange":"N\/A",
"Low":"N\/A",
"Open":"N\/A",
"Last":0.0,
"Time":"N\/A",
"MktCap":"N\/A",
"Change":"N\/A",
"Date":"N\/A",
"PreviousClose":"N\/A",
"Volume":"N\/A",
"Symbol":"IBM",
"AnnRange":"N\/A - N\/A",
"Earns":"N\/A",
"High":"N\/A",
"P-E":"N\/A"
},
{
"Name":"WSO2",
"PercentageChange":"N\/A",
"Low":"N\/A",
"Open":"N\/A",
"Last":0.0,
"Time":"N\/A",
"MktCap":"N\/A",
"Change":"N\/A",
"Date":"N\/A",
"PreviousClose":"N\/A",
"Volume":"N\/A",
"Symbol":"WSO2",
"AnnRange":"N\/A - N\/A",
"Earns":"N\/A",
"High":"N\/A",
"P-E":"N\/A"
}
]
}
}
2) Single Stock
XML request:
<StockQuotes>
<Stock>
<Symbol>WSO2</Symbol>
<Last>0.00</Last>
<Date>N/A</Date>
<Time>N/A</Time>
<Change>N/A</Change>
<Open>N/A</Open>
<High>N/A</High>
<Low>N/A</Low>
<Volume>N/A</Volume>
<MktCap>N/A</MktCap>
<PreviousClose>N/A</PreviousClose>
<PercentageChange>N/A</PercentageChange>
<AnnRange>N/A - N/A</AnnRange>
<Earns>N/A</Earns>
<P-E>N/A</P-E>
<Name>WSO2</Name>
</Stock>
</StockQuotes>
JSON response (As an array):
{
"StockQuotes":{
"Stock":[
{
"Name":"WSO2",
"PercentageChange":"N\/A",
"Low":"N\/A",
"Open":"N\/A",
"Last":0.0,
"Time":"N\/A",
"MktCap":"N\/A",
"Change":"N\/A",
"Date":"N\/A",
"PreviousClose":"N\/A",
"Volume":"N\/A",
"Symbol":"WSO2",
"AnnRange":"N\/A - N\/A",
"Earns":"N\/A",
"High":"N\/A",
"P-E":"N\/A"
}
]
}
}
This is with following message formatter and builder
        <messageformatter class="org.apache.synapse.commons.json.JsonStreamFormatter" contenttype="application/json" />

        <messageformatter class="org.apache.synapse.commons.json.JsonStreamFormatter" contenttype="application/json" />

Wednesday, November 5, 2014

[Active-MQ] PortOffset

1) Changing transport ports. Edit /conf/activemq.xml
and change ports numbers in following configuration.
<beans ...>
<broker ...>
...
<!--
The transport connectors expose ActiveMQ over a given protocol to
clients and other brokers. For more information, see:
http://activemq.apache.org/configuring-transports.html
-->
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
...
</broker>
</beans>
view raw activemq.xml hosted with ❤ by GitHub

2) Changing web console port. Edit /conf/jetty.xml
and change following port in following config.
<beans ..>
..
<bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
<!-- the default port number for the web console -->
<property name="host" value="0.0.0.0"/>
<property name="port" value="8161"/>
</bean>
...
</beans>
view raw jetty.xml hosted with ❤ by GitHub

[Active-MQ] Setting up AMQ with MySQL database.



1) Create MySQL database.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| phpmyadmin |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database activemq;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| activemq |
| mysql |
| performance_schema |
| phpmyadmin |
+--------------------+
5 rows in set (0.00 sec)
mysql> use activemq;
Database changed
mysql> show tables;
Empty set (0.00 sec)
mysql>
view raw mysql hosted with ❤ by GitHub
2) Download activeMQ and extract it.
3) Edit /conf/activemq.xml
4) Add following configuration.

<beans ...>
<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
<broker ...>
<!--
Configure message persistence for the broker. The default persistence
mechanism is the KahaDB store (identified by the kahaDB tag).
For more information, see:
http://activemq.apache.org/persistence.html
-->
<persistenceAdapter>
<!--kahaDB directory="${activemq.data}/kahadb"/-->
<jdbcPersistenceAdapter dataSource="#mysql-ds"/>
</persistenceAdapter>
</broker>
</beans>
view raw activemq.xml hosted with ❤ by GitHub
5) Copy mysql jdbc driver (mysql-connector-java-5.1.25-bin.jar) in the directory "activemq_home/lib/optional"

6) Start ActiveMQ server using $ ./activemq start ( To stop the server use ./activemq stop )

7) Log in to activeMQ management console using http://localhost:8161/ with admin:admin credentials.

8) Create a queue and send a message to the queue with persistence enabled.

9) You can see the message in database.

mysql>
mysql> show tables;
+--------------------+
| Tables_in_activemq |
+--------------------+
| ACTIVEMQ_ACKS |
| ACTIVEMQ_LOCK |
| ACTIVEMQ_MSGS |
+--------------------+
3 rows in set (0.00 sec)
mysql> select * from ACTIVEMQ_MSGS;
+----+-------------------+-----------------------------------------------+-----------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
| ID | CONTAINER | MSGID_PROD | MSGID_SEQ | EXPIRATION | MSG | PRIORITY | XID |
+----+-------------------+-----------------------------------------------+-----------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
| 1 | queue://TestQueue | ID:hasitha-laptop-48562-1415139260206-3:1:1:1 | 1 | 0 | � { )ID:hasitha-laptop-48562-1415139260206-3:1  d TestQueue n{ )ID:hasitha-laptop-48562-1415139260206-3:1       I|��  
Hello world. I|�� | 0 | NULL |
+----+-------------------+-----------------------------------------------+-----------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
1 row in set (0.00 sec)
mysql>


Saturday, November 1, 2014

Packt offers its library subscription with an additional $150 worth of free content

Packt provides full online access to over 2000 books and videos to give users the knowledge they need, when they need it. From innovative new solutions and effective learning services to cutting edge guides on emerging technologies, Packt’s extensive library has got it covered.

For a limited time only, Packt is offering 5 free eBook or Video downloads in the first month of a new annual subscription – up to $150 worth of extra content. That’s in addition to one free download a month for the rest of the year.

This special PacktLib Plus deal expires on 4th November, 2014.

Check out the deal here http://bit.ly/1wN0Rq0

Monday, October 20, 2014

Book Review : WS-BPEL 2.0 Beginners Guide

WS-BPEL 2.0 Beginners Guide: As name suggest, This is a good reading for who wants to learn BPEL concepts from beginning. Authors start book with a very simple BPEL sample. They give details instructions from setting up IDE, creating schema and wsdl, etc. They finish their first sample giving instructions to how you can test your first BPEL process using a BPEL engine. That is why I recommend this book as a true beginner guide.

BPEL specifications is so long and even BPEL 2.0 primer is very hard to understand without prior knowledge on BPEL. But authors have structured book chapters from simple to complex BPEL concepts, so that beginners can easily understand. It contains chapters for fault handling, compensation, parallel processing  asynchronous invocation etc. Best part is authors have given samples for each section including guidance how you can do it in IDE.

This book contains special chapter for Humantask with samples. That adds a true value to this book.

Even BPEL 2.0 is published in 2007, (Nearly 7 years ago) it is usage is increasing in enterprise world. It is an widely used industrial standard for Business process management (BPM). I think knowing BPEL is an added advantage for a programmer, architect and students; and this is the best book to start with.

Have a look on this book by clicking this link.

Sunday, September 21, 2014

ESB: Invoking secured backend - Part 3 - Username Token with BasicAuth

This post shows, how to invoke an UsernameToken secured backend ( Hosted in WSO2 AS ), using basic auth. For this we use POXSecurityHandler, (Which comes default with WSO2 Products) to convert the HTTP basic auth information into wsse:UsernameToken.

Setting up environment : 

Setup both WSO2 AS and WSO2 ESB as mentioned in previous post.


ESB Proxy
  • Create a proxy called EchoUTBasicProxy with following content. 
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="EchoUTBasicProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log level="custom" separator="," description="Log">
<property name="Proxy" value="EchoUTWithBasicAuthProxy"/>
</log>
<property name="user_name" value="bob" scope="default" type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="Authorization"
expression="fn:concat('Basic ', base64Encode(fn:concat(get-property('user_name'),':','bobpass')))"
scope="transport"
type="STRING"/>
<log level="custom">
<property name="Generated Authorization token" expression="$trp:Authorization"/>
</log>
<send>
<endpoint>
<address uri="https://localhost:9443/services/echo"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
name="wsse:Security"
scope="default"
action="remove"/>
<send/>
</outSequence>
<faultSequence/>
</target>
<publishWSDL uri="http://localhost:9763/services/echo?wsdl"/>
<description/>
</proxy>

Testing Scenario
  • Enable Soap tracer on WSO2 AS.
  • Enable wire log in WSO2 ESB.
  • Invoke EchoUTBasicProxy  using SOAP UI. 
You can see, there is no username token in incoming message to backend. Instead you see basic auth header in outgoing message to backend from ESB.




ESB: Invoking secured backend - Part 2 - Username Token - Dynamic username

My previous post shows how to invoke an username token secured backend using an ESB proxy. But we used static value for the username ( tom ), which is hard coded in the policy file. So each request authenticated as tom at the backend service.

But some may wants to access backend service as different users. This post discusses how you can extend it to support dynamic user name in policy file.


Setting up environment : 

Setup both WSO2 AS and WSO2 ESB as mentioned in previous post. 


ClassMediator (ESB)
  • In this scenario, we set username as a property in the ESB proxy. 
  • To pass username into RampartConfiguration, we use custom class mediator called, SetUserMediator.
  • This custom mediator, adds username into rampartConfigCallbackProperties map and set the map into Axis2MessageContext. So later we can access these properties from Rampart ConfigCallbackHandlers. 
  • We have to use customMediator, since we can't set a Map using standard ESB mediators.  
  • ( Maven Project is located here. )
package org.example.rampart.mediator;
import java.util.Hashtable;
import java.util.Map;
import org.apache.synapse.Mediator;
import org.apache.synapse.MessageContext;
import org.apache.synapse.core.axis2.Axis2MessageContext;
public class SetUserMediator implements Mediator {
private String username;
@Override
public boolean mediate(MessageContext synCtx) {
org.apache.axis2.context.MessageContext msgContext = ((Axis2MessageContext) synCtx)
.getAxis2MessageContext();
Map<String, String> rampConfigCBProperties = new Hashtable<String, String>();
System.out.println("Setting username to rampartConfigCallbackProperties: " + getUsername());
rampConfigCBProperties.put("user_name", getUsername());
msgContext.setProperty("rampartConfigCallbackProperties",
rampConfigCBProperties);
return true;
}
public String getUsername() {
if (username == null) {
username = "";
}
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String getDescription() {return null;}
@Override
public void setDescription(String arg0) {}
@Override
public int getMediatorPosition() {return 0; }
@Override
public String getShortDescription() {return null; }
@Override
public int getTraceState() {return 0; }
@Override
public String getType() {return null; }
@Override
public boolean isContentAware() {return false; }
@Override
public void setMediatorPosition(int arg0) {}
@Override
public void setShortDescription(String arg0) {}
@Override
public void setTraceState(int arg0) {}
}


Rampart ConfigCallbackHandler (ESB)
  • Similar to PasswordCallback handler, Rampart provides Configuration Callback handler to dynamically load Rampart configuaraion to runtime. We use this to set username dynamically. 
  • ( Maven Project is located here. )

package org.example.rampart;
import java.util.Map;
import org.apache.rampart.RampartConfigCallbackHandler;
import org.apache.rampart.policy.model.RampartConfig;
public class UTConfigCallbackHandler implements RampartConfigCallbackHandler{
@Override
public void update(RampartConfig rampartConfig) {
Map<String, String> propertyMap = rampartConfig.getPropertyMap();
if (propertyMap != null && propertyMap.containsKey("user_name")) {
System.out.println("Updating UT user name dynamically : " + propertyMap.get("user_name"));
rampartConfig.setUser(propertyMap.get("user_name"));
}
rampartConfig.setPwCbClass("org.example.rampart.PWCBHandler");
}
}

Policy for UsernameToken  ( ESB )
  • Create an ESB in-line xml local entry called "UTOverTransportDynamic.xml" with following content. 

<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UTOverTransport">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"></sp:HttpsToken>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256></sp:Basic256>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax></sp:Lax>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp></sp:IncludeTimestamp>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"></sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:rampartConfigCallbackClass>org.example.rampart.UTConfigCallbackHandler</ramp:rampartConfigCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>

Proxy Service (ESB)

  • Create a proxy called EchoUTDynamicProxy with following content. 
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="EchoUTDynamicProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log level="full"/>
<class name="org.example.rampart.mediator.SetUserMediator">
<property name="username" value="bob"/>
</class>
<send>
<endpoint>
<address uri="https://localhost:9443/services/echo">
<enableSec policy="UTOverTransportDynamic.xml"/>
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
name="wsse:Security"
scope="default"
action="remove"/>
<send/>
</outSequence>
</target>
<publishWSDL uri="http://localhost:9763/services/echo?wsdl"/>
<description/>
</proxy>

Testing Scenario

  • Enable Soap tracer on WSO2 AS.
  • Invoke EchoUTDynamicProxy  using SOAP UI. 
You can see Username token in request message as follows.


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:echo="http://echo.services.core.carbon.wso2.org">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-7">
<wsu:Created>2014-09-21T06:38:53.795Z</wsu:Created>
<wsu:Expires>2014-09-21T06:43:53.795Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-8">
<wsse:Username>bob</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobpass</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<echo:echoString>
<!--Optional:-->
<in>?</in>
</echo:echoString>
</soapenv:Body>
</soapenv:Envelope>
view raw gistfile1.xml hosted with ❤ by GitHub

ESB: Invoking secured backend - Part 1 - Username Token



Scenario 
  1. Backend service is secured using Username token. 
  2. Client invokes ESB proxy using http. ( no security between client and ESB) 
  3. At the ESB, proxy adds username token to outgoing message and invokes secured backend.
  4. ESB sends back echo service's response back to client. 

Setting up environment 

Backend ( WSO2 Application server 5.2.1)
  1. Start WSO2 AS 5.2.1 using ( Unix: sh wso2server.sh / Windows: wso2server.bat ) 
  2. Log in to management console. ( https://localhost:9443/carbon/ ) 
  3. Create two user called tom and bom
    • Goto Configure -> Users and Roles -> Users
    • Create an user called tom with password "tompass". 
    • Create another user called bob with password "bobpass"
    • Assign both users to "admin" role.
  4. Secure Echo service with Username token. 
    • Goto Main -> Services -> List 
    • Click on "echo" service. This will open up "Service Dashboard (echo)" page.
    • Under "Quality of Service Configuration", Select "security".
    • In "Security for the service" page, Select Enable security.
    • Under Security scenarios, select "Username token"  ( First security policy) and click next. 
    • In next page, select "admin" under user group. 
    • Click Finish. 
ESB ( WSO2 ESB 4.8.1 )
  1. Start WSO2 ESB with port offset =1 ( Unix: sh wso2server.sh -DportOffset=1 / Windows: wso2server.bat --DportOffset=1) 


Rampart configuration for UsernameToken  ( ESB )
  • Create an ESB in-line xml local entry called "UTOverTransport.xml" with following content. 
<wsp:Policy wsu:Id="UTOverTransport"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:user>tom</ramp:user>
<ramp:passwordCallbackClass>org.example.rampart.PWCBHandler</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>

Password callback Implementation

  • Create a jar with following class, and drop it to /repository/components/lib/
  • Then restart ESB server. 
  • ( Maven Project is located here. )
package org.example.rampart;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
import java.io.IOException;
public class PWCBHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i];
int usage = pwcb.getUsage();
String id = pwcb.getIdentifier();
if (usage == WSPasswordCallback.USERNAME_TOKEN) {
System.out.println("Resolving password for user " + id);
// Getting password
if ("tom".equals(id)) {
pwcb.setPassword("tompass");
}else if ("bob".equals(id)){
pwcb.setPassword("bobpass");
} else {
pwcb.setPassword("");
}
} else if (usage == WSPasswordCallback.SIGNATURE
|| usage == WSPasswordCallback.DECRYPT) {
// Logic to get the private key password for signature or
// decryption
// TODO : Implement me
}
}
}
}
Some useful References on Rampart password callback handler:  
  1. http://wso2.com/library/3733/
  2. http://wso2.com/library/240/

ESB Proxy

  • Create a proxy called EchoUTProxy with following content. 
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="EchoUTProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<send>
<endpoint>
<address uri="https://localhost:9443/services/echo">
<enableSec policy="UTOverTransport.xml"/>
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
name="wsse:Security"
scope="default"
action="remove"/>
<send/>
</outSequence>
</target>
<publishWSDL uri="http://localhost:9763/services/echo?wsdl"/>
<description/>
</proxy>
view raw EchoUTProxy.xml hosted with ❤ by GitHub


Testing Scenario

  • Enable Soap tracer on WSO2 AS.
  • Invoke EchoUTProxy  using SOAP UI. 
You can see Username token in request message as follows. 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:echo="http://echo.services.core.carbon.wso2.org">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-13">
<wsu:Created>2014-09-21T04:17:56.541Z</wsu:Created>
<wsu:Expires>2014-09-21T04:22:56.541Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-14">
<wsse:Username>tom</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">tompass</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<echo:echoString>
<!--Optional:-->
<in>?</in>
</echo:echoString>
</soapenv:Body>
</soapenv:Envelope>
view raw gistfile1.xml hosted with ❤ by GitHub



Saturday, May 17, 2014

Java4BPEL - Java Class extension activity for WSO2 BPS


java4bpel

java4bpel is an extension for Apache ODE and WSO2 BPS. java4bpel introduces new BPEL extension activity called invokeClass, which can be used to invoke a JAVA class.

Project home page

Project git location
Clone project from 
https://github.com/hasithaa/java4bpel.git

Tip: Find and Replace a string in multiple files at onces by avoiding LTS (Leaning toothpick syndrome)

Linux Command:

$ grep -lR "oldString" -r | xargs sed -i 's/oldString/newString/g'


How to avoid LST.

If your oldString or newString contains character "/" (the delimiter), then Delimiter collision occurs, which cause to LST.  To avoid that, select another delimiter such as # or ? in sed command.

examples:

sed -i 's#oldString#newString#g'
sed -i 's?oldString?newString?g'




WSO2 BPS 3.2.0 - Performance Tuning - Know When, Why and How


  • Following instructions are only applied to WSO2 BPS 3.2.0
  • All configuration files are located under $WSO2BPS-3.2.0_HOME/repository/conf/ directory

JDBC connections.

When ?

  • When your application requires high throughput  

Why ?

  • BPS server has two engines; Apache ODE BPEL processor and HumanTask engine. These two engines are tightly coupled with database layer. They persist every instance data into database. Thus to function BPS properly, you need to allocate enough database connections for BPS datasource.
  • Both these engine share same BPS datasource and db connections. Thus generally we are recommending to allocate db connections 50-50 manner for a BPEL + HumanTask application.
  • For example if you have total 100 db connections, for a BPEL + HumanTask application, you can use upto 50 db connections for ODE engine and leave the rest of the db connections for HumanTask operations.
  • If you have only BPEL usecase, you can allocate many db connections ( see next topic) for ODE engine. 
  • Also note that, even you have allocated higher number of db connections for BPS datasource, performance may not increase as excepted. One reason would be, there are no enough db sessions from database side. If that is the case, you need to increase number of db session from database side.  

How ?

  • Configure BPS data source using datasources.properties file.
  • eg: see highlighted section. 
 ...
 synapse.datasources.bpsds.validationQuery=SELECT 1 FROM DUAL
 synapse.datasources.bpsds.dsName=bpsds
 synapse.datasources.bpsds.maxActive=100
 synapse.datasources.bpsds.maxIdle=20
 synapse.datasources.bpsds.maxWait=10000

 

ODE Scheduler threads

When ?

  •  When your application requires high throughput  

Why ?

  • In ODE engine, every scheduler thread is associated with a db connection. So the rule of thumb is, number of ODE scheduler threads should be less than or equal to number of db connections allocated for ODE engine. Otherwise some threads may not work properly, because they can't acquire a db connections to work. 
  • For example In BPEL + HumanTask scenario, if you have total 100 db connections, your can allocate 50 threads for ODE scheduler. This will grantee that at a given time, only 50 db connections are acquired by ODE engine.    

How ?

  • Configure this via bps.xml.
  • eg: 
    <tns:odeschedulerthreadpoolsize>50</tns:odeschedulerthreadpoolsize>

HTTP connections

When ?

  • When your have lot of service invocations.(external or internal) 

Why ?

  • When your BPEL processes do service invocations, they use http connections. By default this http connections are limited. Because of this, thread have to waits for http connections. 
  • To avoid this, you can increase this value using Multithreaded Http Connection Manager Configuration. 
  • If your processes do lot of service invocation to localhost ( or particular host), then it is required to increase maxConnectionsPerHost configuration as well.

How ?

  •  enable this configuration using bps.xml

    <tns:MultithreadedHttpConnectionManagerConfig>
        <tns:maxconnectionsperhost value="350">
        <tns:maxtotalconnections value="400">
    </tns:maxtotalconnections>

 

TimeOuts 

When ?

  •  When partner services take more time (slow) to response.

Why ?

  • When partner services are slow or take more time to response, callee BPEL process's invoke activity fails due to message exchange timeout. By increasing time will avoid these kind of failures. 
  • Also note that, slow partner services will slow entire BPEL process. This will cause to timeout the client application. ( callee of the BPEL process.). Thus it is required increase timeout interval for client application.      

How ?

  • Via bps.xml and axis2.xml
Read for more information.
http://nandikajayawardana.blogspot.com/2012/10/how-to-increase-external-invocation.html

 

HumanTask Caching 

When ?

  • When you have to deal with large user store.

Why ?

  • HumanTasks are tightly coupled with users and user roles/groups. Because of this, BPS does lot of user store lookups for HumanTask operations. These user store calls can take considerable amount of time, if user store is large or located remotely. This causes to degrade performance of the entire HumanTask engine. Caching user and role lookup data at BPS side will reduce those remote user store calls and improve overall HumanTask engine's performance.  

How ?

  • Enable HumanTask caching in humantask.xml
  • eg: 
    <cacheconfiguration>
        <enablecaching>true</enablecaching>
    </cacheconfiguration>

 

Number of HumanTask Scheduler threads.

When ?

  • When you are not using humantask deadline/escalation.

Why ?

  • HumanTask deadline and escalation are scheduled tasks, which are executed by HumanTask scheduler. By default 50 threads are allocated for HumanTask scheduler. If you are not using deadline/escalations, you can configure this value to lower value such as 5. This will utilize idle threads in BPS server.
  • Note that, you can't set this to 0, because humantask engine has several internal scheduled tasks to run.

How ?

  • Configure this value in humantask.xml,
  • eg:
    <schedulerconfig>
        <maxthreadpoolsize>5</maxthreadpoolsize>
    </schedulerconfig>

Sunday, May 4, 2014

An Async BPEL Process and A Human task ?

In Async process ( in other words a long running process ), after the invocation of a partner process or service, the BPEL process continues to carry on with its execution process while that partner service completes performing its operation. This partner service may take couple of seconds, minutes, hours or even days to complete. The Async BPEL process then receives the result of the partner service via a callback service, when the partner service is completed.

HumanTask (Web service) is one type of such a long running partner service which returns the task result when user completes the task. In this case, BPEL use B4P extension, which stops the BPEL execution flow which contains the B4P extension activity and waits till HumanTask output to come.

Wednesday, April 2, 2014

Change maven local repo in one command - Ubuntu/Linux


This will be useful for the developers who works with multiple maven local repositories.

Requirement:  set M2_HOME environment variable, before you start. 

Configuration
Add following  bash function to .bashrc in your home directory. Change M2_LOCATION if you need.



changeM2()
{
if [ -z $M2_HOME ]; then
echo "Set M2_HOME first."
else
# NOTE !.
# M2_LOCATION is the place where I put my all local repos. Change it, if you need.
M2_LOCATION=$M2_HOME/repo
echo "Your Local repository location is set to $M2_LOCATION"
#Validate M2_LOCATION is exist
if [ -d $M2_LOCATION ]; then
CURRENT_M2=$(grep -i "<localRepository>" $M2_HOME/conf/settings.xml | head -1)
echo "Current M2 local repository is set to $CURRENT_M2"
echo "Directories in the $M2_LOCATION"
ls $M2_LOCATION -D
echo ""
read -p "Enter m2 repo name: " NEW_M2_LOCATION;
if [ -z $NEW_M2_LOCATION ]; then
echo "Invalid input. No changes to maven settings."
else
sed -i "s:$CURRENT_M2:<localRepository>$M2_LOCATION/$NEW_M2_LOCATION</localRepository>:g" $M2_HOME/conf/settings.xml
echo ""
echo "localRepository is changed to $M2_LOCATION/$NEW_M2_LOCATION"
echo "New $M2_HOME/conf/settings.xml:"
grep -i "$M2_LOCATION/$NEW_M2_LOCATION" $M2_HOME/conf/settings.xml
fi
else
echo "$M2_LOCATION does not exists. Create $M2_LOCATION first."
fi
fi
}
view raw .bashrc hosted with ❤ by GitHub
Then reload the .bashrc using command,
$ source ~/.bashrc


How to use: 

Type changeM2 in the terminal and give the name of the m2 repo (folder) you wish to change.

Friday, March 28, 2014

Recovering BPEL Activity Failures - WSO2 BPS


Read more about ODE activity failure and recovery from.

 

Method 1: Via WSO2 BPS Management Console 


In WSO2 BPS, BPEL failed activity recovery can be done using WSO2 BPS Management console.

To do this, it is required to enable ODE activityLifecycle events for a BPEL process. To do that modify process-event configuration in deploy.xml as follow.
<process-events>
<enable-event>activityLifecycle</enable-event>
</process-events>
view raw gistfile1.xml hosted with ❤ by GitHub
(refer http://ode.apache.org/ode-execution-events.html for to see how you can enable ODE events for a BPEL process.)

Users can view activity failures for a BPEL process instance in the instance view page. 

1) Goto Instances -> click on of the instance ID to open the instance view for that instance.


 2) In the instance view, you can find failed activity/activities under activity informations. (See image). Also you can retry/cancel (ignore a failed activity) a failed activity using two buttons listed under Action column.





Method 2 - Via InstanceManagementService admin API



Also users can recover failed activities by using BPS InstanceManagementService. Unfortunately there is no UI functionality for this when ode events are disabled. (BPS 3.2.0 & older)


These are the steps, to retry activities using InstanceManagementService admin service.

1) Execute following SQL query on BPS database.

SELECT * FROM ODE_ACTIVITY_RECOVERY;
view raw gistfile1.sql hosted with ❤ by GitHub
This will return the failed activities with corresponding BPEL process instance id. You will require following information to retry a failed activity.
  • INSTANCE_ID
  • ACTIVITY_ID

2) Set HideAdminServiceWSDLs configuration to false in /repository/conf/carbon.xml file.

eg:
<HideAdminServiceWSDLs>false</HideAdminServiceWSDLs>
view raw gistfile1.txt hosted with ❤ by GitHub


3) Then start the BPS server.


4) Now create a SOAP-UI project using https://localhost:9443/services/InstanceManagementService?wsdl


5) Create a new request under recoverActivity operation. A sample request will be like this.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://wso2.org/bps/management/schema">
<soapenv:Header/>
<soapenv:Body>
<sch:recoverActivity>
<sch:iid>260</sch:iid> <!-- Process instance ID -->
<sch:aid>11</sch:aid> <!-- Activity ID-->
<sch:action>retry</sch:action> <!-- Action to perform, either retry,cancel-->
</sch:recoverActivity>
</soapenv:Body>
</soapenv:Envelope>
view raw gistfile1.txt hosted with ❤ by GitHub

6) Then Authenticate soap-ui request by configuring authentication and security related settings.
For Basic Auth select Authorization type as preemptive, and give admin user name and password.

7) Then for each failed activity (results in step 1), send a recoverActivity request. Use "retry" action to retry activity, and use "cancel" action to cancel the activity retry and continue instance execution.



Tuesday, March 18, 2014

Running HumanTask Cleanup Job - WSO2 BPS

HumanTask engine allows you to configure periodic cleanup tasks from the WSO2 BPS persistence storage based on task status. To enable Task clean up task, uncomment TaskCleanupConfig element in HumanTask.xml

<TaskCleanupConfig>
<cronExpression>0 0 0/4 * * ?</cronExpression>
<statuses>COMPLETED,OBSOLETE,EXITED</statuses>
</TaskCleanupConfig>
view raw htconfig.xml hosted with ❤ by GitHub

HumanTask engine uses quartz-scheduler for cron jobs. Refer [1] to declare cron expressions format. In above example, Cron scheduler will trigger TaskCleanup task every Four Hours, to remove COMPLETED, OBSOLETE, EXITED from the database.

[1] -http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger


Tuesday, March 11, 2014

Generating a random unique number in a SOAP UI request


In the request use,

${=System.currentTimeMillis() + ((int)(Math.random()*10000))}

example :  

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:ode-apache-org:example:async:client">
<soapenv:Header/>
<soapenv:Body>
<urn:ClientRequest>
<urn:id>${=java.util.UUID.randomUUID()}</urn:id>
<urn:input>Hello Wolrd</urn:input>
</urn:ClientRequest>
</soapenv:Body>
</soapenv:Envelope>
Note : Here I am generating this number by adding currant milliseconds as a prefix. So this will generate almost unique number.


Update: 20th June 2014. 

Another simple way to do this. 

${=java.util.UUID.randomUUID()}