Mule 2.x JCR Transport Examples
Introduction
The transport comes with several examples grouped in a unique configuration file. To load and run it do the following:
- Ensure $MULE_HOME is correctly set
- Open a command line terminal and go to the examples directory
- Run mvn install
- Run jcr-example or jcr-example.bat, depending on your OS.
The following chapters detail the different parts of this configuration.
For the test, a transient JackRabbit JCR repository is used: it is instantiated via a Spring container configuration and injected directly in the connector of the transport, as shown hereafter:
<spring:beans>
<spring:import resource="jcr-example-beans.xml" />
</spring:beans>
<jcr:connector name="jcrConnector" repository-ref="jcrRepository"
username="admin" password="admin" eventTypes="31" />
Storing Content
This example shows how to store content in different JCR targets, ie node or property. In the example, data is entered by the user in the console and gets dispatched to three different VM queues, each of them consumed by a component that highlights a particular JCR storage target.
The following demonstrates an endpoint that receives data and saves it in an already existing property of the JCR container:
<service name="jcrStoreToProperty">
<inbound>
<vm:inbound-endpoint path="storeInProperty" />
</inbound>
<outbound>
<pass-through-router>
<jcr:outbound-endpoint path="/example/targetProperty" />
</pass-through-router>
</outbound>
</service
Here is an endpoint that receives data and saves it as a node of type
nt:resource that is auto-created the first time, then updated on any subsequent calls:
<service name="jcrStoreToSingleNode">
<inbound>
<vm:inbound-endpoint path="storeInSingleNode" />
</inbound>
<outbound>
<pass-through-router>
<jcr:outbound-endpoint path="/example" nodeRelPath="targetSingleNtResourceNode"
nodeTypeName="nt:resource" >
<property key="jcr:mimeType" value="text/plain" />
</jcr:outbound-endpoint>
</pass-through-router>
</outbound>
</service>
This last example shows an endpoint that receives data and saves it as a new child node of type nt:unstructured:
<service name="jcrStoreToNewChildNode">
<inbound>
<vm:inbound-endpoint path="storeInNewChildNodeEachTime" />
</inbound>
<outbound>
<pass-through-router>
<jcr:outbound-endpoint path="/example" nodeRelPath="targetMultipleUnstructuredNode"
alwaysCreate="true" nodeTypeName="nt:unstructured" />
</pass-through-router>
</outbound>
</service>
Event Serialization
If you tried the previous example, you have noticed that a lot of XML has been output to the console every time you have entered text in the console.
This is because another component is listening to JCR events (observations) and is outputting them to the console, after having serialized them in XML:
<service name="jcrEventDumper">
<inbound>
<jcr:inbound-endpoint path="/example" contentPayloadType="FULL" />
</inbound>
<echo-component/>
<outbound>
<pass-through-router>
<stdio:outbound-endpoint system="OUT" transformer-refs="ObjectToXml"/>
</pass-through-router>
</outbound>
</service>
Reading Content
The previous examples shows an inbound endpoint that receives notifications of changes but you might need to actively read content from any path in your JCR repository, upon the reception of any kind of inbound event.
The following shows how it is possible to achieve this by using a global endpoint that defines a root path under which the reading operations will be performed and a simple component (scripted in this example) that extracts from the current event what is required to established the desired specific path. Indeed, this examples shows how to turn Mule into a (very inefficient) JCR-backed image server:
<jcr:endpoint name="jcrImages" path="/example/images">
<and-filter>
<jcr:node-name-filter pattern="jcr:content"/>
<jcr:property-name-filter pattern="jcr:data"/>
</and-filter>
</jcr:endpoint>
<script:script name="httpImageFetcher" engine="groovy">
<script:text><![CDATA[
def imageName = message.payload.substring(8)
message.setStringProperty("nodeRelPath", imageName)
return eventContext.requestEvent("jcrImages", -1).payload ]]>
</script:text>
</script:script>
<service name="jcrHttpContentFetcher">
<inbound>
<http:inbound-endpoint host="localhost" port="8080"
path="images" synchronous="true" >
<not-filter>
<custom-filter class="org.mule.transport.http.filters.HttpRequestWildcardFilter">
<spring:property name="pattern" value="/favicon.ico"/>
</custom-filter>
</not-filter>
<response-transformers>
<message-properties-transformer>
<add-message-property key="Content-Type" value="image/gif"/>
</message-properties-transformer>
</response-transformers>
</http:inbound-endpoint>
</inbound>
<script:component script-ref="httpImageFetcher" />
</service>
Browsing
http://localhost:8080/images/mule.gif or
http://localhost:8080/images/jackrabbit.gif should return a pretty image!
Streaming Content
The JCR connector is capable of streaming content in and out of the repository. For this, the endpoint's transport used to receive or return the content as a stream must support streaming.
Streaming is handled automatically by the JCR transport. If it receives a Mule message that contains an input stream it will directly store it in the repository, without first transforming it as a byte array. Similarly, if the content stored in the repository was of binary type, the transport will extract it as a stream, leaving to the rest of the transports involved in processing the event the task of streaming it back to the caller.