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.
Related
How to customize start/stop of aws s3 inbound-channel-adapter . I want to set auto-startup="false" initially and start manually when server starts.Looking for a solution which is similar like we have the below solution for file inbound channel adaptor.
inboundFileAdapterChannel.send(new GenericMessage("#'s3FilesChannelId.adapter'.start()"));
Config:
If i try the same approach for s3 inbound adapter channel . I am getting the below error
APPLICATION FAILED TO START
Description:
A component required a bean named 's3FilesChannelId.adapter' that could not be found.
Action:
Consider defining a bean named 's3FilesChannelId.adapter' in your configuration.
Let's assume we have a channel adapter like this:
<int-aws:s3-inbound-channel-adapter id="s3Inbound"
channel="s3Channel"
session-factory="s3SessionFactory"
auto-create-local-directory="true"
auto-startup="false"
delete-remote-files="true"
preserve-timestamp="true"
filename-pattern="*.txt"
local-directory="."
remote-file-separator="\"
local-filename-generator-expression="#this.toUpperCase() + '.a' + #fooString"
comparator="comparator"
temporary-file-suffix=".foo"
local-filter="acceptAllFilter"
remote-directory-expression="'foo/bar'">
<int:poller fixed-rate="1000"/>
</int-aws:s3-inbound-channel-adapter>
Pay attention to the auto-startup="false" and to the id="s3Inbound".
So, it isn't going to be started automatically after application context initialization.
However using that s3Inbound id we can do that manually whenever it is convenient for us.
Your story about inboundFileAdapterChannel is not clear though, but you still can inject a Lifecycle for the mentioned channel adapter and perform its start():
#Autowired
#Qualifier("s3Inbound")
private Lifecycle s3Inbound;
...
this.s3Inbound.start();
The piece of code about inboundFileAdapterChannel seems like a reference to the Control Bus approach, but that's already slightly different story: https://docs.spring.io/spring-integration/docs/current/reference/html/system-management-chapter.html#control-bus
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
I have a stand alone application that uses File inbound channel adapter to poll for a file from a Specified location at certain interval.
I don't have a taskScheduler instance defined.
When running the application with both Spring integration 2.2.0 and 3.0.2, I see that there are 10 threads created with name task-scheduler-x after certain amount of time. I believe this is the default behavior.
I removed the file inbound channel adapter configuration from my application and re-run it, I noticed the following behavior.
In 3.0.2 , 10 threads are getting created with name task-scheduler-x.
In 2.2.0, Though a taskScheduler instance is getting created (I can see the message about the bean creation in the logs), I don't see any threads getting created with the name task-scheduler-x.
Why is this behavior different between these two versions? What should I do if I don't want to create a taskScheduler instance or I don't want to create any threads for task scheduling?
Thanks for the help.
The framework now has a built-in component (header channel registry) that uses the taskScheduler.
It's not really using many resources although it does have this side effect of instantiating the scheduler thread pool.
We'll look at adding an option to disable it if you don't need/use it. In the meantime, you can revert to the pre 3.0 behavior by adding this bean to your context:
<bean id="integrationHeaderChannelRegistry" class="org.springframework.integration.channel.DefaultHeaderChannelRegistry">
<property name="autoStartup" value="false" />
</bean>
I opened a JIRA Issue for this.
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.
so I'm new to Spring Integration, and mostly to Spring as well, so I might not be up on all of the terminology, but I'm running across the following scenario:
I have a small Spring Integration application with three SI flows... each flow has its own Gateway, and each Gateway has its own request channel and reply channel. These flows receive a null invocation (for all intensive purposes... basically just a 'GO' signal / empty message) and reply with a status message, depending upon the (trivial) business logic results.
I would now like to wire each of these flows together to run in one 'master flow', given one request, without taking away their ability to run separately, and I'd like to wire it up completely through annotation / XML (IE. given a controller that invokes the main gateway's service interface, no additional code needs to be written outside of annotation / XML configuration.)
Is this feasible, what Integration components should I be using to do so, and/or should I just be adjusting the expected channels for each of these gateways to be meeting each other end-to-end (and if so, how would that strategy compensate to allow each of the flows to be called on a case-by-case basis)?
In addition, if this is not feasible, would it be appropriate to use a service activator to invoke each of the child flows? I wanted to avoid coding more, but if that is the only option, I guess that it'll have to do.
Thanks!
Probably the simplest way to do this is use Spring Profiles (a Spring 3.1 feature). When deployed in stand-alone mode, the final element can be a "bridge to nowhere"...
<int:bridge input-channel="app1Final" />
... when the final element in a flow has no output channel, the message is returned to the gateway's reply channel. If you prefer to explicitly configure the bridge to point to the gateway's reply-channel, that's ok too; it just not needed.
In the "linked" profile, you configure the bridge thus...
<int:bridge input-channel="app1Final" output-channel="app2Inbound"/>
...where app2Inbound is the same as that app's gateway's request-channel.
<beans profile="default">
<int:bridge input-channel="app1Final" />
</beans>
<beans profile="linked">
<int:bridge input-channel="app1Final" output-channel="app2Inbound"/>
</beans>
To run with the linked profile, set system property 'spring.profiles.active' to 'linked'