smilin_stan
smilin_stan

Reputation: 1733

Concurrency issue with Spring Integration - "Cannot publish to a deleted Destination"

I have two applications running either side of an ActiveMQ broker; application 1 sends synchronous requests to application 2 which returns the response back to application 1.

Application 1

@MessagingGateway
public interface OrderGateway {

    @Gateway(requestChannel = "requestChannel", replyChannel = "responseChannel")
    public OrderDto fetchOrder(OrderRequest orderRequest);
}

@Bean
public IntegrationFlow outgoingRequestFlow(ConnectionFactory connectionFactory) {

    return IntegrationFlows.from("requestChannel")
                           .handle(Jms.outboundGateway(connectionFactory).requestDestination("order.queue"))
                           .get();
}

Application 2

@Bean
public IntegrationFlow incomingRequestFlow(ConnectionFactory connectionFactory) {

    return IntegrationFlows.from(Jms.inboundGateway(connectionFactory).destination("order.queue"))
                           .channel("requestChannel")
                           .handle("orderServiceActivator", "fetchOrder")
                           .channel("responseChannel")
                           .get();
}

@Component
public class OrderServiceActivator {

    @Autowired
    OrderService orderService;

    @ServiceActivator
    public OrderDto fetchOrder(OrderRequest orderRequest) {

        return orderService.getById(orderRequest.getId());
    }
}

Both applications contain the following broker connection factory config:

@Bean(destroyMethod = "stop")
public PooledConnectionFactory activeMQConnectionFactory() {

    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
    activeMQConnectionFactory.setBrokerURL("tcp://broker.local:61616");

    return new PooledConnectionFactory(activeMQConnectionFactory);
}

I have created a REST controller in application 1 /myapp/order/{id} which submits a request to orderGateway.fetchOrder, which is working fine. I then tested it by running while true; do curl http://localhost:8080/myapp/order/1; done at the command line and left it running for several minutes, which sent hundreds of requests through the app, no errors, everything was fine. I can see that request.queue is enqueuing and dequeuing the messages in the ActiveMQ admin tool, and ActiveMQ.Advisory.TempQueue also has a high enqueue/dequeue count.

The problem occurs when there are concurrent requests; if I open up two terminal windows and run the curl-loop in both windows, very quickly I start to see the following errors:

Sep 21, 2015 4:35:25 PM org.springframework.jms.listener.DefaultMessageListenerContainer invokeErrorHandler
WARNING: Execution of JMS message listener failed, and no ErrorHandler has been set.
javax.jms.InvalidDestinationException: Cannot publish to a deleted Destination: temp-queue://ID:Stans-MacBook-Pro.local-64816-1442849675850-1:1:559

Is my SI configuration wrong? Are there some other configuration parameters I need to apply? Thanks for any guidance.

Upvotes: 1

Views: 467

Answers (1)

Gary Russell
Gary Russell

Reputation: 174699

I'd need to see a debug log from both sides to figure out what's happening - it implies the client side has timed out; the default timeout is 5 seconds, however. You can increase the receiveTimeout on the outbound gateway.

That said, it's generally better to use a named reply destination, to avoid creating a temporary reply queue for each request. Bear in mind that the same timeout applies there too.

Upvotes: 1

Related Questions