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

org.springframework.jdbc.datasource.WebSphereDataSourceAdapter Maven / Gradle / Ivy

There is a newer version: 5.3.39
Show newest version
/*
 * 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.jdbc.datasource;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

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

import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

/**
 * {@link DataSource} implementation that delegates all calls to a WebSphere
 * target {@link DataSource}, typically obtained from JNDI, applying a current
 * isolation level and/or current user credentials to every Connection obtained
 * from it.
 *
 * 

Uses IBM-specific API to get a JDBC Connection with a specific isolation * level (and read-only flag) from a WebSphere DataSource * (IBM code example). * Supports the transaction-specific isolation level exposed by * {@link org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel()}. * It's also possible to specify a default isolation level, to be applied when the * current Spring-managed transaction does not define a specific isolation level. * *

Usage example, defining the target DataSource as an inner-bean JNDI lookup * (of course, you can link to any WebSphere DataSource through a bean reference): * *

 * <bean id="myDataSource" class="org.springframework.jdbc.datasource.WebSphereDataSourceAdapter">
 *   <property name="targetDataSource">
 *     <bean class="org.springframework.jndi.JndiObjectFactoryBean">
 *       <property name="jndiName" value="jdbc/myds"/>
 *     </bean>
 *   </property>
 * </bean>
* * Thanks to Ricardo Olivieri for submitting the original implementation * of this approach! * * @author Juergen Hoeller * @author Lari Hotari * @author Ricardo N. Olivieri * @since 2.0.3 * @see com.ibm.websphere.rsadapter.JDBCConnectionSpec * @see com.ibm.websphere.rsadapter.WSDataSource#getConnection(com.ibm.websphere.rsadapter.JDBCConnectionSpec) * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel() * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly() */ public class WebSphereDataSourceAdapter extends IsolationLevelDataSourceAdapter { protected final Log logger = LogFactory.getLog(getClass()); private Class wsDataSourceClass; private Method newJdbcConnSpecMethod; private Method wsDataSourceGetConnectionMethod; private Method setTransactionIsolationMethod; private Method setReadOnlyMethod; private Method setUserNameMethod; private Method setPasswordMethod; /** * This constructor retrieves the WebSphere JDBC connection spec API, * so we can get obtain specific WebSphere Connections using reflection. */ public WebSphereDataSourceAdapter() { try { this.wsDataSourceClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSDataSource"); Class jdbcConnSpecClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.JDBCConnectionSpec"); Class wsrraFactoryClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSRRAFactory"); this.newJdbcConnSpecMethod = wsrraFactoryClass.getMethod("createJDBCConnectionSpec", (Class[]) null); this.wsDataSourceGetConnectionMethod = this.wsDataSourceClass.getMethod("getConnection", new Class[] {jdbcConnSpecClass}); this.setTransactionIsolationMethod = jdbcConnSpecClass.getMethod("setTransactionIsolation", new Class[] {int.class}); this.setReadOnlyMethod = jdbcConnSpecClass.getMethod("setReadOnly", new Class[] {Boolean.class}); this.setUserNameMethod = jdbcConnSpecClass.getMethod("setUserName", new Class[] {String.class}); this.setPasswordMethod = jdbcConnSpecClass.getMethod("setPassword", new Class[] {String.class}); } catch (Exception ex) { throw new IllegalStateException( "Could not initialize WebSphereDataSourceAdapter because WebSphere API classes are not available: " + ex); } } /** * Checks that the specified 'targetDataSource' actually is * a WebSphere WSDataSource. */ public void afterPropertiesSet() { super.afterPropertiesSet(); if (!this.wsDataSourceClass.isInstance(getTargetDataSource())) { throw new IllegalStateException( "Specified 'targetDataSource' is not a WebSphere WSDataSource: " + getTargetDataSource()); } } /** * Builds a WebSphere JDBCConnectionSpec object for the current settings * and calls WSDataSource.getConnection(JDBCConnectionSpec). * @see #createConnectionSpec * @see com.ibm.websphere.rsadapter.WSDataSource#getConnection(com.ibm.websphere.rsadapter.JDBCConnectionSpec) */ protected Connection doGetConnection(String username, String password) throws SQLException { // Create JDBCConnectionSpec using current isolation level value and read-only flag. Object connSpec = createConnectionSpec( getCurrentIsolationLevel(), getCurrentReadOnlyFlag(), username, password); if (logger.isDebugEnabled()) { logger.debug("Obtaining JDBC Connection from WebSphere DataSource [" + getTargetDataSource() + "], using ConnectionSpec [" + connSpec + "]"); } // Create Connection through invoking WSDataSource.getConnection(JDBCConnectionSpec) return (Connection) ReflectionUtils.invokeJdbcMethod( this.wsDataSourceGetConnectionMethod, getTargetDataSource(), new Object[] {connSpec}); } /** * Create a WebSphere JDBCConnectionSpec object for the given charateristics. *

The default implementation uses reflection to apply the given settings. * Can be overridden in subclasses to customize the JDBCConnectionSpec object * (JDBCConnectionSpec javadoc; * IBM developerWorks article). * @param isolationLevel the isolation level to apply (or null if none) * @param readOnlyFlag the read-only flag to apply (or null if none) * @param username the username to apply (null or empty indicates the default) * @param password the password to apply (may be null or empty) * @throws SQLException if thrown by JDBCConnectionSpec API methods * @see com.ibm.websphere.rsadapter.JDBCConnectionSpec */ protected Object createConnectionSpec( Integer isolationLevel, Boolean readOnlyFlag, String username, String password) throws SQLException { Object connSpec = ReflectionUtils.invokeJdbcMethod(this.newJdbcConnSpecMethod, null); if (isolationLevel != null) { ReflectionUtils.invokeJdbcMethod(this.setTransactionIsolationMethod, connSpec, new Object[] {isolationLevel}); } if (readOnlyFlag != null) { ReflectionUtils.invokeJdbcMethod(this.setReadOnlyMethod, connSpec, new Object[] {readOnlyFlag}); } // If the username is empty, we'll simply let the target DataSource // use its default credentials. if (StringUtils.hasLength(username)) { ReflectionUtils.invokeJdbcMethod(this.setUserNameMethod, connSpec, new Object[] {username}); ReflectionUtils.invokeJdbcMethod(this.setPasswordMethod, connSpec, new Object[] {password}); } return connSpec; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy