Custom Datasource & Class Mediators
Quick Guide: Define and Access a Custom Datasource in WSO2 APIM & Class Mediator
Intro
This medium narrates on how to define an external data source and then access and use them within custom class mediators of WSO2 API-M Servers.
As an example, we have a use case in which we are required to fetch additional data from an external data source to process and retrieve related data for a particular API request.
The data source which is used to store and retrieve the additional data is maintained in-house, but we need to access them in order to retrieve all related data with the class mediator.
To fulfill the above-mentioned requirement/use-case we can implement and config the following
- Define our custom data source in the
master-datasource.xml
- Develop a custom class mediator
- Develop an
in-sequence
and execute the developed class mediator
Guide
Define Custom Datasource
First, we will define our custom in-house data source configurations in the master-datasource.xml
which is placed inside the <APIM>/repository/conf/datasource
directory.
Given below is a sample JNDI data source configuration
<datasource>
<name>InHouse_DB</name>
<description>The datasource used for registry and user manager</description>
<jndiConfig>
<name>jdbc/InHouseDB</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://localhost:3306/custominhousedb?useSSL=false</url>
<username>root</username>
<password>root</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>80</maxActive>
<maxWait>60000</maxWait>
<minIdle>5</minIdle>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
</configuration>
</definition>
</datasource>
With the above-mentioned changes, we will be able to look up and access the JNDI source configurations programmatically.
Develop a Custom Class Mediator
Next, we will be developing a custom class mediator to create a connection with our in-house data source and to retrieve data.
Given below is a sample code block developed to create a database connection with the defined JNDI source configurations
@Override
public boolean mediate(MessageContext synCtx) {
// sql connection variables
Object jndiObj = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null; try {
jndiObj = new InitialContext().lookup("jdbc/WSO2ExternalDB"); DataSource externalDatasource = (DataSource) jndiObj;
conn = externalDatasource.getConnection();
stmt = conn.createStatement(); // given below is a sample block on using the datasource connection to connect
// with the external datasource
// rs = stmt.executeQuery("SELECT version()");
// if (rs.next()) {
// String version = rs.getString(1);
// synCtx.setProperty("ExternalResults", version);
// log.info("Database Version : " + version);
// } // TODO: implement mediation logic } catch (NamingException e) {
log.error("Error while getting datasource configurations", e);
} catch (SQLException e) {
log.error("Error while accessing DB connection", e);
} finally {
// close all the datasource connections
} return true;
}
Develop In-Sequence
At last, we will develop an in-sequence
to invoke and execute our custom class mediator implementation for that particular API.
Given below is a sample sequence
defined to invoke the custom class mediator …
<sequence xmlns="http://ws.apache.org/ns/synapse" name="in-sequence-sample">
<log level="custom">
<property name="TRACE" value="API Mediation Extension" />
</log> <!-- defining the class mediator -->
<class name="com.sample.mediator.ClassMediatorJNDIDatasource" /> <!-- sample get-property -->
<log level="custom">
<property name="Database version from class mediator : " value="get-property('ExternalResults')"/>
</log>
</sequence>
Add the in-sequence
to the required API and invoke the flow.