001/* 002 * Copyright 2012-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.jta.bitronix; 018 019import java.util.Properties; 020 021import javax.jms.JMSException; 022import javax.jms.XAConnection; 023import javax.jms.XAConnectionFactory; 024import javax.jms.XAJMSContext; 025 026import bitronix.tm.resource.common.ResourceBean; 027import bitronix.tm.resource.common.XAStatefulHolder; 028import bitronix.tm.resource.jms.PoolingConnectionFactory; 029 030import org.springframework.beans.factory.BeanNameAware; 031import org.springframework.beans.factory.DisposableBean; 032import org.springframework.beans.factory.InitializingBean; 033import org.springframework.boot.context.properties.ConfigurationProperties; 034import org.springframework.util.StringUtils; 035 036/** 037 * Spring friendly version of {@link PoolingConnectionFactory}. Provides sensible defaults 038 * and also supports direct wrapping of a {@link XAConnectionFactory} instance. 039 * 040 * @author Phillip Webb 041 * @author Josh Long 042 * @author Andy Wilkinson 043 * @since 1.2.0 044 */ 045@SuppressWarnings("serial") 046@ConfigurationProperties(prefix = "spring.jta.bitronix.connectionfactory") 047public class PoolingConnectionFactoryBean extends PoolingConnectionFactory 048 implements BeanNameAware, InitializingBean, DisposableBean { 049 050 private static final ThreadLocal<PoolingConnectionFactoryBean> source = new ThreadLocal<>(); 051 052 private String beanName; 053 054 private XAConnectionFactory connectionFactory; 055 056 public PoolingConnectionFactoryBean() { 057 setMaxPoolSize(10); 058 setTestConnections(true); 059 setAutomaticEnlistingEnabled(true); 060 setAllowLocalTransactions(true); 061 } 062 063 @Override 064 public synchronized void init() { 065 source.set(this); 066 try { 067 super.init(); 068 } 069 finally { 070 source.remove(); 071 } 072 } 073 074 @Override 075 public void setBeanName(String name) { 076 this.beanName = name; 077 } 078 079 @Override 080 public void afterPropertiesSet() throws Exception { 081 if (!StringUtils.hasLength(getUniqueName())) { 082 setUniqueName(this.beanName); 083 } 084 init(); 085 } 086 087 @Override 088 public void destroy() throws Exception { 089 close(); 090 } 091 092 /** 093 * Set the {@link XAConnectionFactory} directly, instead of calling 094 * {@link #setClassName(String)}. 095 * @param connectionFactory the connection factory to use 096 */ 097 public void setConnectionFactory(XAConnectionFactory connectionFactory) { 098 this.connectionFactory = connectionFactory; 099 setClassName(DirectXAConnectionFactory.class.getName()); 100 setDriverProperties(new Properties()); 101 } 102 103 protected final XAConnectionFactory getConnectionFactory() { 104 return this.connectionFactory; 105 } 106 107 @Override 108 public XAStatefulHolder createPooledConnection(Object xaFactory, ResourceBean bean) 109 throws Exception { 110 if (xaFactory instanceof DirectXAConnectionFactory) { 111 xaFactory = ((DirectXAConnectionFactory) xaFactory).getConnectionFactory(); 112 } 113 return super.createPooledConnection(xaFactory, bean); 114 } 115 116 /** 117 * A {@link XAConnectionFactory} implementation that delegates to the 118 * {@link ThreadLocal} {@link PoolingConnectionFactoryBean}. 119 * 120 * @see PoolingConnectionFactoryBean#setConnectionFactory(XAConnectionFactory) 121 */ 122 public static class DirectXAConnectionFactory implements XAConnectionFactory { 123 124 private final XAConnectionFactory connectionFactory; 125 126 public DirectXAConnectionFactory() { 127 this.connectionFactory = source.get().connectionFactory; 128 } 129 130 @Override 131 public XAConnection createXAConnection() throws JMSException { 132 return this.connectionFactory.createXAConnection(); 133 } 134 135 @Override 136 public XAConnection createXAConnection(String userName, String password) 137 throws JMSException { 138 return this.connectionFactory.createXAConnection(userName, password); 139 } 140 141 public XAConnectionFactory getConnectionFactory() { 142 return this.connectionFactory; 143 } 144 145 @Override 146 public XAJMSContext createXAContext() { 147 return this.connectionFactory.createXAContext(); 148 } 149 150 @Override 151 public XAJMSContext createXAContext(String username, String password) { 152 return this.connectionFactory.createXAContext(username, password); 153 } 154 155 } 156 157}