Example of default and Queue Channel

0

In this article, I will show you the basic difference between the default channel and a QueueChannel. You will come to know when to use a QueueChannel and the subtle things that you need to take care of when you use QueueChannel.

Default Channel

In Spring Integration, a channel is represented by the interface MessageChannel and spring provides a number of channel implementations like QueueChannel, PriorityChannel, DirectChannel etc. The default channels is DirectChannel. It is a SubscribableChannel so there can be multiple subscribers interested in the message but only one subscriber will be getting each message and the important thing to note is the invocation will occur in the sender’s thread so there is no need of polling.
In comparison, a QueueChannel supports buffering messages as it uses a queue data structure to hold the messages in memory. As it implements a queue, there is a capacity associated with it.
Unlike DirectChannel, one has to poll the queue at fixed intervals to receive the message.

In the example, we will use default channels and later substitute one of the channel with a QueueChannel.
We have three channels orderConfirmationChannel, orderBilledChannel and emailOrderConfirmationChannel.
orderConfirmationChannel receives a message for the Order to be billed. The order confirmation channel delegates the message to the billing service for billing. Once billed, the message is sent to orderBilledChannel which in turn delegates it to the inventory service for revising the inventory stock. Once the inventory is updated, the message is sent to orderBilledChannel for sending order confirmation email.

applicationContext.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:int-jms="http://www.springframework.org/schema/integration/jms"
	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/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd">

	<int:channel id="orderConfirmationChannel" />

	<int:channel id="orderBilledChannel" />

	<int:channel id="emailOrderConfirmationChannel" />

	<int:service-activator input-channel="orderConfirmationChannel"
		output-channel="orderBilledChannel" ref="orderManager" method="billOrder" />

	<int:service-activator input-channel="orderBilledChannel"
		output-channel="emailOrderConfirmationChannel" ref="orderManager"
		method="updateInventory" />

	<int:outbound-channel-adapter channel="emailOrderConfirmationChannel"
		ref="orderManager" method="emailOrderConfirmation" />

	<bean id="orderManager" class="com.javarticles.spring.integration.OrderManager" />

	<bean id="springIntChannelExample"
		class="com.javarticles.spring.integration.SpringIntegrationInterChannelExample">
		<property name="orderConfirmationChannel" ref="orderConfirmationChannel" />
	</bean>
</beans>

Order:

package com.javarticles.spring.integration;

import java.io.Serializable;

public class Order implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private boolean billed;
    private boolean invUpdated;
    private boolean emailSent;

    public Order(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
    
    public void setInvUpdated(boolean invUpdated) {
        this.invUpdated = invUpdated;
    }

    public void setEmailSent(boolean emailSent) {
        this.emailSent = emailSent;
    }
    
    public void setBilled(boolean billed) {
        this.billed = billed;
    }

    public String toString() {
        return "Order: [ID: " + id + " order billed: " + billed + ", inventory update: " + invUpdated + ", email sent: " + emailSent + "]";
    }
}

For simplicity sake, billing, inventory and email service, all are taken care by OrderManager.

OrderManager:

package com.javarticles.spring.integration;

public class OrderManager {
    public Order billOrder(Order order) {
        System.out.println("Bill Order " + order);
        order.setBilled(true);
        return order;
    }

    public Order updateInventory(Order order) {
        System.out.println("Update inventory for " + order);
        order.setInvUpdated(true);
        return order;
    }

    public void emailOrderConfirmation(Order order) {
        order.setEmailSent(true);
        System.out.println("Email order confirmation " + order);
    }
}

The process is initiated in the main method where we create an order and post it to orderConfirmationChannel channel.
SpringIntegrationInterChannelExample:

package com.javarticles.spring.integration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;

public class SpringIntegrationInterChannelExample {
    private MessageChannel orderConfirmationChannel;
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        SpringIntegrationInterChannelExample springIntExample = (SpringIntegrationInterChannelExample) context.getBean("springIntChannelExample");
        springIntExample.postOrder();
    }
    
    public void postOrder() {
        Order emp = new Order(1);
        Message msg = MessageBuilder.withPayload(emp).build();        
        orderConfirmationChannel.send(msg);
    }

    public void setOrderConfirmationChannel(MessageChannel orderConfirmationChannel) {
        this.orderConfirmationChannel = orderConfirmationChannel;
    }     
}

Output:

Bill Order Order: [ID: 1 order billed: false, inventory update: false, email sent: false]
Update inventory for Order: [ID: 1 order billed: true, inventory update: false, email sent: false]
Email order confirmation Order: [ID: 1 order billed: true, inventory update: true, email sent: true]

Use QueueChannel for email confirmation

I will now show you an example of QueueChannel.
Internally, a QueueChannel uses a queue datastructure and any service relying on this queue will asynchronously handle the message.

In our example, sending the confirmation email isn’t time critical and we can improve the performance by executing it in a separate thread using a QueueChannel. Since QueueChannel uses a queue between the mainline business logic execution and the email service, the service interested in the channel has to explicitly poll for the messages.

Let’s modify for applicationContext.xml.

applicationContext.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:int-jms="http://www.springframework.org/schema/integration/jms"
	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/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd">

	<int:channel id="orderConfirmationChannel" />

	<int:channel id="orderBilledChannel" />

	<int:channel id="emailOrderConfirmationChannel">
		<int:queue />
	</int:channel>

	<int:service-activator input-channel="orderConfirmationChannel"
		output-channel="orderBilledChannel" ref="orderManager" method="billOrder" />

	<int:service-activator input-channel="orderBilledChannel"
		output-channel="emailOrderConfirmationChannel" ref="orderManager"
		method="updateInventory" />

	<int:outbound-channel-adapter channel="emailOrderConfirmationChannel"
		ref="orderManager" method="emailOrderConfirmation">
		<int:poller fixed-delay="500" />
	</int:outbound-channel-adapter>	
		
	<bean id="orderManager" class="com.javarticles.spring.integration.OrderManager" />

	<bean id="springIntChannelExample"
		class="com.javarticles.spring.integration.SpringIntegrationInterChannelExample">
		<property name="orderConfirmationChannel" ref="orderConfirmationChannel" />
	</bean>
</beans>

Download Source Code

In this article, I showed you an example of DirectChannel and QueueChannel. You can download the source code here: springintegrationInterChannel.zip

Share.

Leave A Reply