I have this kind of chains at different places in my application:
<int:chain input-channel="updateAdministratorChannel">
<int:filter expression="payload.isAdministatorPublished"/>
<int:service-activator expression="..."/>
<int:gateway request-channel="mergeEntityChannel"/>
<int:logging-channel-adapter logger-name="..." expression="'...'"/>
</int:chain>
Everything was working fine with Spring Integration version 3.0.1.RELEASE. We decided to migrate to version 4.2.x and we have an issue with the filter : when the condition is false the system hangs (until it timeout i suppose).
In the end i had to add a discard channel and modify my chains like so:
<int:chain input-channel="updateAdministratorChannel">
<int:filter expression="payload.isAdministatorPublished" discard-channel="defaultDiscardChannel"/>
<int:service-activator expression="..."/>
<int:gateway request-channel="mergeEntityChannel"/>
<int:logging-channel-adapter logger-name="..." expression="'...'"/>
</int:chain>
<int:header-value-router input-channel="defaultDiscardChannel" header-name="replyChannel"/>
I've read the Migration Guides but i don't see anything about that.
Did i miss something ?
Spring version : 4.2.5.RELEASE
Spring Integration version : 4.2.6.RELEASE
Your concern isn't clear because the behavior is expected: when filter is used by default, a discarded message is just dropped.
Not sure what behavior you are expecting or what you are claiming is working in version 3.0.x, but what I guess by your config that you have a messaging gateway in the beginning you expect some reply from your <chain>. Of course this is not possible when you do nothing on the filter level.
What you do with the discard-channel is the correct solution.
Another option would be possible with the throw-exception-on-rejection="true" and an error-channel on the <gateway> to catch those discarded messages there and resend as a reply.
Note: Spring Integration 4.2 is out of support already. It is recommended to upgrade at least to the 4.3.x if can't to 5.0.x: https://spring.io/projects/spring-integration#learn
Related
I have one transformer who's output is input for one of my http:outbound-gateway and the output channel of this outbound-gateway is input for my one of activator. My requirement is to get some of data from my Transformer to my activator.
Something like below.
<int:transformer ref="jsonToXmlTransformer" input-channel="replyChannel" output-channel="someObj"/>
<http:outbound-gateway
request-channel="someObj"
expected-response-type="o.s.h.ResponseEntity"
reply-channel="replyChannel"
url="{someurl}"
http-method="POST"
extract-request-payload="true">
</http:outbound-gateway>
<int:service-activator id="expressionConverter" input-channel="replyChannel"
ref="lastActivator"/>
Dont focus on this config. I mean, I am at home and tried my best to recall my configs as office one. Nothing wrong with that. Only that I am not getting my expected data from my transformer to my last activator. Which is nothing but like an endpoint for application flow.
Consider to transfer required data in headers. Add it into headers after transformer before outbound Gateways and get it from there in the activator.
This is similar to Intermittent BridgeHandler & PublishSubscribeChannel call when gateways' reply channel is pub/sub but the scenario is different in that the reply-channel is not getting "lost". The question is what is the best resolution for my scenario.
I am using Spring integration to launch Spring batch jobs. I have a number of input routes e.g. file polling and http requests. These all route to a batch-int Job Launching Gateway. The referenced Job Launcher has a task executor so job launches are asynchronous. This gateway replies on a specified channel.
<int:gateway service-interface="c.c.c.etl.gateway.JobSubmissionService" id="jobSubmissionService" default-request-channel="jobLauchInputChannel" default-reply-channel="jobLaunchReplyChannel">
</int:gateway>
<int:bridge id="filePollerBridge" input-channel="filePollerOutputChannel" output-channel="jobLauchInputChannel" />
<batch-int:job-launching-gateway request-channel="jobLauchInputChannel" reply-channel="jobLaunchReplyChannel" job-launcher="jobLauncher">
</batch-int:job-launching-gateway>
<int:publish-subscribe-channel id="jobLaunchReplyChannel" />
<int:bridge id="jobLaunchReplyChannelBridge" input-channel="jobLaunchReplyChannel" output-channel="loggingChannel">
</int:bridge>
This specified channel 'jobLaunchReplyChannel' is pub/sub and has a logger listening to it. This channel is also used as the reply channel for a service-interface gateway.
The issue I am having is that when jobs are requested via sources that are not the gateway (e.g. the poller) the Bridge that is added by gateway throws an exception because no reply channel is set on replies.
I have resolved this by adding a header to messages sent via the gateway and filtering out messages only with this header to a new 'gatewayReplyChannel'.
<int:gateway service-interface="c.c.c.etl.gateway.JobSubmissionService" id="jobSubmissionService" default-request-channel="httpJobRequestInputChannel" default-reply-channel="jobSubmissionServiceReplyChannel">
<int:default-header name="isJobSubmissionServiceMessage" value="true" />
</int:gateway>
<int:channel id="jobSubmissionServiceReplyChannel"></int:channel>
<int:filter id="jobSubmissionServiceReplyChannelFilter" input-channel="jobLaunchReplyChannel" expression="headers.get('isJobSubmissionServiceMessage') == null ? false : headers.get('isJobSubmissionServiceMessage')" output-channel="jobSubmissionServiceReplyChannel"
throw-exception-on-rejection="false" />
Is there a better way to do this?
Eh.. That's an interesting issue. The main cause is because MessagingGatewaySupport creates replyMessageCorrelator endpoint for an internal BridgeHandler.
And we really have that strange behaviour when we send message to the reply-channel directly. That BridgeHandler tries to send message to the replyChannel from headers.
And we really can't do anything to prevent that logic. And can't protect that explicit reply-channel from direct messages.
I think your solution is correct. Another way to overcome that: add replyChannel header from the start of another flow (file polling in your case) just using something like this:
<header-enricher>
<reply-channel ref="nullChannel"/>
</header-enricher>
Feel free to raise a JIRA issue on the matter and we'll take a look what we can do. At least we can document these specifics.
I'm working on abstracting out any sort of messaging framework for some code I'm working on. Basically, I'm using a combination of Spring AOP and Spring Integration to generate messages without the Java code knowing anything about RabbitMQ, JMS, or even Spring Integration. That said, what I'm using to generate the messages is contained in its own .jar, and it re-used by several other areas of the application. I currently have the messaging system set up such that the channels on which messages are sent are specified by the code that calls the system (i.e., channels are generated automatically based on the external method invocation) by specifying the channel name in the message header and using a header-value router to create the channels if they don't exist. My issue comes in on the endpoint of these channels - the intention of the current structure is to allow Spring to change to any messaging structure as requirements specify or change. I know how to take a static channel and use outbound channel converters/gateways to send it to a pre-specified RabbitMQ/JMS queue and process from there; what I'm struggling with is how to tell Spring that I need every channel created by the router to have a RabbitMQ (or whatever other messaging system gets implemented) outbound channel adapter that's dynamically generated based on the channel name since we don't know channel names beforehand.
Is this possible? And if not, would you mind providing input as to what could perhaps be a better way?
Thanks ahead of time!
Here's a basic template of what my config file looks like - I have an initial channel ("messageChannel") which gets sent to a publish-subscribe-channel and queuing channel depending on one of the message headers and is routed from there.
<!--Header value based channel configurations-->
<int:channel id="messageChannel" />
<int:channel id="queue" />
<int:publish-subscribe-channel id="topic" />
<!--Header-based router to route to queue or topic channels-->
<int:header-value-router input-channel="messageChannel"
header-name="#{ T(some.class.with.StringConstants).CHANNEL_TYPE}" />
<!--Re-routes messages according to their destination and messaging type-->
<int:header-value-router input-channel="queue"
header-name="#{ T(some.class.with.StringConstants).MESSAGE_DESTINATION}" />
<int:header-value-router input-channel="topic"
header-name="#{ T(some.class.with.StringConstants).MESSAGE_DESTINATION}" />
<!--AOP configuration - picks up on any invocation of some.class.which.generates.Messages.generateMessage()
from a Spring-managed context.-->
<aop:config>
<aop:pointcut id="eventPointcut"
expression="execution(* some.class.which.generates.Messages.generateMessage(..))" />
<aop:advisor advice-ref="interceptor" pointcut-ref="eventPointcut"/>
</aop:config>
<int:publishing-interceptor id="interceptor" default-channel="messageChannel">
<int:method pattern="generateMessage" payload="#return" channel="messageChannel" />
</int:publishing-interceptor>
See the dynamic-ftp sample; it uses a dynamic router that creates new outbound endpoints/channels on demand.
I am using
<int:inbound-channel-adapter id="dummyMessageA" channel="messages" method="getMessage" auto-startup="true" ref="messageGenerator">
<int:poller error-channel="errorChannel" fixed-rate="10000"/>
</int:inbound-channel-adapter>
<int:inbound-channel-adapter id="dummyNotif" channel="notifs" method="gtNotif" auto-startup="true" ref="notifGenerator">
<int:poller error-channel="errorChannel" fixed-rate="10000"/>
</int:inbound-channel-adapter>
These inbound channels are independent but when I deploy my Web Application, Only the second inbound channel adapter is taken into consideration (although the other one was working before adding the dummyNotif). Is this normal, should I add something in the config (NB : I don't aggregate the messages)
My guess you catched this issue https://jira.spring.io/browse/INT-3240 - 'Inbound Channel Adapter Parser doesn't generate unique bean Id for MessageSources'. That's mean that you use Spring Integration 3.0.
So, just upgrade to the latest - 3.0.2.RELEASE - and let us know.
UPDATE
Regarding the same id for several beans. By default Spring allow to do it and the last bean wins. All others will be ignored and skipped.
It can be disabled by AbstractRefreshableApplicationContext#setAllowBeanDefinitionOverriding(false).
From other side if you setup DEBUG logging level for org.springframework category you'll the message in the logs that your beans are overriden.
as far as your question is concerned, Spring Integration allows to have multiple inbound-channel-adapter definition in a single context.
However, from your comments, seems that you have some different issue in your configuration multiple Service Activators with same Id.
It can be disabled as #Artem described in his answer.
I'm still new to Spring Integration and I've few question.
I have a service with WSDL deploy in tomcat server.
and I would like to send parameter from my spring integration flow to that service and receive
response back to do next things in the flow.
I should use outbound WS gateway to do this right?
and how to config the xml to do this?
i've try temperature example but still don't understand it.
thank you.
///////////////////////////////////////////////////////////////
Here is my config:
<int:gateway service-interface="com.app.service.IRequester" id="IRequester"
default-request-channel="requestChannel"
default-reply-channel="responseChannel"
error-channel="errorChannel" >
</int:gateway>
<int:service-activator input-channel="requestChannel" id="bu1"
ref="BU1" method="bu1Method"
output-channel="buChannel">
</int:service-activator>
<int:service-activator input-channel="errorChannel"
ref="handlerError" method="errorReturnToGateway"
output-channel="responseChannel" >
</int:service-activator>
<int:router id="routingChannel" input-channel="buChannel" ref="RoutingChannel" method="routingChannel">
<int:mapping value="firstChannel" channel="channelFirst" />
<int:mapping value="otherChannel" channel="channelOther" />
</int:router>
<int:service-activator id="firstBU" input-channel="channelFirst"
ref="FirstBU" method="doSomething" output-channel="responseChannel">
</int:service-activator>
<int:service-activator id="otherBU" input-channel="channelOther"
ref="OtherBU" method="doSomething" output-channel="responseChannel">
</int:service-activator>
I need to change output channel from both firstBU and otherBU activator to call web service which is send a paremeter to that service(paremeter type is Hashmap) and receive same type response.
I don't know how to call web service by using ws:outbound-gateway.Since I have only known to call web service using java way by generate client java class and may be i'll call service in method doSomething.
In my case,Do you think which way is better?
And I still want to know how to solve this by use ws:outbound-gateway too.
thank you.
As far as it is SOAP, so you get deal with XML. And your WSDL provides you the contract - an XSD which XML should be sent to the service and which will be returned as a response.
So, your task to configure <int-ws:outbound-gateway> and provide correct XML as a message payload to the request-channel of that component.
The same is about a response: you get an XML as payload.
However, it is for simple WS Outbound Gateway. You can configure it with marshaller and send to the request-channel some domain POJO and that marshaller takes care about converting that POJO to the XML representation for the SOAP request.
Show, your config, please, and maybe we can help more with your concreate issues.