|
Spring Framework example source code file (CachingConnectionFactory.java)
The Spring Framework CachingConnectionFactory.java source code/* * Copyright 2002-2008 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.connection; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.jms.Connection; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.QueueSession; import javax.jms.Session; import javax.jms.TopicSession; import org.springframework.util.Assert; /** * {@link SingleConnectionFactory} subclass that adds {@link javax.jms.Session} * caching as well {@link javax.jms.MessageProducer} caching. This ConnectionFactory * also switches the {@link #setReconnectOnException "reconnectOnException" property} * to "true" by default, allowing for automatic recovery of the underlying Connection. * * <p>By default, only one single Session will be cached, with further requested * Sessions being created and disposed on demand. Consider raising the * {@link #setSessionCacheSize "sessionCacheSize" value} in case of a * high-concurrency environment. * * <p>NOTE: This ConnectionFactory decorator requires JMS 1.1 or higher. * For JMS 1.0.2, consider using {@link SingleConnectionFactory102} instead. * * @author Juergen Hoeller * @since 2.5.3 */ public class CachingConnectionFactory extends SingleConnectionFactory { private int sessionCacheSize = 1; private boolean cacheProducers = true; private final Map cachedSessions = new HashMap(); public CachingConnectionFactory() { setReconnectOnException(true); } /** * Specify the desired size for the JMS Session cache (per JMS Session type). * <p>This cache size is the maximum limit for the number of cached Sessions * per session acknowledgement type (auto, client, dups_ok, transacted). * As a consequence, the actual number of cached Sessions may be up to * four times as high as the specified value - in the unlikely case * of mixing and matching different acknowledgement types. * <p>Default is 1: caching a single Session, (re-)creating further ones on * demand. Specify a number like 10 if you'd like to raise the number of cached * Sessions; that said, 1 may be sufficient for low-concurrency scenarios. * @see #setCacheProducers */ public void setSessionCacheSize(int sessionCacheSize) { Assert.isTrue(sessionCacheSize >= 1, "Session cache size must be 1 or higher"); this.sessionCacheSize = sessionCacheSize; } /** * Return the desired size for the JMS Session cache (per JMS Session type). */ public int getSessionCacheSize() { return this.sessionCacheSize; } /** * Specify whether to cache JMS MessageProducers per JMS Session instance * (more specifically: one MessageProducer per Destination and Session). * <p>Default is "true". Switch this to "false" in order to recreate * MessageProducers on demand. */ public void setCacheProducers(boolean cacheProducers) { this.cacheProducers = cacheProducers; } /** * Return whether to cache JMS MessageProducers per JMS Session instance. */ public boolean isCacheProducers() { return this.cacheProducers; } /** * Resets the Session cache as well. */ public void resetConnection() { synchronized (this.cachedSessions) { this.cachedSessions.clear(); } super.resetConnection(); } /** * Checks for a cached Session for the given mode. */ protected Session getSession(Connection con, Integer mode) throws JMSException { LinkedList sessionList = null; synchronized (this.cachedSessions) { sessionList = (LinkedList) this.cachedSessions.get(mode); if (sessionList == null) { sessionList = new LinkedList(); this.cachedSessions.put(mode, sessionList); } } Session session = null; synchronized (sessionList) { if (!sessionList.isEmpty()) { session = (Session) sessionList.removeFirst(); } } if (session != null) { if (logger.isDebugEnabled()) { logger.debug("Found cached Session for mode " + mode + ": " + session); } } else { boolean transacted = (mode.intValue() == Session.SESSION_TRANSACTED); int ackMode = (transacted ? Session.AUTO_ACKNOWLEDGE : mode.intValue()); Session targetSession = con.createSession(transacted, ackMode); session = getCachedSessionProxy(targetSession, sessionList); if (logger.isDebugEnabled()) { logger.debug("Created cached Session for mode " + mode + ": " + session); } } return session; } /** * Wrap the given Session with a proxy that delegates every method call to it * but adapts close calls. This is useful for allowing application code to * handle a special framework Session just like an ordinary Session. * @param target the original Session to wrap * @param sessionList the List of cached Sessions that the given Session belongs to * @return the wrapped Session */ protected Session getCachedSessionProxy(Session target, LinkedList sessionList) { List classes = new ArrayList(3); classes.add(Session.class); if (target instanceof QueueSession) { classes.add(QueueSession.class); } if (target instanceof TopicSession) { classes.add(TopicSession.class); } return (Session) Proxy.newProxyInstance( getClass().getClassLoader(), (Class[]) classes.toArray(new Class[classes.size()]), new CachedSessionInvocationHandler(target, sessionList)); } /** * Invocation handler for a cached JMS Session proxy. */ private class CachedSessionInvocationHandler implements InvocationHandler { private final Session target; private final LinkedList sessionList; private final Map cachedProducers = new HashMap(); public CachedSessionInvocationHandler(Session target, LinkedList sessionList) { this.target = target; this.sessionList = sessionList; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("equals")) { // Only consider equal when proxies are identical. return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); } else if (method.getName().equals("hashCode")) { // Use hashCode of Connection proxy. return new Integer(hashCode()); } else if (method.getName().equals("close")) { // Handle close method: don't pass the call on. synchronized (this.sessionList) { if (this.sessionList.size() < getSessionCacheSize()) { if (!this.sessionList.contains(proxy)) { this.sessionList.addLast(proxy); if (logger.isDebugEnabled()) { logger.debug("Returned cached Session: " + proxy); } } return null; } else { for (Iterator it = this.cachedProducers.values().iterator(); it.hasNext();) { ((MessageProducer) it.next()).close(); } this.target.close(); if (logger.isDebugEnabled()) { logger.debug("Closed cached Session: " + proxy); } return null; } } } else if ((method.getName().equals("createProducer") || method.getName().equals("createSender") || method.getName().equals("createPublisher")) && isCacheProducers()) { Destination dest = (Destination) args[0]; MessageProducer producer = (MessageProducer) this.cachedProducers.get(dest); if (producer != null) { if (logger.isDebugEnabled()) { logger.debug("Found cached MessageProducer for destination [" + dest + "]: " + producer); } } else { producer = this.target.createProducer(dest); this.cachedProducers.put(dest, producer); if (logger.isDebugEnabled()) { logger.debug("Created cached MessageProducer for destination [" + dest + "]: " + producer); } } return new CachedMessageProducer(producer); } try { return method.invoke(this.target, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } } Other Spring Framework examples (source code examples)Here is a short list of links related to this Spring Framework CachingConnectionFactory.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 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.