Reputation: 23
I need to intercept ALL the Spring Integration components at runtime and should be able to fetch the attribute values in order to log a meaningful message. For example:
<int-http:outbound-gateway url="someURL" http-method="GET"
request-channel="channel1"
expected-response-type="com.example.Test"
message-converters="customMessageConverters">
<int-http:uri-variable name="testId" expression="headers.testId"/>
</int-http:outbound-gateway>
In the example above, I need to intercept int-http:outbound-gateway and capture the value for url, request-channel and expected-response-type. We need to do this for all http outbound gateway.
Similarly, for all other components like int-http:inbound-gateway, int-http:inbound-channel-adapter, int:transformer, int:header-enricher, int:chain, int:router, etc.
I have tried creating a custom class implementing BeanPostProcessor - postProcessAfterInitialization method. Checked for the bean name to be matching with the component, and tried to retrieve all the details but the beans are created and this method is called at the server startup itself. My requirement is to capture the flow as and when the user navigates and any particular route is being called. Also I am not able to find Java class name for all the component apart from the below. Still finding for the rest. org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway for int-http:inbound-gateway, org.springframework.integration.http.outbound.AbstractHttpRequestExecutingMessageHandler for int-http:outbound-gateway
Update: I have tried the below but cant see any extra output in logs with respect to message history. Is anything missing in the above code?
<int:message-history />
<int:logging-channel-adapter id="logging"
log-full-message="true" logger-name="message.history" level="DEBUG"/>
<int:wire-tap pattern="*" order="3" channel="logging" />
or
<int:message-history />
<int:logging-channel-adapter id="logger"
log-full-message="true" logger-name="message.history" level="DEBUG"/>
<int:channel id="wiretapChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
Also, I am trying to inject LogMessage into wire-tap inorder to perform some additional tasks from MessageHistory data. But the control doesn't enter handleMessage method. Please help.
<bean id="logMessage" class="com.logging.LogMessage"/>
<int:service-activator input-channel="wiretapChannel" ref="logMessage" method="handleMessage"></int:service-activator>
public class LogMessage {
public void handleMessage(org.springframework.messaging.Message<?> message) throws MessagingException {
MessageHistory history = MessageHistory.read(message);
for (int i = 0; i < history.size(); i++) {
Properties properties = history.get(i);
getLogger().info("history: " + properties.get("name"));
}
}
}
Upvotes: 1
Views: 1812
Reputation: 121560
Well, it's not so standard task, especially for the reading properties you would like to print. More over many of them are based on the SpEL expressions and the actual value depends on the request message.
There is though a component which is very close what you would like to get. It is called Message History.
All what you need is <int:message-history/>
- and all the Spring Integration components will be tracked and will store they point into the MessageHistory.HEADER_NAME
to show the whole path of the message over integration flow.
In addition I usually also use something like this:
<wire-tap channel="logger"/>
<logging-channel-adapter id="logger" log-full-message="true" logger-name="message.history"/>
To intercept all the channels in the application and log messages with their message history.
You may create your own POJO subscriber (<service-activator>
) for the global <wire-tap>
and perform some smart logic to extract a MessageHistory
from the message: MessageHistory.read(Message<?>)
. Such a MessageHistory
is a List<Properties>
where, actually you can cast that Properties
in the MessageHistory.Entry
class and walk over its properties:
public String getName() {
return this.getProperty(NAME_PROPERTY);
}
public String getType() {
return this.getProperty(TYPE_PROPERTY);
}
public String getTimestamp() {
return this.getProperty(TIMESTAMP_PROPERTY);
}
With the name
you can go to the BeanFactory
to get the real component instance and already there try to extract required properties for your purpose, but again: not all of them are going to be available just because...
You also can consult with the Integration Graph for possible public properties of the IntegrationNode
implementations.
Upvotes: 0