CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework--spring-jms

Spring JMS integration module that simplifies JMS development by providing template-based messaging, message-driven POJOs, declarative transaction management, and comprehensive exception handling

Pending
Overview
Eval results
Files

destination-resolution.mddocs/

Destination Resolution

Pluggable destination resolution supporting JNDI lookups, dynamic destination creation, bean factory integration, and caching for flexible destination management. Spring JMS provides multiple strategies for resolving JMS destinations to accommodate various deployment environments and naming conventions.

Capabilities

DestinationResolver Interface

Core strategy interface for resolving destination names to JMS Destination objects, enabling pluggable destination resolution strategies.

/**
 * Strategy interface for resolving JMS destination names to Destination objects
 */
public interface DestinationResolver {
    
    /**
     * Resolve the given destination name to a JMS Destination
     * @param session the current JMS session
     * @param destinationName the name of the destination to resolve
     * @param pubSubDomain whether the domain is pub-sub (topic) or point-to-point (queue)
     * @return the resolved Destination object
     * @throws JMSException in case of JMS errors
     * @throws DestinationResolutionException in case of resolution errors
     */
    Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
        throws JMSException;
}

DynamicDestinationResolver

Default destination resolver that creates destinations dynamically using JMS Session methods, suitable for JMS providers that support dynamic destination creation.

/**
 * Default destination resolver that creates destinations dynamically
 */
public class DynamicDestinationResolver implements DestinationResolver {
    
    public DynamicDestinationResolver();
    
    /**
     * Resolve destination name by creating queue or topic dynamically
     * @param session the JMS session
     * @param destinationName the destination name
     * @param pubSubDomain true for topics, false for queues
     * @return the resolved destination
     * @throws JMSException in case of JMS errors
     */
    @Override
    public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
        throws JMSException;
    
    // Template methods for creating destinations
    protected Queue resolveQueueName(Session session, String queueName) throws JMSException;
    protected Topic resolveTopicName(Session session, String topicName) throws JMSException;
}

JndiDestinationResolver

JNDI-based destination resolver that looks up destinations from a JNDI directory, commonly used in Java EE application servers.

/**
 * Destination resolver that uses JNDI lookups
 */
public class JndiDestinationResolver extends JndiLocatorSupport implements DestinationResolver {
    
    // Constructors
    public JndiDestinationResolver();
    
    // JNDI configuration
    public void setJndiTemplate(JndiTemplate jndiTemplate);
    public void setJndiEnvironment(Properties jndiEnvironment);
    public void setResourceRef(boolean resourceRef);
    
    // Caching configuration
    public void setCache(boolean cache);
    public boolean isCache();
    public void clearCache();
    
    // Fallback configuration
    public void setFallbackToDynamicDestination(boolean fallbackToDynamicDestination);
    public boolean isFallbackToDynamicDestination();
    
    // Lookup methods
    protected Destination lookupDestination(String destinationName) throws NamingException;
    protected Queue lookupQueue(String queueName) throws NamingException;
    protected Topic lookupTopic(String topicName) throws NamingException;
    
    // Resolution method
    @Override
    public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
        throws JMSException;
}

BeanFactoryDestinationResolver

Destination resolver that resolves destinations as Spring-managed beans from the application context, providing integration with Spring's dependency injection.

/**
 * Destination resolver that resolves destinations as Spring beans
 */
public class BeanFactoryDestinationResolver implements DestinationResolver, BeanFactoryAware {
    
    public BeanFactoryDestinationResolver();
    public BeanFactoryDestinationResolver(BeanFactory beanFactory);
    
    // Bean factory configuration
    public void setBeanFactory(BeanFactory beanFactory);
    protected BeanFactory getBeanFactory();
    
    // Resolution method
    @Override
    public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
        throws JMSException;
    
    // Template method for bean lookup
    protected Destination resolveDestinationName(String destinationName);
}

CachingDestinationResolver

Decorator for destination resolvers that caches resolved destinations for improved performance by avoiding repeated resolution calls.

/**
 * Caching wrapper for destination resolvers
 */
public class CachingDestinationResolver implements DestinationResolver {
    
    // Constructors
    public CachingDestinationResolver();
    public CachingDestinationResolver(DestinationResolver targetResolver);
    
    // Target resolver configuration
    public void setTargetResolver(DestinationResolver targetResolver);
    public DestinationResolver getTargetResolver();
    
    // Cache management
    public void clearCache();
    public int getCacheSize();
    
    // Resolution method with caching
    @Override
    public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
        throws JMSException;
}

JmsDestinationAccessor

Abstract base class for JMS accessor objects that use destination resolvers, providing common configuration for destination resolution and pub/sub domain handling.

/**
 * Base class for JMS accessor objects with destination resolution support
 */
public abstract class JmsDestinationAccessor extends JmsAccessor {
    
    // Destination resolver configuration
    public void setDestinationResolver(DestinationResolver destinationResolver);
    public DestinationResolver getDestinationResolver();
    
    // Pub/Sub domain configuration
    public void setPubSubDomain(boolean pubSubDomain);
    public boolean isPubSubDomain();
    
    // Destination resolution methods
    protected Destination resolveDestinationName(Session session, String destinationName) throws JMSException;
    protected Queue resolveQueueName(Session session, String queueName) throws JMSException;
    protected Topic resolveTopicName(Session session, String topicName) throws JMSException;
}

Destination Resolution Exceptions

Exception hierarchy for destination resolution errors with specific error categorization.

/**
 * Exception thrown when destination resolution fails
 */
public class DestinationResolutionException extends JmsException {
    
    public DestinationResolutionException(String msg);
    public DestinationResolutionException(String msg, Throwable cause);
}

Usage Examples:

import org.springframework.jms.support.destination.*;
import javax.naming.Context;
import java.util.Properties;

// Configuration for different destination resolution strategies
@Configuration
public class DestinationConfig {
    
    // Dynamic destination resolver (default)
    @Bean
    public DestinationResolver dynamicDestinationResolver() {
        return new DynamicDestinationResolver();
    }
    
    // JNDI destination resolver for Java EE environments
    @Bean
    public DestinationResolver jndiDestinationResolver() {
        JndiDestinationResolver resolver = new JndiDestinationResolver();
        resolver.setResourceRef(true); // Use java:comp/env/ prefix
        resolver.setCache(true); // Enable caching for performance
        resolver.setFallbackToDynamicDestination(true); // Fallback if JNDI lookup fails
        
        // Configure JNDI environment
        Properties jndiProps = new Properties();
        jndiProps.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
        jndiProps.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");
        resolver.setJndiEnvironment(jndiProps);
        
        return resolver;
    }
    
    // Bean factory destination resolver
    @Bean
    public DestinationResolver beanFactoryDestinationResolver() {
        return new BeanFactoryDestinationResolver();
    }
    
    // Caching destination resolver wrapper
    @Bean  
    public DestinationResolver cachingDestinationResolver() {
        return new CachingDestinationResolver(jndiDestinationResolver());
    }
    
    // Define destinations as Spring beans
    @Bean
    public Queue orderQueue() {
        return new ActiveMQQueue("order.queue");
    }
    
    @Bean
    public Topic notificationTopic() {
        return new ActiveMQTopic("notification.topic");
    }
    
    // JmsTemplate with custom destination resolver
    @Bean
    public JmsTemplate jmsTemplate() {
        JmsTemplate template = new JmsTemplate(connectionFactory());
        template.setDestinationResolver(cachingDestinationResolver());
        return template;
    }
    
    // Message listener container with destination resolver
    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setDestinationResolver(cachingDestinationResolver());
        return factory;
    }
}

// Service using destination resolution
@Service
public class MessagingService {
    
    @Autowired
    private JmsTemplate jmsTemplate;
    
    @Autowired
    private DestinationResolver destinationResolver;
    
    // Using destination names (resolved automatically by JmsTemplate)
    public void sendToQueue(String queueName, Object message) {
        jmsTemplate.convertAndSend(queueName, message);
    }
    
    public void sendToTopic(String topicName, Object message) {
        jmsTemplate.setPubSubDomain(true);
        jmsTemplate.convertAndSend(topicName, message);
    }
    
    // Manual destination resolution
    public void sendWithManualResolution(String destinationName, Object message) {
        jmsTemplate.send(session -> {
            // Manually resolve destination
            Destination destination = destinationResolver.resolveDestinationName(
                session, destinationName, false); // false = queue, true = topic
            
            MessageProducer producer = session.createProducer(destination);
            ObjectMessage objMessage = session.createObjectMessage((Serializable) message);
            producer.send(objMessage);
            
            return objMessage;
        });
    }
}

// Custom destination resolver implementation
@Component
public class CustomDestinationResolver implements DestinationResolver {
    
    private final Map<String, String> destinationMappings = new HashMap<>();
    private final DestinationResolver fallbackResolver = new DynamicDestinationResolver();
    
    @PostConstruct
    public void initializeMappings() {
        // Map logical names to physical destinations
        destinationMappings.put("orders", "app.orders.v1");
        destinationMappings.put("notifications", "app.notifications.v1");
        destinationMappings.put("audit", "app.audit.v1");
    }
    
    @Override
    public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
            throws JMSException {
        
        // Apply destination mapping
        String physicalName = destinationMappings.getOrDefault(destinationName, destinationName);
        
        // Add environment prefix
        String environment = System.getProperty("app.environment", "dev");
        String resolvedName = environment + "." + physicalName;
        
        // Use fallback resolver for actual destination creation
        return fallbackResolver.resolveDestinationName(session, resolvedName, pubSubDomain);
    }
}

// Destination resolver with conditional logic
@Component
@Profile("production")
public class ProductionDestinationResolver implements DestinationResolver {
    
    @Autowired
    private JndiDestinationResolver jndiResolver;
    
    @Autowired
    private DynamicDestinationResolver dynamicResolver;
    
    @Override
    public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) 
            throws JMSException {
        
        // Try JNDI first for production destinations
        try {
            return jndiResolver.resolveDestinationName(session, destinationName, pubSubDomain);
        } catch (DestinationResolutionException e) {
            // Fallback to dynamic resolution for temporary destinations
            if (destinationName.startsWith("temp.") || destinationName.startsWith("reply.")) {
                return dynamicResolver.resolveDestinationName(session, destinationName, pubSubDomain);
            }
            throw e;
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework--spring-jms

docs

configuration.md

connection-management.md

core-operations.md

destination-resolution.md

index.md

message-conversion.md

message-listeners.md

tile.json