0

Considering any message bus can be deployed with spring-xd, is there any API provided by spring-xd that can write to the message bus deployed, say, Kafka/rabbitmq based on the configurations in xd/config/servers.yml or any other such place.

I am writing a processor (itemprocessor), which does some processing of the data and the writer will write the data to a rabbitmq queue for now. Since, in the current deployment scenario, rabbitmq may or may not be deployed, the processor should be able to write to the default Redis message bus.I know I can write to rabbitmq using apis provided by spring-rabbit, but that will tie my processor to RabbitMQ. I am looking for a way to generalize it. I tried to looked into spring-xd code to see if there were any examples like this. I found a MessageProcessor example, but this one is a stream processor, not sure how I can apply it or if I am on the right track.

https://github.com/spring-projects/spring-xd/blob/master/spring-xd-rxjava/src/test/java/org/springframework/xd/rxjava/PongMessageProcessor.java

I just started working with spring-xd, so please pardon my ignorance if this has already been discussed. Any pointers are greatly appreciated.

Update

Thanks Gary, based on your answer I tried out the spring-integration jms samples.

I have a spring batch job which has

<batch:chunk reader="reader" processor="processor" writer="writer" /> 

I want the output of the writer to be written to any underlying message bus, RabiitMQ to start with. So I added the following, based on what I saw in the examples:

 <beans:bean id="writer" class="abc" scope="step">
</beans:bean>

<channel id="outputme"/>

<beans:bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <beans:constructor-arg value="queue.demo"/>
</beans:bean>

<beans:bean id="replyQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <beans:constructor-arg value="queue.reply"/>
</beans:bean>

<jms:outbound-gateway request-channel="outputme"
                      request-destination="requestQueue"
                      reply-channel="jmsReplyChannel"/>

<channel id="jmsReplyChannel" />

<beans:beans profile="default">

    <stream:stdout-channel-adapter channel="jmsReplyChannel" append-newline="true"/>

</beans:beans>

When I execute this, I see the following output, which leads me to believe that something is getting written to the embedded ActiveMQ broker.

16:05:42,400 [AbstractApplicationContext] - Closing org.springframework.context.support.GenericApplicationContext@125a6d70: startup date [Tue Feb 03 16:05:40 PST 2015]; root of context hierarchy
16:05:42,401 [DefaultLifecycleProcessor$LifecycleGroup] - Stopping beans in phase 0
16:05:42,402 [EventDrivenConsumer] - Removing {jms:outbound-gateway} as a subscriber to the 'outputme' channel
16:05:42,402 [AbstractSubscribableChannel] - Channel 'org.springframework.context.support.GenericApplicationContext@125a6d70.outputme' has 0 subscriber(s).
16:05:42,402 [AbstractEndpoint] - stopped org.springframework.integration.config.ConsumerEndpointFactoryBean#0
16:05:42,402 [EventDrivenConsumer] - Removing {service-activator} as a subscriber to the 'jmsReplyChannel' channel
16:05:42,402 [AbstractSubscribableChannel] - Channel 'org.springframework.context.support.GenericApplicationContext@125a6d70.jmsReplyChannel' has 1 subscriber(s).
16:05:42,402 [AbstractEndpoint] - stopped org.springframework.integration.config.ConsumerEndpointFactoryBean#1
16:05:42,402 [EventDrivenConsumer] - Removing {stream:outbound-channel-adapter(character)} as a subscriber to the 'jmsReplyChannel' channel
16:05:42,403 [AbstractSubscribableChannel] - Channel 'org.springframework.context.support.GenericApplicationContext@125a6d70.jmsReplyChannel' has 0 subscriber(s).
16:05:42,403 [AbstractEndpoint] - stopped org.springframework.integration.config.ConsumerEndpointFactoryBean#2

However, when I try to change ActiveMQ with RabbitMQ by changing the connectionfactory like this:

<rabbit:connection-factory id="connectionFactory" />

I get an error saying:

 Cannot convert value of type [org.springframework.amqp.rabbit.connection.CachingConnectionFactory] to required type [javax.jms.ConnectionFactory] for property 'connectionFactory'

which I understand based on what is mentioned in the schema file at http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd, as the required type is javax.jms.ConnectionFactory for the element connection-factory. I looked around, did not find a way to create the conenctionFactory for RabbitMQ the same way as we create the ConnectionFactory for ActiveMQ.

I looked around and am not sure how to fix this. Maybe I am missing something very basic. I am not even sure if this is the right approach. Can you please let me know what I am missing and if this is the right approach? I apologize in advance if this has been discussed already.

Thank you again for your time.


Thank you so much for your time.

regards,

Alice

Alice
  • 95
  • 4
  • 12

1 Answers1

1

The MessageBus SPI is very specific for XD intra-module commmunication; it's not designed for arbitrary application-level messaging.

That said, XD (and its message bus implementations) uses the Spring Integration project extensively.

That project provides the abstraction you need. You can send to a message channel (either using a MessagingGateway or a MessagingTemplate and, downstream of that channel, you can wire in any kind of channel adapter (rabbit [amqp], redis, etc).

So your item processor is decoupled from the actual technology that receives the message.

Take a look at the Spring Integration reference manual (there's a link on the project page).

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Thanks Gary, I tried this one out. Needless, to say ran into a lot of newbie issues. I updated my question with my findings. Thanks again for your time. – Alice Feb 04 '15 at 00:25
  • RabbitMQ is not a JMS provider; it's a completely different protocol. Pivotal does have a commercial JMS client for rabbitmq but if you want to talk native rabbitmq (amqp), then you need to change the `int-jms:outbound-gateway` to an `int-amqp:outbound-gateway`. See [the spring integration documentation](http://docs.spring.io/spring-integration/reference/html/). – Gary Russell Feb 04 '15 at 01:29
  • Thanks Gary, that helped. I added the following rabbitmq configuration and added the named exchange to the outbound gateway. This should make all the messages appear in RabbitMQ. I dont see it yet, probably because I am running as a test. I will try to run as the actual application. ... ... ' – Alice Feb 04 '15 at 15:53
  • You need a `` to declare the queues etc (or set them up manually in the broker). – Gary Russell Feb 04 '15 at 18:19
  • Thanks Gary for the help. I did have rabbit:admin, but I was messing up a few things in the configs by calling the processors twice (for 2 separate execution paths). I just split it up and it started working like a charm. – Alice Feb 09 '15 at 17:16