Error message handling behaviour, spring integration - java

Im having 2 outbound gateways with similar but not equal data and format. I'd want to use one as alternative in case 1st doesn't reply or reply too long. Also in future I want to have option to choose which one to get data from.(So Id like to have it as separate outbound gateway, I saw examples with retry advices and would like to avoid this variant)
Atm at very simplified schema I use error channel as incoming channel of alternative gateway. Works perfect until alternative gateway fails too, then I receive:
org.springframework.integration.MessagingException: failure occurred in error-handling flow
There's a real reason of this (connection timeout or any) in stacktrace, but it seems not satisfying for me, since i'd like to handle some exception types differently. I'd like to get error message (and exception) from alternative gateway, not wrapped one.
Is there any way to get it right or Im totally wrong in architecture of this?

Looks like you want to achieve a failover pattern. For this purpose you can simply subscribe both endpoints to the same channel, but without load-balancing:
<channel id="input">
<dispatcher load-balancer="none"/>
</channel>
<service-activator input-channel="input" ref="service1"/>
<service-activator input-channel="input" ref="service2"/>
In this case, if the first <service-activator> will fail by some reason, the Message will be delivered to the second one.
And there is no reason to use retry, or try to reestablish flow from error handling.
UPDATE:
To skip some exceptions and do failover to the next subscriber you can use some custom RequestHandlerAdvice(Expression Evaluating Advice):
class ExceptionProviderRequestHandlerAdvice extends ExpressionEvaluatingRequestHandlerAdvice {
#Override
protected Object doInvoke(AbstractRequestHandlerAdvice.ExecutionCallback callback, Object target, Message<?> message) throws Exception {
def result = super.doInvoke(callback, target, message)
if (result in Exception) {
throw result
}
return result
}
}
And your onFailureExpression should decide: to return exception for rethrow or not:
<int:request-handler-advice-chain>
<beans:bean class="com.cs.otppr.core.aop.ExceptionProviderRequestHandlerAdvice">
<beans:property name="returnFailureExpressionResult" value="true"/>
<beans:property name="onFailureExpression"
value="#exception instanceof T (com.my.proj.MyException) ? #exception : null"/>
</beans:bean>
</int:request-handler-advice-chain>
Or, of course, you can try to find solution on your own...

found a solution that suits me, not sure its proper one, but for now it satisfies all suggested future requirements. I separated my outbound gateways to 2 segments with independent error channels, where error channel of first is input of second. I can process errors from both outbounds, route exceptions and as seems to me easily add some logic futher.
In case of both outbound gateway fails there will be only last gateway exception recieved but that suits me since i dont need to aggregate those errors.
More suggestions are gladly accepted of course.
app-config.xml looks like this
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:elasticsearch="http://www.pilato.fr/schema/elasticsearch"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-3.0.xsd
http://www.pilato.fr/schema/elasticsearch http://www.pilato.fr/schema/elasticsearch/elasticsearch-0.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<int-http:inbound-gateway id="inboundController"
request-channel="requests"
reply-channel="replies-f"
path="/item_info"
supported-methods="GET"
payload-expression="#requestParams"
>
<int-http:request-mapping
params="id"/>
</int-http:inbound-gateway>
<int-http:outbound-gateway id="simpleGateway"
request-channel="outboundRequests"
reply-channel="replies-f"
http-method="GET"
expected-response-type="com.dph.iteminfo.transformer.ItemInfoDTO"
url="http://10.5.4.134:8080/ess/iteminfo?id={itemId}&group_size={groupSize}"
>
<int-http:uri-variable name="itemId" expression="payload.get('id')[0]"/>
<int-http:uri-variable name="groupSize" expression="payload.containsKey('group_size') ? payload.get('group_size')[0] : 5"/>
</int-http:outbound-gateway>
<int-http:outbound-gateway id="alternativeSource"
request-channel="altOutboundChannel"
reply-channel="replies-f"
http-method="GET"
expected-response-type="java.lang.String"
url="http://10.5.4.134:8080/ess/iteminfo?id={itemId}&len={groupSize}"
>
<int-http:uri-variable name="itemId" expression="payload.get('id')[0]"/>
<int-http:uri-variable name="groupSize" expression="payload.containsKey('group_size') ? payload.get('group_size')[0] : 5"/>
</int-http:outbound-gateway>
<int:service-activator input-channel="requests" ref="outboundMain"/>
<int:gateway id="outboundMain" default-request-channel="outboundRequests" error-channel="altChannel" />
<int:exception-type-router default-output-channel="replies-f" input-channel="altChannel">
<int:mapping exception-type="org.springframework.web.client.HttpServerErrorException" channel="resendableMessagesChannel"/>
<int:mapping exception-type="org.springframework.web.client.ResourceAccessException" channel="resendableMessagesChannel"/>
</int:exception-type-router>
<int:service-activator input-channel="resendableMessagesChannel" ref="resender"/>
<int:gateway id="resender" default-request-channel="processedErrorsChannel" error-channel="finalErrors"/>
<int:transformer input-channel="processedErrorsChannel" output-channel="altOutboundChannel" expression="payload.getFailedMessage().getPayload()" />
<int:bridge input-channel="finalErrors" output-channel="replies-f"/>
<!-- will be error processing here -->
<int:channel id="finalErrors" />
<int:channel id="requests" />
<int:channel id="replies-f" />
</beans>

Related

How do I implement a route in camel to receive messages from a JMS queue?

I've referred to the JMS page of the Camel documentation and many related SO questions such as this one, but I'm unable to find a comprehensive list on the implementation.
I'm using Spring XML along with Camel and Weblogic for the server. I've made a test queue with the following names:
Server: TestJMSServer, Module: TestJMSModule, Queue: TestJMSQueue, CF: TestConnectionFactory.
According to the Camel documentation, my route should look something like this:
<camel:route id="test">
<camel:from uri="jms:TestJMSQueue" />
<camel:to uri="file:/Users/...." />
</camel:route>
This gives me an error saying "connectionFactory must be specified". So exactly what else do I need to add to my applicationContext.xml in order to listen to this queue?
You need to tell Camel's jms-component which JMS connection factory to use. Most likely you'll get that from jndi if you're using WebLogic.
In the example below i am looking up the connection factory using spring's jee:jndi-lookup (i believe that might even be a name you can use in WebLogic). The looked up factory is then made available as a spring bean with id myConnectionFactory.
This connection factory bean is then used for the connectionFactory property for camel's JmsComponent. Notice the id attribute: jms. This defines the camel endpoint uri scheme to be used in your routes.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<jee:jndi-lookup id="myConnectionFactory" jndi-name="jms/connectionFactory"/>
<route id="test" xmlns="http://camel.apache.org/schema/spring">
<from uri="jms:TestJMSQueue"/>
<to uri="file:/Users/...."/>
</route>
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="myConnectionFactory"/>
<!-- more configuration required based on your requirements -->
</bean>
<!--
example uses invm amq broker:
<bean id="anothercnf" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://mybroker"/>
</bean>
-->
</beans>
Important Note: You will need to tune this further (setup transactions, setup concurrent consumers, possible configure a spring jms connection pool)

Spring polling + Hibernate

Scenario : poll the database every 'n' seconds and retrieve list. Do some internal business validations.If validations are success only, send the retrieved list to an external system.Receive an acknowledgment response from that system(After receiving this,poller should send next list).Then perform some business operations like calling other systems where polling is not needed.
can any one tell me how this scenario can be handled?
poller.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task" xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
http://www.springframework.org/schema/integration/http
http://www.springframework.org/schema/integration/http/spring-integration-http-4.1.xsd
http://www.springframework.org/schema/integration/jdbc
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc-4.1.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd">
<import resource="persistence-config.xml" />
<int:channel id="inchannel">
</int:channel>
<int:channel id="outchannel">
<int:dispatcher task-executor="taskExecutor"/>
</int:channel>
<task:executor id="taskExecutor" pool-size="2"/>
<bean id="poller" class="main.java.com.as.poller.PollerService" />
<int:service-activator input-channel="inchannel"
output-channel="outchannel" ref="poller" method="sendMessage" />
<int-jdbc:inbound-channel-adapter
query="select loyalty_id from TBL_RECEIPT where receipt_status=0"
channel="inchannel" data-source="dataSource" max-rows-per-poll="1">
<int:poller fixed-rate="5000">
</int:poller>
</int-jdbc:inbound-channel-adapter>
</beans>
ackage main.java.com.as.poller;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.stereotype.Component;
#Component
public class PollerService{
public void sendMessage()
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"AS-servlet.xml");
DirectChannel directChannel = (DirectChannel) context.getBean("inchannel");
}
}
I added a direct channel to poll the DB.Also added an executer channel..But i am getting the exception
Error creating bean with name 'org.springframework.integration.config.ServiceActivatorFactoryBean#0': Cannot resolve reference to bean 'executerChannel' while setting bean property 'outputChannel'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'executerChannel' is defined
rg.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1222)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
Can anyone please help with this...I have created only PollerService.java and dont have any idea to implement executer channel and task executer
The <poller> does that for you by default if you use fixed-delay option and your downstream flow is single threaded (only DirectChannels). In that case the next polling task (in your case reading DB using JPA) won't be started until the finish of previous one and some time like fixed-delay. See PeriodicTrigger, BTW.
Regarding your "Then perform some business operations". You should just make the next channel after "Receive an acknowledgment response" as an ExecutorChannel to free the polling Thread for the next poll.
You should really read more in the Spring Integration Reference Manual and especially about the Poller.

Persist message in topic after server restart

I am learning Spring Integration JMS. I ran into a problem where my topic does not persist pending messages which are not yet consumed by the client.
Basically I start ActiveMQ then using REST Client I am invoking producer to send message for 50 times so that 50 messages gets enqueued in topic. At consumer end I have applied sleep timer of 5 seconds so that each message gets consumed at regular interval of 5s. Then in between I stopped ActiveMQ. Meanwhile some messages are consumed by client lets say 15 out of 50 have been consumed. Then If I restart ActiveMQ I was expecting topic to persist pending 35 messages but I can not see that in admin console under topics tab.
Here is my configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:int-jme="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
<!-- Component scan to find all Spring components -->
<context:component-scan base-package="com.geekcap.springintegrationexample" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="order" value="1" />
<property name="messageConverters">
<list>
<!-- Default converters -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</list>
</property>
</bean>
<!-- Define a channel to communicate out to a JMS Destination -->
<int:channel id="topicChannel"/>
<!-- Define the ActiveMQ connection factory -->
<bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<!--
Define an adaptor that route topicChannel messages to the myTopic topic; the outbound-channel-adapter
automagically fines the configured connectionFactory bean (by naming convention
-->
<int-jms:outbound-channel-adapter channel="topicChannel"
destination-name="topic.myTopic"
pub-sub-domain="true" />
<!-- Create a channel for a listener that will consume messages-->
<int:channel id="listenerChannel" />
<int-jms:message-driven-channel-adapter id="messageDrivenAdapter"
channel="getPayloadChannel"
destination-name="topic.myTopic"
pub-sub-domain="true" />
<int:service-activator input-channel="listenerChannel" ref="messageListenerImpl" method="processMessage" />
<int:channel id="getPayloadChannel" />
<int:service-activator input-channel="getPayloadChannel" output-channel="listenerChannel" ref="retrievePayloadServiceImpl" method="getPayload" />
</beans>
I also read that default mode is persistent. But in my case it does not seems to be worked.
EDIT:
As per the answer given by Gary Russel after adding attributes
subscription-durable="true"
durable-subscription-name="mySubscription"
in <int-jms:message-driven-channel-adapter> I am facing XML related issues
cvc-complex-type.3.2.2: Attribute 'subscription-durable' is not allowed to appear in element 'int-jms:message-driven-channel- adapter'.
cvc-complex-type.3.2.2: Attribute 'durable-subscription-name' is not allowed to appear in element 'int-jms:message-driven-channel- adapter'.
Please Help
That is how topics work, by default, read the JMS specification.
Topics are publish/subscribe; only subscribers that are present get to receive the message.
If you publish 5, start the consumer, publish another 5; he will only get the second 5.
If you kill the broker before he gets all 5; during the restart, the broker sees there are no consumers so he purges the messages.
You can change this behavior by using durable subscriptions, in which case the broker will indeed retain messages for each such subscription, even if not currently connected.
To configure this with Spring Integration, set subscription-durable on the message-driven channel adapter and give it a unique subscription-name.
Topics in Activemq are not durable and persistent, so in case one of your consumer is down. You would lost your messages.
To make topic durable and persistent you can create a durable consumer by creating unique client id per consumer.
But again, that is not distributed in case you are following microservices architecture. So multiple pods or replicas will create problem while consuming messages as in no load balancing is possible for durable consumers.
To mitigate this scenario, there is a option of Virtual topics in Activemq.More details have been provided below,
You can send your messages via your producer in topic named as VirtualTopic.MyTopic.
** Note: you must have to follow this naming convention for default activemq configuration. But yes there is also a way to override this naming convention.
Now, to consume your messages via multiple consumers(A and B here), you have to set naming convention for your consumer side destination as well for eg. Consumer.A.VirtualTopic.MyTopic Consumer.B.VirtualTopic.MyTopic These two consumer will receive messages through the topic created above, also with load balancing enabled between multiple replicas of same consumer.
I hope this will help you fixing your problem with activemq topic.

CXF validation custom handler

I'm creating a webservice with cxf in the following way:
<cxf:cxfEndpoint id=XXXEndpoint"
serviceClass="com.Sth"
address="${webservices.url}/XXX"
wsdlURL="${wsdl.address}/services/XXX.wsdl"
endpointName="m:XXXPort"
serviceName="m:XXXService"
xmlns:m="http://com.sth/XXX">
<cxf:properties>
<entry key="schema-validation-enabled" value="true" />
</cxf:properties>
</cxf:cxfEndpoint>
it works perfectly, also added schema validation. I cannot add a custom validation handler. How can I do that?
I'm not sure what you mean by custom validation handler.
If you want to change validation error handling you can create class implementing javax.xml.bind.ValidationEventHandler
For instance I used this approach to prevent JAXB from throwing exception on the first encountered error. My custom event handler collected all non-fatal validation errors and thrown appropriate exception after validating whole incoming message.
Sample use of ValidationEventHandler
In order to use your custom validation event handler you should add jaxb-validation-event-handler property:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<jaxws:endpoint id="HTTPEndpoint"
implementor="org.dpytel.servicemix.cxf.wsdlfirst.PersonImpl" address="/PersonService"
wsdlLocation="wsdl/person.wsdl" endpointName="e:soap" serviceName="s:PersonService"
xmlns:e="http://servicemix.apache.org/samples/wsdl-first" xmlns:s="http://servicemix.apache.org/samples/wsdl-first">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
<entry key="jaxb-validation-event-handler">
<bean class="org.dpytel.servicemix.cxf.wsdlfirst.MyCustomHandler"></bean>
</entry>
</jaxws:properties>
</jaxws:endpoint>
</beans>
Camel CXF endpoint configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd">
<cxf:cxfEndpoint id="personEndpoint" address="/person"
serviceClass="org.apache.servicemix.samples.wsdl_first.Person"
wsdlURL="wsdl/person.wsdl">
<cxf:properties>
<entry key="schema-validation-enabled" value="true" />
<entry key="jaxb-validation-event-handler">
<bean class="org.dpytel.servicemix.camel.MyCustomHandler" />
</entry>
</cxf:properties>
</cxf:cxfEndpoint>
</beans>
Example handler that disables validation error and just logs the validation message:
import java.util.logging.Logger;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
public class MyCustomHandler implements ValidationEventHandler {
private Logger logger = Logger.getLogger(this.getClass().getCanonicalName());
public boolean handleEvent(ValidationEvent event) {
logger.severe("Error: " + event.getMessage());
return true;
}
}
Please note that some validation errors will cause CXF to skip calling your handler (See details of DataReaderImpl.WSUIDValidationHandler.handleEvent(...)). Your handler will be skipped if error message contains ":Id" string, or is one of the following errors:
cvc-type.3.1.1
cvc-type.3.2.2
cvc-complex-type.3.1.1
cvc-complex-type.3.2.2
(frankly it seems like a dirty hack in CXF and if it is a problem for you I would create a bug for CXF team).
If you want more error handling customization you should probably consider writing your own Interceptor. Probably the best phase to perform such validation would be one of (PRE/USER/POST)_LOGICAL.

Configure the poller in Spring Integration as queue

I'm working at implementing a buffer, in order to execute various jobs.
I'm working on a Spring-based project.
I decided to use Spring Integration to accomplish my aim. I went through a Cafè sample project in order to understand how SI works.
To demonstrate Spring Integration I implemented a table where I dynamically insert jobs to be executed.
This table is the "gateway". Then I configured a router and various channels.
What I don't fully understand are the poller elements which have to check if new jobs in the "gateway" are present.
Is this correct?
If so, how can I configure the poller?
Thanks in advance!
Here the xml code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-feed="http://www.springframework.org/schema/integration/feed"
xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/stream
http://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd">
<int:gateway id="usersToSend" service-interface="it.stasbranger.spidly.rss.UsersToSend" />
<int:channel id="channel" />
<int:channel id="providers"/>
<int:router input-channel="providers" ref="providerRouter" method="resolveProviderChannel"/>
<int:channel id="twitterChannel">
<int:queue capacity="10"/>
</int:channel>
<int:service-activator input-channel="twitterChannel" ref="twitterService" method="updateStatusByProfile"/>
<int:channel id="facebookChannel">
<int:queue capacity="10"/>
</int:channel>
<int:service-activator input-channel="facebookChannel" ref="facebookService" method="updateStatusByProfile"/>
<int:channel id="linkedinChannel">
<int:queue capacity="10"/>
</int:channel>
<int:service-activator input-channel="linkedinChannel" ref="linkedinService" method="writeSlogan2Linkedin"/>
<bean id="twitterService" class="it.social.TwitterService"/>
<bean id="facebookService" class="it.social.FacebookService"/>
<bean id="linkedinService" class="it.social.LinkedinService"/>
<int:poller id="poller" default="true">
</int:poller>
FB
<gateway/>s are not polled, they are "message-driven" in that the caller "sends" a message into the flow using the gateway.
For a polling scenario, use an <int:inbound-channel-adapter/> which polls a method (on the poller's schedule) looking for work to do.
If the method returns null, the poller goes back to sleep (until the next trigger). If the method returns a value, the message is sent to the channel.

Categories

Resources