3. ESB:
An enterprise service bus (ESB) is a "software architecture"
model used for designing and implementing communication
between mutually interacting software applications in a
service-oriented architecture (SOA).
An Enterprise Service Bus (ESB) is fundamentally an architecture. It is a set of rules and principles
for integrating numerous applications together over a bus-like infrastructure.
4. Mule Message Anatomy
The MuleMessage is the object used to pass any kind of data through Mule. It
enables generic access to any type of message format an encapsulates properties
and attachments associated with the current event being processed.
A Mule message consists of three parts:
● the header, which contains sets of named properties, partitioned into
scopes
● the payload, which consists of business-specific data
● optional attachments
When a message transits in Mule, it is in fact an event (for example, an instance of
org.mule.api.MuleEvent) that’s moved around. This event carries not only a reference
to the actual message itself (for example, an instance of org.mule.api.Mule-
Message), but also the context in which this message is processed.
5. MuleStudio
● Graphical drag-and-drop environment shrinks on-ramp
to days, not weeks
● Visual debugging and auto-documentation speeds
project delivery
● Two-way editing between the graphical and XML
views eliminates the trade-off between ease-of-use
and control
● One-click deployment of applications to the Mule
runtime, on-premises or in the cloud
6. What is mule flow?
A flow is the construct within which you link together
several individual elements to handle the receipt,
processing, and eventual routing of a message. You can
connect many flows together to build a complete application
which you can then deploy on premise, on Mule or another
application server, or in the cloud.
At the simplest level, flows are sequences of message-
processing events. A message that enters a flow may pass
through a wide variety of processors.
7. Subflow vs Private Flow?
The primary reason for using a private flow instead of a
subflow is to define in it a different exception strategy
from the calling flow (something that is impossible with a
subflow).
Another reason is that subflows aren’t materialized at runtime
and, as such, don’t have specific statistics or debug properties
attached to them and can’t be controlled or monitored
independently. Private flows offer all this.
8. Composite message source
<vm:inbound-endpoint path="payment-processor" />
<composite-source>
<jms:inbound-endpoint queue="payment-processor" />
<http:inbound-endpoint host="localhost"
port="8080"
path="payment-processor" />
</composite-source>
While not common, generic endpoints that aren’t
prefixed with a transport’s namespace can be used.
This might be useful if you want to use a different
transport depending on the environment (for example,
using the VM transport instead of the JMS transport
depending on where the app is deployed).
10. MEL
It’s valid to place several statements in the same expression, as long
as they’re separated by semicolons. The value of the last statement is
used as the value of the whole
expression. For example, evaluating the following expression:
targetDir = new java.io.File(server.tmpDir, 'target');
targetDir.mkdir();
targetDir
returns targetDir as a java.io.File (and also ensures that it exists).
With MEL, you can do the following:
● Use any Java class available on the classpath;
● Easily navigate lists, maps, arrays, and bean properties;
● Express complex logic, including ternary expressions;
● Define local variables and use them in statements;
#[message.inboundProperties.'locale' == 'en_us']
12. Mule message scopes
Mule has the following scopes:
1. Inbound - properties/headers coming from the client's request
2. Invocation - used mostly internally by Mule for the duration of this service's call, not typically utilized
nor meant for end-user. They are strictly bound to a flow.
3. Outbound - values deemed to be sent out from this service. They become either request properties for
the next service, or response properties in case of a synchronous invocation
4. Session - values which are passed from invocation to invocation. This scope is bound to the in-flight
message and can therefore span multiple flows, as it follows the message through them (think of Java’s
ThreadLocal mechanism but with a MessageLocal twist).
13. A bit more on Message Scopes
When using http endpoints Mule session
is stored as a custom http header so
there are some limitations in header
size. HTTP specification does not limit
length of headers at all. However web-
servers do limit header size they accept,
throwing “413 Entity Too Large” if it
exceeds or you can also get a java.io.
SocketException: Broken Pipe in the
client side
14. What is Session in Mule?
The mule session has nothing to do with the Java EE session that is shared across
threads.
Mule Session Properties
● Session Properties can be set by you.
● Session properties are preserved when crossing a “transport barrier”.
15. Component Lifecycle
Components have a lifecycle like any other object in the Mule registry. Lifecycle can be configured by
adding one or more lifecycle interfaces to your component. Since Mule 3.0 JSR-250 annotations can
be used to configure initialise and destroy methods.
ONE INTERFACE TO RULE THEM ALL If your custom object needs to implement the four
standard lifecycle interfaces, you can save yourself a lot of typing by implementing org.mule.api.
lifecycle.Lifecycle, which extends the four standard ones.
16. Component Lifecycle
Components have a lifecycle like any other object in the Mule registry. Lifecycle can be configured by adding
one or more lifecycle interfaces to your component. Since Mule 3.0 JSR-250 annotations can be used to
configure initialise and destroy methods.
Lifecycl
e
Description Interface Annotation
initialise The first lifecycle method called once any injectors on the component
have been called. This means any properties on the component will
be set before the initialise lifecycle is called.
org.mule.api.lifecycle.Initialisable javax.annotation.PostConstruct
start This is called when the MuleContext is started. org.mule.api.lifecycle.Startable
stop This is called when the MuleContext is stopped, or the service that
owns this component is stopped.
org.mule.api.lifecycle.Stoppable
dispose Called as the object is being disposed off. Typically this happens
because either the MuleContext is shutting down or the service that
wraps this component was unregistered.
org.mule.api.lifecycle.Disposible javax.annotation.PreDestroy
17. Configuring Java Components
Configuration options:
● An ObjectFactory is used to obtain the Java service component implementation.
● EntryPointResolvers can be configured to define how Mule services should invoke the
component methods when processing a message.
● A custom LifecycleAdaptor can be configured to customize the way in which the component
implementation is initialized and disposed.
● Bindings can be configured to bind component interface methods to endpoints. These
endpoints are then invoked synchronously when the method is called.
19. Entry Point Resolvers
At a high level, Mule uses three types of Entry Point Resolvers:
● Reflection
● Annotated
● Callable interface
The LegacyEntryPointResolverSet is used if no other resolver is configured. It contains a
combination of different resolvers.
20. Lifecycle Adapters
You can configure your Java component to use a custom lifecycle adaptor.
Example:
<component class="org.my.PrototypeObjectWithMyLifecycle">
<custom-lifecycle-adapter-factory class="org.my.MyLifecycleMuleAdapterFactory"/>
</component>
21. Bindings
Components can use bindings to call an external service during execution. The bindings used with a
Java component bind a Java interface, or single interface method, to an outbound endpoint.
<component>
<spring-object bean="toscaCostBinding"/>
<binding interface="com.thomascook.tosca.service.cost.CostProviderService"
method="callAvailProviderService">
<http:outbound-endpoint name="soa-bapi-tosca-service-avail"
address="${bapi.tosca.provider.endpoint}"
method="POST"
encoding="UTF-8"
connector-ref="httpConnector"
</http:outbound-endpoint>
</binding>
22. Transaction Management
Mule supports both Single Resource transactions as well as XA-transactons:
<flow name="transactedMulticastingRouterService" >
<jms:inbound-endpoint queue="billingData">
<xa-transaction action="ALWAYS_BEGIN" />
</jms:inbound-endpoint>
<component class="com.prancingdonkey.component.BillingService" />
<jdbc:outbound-endpoint connector-ref="operationalDb"
queryKey="operationalBillingInsert">
<xa-transaction action="ALWAYS_JOIN" />
</jdbc:outbound-endpoint>
<jdbc:outbound-endpoint connector-ref="warehouseDb"
queryKey="warehouseBillingInsert">
<xa-transaction action="ALWAYS_JOIN" />
</jdbc:outbound-endpoint>
</flow>
23. Transaction Management Considerations
Configuration Tips and Tricks
● Operations that occur inside a transaction execute synchronously. You cannot build an asynchronous flow
inside a transaction.
● Mule creates a transaction for the first outbound connector that can be part of a transaction (JMS, JDBC, VM).
All the outbound connectors in the flow that appear after the first outbound connector, and which use the
same type of resource, then participate in the transaction. Where such a following connector does not use
the same type of resource (such as where a JDBC connector follows a JMS connector), the transaction
initiated by the first outbound connector fails. To avoid execution failure in such a situation, configure the
secondary outbound connector outside the transaction by setting the action attribute to NOT_SUPPORTED.
● Mule can manage non-transactional outbound connectors. By default, an outbound connector from a non-
transactional transport ignores an active transaction rather than rejecting it. For example, let’s assume
here is a file transport in the end of the flow. Mule processes messages it receives from the VM queue
synchronously and transactionally. The file transport is not transactional thus, writing to the file is not part of
the transaction. However, if a message throws an exception while Mule is creating the file, Mule rolls back
the transaction and reprocesses the message.
24. JTA
USING XA TRANSACTIONS IN A CONTAINER
If you’re running Mule embedded in an application that’s deployed in a container, such as
an application server or servlet container, you have the option to use the container’s JTA
implementation (if one exists).
If you need access to a JTA provider that isn’t explicitly supported by Mule, you can use
the jndi-transaction-manager. This allows you to specify the JNDI location of a JTA
implementation for Mule to use.
25. Rolling back
Finally, transactional demarcators also support the use of exception
handlers. For instance, let’s say that you want to log a message when the transaction goes wrong. You
can do that by adding a rollback-exception-strategy to the transactional element
and including a logger in it:
<subflow name="transactionalFlowWithLogger">
<transactional action="BEGIN_OR_JOIN">
<jms:outbound-endpoint queue="billingOrders"/>
<jms:outbound-endpoint queue="productionOrders"/>
<rollback-exception-strategy>
<logger message="Problem in the transaction!" />
</rollback-exception-strategy>
</transactional>
</subflow>
26. Pool or not to Pool components
Pooled components decrease throughput. Pools of components are almost always less
performant than singletons. Under load there will be contention of threads for
objects in the pool. There’s also overhead in growing the pool. Use singleton
components unless you have a good reason not to.
<pooled-component class="org.my.PrototypeObject">
<pooling-profile exhaustedAction="WHEN_EXHAUSTED_FAIL"
initialisationPolicy="INITIALISE_ALL" maxActive="1" maxIdle="2" maxWait="3" />
</pooled-component>
Pooling ensures that each component instance will handle only one request at a time. It’s
important to understand that this pooling profile, if used, influences the number of
requests that can be served simultaneously by the service.
Makes sense when::
The component is expensive to create—
It’s important that the total number of
component
object instances remains under control.
The component is thread-unsafe—It’s
essential to ensure that only one thread at
a time will ever enter a particular instance
of the component.
28. What if we need to store some data across
multiple calls and across multiple
messages?
Use ObjectStore for this!
An object store is a facility for storing objects in Mule. Mule
uses object stores whenever it needs data to persist for
later retrieval. Internally, Mule uses object stores in
various filters, routers, and other message processors that
need to store state between messages. In most cases, Mule
creates and manages object stores automatically, so no user
configuration is necessary.
If you want to use a database to persist Mule data, look no
further than the org.mule.transport.jdbc.store.
JdbcObjectStore.
29. Examples of where persistence can be very
desirable in Mule
In most cases, Mule creates and manages object stores for you, so
no configuration is necessary. However, you may explicitly
configure an object store in the following cases:
1. When configuring a custom component that must use an
object store to persist information.
2. When configuring an idempotent message filter or until
successful scope.
<until-successful objectStore-ref="objectStore"
maxRetries="5"
secondsBetweenRetries="60">
<outbound-endpoint ref="retriableEndpoint" />
</until-successful>
3. When storing or retrieving information from a Mule flow
through the Object Store module, available as an extension.
ObjectStore
In-memory Persistent
30. Storing objects in the Registry
If you need to store runtime data that is available across the application, you can store the data as objects in the
Registry . You can get a handle to the Registry from anywhere that you have access to the MuleContext , as in most
Mule ESB entities. For example, you could store the object as follows:
muleContext.getRegistry().registerObject("foo", new MyFoo());
When using a Spring XML configuration, the registry is created and populated for you. In that case, it’s composed of
a Mule-specific transient registry that delegates to a read-only Spring bean factory:
private MessageService lookupMessageService(MuleContext muleContext) {
return muleContext.getRegistry().lookupObject("MessageServiceNurvis");
}
@Service("MessageServiceNurvis")
public class MessageServiceNurvis extends AbstractMessageService {
…
}
In terms of software
design, dependency
injection should be
preferred to registry
lookups.
31. Working with different persistence providers
Mule has an extensive support for JDBC components(relational DBs) as well as many other non-relationals components.
Since mongo is a subject of a lot of watercooler talking in Checkout lately, let’s see how Mule can interact with mongo:
<mongo:config name="mongoDB"
database="prancingdonkey"
username="${mongo.user}"
password="${mongo.password}"
host="${mongo.host}"/>
<jms:activemq-connector name="jmsConnector"
specification="1.1"
brokerURL="${jms.url}"/>
<flow name="saveCoolingAlerts">
<jms:inbound-endpoint topic="cooling.alerts" connector-ref="jmsConnector"/>
<mongo:json-to-dbobject/>
<mongo:insert-object collection="cooling_alerts" config-ref="mongoDB"/>
</flow>
32. Threads and Pools
By default, Mule ensures that only a single thread can modify a message at any point in
time. Message copying is a common way to pass messages between threads.
Tuning thread pools
Thread pools aren’t configured directly but via the configuration of threading profiles.
Threading profiles are organized in a hierarchy of configuration elements whose
scope varies from the most generic (Mule-level configuration) to the most specific
(connector-level or flow-level).
<configuration>
<default-threading-profile
maxBufferSize="100" maxThreadsActive="20"
maxThreadsIdle="10" threadTTL="60000"
poolExhaustedAction="ABORT" />
</configuration>
33. Possible Threading Scenarios
In fully
synchronous mode,
the receiver thread is
used throughout all
the stages of the
message processing.
1
34. Possible Threading Scenarios
When a flow needs to return a response
to the caller, its message source is configured
to be request-response. It’s still possible
to use the dispatcher thread pool by configuring
the exchange-pattern on the outbound endpoint
to be one-way. Notice how the receiver
thread is used for calling the message
processors in the flow; this makes sense
when you consider that the last processor
in the flow will return the result to the caller
on that thread.
2
35. Possible Threading Scenarios
If only
the dispatcher is
synchronous, the
receiver thread is used
up to the flow in which
a thread is taken from
the pool and used
throughout the
dispatcher.
3
36. Processing Strategy
<flow processingStrategy="synchronous">
<vm:inbound-endpoint path="in" exchange-pattern="one-
way"/>
<vm:outbound-endpoint path="out" exchange-pattern="one-
way"/>
</flow>
By explicitly setting the processingStrategy for the above flow to synchronous, you
tell Mule to bypass the default queued asynchronous behavior and use a single thread
per every request.
Events generated from one-way endpoints will be executed
asynchronously even if the calling flow is expecting a response from the private flow.
38. Reliability Pattern
-Do we use it?
-No
-Why?
-Because bapi internal modules designed in a way to support independent use.
So that the external component(like web-api) can call, for instance,
nurvis module directly overpassing the central entry-point(service module)
-Ok, what is it anyway?
39. Reliability Pattern
Messages sent over VM endpoints can be made
transactional and persisted to disk. This enables
you to layer-in reliability and decouple your
flows without the need for an external
messaging broker.
This approach is analogous to using a JMS
queue to decouple the flows. The benefit
here is that you don’t incur the administrative
and performance overheads of running
a JMS broker to reap the benefits of durable,
asynchronous messaging.
You can use the Java Virtual Machine (VM) transport for intra-JVM
communication between Mule flows. This transport by default uses in-
memory queues but can optionally be configured to use persistent
queues. Note: VM file persistency does not work on clusters.
<vm:inbound-endpoint path="call-cost-bapi-nurvis"
connector-ref="vmConnector"
exchange-pattern="request-response"
disableTransportTransformer="true">
40. Reliability Pattern
Considerations:
● Reliability has performance implications;
● If the outbound transport in the reliable acquisition flow is not
transactional (for example, a flow from file-to-FTP), the only
way to ensure message delivery is to turn off threading on the
respective connector. To understand this, imagine if an exception
occurs while sending the message to the outbound endpoint (this
might happen if the FTP server is down). If threading is not turned
off, the caller may not notice the exception. That's because the
exception occurred in a different thread, and there is no way that one
thread can see exceptions that occur in another thread. The
following example shows how to turn off threading in the connector:
<ftp:connector name="ftpConn">
<dispatcher-threading-profile
doThreading="false"/>
</ftp:connector>
41. Scripting
Mule lets you use any JSR 223–compliant script engine such as Groovy, JavaScript,
Jython, or JRuby to implement custom transformations.
<flow name="rhino-message-enritchment-service">
<inbound-endpoint
address="vm://rhino-message-enritchment-service.in"
exchange-pattern="request-response" />
<scripting:component>
<scripting:script engine="javascript">
<scripting:text>
if (payload.search("STATUS: CRITICAL") != -1) {
message.setProperty("PRIORITY", 'HIGH');
}
result = message
</scripting:text>
</scripting:script>
</scripting:component>
</flow>
Variables made available to a scripting
context:
message
payload
originalPayload
muleContext
eventContext
id
result
*Alternatively a reference to a script can be provided.
43. Mule deployment options
1. Embedded(run on a AS of choise, usually JBoss)
Because the context listener took care of starting Mule, you have no reference to the context, unlike the case in which you
bootstrap Mule yourself. This is why the Mule client is instantiated with a context retrieved from the servletContext:
muleContext = (MuleContext) getServletContext()
.getAttribute(MulePropertis.MULE_CONTEXT_PROPERTY);
Also be sure to use Servlet inbound endpoints instead of HTTP inbound endpoints otherwise Mule will open another
HTTP server inside the web container. You want Mule to use the servlet container for its inbound HTTP requests.
2. Standalone(the way we use it in Checkout)
Mule relies on the Java Service Wrapper from Tanuki Software to control its execution.
The Java Service Wrapper enables a Java Application to be run as a Windows Service or UNIX Daemon.
Because of the wrapping nature of the wrapper, the system properties you’ll try to set with the classic -Dkey=value construct will be
applied on the wrapper itself. They won’t be set on the Mule instance that’s wrapped. The solution is to use a specific construct such
as this one: -M-Dkey=value.
44. Deployment considerations
VM endpoints don’t communicate between
applications
The “VM” part of VM transport mistakenly suggests
virtual machine. Given that many Mule applications can run in the
same Mule standalone server, and therefore in the same Java
Virtual Machine, you may think that you can use VM endpoints to
communicate with applications in the same server. But you would
be wrong.
The VM transport is an in-memory transport, and
therefore each application has a different set of VM endpoints
that are completely local to that application.