| res ipsa loquitur

~ Latest Posts ~

There are several ways to retrieve query parameters from an HTTP request using WSO2 ESB.

  • Using Synapse XPath $url variable
  • Using get-property(‘query.param.xxx’)

We can use the following curl GET request for the following sample API

$ curl “http://localhost:8280/store/view?name=john&age=29” -v

Using Synapse $url XPath variable

There is an XPath variable $url which we can use to retrieve query parameters from an HTTP request.

<property name=”name” expression=”$url:name” type=”STRING”/>

Following is an example using the $url. Note that you don’t have to mention the query params in the uri-template

Using get-property(‘query.param.xxx’)

Another option is to use the get-property function with argument as query.param. where **value** is the relevant name of the query parameter

get-property(‘query.param.name’)

Example API with get-property function

Sample curl rquest and response

$ curl “http://localhost:8280/store/view?name=john&age=29” -v

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8280 (#0)
> GET /store/view?name=john&age=29 HTTP/1.1
> Host: localhost:8280
> User-Agent: curl/7.50.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Accept: */*
< Host: localhost:8280
< Content-Type: application/x-www-form-urlencoded; charset=UTF-8
< Date: Sun, 13 Aug 2017 14:40:01 GMT
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
<user><name>john</name><age>29</age></user>

You can test this out with WSO2 Integrator which is the WSO2 ESB product packaged with other integration products like WSO2 Message Broker, WSO2 Business Process Engine and WSO2 Data Services Server.

Cheers!

Written by Asitha Nanayakkara

This post describes how to check whether the current node is the leader node of an ESB cluster. An example use-case of using this property is to write a cluster aware scheduled task in WSO2 ESB.

While writing a proxy service or a sequence, there might be an instance where you want only one ESB node to do a particular task. In that case, we can use the leader node in the cluster or try to get hold of a cluster-wide lock (using a DB based solution or Hazelcast). This blog post explains how to achieve this using Hazelcast leader node.

Hazelcast Leader node

WSO2 carbon server which WSO2 ESB is built upon uses Hazelcast as the cluster coordination implementation. In Hazelcast, there is a mechanism to reliably get the leader node of a cluster. Only one node in a cluster at a given time becomes the leader node. We can use this property of Hazelcast within WSO2 ESB using either a script mediator or a class mediator to get the leader node.

Retrieving leader with a Class mediator

Following is a Java code snippet to get the leader node of a Hazelcast cluster. We can use this within a class mediator to get the leader node of the ESB cluster.

You can follow this guide to write your own class mediator.

Retrieving leader with a Script Mediator

We can use the same Java code with some modifications within the script mediator as well. This option is much easier to implement and deploy in an ESB cluster.

Use case

One of the use cases of this property is to create a cluster aware scheduled task in WSO2 ESB.

Up to ESB 4.8.1 scheduled tasks cannot be controlled to be scheduled only in a single node at a time. The only option is to use pinned servers, but this has a single point of failure.

Even though the scheduled tasks deployed in the cluster injects a message to each proxy or sequence in the cluster, we can make only one proxy service to mediate the message by evaluating the leader node property as mentioned above.

Hope this is useful to someone.

Cheers!

Written by Asitha Nanayakkara

With ESB 4.9.0 release we can achieve this directly using the property mediators registry scope.

In WSO2 ESB 4.8.1 there is no direct way to save content to registry through stock synapse mediators. This post describes two possible options we have with ESB 4.8.1 to save content to the registry. Those are by using either the Script Mediator or the Class Mediator.

Following examples shows how to store the value of property myProperty of type String in message context into the registry path conf:/store/myStore

##Script Mediator

Achieving this with script mediator is relatively easy. Note that using the script mediator will have some performance impact on your mediation logic.

Here is a sample code snippet of a script mediator to save the value stored under myProperty in message context to the registry.

##Class Mediator

First of all, you need to create a class mediator. You can follow this guide to write your own class mediator. After that what you need is to write some Java code similar to following to store the content into the registry.

##Retrieve content

To retrieve the stored content you can simply use the get-property XPath function with registry scope as follows.

<property name="regContent"
          expression="get-property('registry', 'conf:/store/myStore')"/>

Cheers!

Written by Asitha Nanayakkara

There are lot of architectural changes in WSO2 Message Broker (MB) 3.0.0. We can fairly say its totally different in terms of the architecture compared to WSO2 MB 2.2.0. All these changes were done to improve performance and give more flexibility to the end user.

One of the key features that’s introduced with MB 3.0.0 is its RDBMS support. Previously it was all about Cassandra. Whether you like it or not If you are using MB you had to stick with Cassandra. With MB 3.0.0 you can connect MB to either Cassandra (Either with Hector or CQL), MySQL, MS-SQL, Oracle, PostgresSQL or H2 data store.

##Design In MB, core functionality is handled by Andes. Andes is protocol independent and is cluster aware. MQTT and AMQP protocol implementations talks to Andes to get its work done. Andes mainly uses two data stores for data persistence. They are AndesContextStore and MessageStore.

Note:

  • MessageStore is an interface in MB. All messages related persistence tasks (message storing/retrival/deletion) are handled by classes implementing this interface.
  • AndesContextStore is an interface in MB. Tasks that are not directly related to messages (create/retrieve/delete queues, exchanges etc) but need to be persisted are handled by classes implementing this interface.

By way of AndesContextStore and MessageStore interfaces, in MB 3.0.0, tight coupling between specific Database Management System (DBMS) and Andes is removed. Therefore supporting a new DBMS is a matter of implementing a class with specific DBMS related implementation and configuring MB to use that implementation at start-up.

Following is the class diagram of MB 3.0.0 that comes with specific implementation for several DBMS types

UML class diagram of DBMS design

RDBMS related implementations are written using ANSI SQL so that it can be used with many RDBMS’s. This includes MS-SQL, Oracle, MySQL, PostgresSQL, H2.

##Extension points With this new design there is an option to write custom RDBMS or any DBMS specific store and plug it to MB. For instance you can write custom classes implementing AndesContextStore and MessageStore interfaces to harness performance gaines by using specific SQL statements supported by a given database.

Written by Asitha Nanayakkara

##Problem There might be an instances where you want to connect to a WSO2 server (eg: WSO2 Identity Server) using an Axis2 client stub with an SSL connection. In that case you need to set a trust store for the client application to trust the server. Trusting the server or not is totally up to the client. And the default trust store of Java doesn’t have the self signed certificate of a default WSO2 server. Hence we usually use system properties to set the correct trust store.

There might be a requirement to totally ignore the certificate and trust whatever the server it connects to by ignoring the trust store. Most probably in a testing environment. Way to do this is some what different from a usual Java HTTP client when we use Axis2 client stub implementations.

##Solution In Axis2 there is a class for this specific purpose, to trust all the servers it connects to, TrustAllTrustManager. We can use that TrustManager to create an SSLContext which trust all the servers.

 SSLContext sslCtx = SSLContext.getInstance("http");
 sslCtx.init(null, new TrustManager[] {new TrustAllTrustManager()}, null);

Next we set SSLContext to axis2 stub implementation as follows.

stub._getServiceClient().getOptions().setProperty(
	HTTPConstants.CUSTOM_PROTOCOL_HANDLER,
	new Protocol("https", new SSLProtocolSocketFactory(sslCtx), 443)
	);

After that we can use this stub to communicate with the server without any failing SSL handshake issue.

##Gotchas Most common mistake we do when trying to ignore the trust store using Axis2 stubs is that we use something similar to following.

// SSLContext sslContext; created to trust all servers

// Then we set the context to HTTPSURLConnection
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

// Create all-trusting host name verifier
HostnameVerifier validateAllHosts = new HostnameVerifier() {

	public boolean verify(String hostname, SSLSession session) {
		return true;
	}
};

// Set the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(validateAllHosts);

Problem is underlying Axis2 client doesn’t use the HTTPSURLConnection hence this code has no effect to the underlying Axis2 client.

Extension points

There might be an instance where we need to add a given set of certificates to be trusted by our client application. We can use System properties to for that. Instead this can be also achieved by adding our own implementation of TrustManager as follows.


// Create the custom trust manager
TrustManager[] customTrustManager = new TrustManager[]{ new X509TrustManager() {

	public java.security.cert.X509Certificate[] getAcceptedIssuers() {
		X509Certificate[] trustedCerts;
		// Set trusted certificates. Or you might return an already
		// created array of trusted certificates
		return trustedCerts;
	}

	public void checkClientTrusted(X509Certificate[] certs, String authType) {
	}

	public void checkServerTrusted(X509Certificate[] certs, String authType) {
	}
}};

// Create the SSL context and set the custom trust manager  
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, customTrustManager, new java.security.SecureRandom());

// Set the SSLContext to the stub as mention above

That’s all for this gotcha!

Written by Asitha Nanayakkara