Reputation: 5709
With Mule, is there a way to intercept all flows? My use case is to look at a flow name and if the flow name matches a particular parameter in the http request, I need to take some action. I don't want to write interceptor configuration for every flow. That would be too tedious and not ideal.
I'd like something like a Spring AOP cross cutting across all flows in the application and then write a single java class that can be called by Mule before the flow executes. I would check the flow name there and if it matches the parameter in the request, I can take an action, otherwise, I won't be required to do anything.
I am new to Mule. Could someone please point me in the right direction?
Upvotes: 1
Views: 1446
Reputation: 1942
You can use Server Notifications to do this, I have already implemented a similar approach that do listen to PRE/AFTER invoke a HTTP endpoint.
Here is the code:
<spring:beans>
<spring:bean name="MuleMessageProcessorNoticationBean" class="com.alexfrndz.MPLogger"></spring:bean>
</spring:beans>
package com.alexfrndz;
import org.mule.api.MuleEvent;
import org.mule.api.MuleMessage;
import org.mule.api.context.notification.MessageProcessorNotificationListener;
import org.mule.api.processor.LoggerMessageProcessor;
import org.mule.api.processor.MessageProcessor;
import org.mule.context.notification.MessageProcessorNotification;
import org.mule.endpoint.AbstractEndpoint;
import org.mule.endpoint.DefaultOutboundEndpoint;
import org.mule.processor.AsyncDelegateMessageProcessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
public class MPLogger implements MessageProcessorNotificationListener<MessageProcessorNotification> {
private Logger log = Logger.getLogger(MPLogger.class);
private long startTime = System.currentTimeMillis();
private long endTime = System.currentTimeMillis();
@Override
public void onNotification(MessageProcessorNotification m) {
MuleEvent ev = m.getSource();
MuleMessage msg = ev.getMessage();
Object payload = msg.getPayload();
String ref = payload != null ? payload.toString() : "null";
MessageProcessor proc = m.getProcessor();
boolean inc = true;
if (m.getAction() == MessageProcessorNotification.MESSAGE_PROCESSOR_PRE_INVOKE) {
startTime = System.currentTimeMillis();
}
if (m.getAction() == MessageProcessorNotification.MESSAGE_PROCESSOR_POST_INVOKE) {
long executionTime = System.currentTimeMillis() - startTime;
AbstractEndpoint ep = (AbstractEndpoint) proc;
log.info("Http call to : "+ ep.getName() + " took " + executionTime + "ms response time");
}
boolean outgoing = proc instanceof DefaultOutboundEndpoint;
if (inc) {
if (outgoing) {
AbstractEndpoint ep = (AbstractEndpoint) proc;
log.warn(msg.getMessageRootId() + " [OUTBOUND] Message " + ref + " -> " + ep.getEndpointURI());
ep.getResponseTimeout();
} else {
log.warn(msg.getMessageRootId() + " [PROCESSING] Message " + ref + " <> " + proc.getClass().getSimpleName());
}
}
}
}
From the code above, you could play around to get the name of the message processor or flow and intercept the payload.
How this helps
Upvotes: 2
Reputation: 8311
So, if you want to control the flows based on http url you can do use a common flow and use choice as the following :-
<http:listener-config name="HTTP_Listener_Configuration" protocol="HTTP" host="0.0.0.0" port="${port}" basePath="mainpath" doc:name="HTTP Listener Configuration"/>
<flow name="Entry_Point">
<http:listener config-ref="HTTP_Listener_Configuration" path="/*" doc:name="HTTP" parseRequest="false">
<http:error-response-builder statusCode="404" reasonPhrase="Path Not Found"/>
</http:listener>
<set-variable variableName="requestUri" value="#[message.inboundProperties['http.request.uri'].replace('/mainpath/','')]" doc:name="Variable"/>
<logger level="INFO" message="PATH :-> #[requestUri]" doc:name="Logger" />
<choice doc:name="Route Message By Path">
<when
expression="#[regex('service/.+', requestUri, java.util.regex.Pattern.CASE_INSENSITIVE)]">
<flow-ref name="flow1" doc:name="flow1" />
</when>
<when
expression="#[regex('audit/.+', requestUri, java.util.regex.Pattern.CASE_INSENSITIVE)]">
<flow-ref name="flow2" doc:name="flow2" />
</when>
//////////// so on
But if you want to control your flow, based on HTTP request, then based on the request you can use XPATH(incase of XML request) or JSON to object transformer(incase of JSON request) and extract the element value, and based on the element value you can route to the flows using Choice router
Upvotes: 1
Reputation: 21
Why dont you use simple "Choice router". Based on the request parameter you set at the input ,the appropriate flow can be invoked matching the condition.
Upvotes: 0
Reputation: 712
what was suggested could work!
BUT, base on your description of the scenario it sound to me that you'll be better of using the APIkit.
Of course it probably has a lot more features that you need, but in short based on a REST API definition (this is the part of http request) it will automatically route it to the flow that implements the that part of the API.
The cool thing is that you just need to write the RAML and the studio will generate the flows for you.
Hope this helps ;)
Upvotes: 0
Reputation: 520
i would like to suggest you an approach to meet the requirement.
Define a common flow with http as an entry point and after that define a choice router which evaluates the parameter which was considered . SO based on the condition evaluation call the respective flow using flow-ref.
Upvotes: 0