001/* 002 * Copyright 2002-2018 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 * https://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.jca.support; 018 019import javax.resource.ResourceException; 020import javax.resource.spi.ConnectionManager; 021import javax.resource.spi.ManagedConnectionFactory; 022 023import org.springframework.beans.factory.FactoryBean; 024import org.springframework.beans.factory.InitializingBean; 025import org.springframework.lang.Nullable; 026 027/** 028 * {@link org.springframework.beans.factory.FactoryBean} that creates 029 * a local JCA connection factory in "non-managed" mode (as defined by the 030 * Java Connector Architecture specification). This is a direct alternative 031 * to a {@link org.springframework.jndi.JndiObjectFactoryBean} definition that 032 * obtains a connection factory handle from a Java EE server's naming environment. 033 * 034 * <p>The type of the connection factory is dependent on the actual connector: 035 * the connector can either expose its native API (such as a JDBC 036 * {@link javax.sql.DataSource} or a JMS {@link javax.jms.ConnectionFactory}) 037 * or follow the standard Common Client Interface (CCI), as defined by the JCA spec. 038 * The exposed interface in the CCI case is {@link javax.resource.cci.ConnectionFactory}. 039 * 040 * <p>In order to use this FactoryBean, you must specify the connector's 041 * {@link #setManagedConnectionFactory "managedConnectionFactory"} (usually 042 * configured as separate JavaBean), which will be used to create the actual 043 * connection factory reference as exposed to the application. Optionally, 044 * you can also specify a {@link #setConnectionManager "connectionManager"}, 045 * in order to use a custom ConnectionManager instead of the connector's default. 046 * 047 * <p><b>NOTE:</b> In non-managed mode, a connector is not deployed on an 048 * application server, or more specifically not interacting with an application 049 * server. Consequently, it cannot use a Java EE server's system contracts: 050 * connection management, transaction management, and security management. 051 * A custom ConnectionManager implementation has to be used for applying those 052 * services in conjunction with a standalone transaction coordinator etc. 053 * 054 * <p>The connector will use a local ConnectionManager (included in the connector) 055 * by default, which cannot participate in global transactions due to the lack 056 * of XA enlistment. You need to specify an XA-capable ConnectionManager in 057 * order to make the connector interact with an XA transaction coordinator. 058 * Alternatively, simply use the native local transaction facilities of the 059 * exposed API (e.g. CCI local transactions), or use a corresponding 060 * implementation of Spring's PlatformTransactionManager SPI 061 * (e.g. {@link org.springframework.jca.cci.connection.CciLocalTransactionManager}) 062 * to drive local transactions. 063 * 064 * @author Juergen Hoeller 065 * @since 1.2 066 * @see #setManagedConnectionFactory 067 * @see #setConnectionManager 068 * @see javax.resource.cci.ConnectionFactory 069 * @see javax.resource.cci.Connection#getLocalTransaction 070 * @see org.springframework.jca.cci.connection.CciLocalTransactionManager 071 */ 072public class LocalConnectionFactoryBean implements FactoryBean<Object>, InitializingBean { 073 074 @Nullable 075 private ManagedConnectionFactory managedConnectionFactory; 076 077 @Nullable 078 private ConnectionManager connectionManager; 079 080 @Nullable 081 private Object connectionFactory; 082 083 084 /** 085 * Set the JCA ManagerConnectionFactory that should be used to create 086 * the desired connection factory. 087 * <p>The ManagerConnectionFactory will usually be set up as separate bean 088 * (potentially as inner bean), populated with JavaBean properties: 089 * a ManagerConnectionFactory is encouraged to follow the JavaBean pattern 090 * by the JCA specification, analogous to a JDBC DataSource and a JPA 091 * EntityManagerFactory. 092 * <p>Note that the ManagerConnectionFactory implementation might expect 093 * a reference to its JCA 1.7 ResourceAdapter, expressed through the 094 * {@link javax.resource.spi.ResourceAdapterAssociation} interface. 095 * Simply inject the corresponding ResourceAdapter instance into its 096 * "resourceAdapter" bean property in this case, before passing the 097 * ManagerConnectionFactory into this LocalConnectionFactoryBean. 098 * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory() 099 */ 100 public void setManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory) { 101 this.managedConnectionFactory = managedConnectionFactory; 102 } 103 104 /** 105 * Set the JCA ConnectionManager that should be used to create the 106 * desired connection factory. 107 * <p>A ConnectionManager implementation for local usage is often 108 * included with a JCA connector. Such an included ConnectionManager 109 * might be set as default, with no need to explicitly specify one. 110 * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager) 111 */ 112 public void setConnectionManager(ConnectionManager connectionManager) { 113 this.connectionManager = connectionManager; 114 } 115 116 @Override 117 public void afterPropertiesSet() throws ResourceException { 118 if (this.managedConnectionFactory == null) { 119 throw new IllegalArgumentException("Property 'managedConnectionFactory' is required"); 120 } 121 if (this.connectionManager != null) { 122 this.connectionFactory = this.managedConnectionFactory.createConnectionFactory(this.connectionManager); 123 } 124 else { 125 this.connectionFactory = this.managedConnectionFactory.createConnectionFactory(); 126 } 127 } 128 129 130 @Override 131 @Nullable 132 public Object getObject() { 133 return this.connectionFactory; 134 } 135 136 @Override 137 public Class<?> getObjectType() { 138 return (this.connectionFactory != null ? this.connectionFactory.getClass() : null); 139 } 140 141 @Override 142 public boolean isSingleton() { 143 return true; 144 } 145 146}