Wednesday, November 4, 2015

How to use Cache Mediator in WSO2 ESB

Cache mediator in WSO2 ESB used when we see same type of message again and again and also process with same output. In this scenario if we want to optimize our ESB performance, we can use cache mediator. Cache mediator checks if the same type of message has been processed before, it cashes the message and on the same request mediator gets the message from the cache and reply back.


Cache mediator uses the hashes for checking the equivalence the message. In cache mediator you can define the cache response time and message size in bytes.

Test Case:

In our test case, we will use same service I have created in my last blog. Basically it is a data service and we have created a pass through proxy of this DSS service in ESB. This service gives the employee details based on the Employee Id.

We will try to cache the DSS response in ESB so that on same request of ESB does not hit the DSS server and reply the cached response to the client.

To understand whether cache is working fine or not, I will change the employee details in Database but change should not reflect in our response till message is cached. We are assuming that ESB cache Mediator will not hit the DSS and it will give response from the cached message.

Below is the DSS service I have created in my last blog.


Below is the ESB service, pass through proxy of DSS.


Service gives the details of employee based on the Employee Id. Below is the SOAP UI request and response of ESB pass through proxy.


 To use the caching mediator I am going to sequences and updating the IN Sequence of this service.


You can add Cache mediator in Advance group.


Below are the fields you need to fill to use Cache mediator.


  • Cache Id: This is the cache id for the configuration.
  • Cache Scope: It is important when you are using cluster.
    • Per Host: It Cache the message for the current host of the cluster.
    • Per-Mediator: It Cache the message once for the whole cluster.
  • Cache Type: It is used to check the message is coming from the request or we need to cache the response for outgoing message.
    • Finder: When message needs to be cached from incoming path, it hash the each incoming message.
    • Collector: It indicates the message needs to be collected from cached message. It is used for outgoing path.
  • Hash Generator: It is by default selected to org.wso2.caching.digest.DOMHASHGenerator and it has the hash logic to check each incoming message.
  • Cache Timeout:  We need to specify the timeout in seconds that how much we want to cache the message.
  • Maximum Message Size: The limit of cache message in bytes.
Cache Implementation Details
  • Implementation Type: Default to set “In-Memory” and this is the only available.
  • Maximum Size: 1000 is default selected.
On Cache Hit: It basically tells that which sequence needs to be followed from registry.

Now edit the out sequence as defined below.


Specify the Cache id, cache Scope and Cache Type. In out sequence we are using “Collector” Cache type because we need to get the response from cache in out going message.


Now we check that what is there in our database. You can see that for Employee Id 1, we have Employee Name as ‘Shri’ and address is ‘Delhi’ as highlighted in Yellow.


Let see what we are getting in SOAP UI response.


Same thing we are getting in response and in one hit the response is cached.
Now I am going to change the address from “Delhi” to “Noida” as below.


Now if you try within 20 second, this is what we have mentioned in our cache response. We should be getting same response.


And Yes, as above we are getting the same response because response is cached we it is not coming from DSS server. If we hit just after 20 second we can see the address is now updated from “Delhi” to “Noida”.


Now this response will be cached till net 20 second in each hit.

You can see that from the IN sequence we are getting the response.



ESB Synapse Code:

<proxy name="DSS_EmployeeDetailDataServiceProxy" transports="http" startOnLoad="true" trace="disable" statistics="enable">
  <target inSequence="DSS_EmployeeDetailDataService_IN" outSequence="CommonSequence_OUT" faultSequence="DSS_EmployeeDetailDataService_Fault"/>
        <publishWSDL key="DSS_EmployeeDetailDataService_wsdl"/>
    </proxy>
<localEntry key="DSS_EmployeeDetailDataService_wsdl" src="file:repository/conf/employee/EmployeeDetailDataService.wsdl"/>
   
    <sequence name="DSS_EmployeeDetailDataService_Fault">
        <log level="full"/>
        <payloadFactory>
            <format>
                <shr:employees xmlns:shr="http://shriwithjava.blogspot.co.nz/">
                    <shr:employee>
                        <shr:id>Exception has been caught</shr:id>
                        <shr:name>Exception has been caught</shr:name>
                        <shr:address>Exception has been caught</shr:address>
                    </shr:employee>
                </shr:employees>
            </format>
        </payloadFactory>
        <property name="RESPONSE" value="true"/>
        <header name="To" action="remove"/>
        <send/>
        <drop/>
    </sequence>
    <sequence name="DSS_EmployeeDetailDataService_IN">
        <log level="full"/>
        <cache id="GetEmpDetailCache" scope="per-host" collector="false" hashGenerator="org.wso2.caching.digest.DOMHASHGenerator" timeout="20" maxMessageSize="500">
            <implementation type="memory" maxSize="1000"/>
        </cache>
        <send>
            <endpoint key="DSS_EmployeeDetailDataService_EPR"/>
        </send>
    </sequence>
    <sequence name="CommonSequence_OUT">
        <log level="full"/>
           <cache id="GetEmpDetailCache" scope="per-host" collector="true"/>
           <send/>
    </sequence>
   <endpoint name="DSS_EmployeeDetailDataService_EPR">
        <address uri="http://10.251.162.192:9763/services/EmployeeDataService">
            <timeout>
                <duration>10000</duration>
                <responseAction>fault</responseAction>
            </timeout>
            <suspendOnFailure>
                <errorCodes>101500,101501,101506,101507,101508</errorCodes>
                <initialDuration>3000</initialDuration>
                <progressionFactor>1.0</progressionFactor>
            </suspendOnFailure>
            <markForSuspension>
                <errorCodes>101504,101505</errorCodes>
                <retriesBeforeSuspension>3</retriesBeforeSuspension>
                <retryDelay>1</retryDelay>
            </markForSuspension>
        </address>
    </endpoint>

Tuesday, November 3, 2015

How to use Fault sequence in WSO2 ESB

In WSO2 ESB, fault sequence is used for exception handling. In service logic if any exception comes and you want ESB to execute a particular scenario or just send a proper exception error to client, just put the logic in fault sequence and it will be executed. This is the same exception handling as we have in other programming language.

Test Case:

In our example, we are trying to call DSS service from the ESB. We have created a simple pass through proxy of DSS service. This DSS service gives you detail of employee based on the Employee ID.

To get an exception, I will stop the DSS server so that ESB will get an exception and we are assuming that on getting the exception, fault sequence will be executed. In fault sequence I have mentioned a normal exception message on the response and same response we will give back to the client.

Below is the EmployeeDataservice I have created in DSS.




Above service gives you detail of employee on passing Employee Id.


Below is the pass through proxy I have created in ESB with name of 'DSS_EmployeeDetailDataServiceProxy’.



From ESB URL, I have created a SOAP UI project which work the same as DSS does as it’s a pass through proxy.





Now I have stopped the DSS server and expecting to get an Exception in ESB for DSS and this scenario will trigger the fault sequence. In fault sequence I have put normal exception message in EmployeeDetailService response.

Exception in Logs:

Complete Exception Message:




You can see that fault block now have been executed and that is why we are getting expected error message what we have put in fault sequence.

ESB Synapse Code:

<proxy name="DSS_EmployeeDetailDataServiceProxy" transports="http" startOnLoad="true" trace="disable" statistics="enable">

<target inSequence="DSS_EmployeeDetailDataService_IN" outSequence="CommonSequence_OUT" faultSequence="DSS_EmployeeDetailDataService_Fault"/>

<publishWSDL key="DSS_EmployeeDetailDataService_wsdl"/>
</proxy>

<localEntry key="DSS_EmployeeDetailDataService_wsdl" src="file:repository/conf/employee/EmployeeDetailDataService.wsdl"/>

<sequence name="DSS_EmployeeDetailDataService_IN">
        <log level="full"/>
        <send>
            <endpoint key="DSS_EmployeeDetailDataService_EPR"/>
        </send>
    </sequence>
                          
  <sequence name="DSS_EmployeeDetailDataService_Fault">
        <log level="full"/>
        <payloadFactory>
            <format>
                <shr:employees xmlns:shr="http://shriwithjava.blogspot.co.nz/">
                    <shr:employee>
                        <shr:id>Exception has been caught</shr:id>
                        <shr:name>Exception has been caught</shr:name>
                        <shr:address>Exception has been caught</shr:address>
                    </shr:employee>
                </shr:employees>
            </format>
        </payloadFactory>
        <property name="RESPONSE" value="true"/>
        <header name="To" action="remove"/>
        <send/>
        <drop/>
    </sequence>
<sequence name="CommonSequence_OUT">
        <log level="full"/>
        <send/>
</sequence>
<endpoint name="DSS_EmployeeDetailDataService_EPR">
        <address uri="http://localhost:9763/services/EmployeeDataService">
            <timeout>
                <duration>10000</duration>
                <responseAction>fault</responseAction>
            </timeout>
            <suspendOnFailure>
                <errorCodes>101500,101501,101506,101507,101508</errorCodes>
                <initialDuration>3000</initialDuration>
                <progressionFactor>1.0</progressionFactor>
            </suspendOnFailure>
            <markForSuspension>
                <errorCodes>101504,101505</errorCodes>
                <retriesBeforeSuspension>3</retriesBeforeSuspension>
                <retryDelay>1</retryDelay>
            </markForSuspension>
        </address>
</endpoint>
   

Tuesday, October 27, 2015

How to use Switch Mediator in WSO2 ESB

Whenever in ESB logic a conditional filter is required and based on the value of the filter a particular functionality needs to be executed, switch mediator can be used. This switch mediator is same like as we have for other programming language in java, .net, php etc. so overall concept is same in WSO2 as well.

In WSO2 ESB, switch mediator filters the XPATH or JSON. We can pass an expression value in it to filter the value and based on the value of an expression a case is executed if it is matched with filtered string.


You can add switch mediator by the UI configuration it comes in the Filter category.




There are some parameter you need to pass to use this Switch Mediator like Source Xpath and number of case as per your logic. At the last there is a default mediator option you can use that to execute if no match is found.



Example:

<switch source="get-property('GetServiceName')">
<case regex="GetEmployeeDetail">
<send>
<endpoint>
<address uri="http://localhost:8280/services/getEmployeeDetail"/>
</endpoint>
</send>
</case >
<case regex="GetDepartmentDetail">
<send>
<endpoint>
<address uri="http://localhost:8280/services/getDepartmnetDetail"/>
</endpoint>
</send>
</case>
<case regex="GetITHeadDetail">
<send>
<endpoint>
<address uri="http://localhost:8280/services/getITHeadDetail"/>
</endpoint>
</send>
</case>
<default>
<send/>
<drop/>
</default>
</switch>


In above example we are trying to call the different service based on the ‘'GetServiceName'’ parameter. If the string value of 'GetServiceName' variable is ‘GetEmployeeDetail’ then call ‘getEmployeeDetail’ service and if value is ‘GetDepartmentDetail’ then call ‘getDepartmnetDetail’ service. There is a default case in which we are dropping the response back to the client. If no case is found by the filtered parameter then default case is executed.

Monday, October 26, 2015

How to use drop mediator in WSO2 ESB

Drop mediator is used to stop the process. Once drop mediator is executed, it sends the Http 202 Accepted response to the client. No mediator will be executed written after drop mediator.


There are some scenario in programming like just stop the process and send response back to the client, drop mediator can be used.


Example:

<filter xpath="string-length(get-property('getBlogName'))='shriwithjava'">
<then> 
<send>
<endpoint>
<address uri="http://localhost:8280/services/getEpmList"/>
</endpoint>
</send>
</then>
<else>
<send/>
<drop/>
</else>
</filter>

In the above example we are trying to match the condition like is blog name is ‘shriwithjava’ then send it to get employee list service otherwise drop the message right there.

How to use property mediator in WSO2 ESB

WSO2 ESB provides Property mediator to use is in your code. It is like a variable in programming language. You can set a value into it or also you can remove value from it. If you have enabled the logs, you can see the property variable’s value coming into the logs at what stage what value is assigned for this this variable.

To use a property mediator you can edit a sequence and go to ‘’Add Child then Core then Property mediator as mentioned below.



You will get a below screen in which you can pass the property name, Action (Add or Remove) property type (String, Boolean, Integer, float, long etc.)


  • In Action you can set or remove a value of the property
  • In Set Action as : you can assign a value or can get a value from the expression
  • You can also get a value from other property by using expression="get-property('symbol')" expression.



You can see the property mediator value by putting logs in synapse.


Wednesday, October 14, 2015

How to use log mediator in WSO2 ESB

You can log all the information which is mediated in your ESB logic written in synapse. You can define the category of the logs, this is same as other programming language like DEBUG, ERROR, and INFO etc.

All the below category you can define in “log4j.properties” file location in below location.
wso2esb-4.0.3\lib\log4j.properties or \repository\conf\log4j.properties

  •  TRACE: It is similar to DEBUG but provide more information it is normally used in the time of deployment
  • DEBUG: It provides the most useful information when application is executed for debugging
  • INFO: It provides high level information
  • WORN: It generates the logs in case of harmful situation
  • ERROR: It provides error information in your application
  • FATEL: very severe error events that will presumably lead the application to abort

You can define the log level as well including Full, simple, header and custom. Custom is used only for the property mediator however full includes all attribute including “simple” log level

Example (Full):

<log level="full">
<property name="RequestId" expression="//swj:RequestId/text()" type="STRING" xmlns:swj="http://shriwithjavablogspot.co.nz/logpropertyexample/"/>
</log>

In this example we are trying to get the value of RequestId from the request payload, because property value is being fetched from the request expression so we need to pass xml namespace as well to get the value of RequestId.

Example (Custom):

<log level="Custom">
<property name="RequestId" expression="//swj:RequestId/text()" type="STRING" xmlns:swj="http://shriwithjavablogspot.co.nz/logpropertyexample/"/>
<property name=" RequestId" expression="get-property(RequestId)"/>
</log>

In above example we are trying to get again property value from expression and as well as from property mediator.

You can change your log setting in log4j.property file like INFO, DEBUG and ERROR etc. there are some other configuration like if you want to create another separate file you can put it into property file and you will see that another separation file will be created.

log4j.property File:

# Configure the service logger at INFO level. Writes only run-time/mediation-time audit messages
log4j.category.SERVICE_LOGGER=INFO, SERVICE_APPENDER
log4j.additivity.SERVICE_LOGGER=false
log4j.appender.SERVICE_APPENDER=org.apache.log4j.RollingFileAppender
log4j.appender.SERVICE_APPENDER.File=${carbon.home}/repository/logs/${instance.log}/wso2-esb-service${instance.log}.log
log4j.appender.SERVICE_APPENDER.MaxFileSize=1000KB
log4j.appender.SERVICE_APPENDER.MaxBackupIndex=10
log4j.appender.SERVICE_APPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.SERVICE_APPENDER.layout.ConversionPattern=%d{ISO8601} [%X{ip}-%X{host}] [%t] %5p %c{1} %m%n



Tuesday, October 13, 2015

WSSecurityEngine: Invalid timestamp The security semantics of the message have expired

This issue normally comes when your Client machine and server machine timing is not in sync. When request reaches to server with different time then server expire the message and sends the same response with error message.
To avoid this error please make sure your client time and server time should be in sync.


Logs:


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:MessageExpired</faultcode><faultstring>The message has expired (WSSecurityEngine: Invalid timestamp The security semantics of the message have expired)</faultstring></soap:Fault></soap:Body></soap:Envelope>