All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atomikos.jms.extra.AbstractJmsSenderTemplate Maven / Gradle / Ivy

/**
 * Copyright (C) 2000-2020 Atomikos 
 *
 * LICENSE CONDITIONS
 *
 * See http://www.atomikos.com/Main/WhichLicenseApplies for details.
 */

package com.atomikos.jms.extra;

import java.io.Serializable;
import java.util.Map;
import java.util.Map.Entry;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Topic;
import javax.transaction.Status;
import javax.transaction.SystemException;

import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jms.AtomikosConnectionFactoryBean;
import com.atomikos.jms.internal.AtomikosJMSException;
import com.atomikos.jms.internal.AtomikosTransactionRequiredJMSException;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;

 /**
  * Common functionality for the sender templates.
  *
  */

public abstract class AbstractJmsSenderTemplate implements JmsSenderTemplate
{
	private static final Logger LOGGER = LoggerFactory.createLogger(AbstractJmsSenderTemplate.class);

	private AtomikosConnectionFactoryBean connectionFactoryBean;
	private String user;
	private String password;
	private Destination destination;
	private String destinationName;
	private Destination replyToDestination;
	private String replyToDestinationName;
	private int deliveryMode;
	private int priority;
	private long timeToLive;
	private boolean inited;

	protected AbstractJmsSenderTemplate()
	{
		// set default values according to Sun's JMS javadocs
        setTimeToLive ( 0 );
        setDeliveryMode ( javax.jms.DeliveryMode.PERSISTENT );
        setPriority ( 4 );
	}

	protected abstract Session getOrRefreshSession ( Connection c ) throws JMSException;

	protected abstract Connection getOrReuseConnection() throws JMSException;

	protected abstract void afterUseWithoutErrors ( Connection c , Session s ) throws JMSException;


	protected void destroy ( Connection c , Session s)
	throws JMSException {

		try {
			if ( s != null ) s.close();
		} catch ( JMSException warn ) {
			LOGGER.logWarning ( this + ": error closing session" , warn);
		}

		try {
			if ( c != null ) c.close();
		} catch ( JMSException warn ) {
			LOGGER.logWarning ( this + ": error closing connection" , warn);
		}

	}

	protected synchronized Connection refreshConnection() throws JMSException {
		Connection connection = null;
	    if ( getDestinationName() == null )
	        throw new JMSException ( "Please call setDestination or setDestinationName first!" );

	    if ( user != null ) {
	        connection = connectionFactoryBean.createConnection (
	                user, password );

	    } else {
	        connection = connectionFactoryBean.createConnection ();
	    }
	    connection.start ();
	    return connection;
	}


	/**
	 * Initializes the session for sending.
	 * Call this method first.
	 */

	public void init() throws JMSException
	{
		if ( ! inited ) {
			if ( connectionFactoryBean == null ) throw new IllegalStateException ( "Property 'atomikosConnectionFactoryBean' must be set first!" );
			if ( getDestinationName() == null ) {
				throw new IllegalStateException ( "Property 'destination' or 'destinationName' must be set first!" );
			}
			StringBuffer msg = new StringBuffer();
			msg.append ( this + ":configured with [" );
			msg.append ( "user=" ).append ( getUser() ).append ( ", " );
			msg.append ( "password=" ).append ( password ).append ( ", " );
			msg.append ( "deliveryMode=" ).append ( getDeliveryMode() ).append ( ", " );
			msg.append ( "timeToLive=" ).append ( getTimeToLive() ).append ( ", " );
			msg.append ( "priority=" ).append ( getPriority() ).append ( ", " );
			msg.append ( "destination=" ).append( getDestinationName() ).append ( ", " );
			msg.append ( "replyToDestination=" ).append ( getReplyToDestinationName() );
			msg.append ( "]" );
			if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( msg.toString() );
			inited = true;
		}
	}

	private void retrieveDestinationIfNecessary() throws JMSException
	{
		if ( getDestination() == null ) {
			String dName = getDestinationName();
			RetrieveDestinationCallback cb = new RetrieveDestinationCallback ( dName );
			executeCallbackInternal ( cb );
			setDestination ( cb.getDestination() );
		}

	}

	private void retrieveReplyToDestinationIfNecessary() throws JMSException
	{
		if ( getReplyToDestination() == null ) {
			String dName = getReplyToDestinationName();
			if ( dName != null ) {
				RetrieveDestinationCallback cb = new RetrieveDestinationCallback ( dName );
				executeCallbackInternal ( cb );
				setReplyToDestination ( cb.getDestination() );
			}

		}

	}

	/**
	 * Sets the connection factory to use. Required.
	 * @param connectionFactory
	 */
	public void setAtomikosConnectionFactoryBean(AtomikosConnectionFactoryBean connectionFactory) {
		this.connectionFactoryBean = connectionFactory;
	}

	public AtomikosConnectionFactoryBean getAtomikosConnectionFactoryBean() {
		return connectionFactoryBean;
	}

	public Destination getDestination() {
		return destination;
	}


	/**
	 * Sets the (provider-specific) destination name in order
	 * to lookup the destination (rather than providing one directly).
	 *
	 * Required, unless you set the destination directly.
	 *
	 * @param destinationName
	 */

	public void setDestinationName ( String destinationName )
	{
		this.destinationName = destinationName;
	}

	/**
	 * Sets the destination to send to. Required, unless
	 * you set the destinationName instead.
	 *
	 * @param destination
	 */
	public void setDestination(Destination destination) {
		this.destination = destination;
	}

	private String getName(Destination d, String destinationName ) {
		String ret = destinationName;
		if ( ret == null ) {
			if ( d instanceof Queue ) {
				Queue q = ( Queue ) d;
				try {
					ret = q.getQueueName();
				} catch ( JMSException e ) {
					if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( this + ": error retrieving queue name" , e );
				}
			} else if ( d instanceof Topic ) {
				Topic t = ( Topic ) d;
				try {
					ret = t.getTopicName();
				} catch ( JMSException e ) {
					if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( this + ": error retrieving topic name" , e );
				}
			}
		}
		return ret;
	}

	protected String getDestinationName() {
		return getName ( getDestination() , destinationName );
	}

	protected String getReplyToDestinationName() {
		return getName ( getReplyToDestination() , replyToDestinationName );
	}

	/**
	 * @return The user to connect with, or null if no explicit authentication
	 *         is to be used.
	 */
	public String getUser() {
	    return user;
	}

	/**
	 * If this session is used for sending request/reply messages, then this
	 * property indicates the destination where the replies are to be sent (optional). The
	 * session uses this to set the JMSReplyTo header accordingly. This property
	 * can be omitted if no reply is needed.
	 *
	 * 

* The replyToDestination should be in the same JMS vendor domain as the send * queue. To cross domains, configure a bridge for both the request and the * reply channels. */ public void setReplyToDestination(Destination destination) { this.replyToDestination = destination; } /** * Sets the provider-specific replyToDestinationName. Optional. * * @param replyToDestinationName */ public void setReplyToDestinationName ( String replyToDestinationName ) { this.replyToDestinationName = replyToDestinationName; } /** * Gets the replyToDestination. * * @return */ public Destination getReplyToDestination() { return replyToDestination; } /** * Set the password for explicit authentication (optional). * This is only required if * the user has also been set. * * @param password * The password. */ public void setPassword(String password) { this.password = password; } /** * Set the user to use for explicit authentication (optional). If no explicit * authentication is required then this method should not be called. * * @param user */ public void setUser(String user) { this.user = user; } protected void executeCallbackInternal ( JmsSenderTemplateCallback callback ) throws JMSException { init(); Session session = null; Connection conn = null; try { conn = getOrReuseConnection(); session = getOrRefreshSession ( conn ); if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( "Calling callback..." ); callback.doInJmsSession ( session ); if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( "Callback done!" ); afterUseWithoutErrors ( conn , session ); } catch ( AtomikosTransactionRequiredJMSException notx ) { destroy ( conn , session ); String msg = "The JMS session you are using requires a JTA transaction context for the calling thread and none was found." + "\n" + "Please correct your code to start a JTA transaction before sending any message."; LOGGER.logWarning ( msg ); AtomikosTransactionRequiredJMSException.throwAtomikosTransactionRequiredJMSException ( msg ); } catch ( JMSException e ) { e.printStackTrace(); destroy ( conn , session ); String msg = this + ": error in sending JMS message"; AtomikosJMSException.throwAtomikosJMSException( msg , e ); } } /* (non-Javadoc) * @see com.atomikos.jms.extra.JmsSenderTemplate#executeCallback(com.atomikos.jms.extra.JmsSenderTemplateCallback) */ public void executeCallback(JmsSenderTemplateCallback callback) throws JMSException { init(); retrieveDestinationIfNecessary(); retrieveReplyToDestinationIfNecessary(); UserTransactionManager tm = new UserTransactionManager (); try { if ( tm.getStatus () != Status.STATUS_ACTIVE ) throw new JMSException ( "This method requires an active transaction!" ); } catch ( SystemException e ) { LOGGER.logError ( this +": error in getting transaction status", e ); throw new RuntimeException ( e.getMessage () ); } executeCallbackInternal ( callback ); } /** * @return The deliverymode for messages sent in this session. */ public int getDeliveryMode() { return deliveryMode; } /** * @return The priority for messages sent in this session. */ public int getPriority() { return priority; } /** * @return The timeToLive for messages sent in this session. */ public long getTimeToLive() { return timeToLive; } /** * * Set the deliverymode for messages sent in this session (optional). Defaults to * persistent. * * @param */ public void setDeliveryMode(int i) { deliveryMode = i; } /** * Set the priority for messages sent in this session (optional). Defaults to 4. * * @param */ public void setPriority(int i) { priority = i; } /** * Set the time to live for messages sent in this session (optional). Defaults to 0. * * @param */ public void setTimeToLive(long l) { timeToLive = l; } /* (non-Javadoc) * @see com.atomikos.jms.extra.JmsSenderTemplate#sendTextMessage(java.lang.String) */ @Override public void sendTextMessage(String content) throws JMSException { retrieveDestinationIfNecessary(); retrieveReplyToDestinationIfNecessary(); MessageCallback cb = new MessageCallback ( getDestination() , getReplyToDestination() , getDeliveryMode() , getPriority() , getTimeToLive() ) { @Override Message createMessage(Session session) throws JMSException { return session.createTextMessage(content); } }; executeCallback ( cb ); } /* (non-Javadoc) * @see com.atomikos.jms.extra.JmsSenderTemplate#sendMapMessage(java.util.Map) */ @Override public void sendMapMessage(Map content) throws JMSException { retrieveDestinationIfNecessary(); retrieveReplyToDestinationIfNecessary(); MessageCallback cb = new MessageCallback ( getDestination() , getReplyToDestination() , getDeliveryMode() , getPriority() , getTimeToLive() ) { @Override Message createMessage(Session session) throws JMSException { MapMessage message = session.createMapMessage(); for (Entry element : content.entrySet()) { message.setObject(element.getKey(), element.getValue()); } return message; } }; executeCallback ( cb ); } /* (non-Javadoc) * @see com.atomikos.jms.extra.JmsSenderTemplate#sendObjectMessage(java.io.Serializable) */ @Override public void sendObjectMessage(Serializable content) throws JMSException { retrieveDestinationIfNecessary(); retrieveReplyToDestinationIfNecessary(); MessageCallback cb = new MessageCallback ( getDestination() , getReplyToDestination() , getDeliveryMode() , getPriority() , getTimeToLive() ) { @Override Message createMessage(Session session) throws JMSException { return session.createObjectMessage(content); } }; executeCallback ( cb ); } /* (non-Javadoc) * @see com.atomikos.jms.extra.JmsSenderTemplate#sendBytesMessage(byte[]) */ @Override public void sendBytesMessage(byte[] content) throws JMSException { retrieveDestinationIfNecessary(); retrieveReplyToDestinationIfNecessary(); MessageCallback cb = new MessageCallback ( getDestination() , getReplyToDestination() , getDeliveryMode() , getPriority() , getTimeToLive() ) { @Override Message createMessage(Session session) throws JMSException { BytesMessage msg = session.createBytesMessage(); msg.writeBytes ( content ); return msg; } }; executeCallback ( cb ); } /** * Closes all resources. */ public void close() { try { Connection c = getOrReuseConnection(); Session s = getOrRefreshSession(c); destroy(c, s); } catch (JMSException e) { LOGGER.logWarning ( this + ": error closing" , e ); } connectionFactoryBean.close(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy