Custom Persistent Object Store in Mule
When you create your own customized Object Store, you can explicitly configure it to be persistent. That way, duplicate messages will be discarded.
Join the DZone community and get the full member experience.
Join For FreeObject Store is used in Mule to store and access objects easily in or across Mule applications. Internally, Mule uses Object Store in filters, routers, and message processors to store message states. Also, Mule provides an Object Store Connector to access the data stored in the Object Stores.
Mule provides two types of object stores:
- In-memory store. Stores objects in local Mule runtime memory. Objects are lost on the shutdown of Mule runtime.
- Persistent store. Mule persists data when an object store is explicitly configured to be persistent. In a standalone Mule runtime, Mule creates a default persistent store in the file system.
Mule provides its own JdbcObjectStore to persist data in an external database. The main purpose of this article is to create our own customized Object Store.
Here are the things you will need.
Object Store Connector
If you have not installed Object Store Connector in your Anypoint Studio, please install it from the Anypoint Exchange.
H2 Database
Please download and start H2 database. I am using H2 as a standalone server in this application. Upon starting the H2 engine, you can browse http://localhost:8082 and it will open the H2 console. Please fill the following values as shown in the figure below:
JDBC URL: jdbc:h2:tcp://localhost/~/db_objectstore.
User Name: admin.
Password: admin.
Hit connect. Please enter the following script in the SQL area of the console and run it. It will create a simple table named key_value
.
Let's Get Our Hands Dirty
The easiest way to create an Object Store is to implement the ObjectStore interface. You can find the complete project here and the Custom Object Store here.
Mule Application
Before creating the flow, let's configure the DataSource and our Custom Object Store. Please check the code snippet below:
<spring:beans>
<!-- Data Source configuration -->
<spring:bean id="dataSource" name="dataSourceBean"
class="org.h2.jdbcx.JdbcDataSource">
<spring:property name="URL"
value="jdbc:h2:tcp://localhost/~/db_objectstore" />
<spring:property name="user" value="admin" />
<spring:property name="password" value="admin" />
</spring:bean>
<!-- My Object Store -->
<spring:bean id="myObjectStore" class="com.anupam.os.MyObjectStore"
init-method="init" name="myObjectStoreBean">
<spring:property name="dataSource" ref="dataSource" />
<spring:property name="insertQueryKey"
value="insert into KEY_VALUE (K,V) values (?,?) " />
<spring:property name="selectQueryKey"
value="select k,v from KEY_VALUE where k = ?" />
<spring:property name="deleteQueryKey"
value="delete from KEY_VALUE where K = ?" />
<spring:property name="clearQueryKey" value="delete from KEY_VALUE" />
</spring:bean>
</spring:beans>
I am configuring everything as Spring Bean. In the first part (Line 3), I am configuring my DataSource using H2 database.
In the second part (Line 13), I am configuring my Custom Object Store. Note that it takes a reference to the DataSource at Line 16.
The Mule application is very simple. I have two simple flows.
object-datastore-test
In this flow, I try to do a CRUD operation using my Custom Object Store:
Upon sending a request on http://localhost:8081/objectstore?k=1&v=android, the Object Store will store, retrieve, and remove the values (param v in the URL). Note that the k should be unique, as I put a unique constraint in the database table.
object-datastore-idempotent-filter
In this flow, I am using an Idempotent Filter. The purpose of Idempotent Filter is to discard duplicate messages. Internally, it uses Object Store to store the unique identity of each message received. The ID can be configured using MEL expression. So, each time it receives a new message, it compares the ID of the new message with existing IDs in the Object Store. If it finds that there is already an existing ID, it simply discards the new message.
Note: In this code example, I am storing the value of the message, as well. The value is nothing but the payload, but it's not mandatory to store value.
Here is the simple flow diagram:
Here is how to configure the Idempotent Message Filter:
<idempotent-message-filter doc:name="Idempotent Message" idExpression="#[flowVars.id]" valueExpression="#[payload]">
<spring-object-store ref="myObjectStore" />
</idempotent-message-filter>
Note that I am using the Spring object reference in the code above.
Here is a sample example of the request:
When sent the first time, you should receive a response like, "Message passed thru the filter." Now, send it again and the filter will discard the message, as it is a duplicate.
Conclusion
In this example, I have shown how to create a custom Object Store using H2 for data persistence. However, it is not only restricted to H2. You can use another database also and, if necessary, just modify the codes for specific database compatibility.
Opinions expressed by DZone contributors are their own.
Comments