Showing posts with label WSO2. Show all posts
Showing posts with label WSO2. Show all posts
Monday, April 22, 2024

Custom Mediator cannot be found by synapse-core

 Caused by: java.lang.ClassNotFoundException: com.chandana.test.CustomMediator cannot be found by synapse-core_4.0.0.wso2v20_43
        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:512)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:423)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:415)
        at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:155)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
        at org.apache.synapse.config.xml.ClassMediatorFactory.createSpecificMediator(ClassMediatorFactory.java:100)


 If you try to build a WSO2 Custom mediator for Micro Integrator 4.2.0 using Maven, you might encounter above exception in the logs. Based on my understanding, there are two ways to overcome this issue. The first option is to use Integration Studio to export the custom mediator JAR file. However, in my use case, it’s not feasible. After going through the WSO2 Integration Studio source code, I found that it uses different Maven-bundle-plugin instructions than what’s available in the pom.xml file.

I have overcome this issue by adding <_removeheaders>Import-Package,Private-Package</_removeheaders> to the Maven-bundle-plugin instructions.

<plugin>

        <groupId>org.apache.felix</groupId>

        <artifactId>maven-bundle-plugin</artifactId>

        <version>2.3.4</version>

        <extensions>true</extensions>

        <configuration>

          <instructions>

            <Bundle-SymbolicName>CustomClassMediator</Bundle-SymbolicName>

            <Bundle-Name>CustomClassMediator</Bundle-Name>

            <Export-Package>com.chandana.test</Export-Package>

            <DynamicImport-Package>*</DynamicImport-Package>

            <_removeheaders>Import-Package,Private-Package</_removeheaders>

          </instructions>

        </configuration>

      </plugin>

Tuesday, December 01, 2020

Integrate With Mutual Certificate Authentication based Service


There are many ways to secure a Service/API using different Authentication mechanisms. Mutual Certificate authentication(AKA: Client Certificate Authentication) is one of the ways to secure Service or API.

Recently I was trying to integrate with an API which is secured using Mutual Certificate Authentication. In this scenario, the backend service team gave me their certificate-based on PKCS#12.

When integrating this backend system with WSO2 Platform, we have to use 'Multi-HTTPS transport'. With this 'Multi-HTTPS transport', it will grant great flexibility to define different SSL profiles with separate trust stores and key stores for different IPs or hosts. This custom SSL profile can be implemented for Client to Synapse Runtime(Client --> ESB) or Synapse Runtime to Backend(ESB --> Backend). If it is Client to ESB, then you have to define custom SSL Profiles in the transportReceiver section.

In my use-case, it was for ESB to Backend. So I had to add custom SSL profiles into the transportSender section of the axis2.xml file. Since I have a PKCS#12 based certificate file, I don't need to convert it to JKS or anything.

Let's assume Mutual Certificate Authentication based backend API URL is https://backendhost.com/api/users. The Custom SSL profiles configuration in the axis2.xml(or senderprofiles.xml in WSO2 EI 7) is like below.


<transportSender name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpSSLSender">
	<parameter name="non-blocking" locked="false">true</parameter>
	<parameter name="keystore" locked="false">
		<KeyStore>
			<Location>repository/resources/security/wso2carbon.jks</Location>
			<Type>JKS</Type>
			<Password>wso2carbon</Password>
			<KeyPassword>wso2carbon</KeyPassword>
		</KeyStore>
	</parameter>
	<parameter name="truststore" locked="false">
		<TrustStore>
			<Location>repository/resources/security/client-truststore.jks</Location>
			<Type>JKS</Type>
			<Password>wso2carbon</Password>
		</TrustStore>
	</parameter>
	<parameter name="customSSLProfiles">
		<profile>
			<servers>backendhost.com:443</servers>
			<KeyStore>
				<Location>repository/resources/security/backendcertificate.p12</Location>
				<Type>PKCS12</Type>
				<Password>certificatePassword</Password>
				<KeyPassword>certificatePassword</KeyPassword>
			</KeyStore>
		</profile>			
	</parameter>
	<!--<parameter name="HostnameVerifier">DefaultAndLocalhost</parameter>-->
	<!--supports Strict|AllowAll|DefaultAndLocalhost or the default if none specified -->
</transportSender>

Docs:

Multi-HTTPS Transport -  WSO2 ESB/EI
Thursday, February 20, 2020

CSV to SOAP Message conversion with Smooks Mediator

Smook Mediator available in WSO2 MI/EI/ESB can be used to do various message transformations. For an example read CSV file and transform to XML. I had a requirement where I wanted to load a CSV file content into the database. So, my initial idea was to convert CSV content into XML, then use the XSLT mediator to generate a data service request. But it will be a costly operation with lots of resource consumption.

Therefore, instead of generating a data service request via XSLT, I tried to use the options available in Smooks. Smooks provides FreeMaker based templating support that can be used to convert CSV to SOAP.

Here, first I have created a sample input CSV file and expected Data Service sample request message. With this, it will be very easy to generate data mapping. Below are the examples of CSV and Data Service models

Sample.csv:
UserId,NameFirst,NameLast
1,Chandana,Napagoda
2,John,Tester

SampleOut.xml : 
<au:addUsers_batch_req xmlns:au="https://blog.napagoda.com">
<au:addUsers>
<au:UserId>1</au:UserId>
<au:NameFirst>Chandana</au:NameFirst>
<au:NameLast>Napagoda</au:NameLast>
<au:System>-1234</au:System>
</au:addUsers>
<au:addUsers>
<au:UserId>2</au:UserId>
<au:NameFirst>John</au:NameFirst>
<au:NameLast>Tester</au:NameLast>
<au:System>-1234</au:System>
</au:addUsers>
</au:addUsers_batch_req>


When I created the Smook configuration using WSO2 IDE, the view will be like this


Eclipse Smooks UI


Next, click on the input task, then select input CSV file as input data. After that, define fields in the CSV file, using the Input configuration section. In Addition to above, I have skipped the first line, and each record was marked as User, and parent Element defined as Users.

Eclipse Smooks Mapping

Next, right-click on the 'Input Task', and mouse hover on the 'Add Task' option and click on the 'Apply Template' option.

Eclipse Smooks Add Template

You will get a dialogue like below to select the output message type. For me, it is XML.  

Eclipse Smooks Add Output type


In the next dialogue, I can select my Output file format(Data Service Request).



Once we select the Smooks Output model and click on the 'Finish' button, Initial data mapping screen will look like below. 



Next, select 'User' element from the input model and drop it into 'addUsers' output model. This will generate necessary Freemaker template elements to iterate input rows.





Next map each input element into expected output elements. When ding that, you have to select each leaf element from the input model and drop into the output leaf element. 




When navigating to source view of Smooks configuration, below configuration has been auto-generated. 


<?xml version="1.0" encoding="UTF-8"?><smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
  <params>
    <param name="stream.filter.type">SAX</param>
    <param name="inputType">input.csv</param>
    <param name="input.csv" type="input.type.actived">File:/E:\test\done\Sample.csv</param>
  </params>
  <csv:reader fields="UserId,NameFirst,NameLast" recordElementName="User" rootElementName="Users" skipLines="1"/>
  <ftl:freemarker applyOnElement="#document">
    <ftl:template><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<au:addUsers_batch_req xmlns:au="https://blog.napagoda.com">
    <#list .vars["Users"]["User"] as User>
    <au:addUsers>
        <au:UserId>${.vars["User"]["UserId"]}</au:UserId>        
        <au:NameFirst>${.vars["User"]["NameFirst"]}</au:NameFirst>        
        <au:NameLast>${.vars["User"]["NameLast"]}</au:NameLast>        
    </au:addUsers>
    </#list>    
</au:addUsers_batch_req>]]></ftl:template>
    <param name="modelSrc">File:/E:\test\done\SampleOut.xml</param>
    <param name="modelSrcType">XML</param>
    <param name="messageType">XML</param>
    <param name="templateDataProvider">input</param>
  </ftl:freemarker>
  <resource-config selector="#document">
    <resource>org.milyn.delivery.DomModelCreator</resource>
  </resource-config>
</smooks-resource-list>



Tuesday, December 03, 2019

Configure Kerberos based Authentication into WSO2 Datasources


As you know, Kerberos can be used to authenticate System or users reside on a none secured network. In my use case, I have Windows AD and MSSQL server and I have a couple of WSO2 Servers running on Linux systems.

In my initial setup I have configured, WSO2 servers has to use SQL users. But instead of using SQL users, I prefer to use AD users. So I have started configuring Kerberos and faced a lot of troubles.

If you are starting from scratch, I would recommend writing a Java class to connect MSSQL server using Kerberos. Then You can identify all small mistakes such as character case issues, typos, JDBC driver compatibility issues, etc. 

Below are a few issues I have faced:

1) CASE is significant in krb5.conf file

2) I found that we need to use MSSQL JDBC 6.4 version in order to get new tickets. But if you are just planning use pre-generated tickets, you can use the older version as well.

Here are the steps you need follow when configuring Kerberos with WSO2 Enterprise Integrator. 

1) Define your krb5.conf File. 

In my config file, I have defined two KDC and admin server(KDC) which will handle the database administration requests and all KDC(master and worker) will generate credentials. KDCs are your Active directory server hostnames

[libdefaults]
default_realm = NAPAGODA.COM
[realms]
NAPAGODA.COM = {
kdc = dc1.napagoda.com
kdc = dc2.napagoda.com
admin_server = dc1.napagoda.com
default_domain = NAPAGODA.COM
}

[domain_realm]
    .napagoda.com = NAPAGODA.COM
    napagoda.com = NAPAGODA.COM

2) . Configure jaas.conf File

This file needs to be created under 'repository/conf/identity/' directory. With WSO2 Enterprise Integrator product they have moved conf directory into product home. However, still, this file needs to be created based on the old folder structure. So make sure to use 'repository/conf/identity/'. Luckily, if not, it will display an error message in the log file(or console). 

SQLJDBCDriver {
   com.sun.security.auth.module.Krb5LoginModule required useTicketCache=true;
};

3). Locating the krb5.conf File

If you have created your krb5.conf file inside lib/security directory of the JRE, you don't need to set the environment variable. Otherwise, you have to pass 'krb5.conf' file location as a 'java.security.krb5.conf' environment variable. Oracle Docs

ex: -Djava.security.krb5.conf=/file/location/krb5.conf 

4) Configure WSO2 Datasources

You can use Kerberos based Authentication in your datasources XML files or datasources defined via the 'admin console'. But make sure to pass correct parameters into SQL connection URL to use Kerberos Authentication. Please note, in the connection user and password fields, you can AD user's credentials. 

ex: jdbc:sqlserver://your.sql.server.com;database=database_name;integratedSecurity=true;authenticationScheme=JavaKerberos



- Kerberos Debugging in Java
- Microsoft JDBC Driver 6.4 for SQL Server

Sunday, December 01, 2019

Compare Two XML Elements and Filter using WSO2 MI


Think about an integration scenario, where you are getting a list of data from a service endpoint(Data 1) and you want to exclude or match this response against the data returned by another service endpoint(Data 2).

In such a situation, first, you need to have a unique attribute in both data set to exclude or match elements. So in my use case, list of data and matching content is as below


<CodeLists>
 <CodeList>
        <Id>O</Id>
        <Name>Open</Name>
    </CodeList>
    <CodeList>
        <Id>C</Id>
        <Name>Cancelled</Name>
    </CodeList>
    <CodeList>
        <Id>X</Id>
        <Name>Denied</Name>
    </CodeList>
 <CodeList>
        <Id>P</Id>
        <Name>Pending</Name>
    </CodeList>
 <CodeList>
        <Id>D</Id>
        <Name>Duplicate</Name>
    </CodeList>
</CodeLists>
Data 1


<CodeLists>
    <CodeList>
        <Id>O</Id>
        <Name>Open</Name>
    </CodeList>
    <CodeList>
        <Id>P</Id>
        <Name>Pending</Name>
    </CodeList>
</CodeLists>
Data 2


So here I am going to use WSO2 Enterprise Integrator and its XSLT mediator to filter the results. First I am joining all the elements that need to be hidden into a single Synapse property.


<property name="elementsToBeHide" expression="string-join(//CodeLists/CodeList/Id, ',')" scope="default" type="STRING"/>


Then I am calling my XSLT with elementsToBeHide as a parameter.


<xslt key="conf:/xslts/xslt_FilterResults.xslt">
    <property name="elementsToBeHide" expression="$ctx:elementsToBeHide"/>
</xslt>

My XSLT file is stored in the registry. However, if you are using a Micro Integrator profile, you can add this XSLT as a local entry.  Inside my XSLT document, I am looping all code list elements and check whether each ID exists in 'elementsToBeHide' parameter. You can use the same XSLT Choose Condition to filter data based on matching or not matching scenarios. In my example, if ID is not matching to the current ID, it will be added to Code element.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sy="http://ws.apache.org/ns/synapse" xmlns:fn="http://www.w3.org/2005/xpath-functions"
 xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
 <xsl:strip-space elements="*" />
 
 <xsl:param name="elementsToBeHide" />

 <xsl:template match="/CodeLists">
  <CodeLists>
   <CodeList>
    <xsl:for-each select="CodeList">
                     <xsl:choose>
             <xsl:when test="matches($elementsToBeHide,Id)">
       <!-- match senarios -->
             </xsl:when>
             <xsl:otherwise>
       <!-- not matching -->
              <Code>
       <Name><xsl:value-of select="Name"/></Name>
       <Id><xsl:value-of select="Id"/></Id>
        </Code>
             </xsl:otherwise>
         </xsl:choose>
    </xsl:for-each>
   </CodeList>
  </CodeLists>
 </xsl:template> 
</xsl:stylesheet>


The output of the XSLT transformation is as below and it only includes elements which are not matching to the filtering data set.


<CodeLists>
 <CodeList>
  <Code>
   <Id>C</Id>
   <Name>Cancelled</Name>
  </Code>
  <Code>
   <Id>X</Id>
   <Name>Denied</Name>
  </Code>
  <Code>
   <Id>D</Id>
   <Name>Duplicate</Name>
  </Code>
 </CodeList>
</CodeLists>
Wednesday, June 06, 2018

Read XML content of the LocalEntry in WSO2 MI

Local Entry is one of the data storage points in the WSO2 Enterprise Service Bus or Micro Integrator, where you can store text strings, XML content, and File URLs.  I have been asked a question that, how can we read the content of the local entry if it as an XML file.

Below is an example to read the content of the local entry(Name: NameOfLocalEntry) and assign the value of XML elements as properties. 

Content of Local Entry:

<?xml version="1.0"?>
<Server>
<userName>chandana</userName>
<URL>blog.napagoda.com</URL>
</Server>

Synapse Configuration: 

<property name="localEntry" expression="get-property('NameOfLocalEntry')" scope="default" type="OM"/>

<property name="userName" expression="$ctx:localEntry//*[local-name()='userName']"/>
<property name="URL" expression="$ctx:localEntry//*[local-name()='URL']"/>
Monday, April 30, 2018

Payload Factory Mediators for JSON Message

WSO2 ESB/EI PayloadFactory mediator can be used to replace the contents of a message. As an example, if the backend is accepting a different message structure than what you are receiving, you can use PayloadFactory mediator to change the message structure. Other than that, if you want to transform XML payload into JSON or JSON to XML with different message structure you can use this mediator.

Recently, I faced an issue while transforming a message into JSON which is originally read from a CSV file(using Smooks Mediator). This message can have empty values in the content sometimes and such messages look like below:

<Users>
<User>
<FirstName>Chandana</FirstName>
<MiddleName/>
</Users>
</User>

I initially wrote a payload factory mediator like below:

<payloadFactory media-type="json">
        <format>
   {
  "UserInfo": {
    "fName": "$1",
    "mName": "$2"

}
}
</format>
<args>
<arg evaluator="xml" expression="//User/FirstName"/>
            <arg evaluator="xml" expression="//User/MiddleName"/>
</args>
</payloadFactory>

JSON Output from the Payloadfactory mediator :

{
  "UserInfo": {
    "fName": "Chandana",
    "mName": "{"MiddleName":null}",

}
}

So you can see that JSON output is malformed, but this will work perfectly when you have a value for MiddleName field.

To avoid this issue, what we have to do is, when we are passing arguments to the PayloadFactory mediator, we should pass text values(ex: FirstName/text()) instead of the XML object.

<payloadFactory media-type="json">
        <format>
   {
  "UserInfo": {
    "fName": "$1",
    "mName": "$2"

}
}
</format>
<args>
<arg evaluator="xml" expression="//User/FirstName/text()"/>
            <arg evaluator="xml" expression="//User/MiddleName/text()"/>
</args>
</payloadFactory>

Thursday, February 22, 2018

WSO2 ESB - How to use filter inside iterate mediator


WSO2 ESB's Iterate mediator plays a very powerful role in the Splitter Enterprise Integration Pattern. Splitter Enterprise Integration Pattern is used when messages contain multiple elements that might have to be processed in different ways. The Splitter breaks out the composite message into a series of individual messages, each containing data related to one item.

WSO2 ESB Iterate mediator split the message based on a given expression and process them separately. So think about a use case like you are getting multiple order items and you want to enrich each order item, by calling another endpoint and finally we need to aggregate all the enriched items.

There you can use the Iterate mediator and after that aggregate mediator to aggregate all the enriched items.

Example:


ESB Proxy Service:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="IteService"
       transports="http,https"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <iterate id="aggregateid"
                  preservePayload="true"
                  attachPath="//Collection"
                  expression="//Collection/Job"
                  sequential="true">
            <target>
               <sequence>
                  <enrich>
                     <source type="body" clone="true"/>
                     <target type="property" property="originalRequest"/>
                  </enrich>
                  <payloadFactory media-type="xml">
                     <format>
                        <p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org">
                           <in>$1</in>
                        </p:echoInt>
                     </format>
                     <args>
                        <arg evaluator="xml" expression="$body/Collection/Job/Id"/>
                     </args>
                  </payloadFactory>
                  <property name="SOAPAction"
                            value="&#34;echoInt&#34;"
                            scope="transport"
                            type="STRING"/>
                  <call>
                     <endpoint>
                        <address uri="https://localhost:8243/services/echo"/>
                     </endpoint>
                  </call>
                  <property xmlns:ns="http://echo.services.core.carbon.wso2.org"
                            name="echoResponse"
                            expression="$body/ns:echoIntResponse"
                            scope="default"
                            type="OM"/>
                  <enrich>
                     <source type="property" clone="true" property="originalRequest"/>
                     <target type="body"/>
                  </enrich>
                  <enrich>
                     <source type="property" clone="true" property="echoResponse"/>
                     <target action="child" xpath="$body/Collection"/>
                  </enrich>
               </sequence>
            </target>
         </iterate>
         <property name="Collections" scope="default">
            <Collections xmlns=""/>
         </property>
         <aggregate id="aggregateid">
            <completeCondition>
               <messageCount min="-1" max="-1"/>
            </completeCondition>
            <onComplete expression="$body/Collection" enclosingElementProperty="Collections">
               <respond/>
            </onComplete>
         </aggregate>
      </inSequence>
   </target>
   <description/>
</proxy>


Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <Collection>
         <Job>
            <Id>12345</Id>
         </Job>
         <Job>
            <Id>12346</Id>
         </Job>
      </Collection>
   </soapenv:Body>
</soapenv:Envelope>


Let me expand this use case. Assume we just need to enrich some of the items only. To do that, we have to use filter mediator inside the Iterate mediator. If we update our existing code with the filter mediator logic, it will never reach to the aggregate on-complete logic. The reason is aggregate mediator waits for total messages that came into the iterate mediator, but due to the filter logic, some messages aren't supposed to be included in the aggregation. To avoid this, what we can do is, we have to define this Iterate mediator inside the In-Sequence and after all the logic inside the Iterate mediator( before the tag) you have to add a loopback mediator and need to move aggregate mediator into Out-Sequence. This will call the aggregate mediator for all the messages.

Example:

ESB Proxy Service:


<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="IteFilterService"
       transports="http,https"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <iterate id="aggregateid"
                  preservePayload="true"
                  attachPath="//Collection"
                  expression="//Collection/Job"
                  sequential="true">
            <target>
               <sequence>
                  <property name="JobId"
                            expression="string(//Job/Id)"
                            scope="default"
                            type="STRING"/>
                  <filter source="$ctx:JobId" regex="[0-9]+">
                     <log level="full">
                        <property name="JobId" expression="string(//Job/Id)"/>
                     </log>
                     <enrich>
                        <source type="body" clone="true"/>
                        <target type="property" property="originalRequest"/>
                     </enrich>
                     <payloadFactory media-type="xml">
                        <format>
                           <p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org">
                              <in>$1</in>
                           </p:echoInt>
                        </format>
                        <args>
                           <arg evaluator="xml" expression="$ctx:JobId"/>
                        </args>
                     </payloadFactory>
                     <property name="SOAPAction"
                               value="&#34;echoInt&#34;"
                               scope="transport"
                               type="STRING"/>
                     <call>
                        <endpoint>
                           <address uri="https://localhost:8243/services/echo"/>
                        </endpoint>
                     </call>
                     <property xmlns:ns="http://echo.services.core.carbon.wso2.org"
                               name="echoResponse"
                               expression="$body/ns:echoIntResponse"
                               scope="default"
                               type="OM"/>
                     <enrich>
                        <source type="property" clone="true" property="originalRequest"/>
                        <target type="body"/>
                     </enrich>
                     <enrich>
                        <source type="property" clone="true" property="echoResponse"/>
                        <target action="child" xpath="$body/Collection"/>
                     </enrich>
                  </filter>
                  <loopback/>
               </sequence>
            </target>
         </iterate>
      </inSequence>
      <outSequence>
         <property name="Collections" scope="default">
            <Collections xmlns=""/>
         </property>
         <aggregate id="aggregateid">
            <completeCondition>
               <messageCount min="-1" max="-1"/>
            </completeCondition>
            <onComplete expression="$body/Collection" enclosingElementProperty="Collections">
               <respond/>
            </onComplete>
         </aggregate>
      </outSequence>
   </target>
   <description/>
</proxy>

Request:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <Collection>
         <Job>
            <Id>AAAA</Id>
         </Job>
         <Job>
            <Id>12345</Id>
         </Job>
         <Job>
            <Id>12346</Id>
         </Job>
      </Collection>
   </soapenv:Body>
</soapenv:Envelope>


Tuesday, December 19, 2017

WSO2 ESB/EI Callout Mediator Error Scenario


When using WSO2 Enterprise Service Bus, you can use Call, Send and Callout mediators to invoke a service. If you are calling multiple service calls within your meditation sequence, you have to use either Call mediator or Callout mediator.

As per the documentation, WSO2 Team is recommending to use Call mediator instead of the Callout mediator, due to much better performance. However, due to some legacy requirements, we might need to stay with Callout mediator for the time being.

In my use case, there are some mediation scenarios with mutual SSL. So if you have noticed an "UnrecoverableKeyException: Password verification failed" exception in the WSO2Carbon log file and terminal when invoking an endpoint(backend service) using callout mediator, I would recommend you to check the Java SSL keyStore Password(values of the javax.net.ssl.keyStorePassword and javax.net.ssl.trustStorePassword environment variables) in  the /bin/wso2server.sh file or relevant location.

TID: [-1234] [] [2017-12-16 13:04:28,193]  INFO {org.apache.axis2.transport.http.HTTPSender} -  Unable to sendViaPost to url[http://blog.napagoda.com] {org.apache.axis2.transport.http.HTTPSender} UUID:[d7602d4a-17ac-4b95-b459-7fec3ffa44c0]
java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
        at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:248)
        at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:285)
        at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.createSocket(SSLProtocolSocketFactory.java:155)
        at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
        at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
        at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
        at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
        at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:688)
        at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:195)
        at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:77)
        at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:451)
        at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:278)
        at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
        at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:430)
        at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:225)
        at org.apache.axis2.client.OperationClient.execute(OperationClient.java:149)
        at org.apache.synapse.message.senders.blocking.BlockingMsgSender.sendReceive(BlockingMsgSender.java:310)
        at org.apache.synapse.message.senders.blocking.BlockingMsgSender.send(BlockingMsgSender.java:216)
        at org.apache.synapse.mediators.builtin.CalloutMediator.mediate(CalloutMediator.java:180)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:89)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:56)
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:149)
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:221)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:89)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:56)
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:149)
        at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:197)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:395)
        at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:142)
        at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
        at java.security.Provider$Service.newInstance(Provider.java:1617)
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
        at javax.net.ssl.SSLContext.getInstance(SSLContext.java:156)
        at javax.net.ssl.SSLContext.getDefault(SSLContext.java:96)
        at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:122)
        ... 33 more
Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
        at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780)
        at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
        at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
        at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
        at java.security.KeyStore.load(KeyStore.java:1445)
        at sun.security.ssl.SSLContextImpl$DefaultSSLContext.getDefaultKeyManager(SSLContextImpl.java:852)
        at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:732)
        at sun.reflect.GeneratedConstructorAccessor131.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.security.Provider$Service.newInstance(Provider.java:1595)
        ... 38 more
Caused by: java.security.UnrecoverableKeyException: Password verification failed
        at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:778)
        ... 48 more

View Counts

Followers