Question

I'm fairly new to Spring Integration. I have a channel that is wired up to a JMS queue. I then have a gateway defined that has that channel setup as the default-request-channel.

This basic configuration is working flawlessly for me. The defined service-interface is being injected into my bean and I'm able to send a message through this interface and it goes all the way through to the queue.

However, I have an additional requirement to have a failover queue defined that if for some reason the primary is unreachable, that an attempt will be made to send to the failover/secondary queue.

I am not finding any examples of this type of configuration.

Since my channels are wired to JMS queues, my first thought was to create another connection factory (pointing to the secondary JMS server), create another queue bean and channel and then have another gateway that would be used if an exception is thrown from the first gateway invocation.

try {
  primaryGateway.sendMessage(message);
} catch (Exception e) {
  secondaryGateway.sendMessage(message);
}

However, I began to wonder if there was a built-in (under-the-covers) way that spring integration could be configured to autmatically try a secondary queue if the send to the primary fails.

Also, I had a problem trying to define a secondary connection factory. I'm not sure how to tell the queue beans (or their owning channels) which connection factory to use. If I did not use the default "connectionFactory" id, it was complaining.

Here is the key portions of my configuration with just the single queue/channel/gateway defined:

<bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
  <property name="transportType" value="1"/>
  <property name="hostName" value="${lsm.primary.sch.outbound.host}"/>
  <property name="port" value="${lsm.primary.sch.outbound.port}"/>
  <property name="queueManager" value="${lsm.primary.sch.outbound.manager}"/>
  <property name="channel" value="${lsm.primary.sch.outbound.channel}"/>
</bean>

<bean id="connectionFactory"
  class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
  <property name="targetConnectionFactory" ref="mqConnectionFactory" />
  <property name="username" value="blah" />
  <property name="password" value="blah" />
</bean>

<bean id="lsmScheduleActualOutboundQueue" class="com.ibm.mq.jms.MQQueue">
  <property name="baseQueueManagerName" value="${lsm.primary.sch.outbound.manager}"/>
  <property name="baseQueueName" value="${lsm.primary.sch.outbound.queue}"/>
</bean>

<int:channel id="lsmScheduleActualOutboundChannel" />

<jms:outbound-channel-adapter id="jmsOutboundAdapter" 
  channel="lsmScheduleActualOutboundChannel" 
  destination="lsmScheduleActualOutboundQueue" />


<int:gateway id="lsmScheduleActualOutboundGateway" 
  service-interface="com.myapp.service.LSMScheduleActualsGateway"
  default-request-channel="lsmScheduleActualOutboundChannel" 
  default-request-timeout="1000" />
Was it helpful?

Solution

The outbound adapter won't fail over but you can wire two outbound adapters to lsmScheduleActualOutboundChannel; by default, the framework will round-robin the requests but you can alter that behavior by configuring the channel's <dispatcher/> with load-balancer="none"; this will send the message to the second adapter if the first fails.

See the Reference Manual 'Direct Channel' Documentation and Configuration for more information

The channel adapter has a connection-factory attribute; if not supplied it defaults to connectionFactory.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top