/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.jms.listener.adapter; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Session; import org.springframework.jms.support.destination.DestinationResolver; import org.springframework.util.Assert; /** * Return type of any JMS listener method used to indicate the actual response * destination alongside the response itself. Typically used when said destination * needs to be computed at runtime. * * <p>The example below sends a response with the content of the {@code result} * argument to the {@code queueOut Queue}: * * <pre class="code"> * package com.acme.foo; * * public class MyService { * @JmsListener * public JmsResponse process(String msg) { * // process incoming message * return JmsResponse.forQueue(result, "queueOut"); * } * }</pre> * * If the destination does not need to be computed at runtime, * {@link org.springframework.messaging.handler.annotation.SendTo @SendTo} * is the recommended declarative approach. * * @author Stephane Nicoll * @since 4.2 * @see org.springframework.jms.annotation.JmsListener * @see org.springframework.messaging.handler.annotation.SendTo * @param <T> the type of the response */ public class JmsResponse<T> { private final T response; private final Object destination; /** * Create a new instance * @param response the content of the result * @param destination the destination */ protected JmsResponse(T response, Object destination) { Assert.notNull(response, "Result must not be null"); this.response = response; this.destination = destination; } /** * Return the content of the response. */ public T getResponse() { return this.response; } /** * Resolve the {@link Destination} to use for this instance. The {@link DestinationResolver} * and {@link Session} can be used to resolve a destination at runtime. * @param destinationResolver the destination resolver to use if necessary * @param session the session to use, if necessary * @return the {@link Destination} to use * @throws JMSException if the DestinationResolver failed to resolve the destination */ public Destination resolveDestination(DestinationResolver destinationResolver, Session session) throws JMSException { if (this.destination instanceof Destination) { return (Destination) this.destination; } if (this.destination instanceof DestinationNameHolder) { DestinationNameHolder nameHolder = (DestinationNameHolder) this.destination; return destinationResolver.resolveDestinationName(session, nameHolder.destinationName, nameHolder.pubSubDomain); } return null; } @Override public String toString() { return "JmsResponse [" + "response=" + this.response + ", destination=" + this.destination + ']'; } /** * Create a {@link JmsResponse} targeting the queue with the specified name. */ public static <T> JmsResponse<T> forQueue(T result, String queueName) { Assert.notNull(queueName, "Queue name must not be null"); return new JmsResponse<>(result, new DestinationNameHolder(queueName, false)); } /** * Create a {@link JmsResponse} targeting the topic with the specified name. */ public static <T> JmsResponse<T> forTopic(T result, String topicName) { Assert.notNull(topicName, "Topic name must not be null"); return new JmsResponse<>(result, new DestinationNameHolder(topicName, true)); } /** * Create a {@link JmsResponse} targeting the specified {@link Destination}. */ public static <T> JmsResponse<T> forDestination(T result, Destination destination) { Assert.notNull(destination, "Destination must not be null"); return new JmsResponse<>(result, destination); } /** * Internal class combining a destination name * and its target destination type (queue or topic). */ private static class DestinationNameHolder { private final String destinationName; private final boolean pubSubDomain; public DestinationNameHolder(String destinationName, boolean pubSubDomain) { this.destinationName = destinationName; this.pubSubDomain = pubSubDomain; } @Override public String toString() { return this.destinationName + "{" + "pubSubDomain=" + this.pubSubDomain + '}'; } } }