Namespace support can be added by using the following code snippet:
<beans
twitter-template="twitterTemplate"
channel="twitterChannel">
</int-twitter:inbound-channel-adapter>
The components in this code are covered in the following bullet points:
- int-twitter:inbound-channel-adapter: This is the namespace support for Twitter's inbound channel adapter.
- twitter-template: This is the most important aspect. The Twitter template encapsulates which account to use to poll the Twitter site. The details given in the preceding code snippet are fake; it should be replaced with real connection parameters.
- channel: Messages are dumped on this channel.
These adapters are further used for other applications, such as for searching messages, retrieving direct messages, and retrieving tweets that mention your account, and so on. Let's have a quick look at the code snippets for these adapters. I will not go into detail for each one; they are almost similar to what have been discussed previously.
- Search: This adapter helps to search the tweets for the parameter configured in the query tag. The code is as follows:
<int-twitter:search-inbound-channel-adapter id="testSearch"
twitter-template="twitterTemplate"
query="#springintegration"
channel="twitterSearchChannel">
</int-twitter:search-inbound-channel-adapter>
- Retrieving Direct Messages: This adapter allows us to receive the direct message for the account in use (account configured in Twitter template). The code is as follows:
<int-twitter:dm-inbound-channel-adapter
id="testdirectMessage"
twitter-template="twiterTemplate"
channel="twitterDirectMessageChannel">
</int-twitter:dm-inbound-channel-adapter>
- Retrieving Mention Messages: This adapter allows us to receive messages that mention the configured account via the @user tag (account configured in the Twitter template). The code is as follows:
<int-twitter:mentions-inbound-channel-adapter
id="testmentionMessage"
twitter-template="twiterTemplate"
channel="twitterMentionMessageChannel">
</int-twitter:mentions-inbound-channel-adapter>
Sending tweets
Twitter exposes outbound adapters to send messages. Here is a sample code:
<int-twitter:outbound-channel-adapter
twitter-template="twitterTemplate"
channel="twitterSendMessageChannel"/>
Whatever message is put on the twitterSendMessageChannel channel is tweeted by this adapter. Similar to an inbound gateway, the outbound gateway provides support for sending direct messages. Here is a simple example of an outbound adapter:
<int-twitter:dm-outbound-channel-adapter
twitter-template="twitterTemplate"
channel="twitterSendDirectMessage"/>
Any message that is put on the twitterSendDirectMessage channel is sent to the user directly. But where is the name of the user to whom the message will be sent? It is decided by a header in the message TwitterHeaders.DM_TARGET_USER_ID. This must be populated either programmatically, or by using enrichers or SpEL. For example, it can be programmatically added as follows:
Message message = MessageBuilder.withPayload("Chandan")
.setHeader(TwitterHeaders.DM_TARGET_USER_ID,
"test_id").build();
Alternatively, it can be populated by using a header enricher, as follows:
<int:header-enricher input-channel="twitterIn"
output-channel="twitterOut">
<int:header name="twitter_dmTargetUserId" value=" test_id "/>
</int:header-enricher>
Twitter search outbound gateway
As gateways provide a two-way window, the search outbound gateway can be used to issue dynamic search commands and receive the results as a collection. If no result is found, the collection is empty. Let's configure a search outbound gateway, as follows:
<int-twitter:search-outbound-gateway id="twitterSearch"
request-channel="searchQueryChannel"
twitter-template="twitterTemplate"
search-args-expression="#springintegration"
reply-channel="searchQueryResultChannel"/>
And here is what the tags covered in this code mean:
- int-twitter:search-outbound-gateway: This is the namespace for the Twitter search outbound gateway
- request-channel: This is the channel that is used to send search requests to this gateway
- twitter-template: This is the Twitter template reference
- search-args-expression: This is used as arguments for the search
- reply-channel: This is the channel on which searched results are populated
This gives us enough to get started with the social integration aspects of the spring framework.
Enterprise messaging
Enterprise landscape is incomplete without JMS—it is one of the most commonly used mediums of enterprise integration. Spring provides very good support for this. Spring Integration builds over that support and provides adapter and gateways to receive and consume messages from many middleware brokers such as ActiveMQ, RabbitMQ, Rediss, and so on.
Spring Integration provides inbound and outbound adapters to send and receive messages along with gateways that can be used in a request/reply scenario. Let's walk through these implementations in a little more detail. A basic understanding of the JMS mechanism and its concepts is expected. It is not possible to cover even the introduction of JMS here. Let's start with the prerequisites.
Prerequisites
To use Spring Integration messaging components, namespaces, and relevant Maven the following dependency should be added:
After adding these two dependencies, we are ready to use the components. But before we can use an adapter, we must configure an underlying message broker. Let's configure ActiveMQ. Add the following in pom.xml:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>${activemq.version}</version>
<exclusions>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
After this, we are ready to create a connection factory and JMS queue that will be used by the adapters to communicate. First, create a session factory. As you will notice, this is wrapped in Spring's CachingConnectionFactory, but the underlying provider is ActiveMQ:
<bean id="connectionFactory" class="org.springframework.
jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost"/>
</bean>
</property>
</bean>
Let's create a queue that can be used to retrieve and put messages:
<bean
id="feedInputQueue"
class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="queue.input"/>
</bean>
Now, we are ready to send and retrieve messages from the queue. Let's look into each message one by one.
Receiving messages – the inbound adapter
Spring Integration provides two ways of receiving messages: polling and event listener. Both of them are based on the underlying Spring framework's comprehensive support for JMS. JmsTemplate is used by the polling adapter, while MessageListener is used by the event-driven adapter. As the name suggests, a polling adapter keeps polling the queue for the arrival of new messages and puts the message on the configured channel if it finds one. On the other hand, in the case of the event-driven adapter, it's the responsibility of the server to notify the configured adapter.
The polling adapter
Let's start with a code sample:
<int-jms:inbound-channel-adapter
connection-factory="connectionFactory"
destination="feedInputQueue"
channel="jmsProcessedChannel">
<int:poller fixed-rate="1000" />
</int-jms:inbound-channel-adapter>
This code snippet contains the following components:
- int-jms:inbound-channel-adapter: This is the namespace support for the JMS inbound adapter
- connection-factory: This is the encapsulation for the underlying JMS provider setup, such as ActiveMQ
- destination: This is the JMS queue where the adapter is listening for incoming messages
- channel: This is the channel on which incoming messages should be put
There is a poller element, so it's obvious that it is a polling-based adapter. It can be configured in one of two ways: by providing a JMS template or using a connection factory along with a destination. I have used the latter approach. The preceding adapter has a polling queue mentioned in the destination and once it gets any message, it puts the message on the channel configured in the channel attribute.
The event-driven adapter
Similar to polling adapters, event-driven adapters also need a reference either to an implementation of the interface AbstractMessageListenerContainer or need a connection factory and destination. Again, I will use the latter approach. Here is a sample configuration:
<int-jms:message-driven-channel-adapter
connection-factory="connectionFactory"
destination="feedInputQueue"
channel="jmsProcessedChannel"/>
There is no poller sub-element here. As soon as a message arrives at its destination, the adapter is invoked, which puts it on the configured channel.
Sending messages – the outbound adapter
Outbound adapters convert messages on the channel to JMS messages and put them on the configured queue. To convert Spring Integration messages to JMS messages, the outbound adapter uses JmsSendingMessageHandler. This is is an implementation of MessageHandler. Outbound adapters should be configured with either JmsTemplate or with a connection factory and destination queue. Keeping in sync with the preceding examples, we will take the latter approach, as follows:
<int-jms:outbound-channel-adapter
connection-factory="connectionFactory"
channel="jmsChannel"
destination="feedInputQueue"/>
This adapter receives the Spring Integration message from jmsChannel, converts it to a JMS message, and puts it on the destination.
Gateway
Gateway provides a request/reply behavior instead of a one-way send or receive. For example, after sending a message, we might expect a reply or we may want to send an acknowledgement after receiving a message.
The inbound gateway
Inbound gateways provide an alternative to inbound adapters when request-reply capabilities are expected. An inbound gateway is an event-based implementation that listens for a message on the queue, converts it to Spring Message, and puts it on the channel. Here is a sample code:
<int-jms:inbound-gateway
request-destination="feedInputQueue"
request-channel="jmsProcessedChannel"/>
However, this is what an inbound adapter does—even the configuration is similar, except the namespace. So, what is the difference? The difference lies in replying back to the reply destination. Once the message is put on the channel, it will be propagated down the line and at some stage a reply would be generated and sent back as an acknowledgement. The inbound gateway, on receiving this reply, will create a JMS message and put it back on the reply destination queue. Then, where is the reply destination? The reply destination is decided in one of the following ways:
- Original message has a property JMSReplyTo, if it's present it has the highest precedence.
- The inbound gateway looks for a configured, default-reply-destination which can be configured either as a name or as a direct reference of a channel. For specifying channel as direct reference default-reply-destination tag should be used.