alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Spring Framework example source code file (AbstractMessageEndpointFactory.java)

This example Spring Framework source code file (AbstractMessageEndpointFactory.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Spring Framework tags/keywords

abstractmessageendpoint, abstractmessageendpoint, applicationserverinternalexception, classloader, failed, reflection, resourceexception, throwable, throwable, transaction, transaction, transactiondelegate, transactiondelegate, transactionfactory, transactionfactory, xaresource

The Spring Framework AbstractMessageEndpointFactory.java source code

/*
 * Copyright 2002-2007 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.jca.endpoint;

import java.lang.reflect.Method;

import javax.resource.ResourceException;
import javax.resource.spi.ApplicationServerInternalException;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.transaction.jta.SimpleTransactionFactory;
import org.springframework.transaction.jta.TransactionFactory;

/**
 * Abstract base implementation of the JCA 1.5
 * {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface,
 * providing transaction management capabilities as well as ClassLoader
 * exposure for endpoint invocations.
 *
 * @author Juergen Hoeller
 * @since 2.5
 * @see #setTransactionManager
 */
public abstract class AbstractMessageEndpointFactory implements MessageEndpointFactory {

	/** Logger available to subclasses */
	protected final Log logger = LogFactory.getLog(getClass());

	private TransactionFactory transactionFactory;

	private String transactionName;

	private int transactionTimeout = -1;


	/**
	 * Set the the XA transaction manager to use for wrapping endpoint
	 * invocations, enlisting the endpoint resource in each such transaction.
	 * <p>The passed-in object may be a transaction manager which implements
	 * Spring's {@link org.springframework.transaction.jta.TransactionFactory}
	 * interface, or a plain {@link javax.transaction.TransactionManager}.
	 * <p>If no transaction manager is specified, the endpoint invocation
	 * will simply not be wrapped in an XA transaction. Check out your
	 * resource provider's ActivationSpec documentation for local
	 * transaction options of your particular provider.
	 * @see #setTransactionName
	 * @see #setTransactionTimeout
	 */
	public void setTransactionManager(Object transactionManager) {
		if (transactionManager instanceof TransactionFactory) {
			this.transactionFactory = (TransactionFactory) transactionManager;
		}
		else if (transactionManager instanceof TransactionManager) {
			this.transactionFactory = new SimpleTransactionFactory((TransactionManager) transactionManager);
		}
		else {
			throw new IllegalArgumentException("Transaction manager [" + transactionManager +
					"] is neither a [org.springframework.transaction.jta.TransactionFactory} nor a " +
					"[javax.transaction.TransactionManager]");
		}
	}

	/**
	 * Set the Spring TransactionFactory to use for wrapping endpoint
	 * invocations, enlisting the endpoint resource in each such transaction.
	 * <p>Alternatively, specify an appropriate transaction manager through
	 * the {@link #setTransactionManager "transactionManager"} property.
	 * <p>If no transaction factory is specified, the endpoint invocation
	 * will simply not be wrapped in an XA transaction. Check out your
	 * resource provider's ActivationSpec documentation for local
	 * transaction options of your particular provider.
	 * @see #setTransactionName
	 * @see #setTransactionTimeout
	 */
	public void setTransactionFactory(TransactionFactory transactionFactory) {
		this.transactionFactory = transactionFactory;
	}

	/**
	 * Specify the name of the transaction, if any.
	 * <p>Default is none. A specified name will be passed on to the transaction
	 * manager, allowing to identify the transaction in a transaction monitor.
	 */
	public void setTransactionName(String transactionName) {
		this.transactionName = transactionName;
	}

	/**
	 * Specify the transaction timeout, if any.
	 * <p>Default is -1: rely on the transaction manager's default timeout.
	 * Specify a concrete timeout to restrict the maximum duration of each
	 * endpoint invocation.
	 */
	public void setTransactionTimeout(int transactionTimeout) {
		this.transactionTimeout = transactionTimeout;
	}


	/**
	 * This implementation returns <code>true if a transaction manager
	 * has been specified; <code>false otherwise.
	 * @see #setTransactionManager
	 * @see #setTransactionFactory
	 */
	public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException {
		return (this.transactionFactory != null);
	}

	/**
	 * This implementation delegates to {@link #createEndpointInternal()},
	 * initializing the endpoint's XAResource before the endpoint gets invoked.
	 */
	public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
		AbstractMessageEndpoint endpoint = createEndpointInternal();
		endpoint.initXAResource(xaResource);
		return endpoint;
	}

	/**
	 * Create the actual endpoint instance, as a subclass of the
	 * {@link AbstractMessageEndpoint} inner class of this factory.
	 * @return the actual endpoint instance (never <code>null)
	 * @throws UnavailableException if no endpoint is available at present
	 */
	protected abstract AbstractMessageEndpoint createEndpointInternal()
			throws UnavailableException;


	/**
	 * Inner class for actual endpoint implementations, based on template
	 * method to allow for any kind of concrete endpoint implementation.
	 */
	protected abstract class AbstractMessageEndpoint implements MessageEndpoint {

		private TransactionDelegate transactionDelegate;

		private boolean beforeDeliveryCalled = false;

		private ClassLoader previousContextClassLoader;

		/**
		 * Initialize this endpoint's TransactionDelegate.
		 * @param xaResource the XAResource for this endpoint
		 */
		void initXAResource(XAResource xaResource) {
			this.transactionDelegate = new TransactionDelegate(xaResource);
		}

		/**
		 * This <code>beforeDelivery implementation starts a transaction,
		 * if necessary, and exposes the endpoint ClassLoader as current
		 * thread context ClassLoader.
		 * <p>Note that the JCA 1.5 specification does not require a ResourceAdapter
		 * to call this method before invoking the concrete endpoint. If this method
		 * has not been called (check {@link #hasBeforeDeliveryBeenCalled()}), the
		 * concrete endpoint method should call <code>beforeDelivery and its
		 * sibling {@link #afterDelivery()} explicitly, as part of its own processing.
		 */
		public void beforeDelivery(Method method) throws ResourceException {
			this.beforeDeliveryCalled = true;
			try {
				this.transactionDelegate.beginTransaction();
			}
			catch (Throwable ex) {
				throw new ApplicationServerInternalException("Failed to begin transaction", ex);
			}
			Thread currentThread = Thread.currentThread();
			this.previousContextClassLoader = currentThread.getContextClassLoader();
			currentThread.setContextClassLoader(getEndpointClassLoader());
		}

		/**
		 * Template method for exposing the endpoint's ClassLoader
		 * (typically the ClassLoader that the message listener class
		 * has been loaded with).
		 * @return the endpoint ClassLoader (never <code>null)
		 */
		protected abstract ClassLoader getEndpointClassLoader();

		/**
		 * Return whether the {@link #beforeDelivery} method of this endpoint
		 * has already been called.
		 */
		protected final boolean hasBeforeDeliveryBeenCalled() {
			return this.beforeDeliveryCalled;
		}

		/**
		 * Callback method for notifying the endpoint base class
		 * that the concrete endpoint invocation led to an exception.
		 * <p>To be invoked by subclasses in case of the concrete
		 * endpoint throwing an exception.
		 * @param ex the exception thrown from the concrete endpoint
		 */
		protected final void onEndpointException(Throwable ex) {
			this.transactionDelegate.setRollbackOnly();
		}

		/**
		 * This <code>afterDelivery implementation resets the thread context
		 * ClassLoader and completes the transaction, if any.
		 * <p>Note that the JCA 1.5 specification does not require a ResourceAdapter
		 * to call this method after invoking the concrete endpoint. See the
		 * explanation in {@link #beforeDelivery}'s javadoc.
		 */
		public void afterDelivery() throws ResourceException {
			this.beforeDeliveryCalled = false;
			Thread.currentThread().setContextClassLoader(this.previousContextClassLoader);
			this.previousContextClassLoader = null;
			try {
				this.transactionDelegate.endTransaction();
			}
			catch (Throwable ex) {
				throw new ApplicationServerInternalException("Failed to complete transaction", ex);
			}
		}

		public void release() {
			try {
				this.transactionDelegate.setRollbackOnly();
				this.transactionDelegate.endTransaction();
			}
			catch (Throwable ex) {
				logger.error("Could not complete unfinished transaction on endpoint release", ex);
			}
		}
	}


	/**
	 * Private inner class that performs the actual transaction handling,
	 * including enlistment of the endpoint's XAResource.
	 */
	private class TransactionDelegate {

		private XAResource xaResource;

		private Transaction transaction;

		private boolean rollbackOnly;

		public TransactionDelegate(XAResource xaResource) {
			if (transactionFactory != null && xaResource == null) {
				throw new IllegalStateException("ResourceAdapter-provided XAResource is required for " +
						"transaction management. Check your ResourceAdapter's configuration.");
			}
			this.xaResource = xaResource;
		}

		public void beginTransaction() throws Exception {
			if (transactionFactory != null) {
				this.transaction = transactionFactory.createTransaction(transactionName, transactionTimeout);
				this.transaction.enlistResource(this.xaResource);
			}
		}

		public void setRollbackOnly() {
			if (this.transaction != null) {
				this.rollbackOnly = true;
			}
		}

		public void endTransaction() throws Exception {
			if (this.transaction != null) {
				try {
					if (this.rollbackOnly) {
						this.transaction.rollback();
					}
					else {
						this.transaction.commit();
					}
				}
				finally {
					this.transaction = null;
					this.rollbackOnly = false;
				}
			}
		}
	}

}

Other Spring Framework examples (source code examples)

Here is a short list of links related to this Spring Framework AbstractMessageEndpointFactory.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.