Jakarta EE 9 migration
Upgrades many dependency declarations; removes old EJB 2.x support and outdated Servlet-based integrations (Commons FileUpload, FreeMarker JSP support, Tiles). Closes gh-22093 Closes gh-25354 Closes gh-26185 Closes gh-27423 See gh-27424
This commit is contained in:
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* Exception thrown when the creating of a CCI Record failed
|
||||
* for connector-internal reasons.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class CannotCreateRecordException extends DataAccessResourceFailureException {
|
||||
|
||||
/**
|
||||
* Constructor for CannotCreateRecordException.
|
||||
* @param msg message
|
||||
* @param ex the root ResourceException cause
|
||||
*/
|
||||
public CannotCreateRecordException(String msg, ResourceException ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
||||
/**
|
||||
* Fatal exception thrown when we can't connect to an EIS using CCI.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class CannotGetCciConnectionException extends DataAccessResourceFailureException {
|
||||
|
||||
/**
|
||||
* Constructor for CannotGetCciConnectionException.
|
||||
* @param msg message
|
||||
* @param ex the root ResourceException cause
|
||||
*/
|
||||
public CannotGetCciConnectionException(String msg, ResourceException ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
/**
|
||||
* Exception thrown when the connector doesn't support a specific CCI operation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class CciOperationNotSupportedException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
/**
|
||||
* Constructor for CciOperationNotSupportedException.
|
||||
* @param msg message
|
||||
* @param ex the root ResourceException cause
|
||||
*/
|
||||
public CciOperationNotSupportedException(String msg, ResourceException ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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
|
||||
*
|
||||
* https://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.cci;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
/**
|
||||
* Exception thrown when a ResultSet has been accessed in an invalid fashion.
|
||||
* Such exceptions always have a {@code java.sql.SQLException} root cause.
|
||||
*
|
||||
* <p>This typically happens when an invalid ResultSet column index or name
|
||||
* has been specified.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see javax.resource.cci.ResultSet
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class InvalidResultSetAccessException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
/**
|
||||
* Constructor for InvalidResultSetAccessException.
|
||||
* @param msg message
|
||||
* @param ex the root cause
|
||||
*/
|
||||
public InvalidResultSetAccessException(String msg, SQLException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
/**
|
||||
* Exception thrown when the creating of a CCI Record failed because
|
||||
* the connector doesn't support the desired CCI Record type.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class RecordTypeNotSupportedException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
/**
|
||||
* Constructor for RecordTypeNotSupportedException.
|
||||
* @param msg message
|
||||
* @param ex the root ResourceException cause
|
||||
*/
|
||||
public RecordTypeNotSupportedException(String msg, ResourceException ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import javax.resource.NotSupportedException;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.spi.LocalTransactionException;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager} implementation
|
||||
* that manages local transactions for a single CCI ConnectionFactory.
|
||||
* Binds a CCI Connection from the specified ConnectionFactory to the thread,
|
||||
* potentially allowing for one thread-bound Connection per ConnectionFactory.
|
||||
*
|
||||
* <p>Application code is required to retrieve the CCI Connection via
|
||||
* {@link ConnectionFactoryUtils#getConnection(ConnectionFactory)} instead of a standard
|
||||
* Java EE-style {@link ConnectionFactory#getConnection()} call. Spring classes such as
|
||||
* {@link org.springframework.jca.cci.core.CciTemplate} use this strategy implicitly.
|
||||
* If not used in combination with this transaction manager, the
|
||||
* {@link ConnectionFactoryUtils} lookup strategy behaves exactly like the native
|
||||
* DataSource lookup; it can thus be used in a portable fashion.
|
||||
*
|
||||
* <p>Alternatively, you can allow application code to work with the standard
|
||||
* Java EE lookup pattern {@link ConnectionFactory#getConnection()}, for example
|
||||
* for legacy code that is not aware of Spring at all. In that case, define a
|
||||
* {@link TransactionAwareConnectionFactoryProxy} for your target ConnectionFactory,
|
||||
* which will automatically participate in Spring-managed transactions.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory)
|
||||
* @see ConnectionFactoryUtils#releaseConnection
|
||||
* @see TransactionAwareConnectionFactoryProxy
|
||||
* @see org.springframework.jca.cci.core.CciTemplate
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class CciLocalTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements ResourceTransactionManager, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new CciLocalTransactionManager instance.
|
||||
* A ConnectionFactory has to be set to be able to use it.
|
||||
* @see #setConnectionFactory
|
||||
*/
|
||||
public CciLocalTransactionManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CciLocalTransactionManager instance.
|
||||
* @param connectionFactory the CCI ConnectionFactory to manage local transactions for
|
||||
*/
|
||||
public CciLocalTransactionManager(ConnectionFactory connectionFactory) {
|
||||
setConnectionFactory(connectionFactory);
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the CCI ConnectionFactory that this instance should manage local
|
||||
* transactions for.
|
||||
*/
|
||||
public void setConnectionFactory(@Nullable ConnectionFactory cf) {
|
||||
if (cf instanceof TransactionAwareConnectionFactoryProxy) {
|
||||
// If we got a TransactionAwareConnectionFactoryProxy, we need to perform transactions
|
||||
// for its underlying target ConnectionFactory, else JMS access code won't see
|
||||
// properly exposed transactions (i.e. transactions for the target ConnectionFactory).
|
||||
this.connectionFactory = ((TransactionAwareConnectionFactoryProxy) cf).getTargetConnectionFactory();
|
||||
}
|
||||
else {
|
||||
this.connectionFactory = cf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CCI ConnectionFactory that this instance manages local
|
||||
* transactions for.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getConnectionFactory() {
|
||||
return this.connectionFactory;
|
||||
}
|
||||
|
||||
private ConnectionFactory obtainConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No ConnectionFactory set");
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getConnectionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'connectionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getResourceFactory() {
|
||||
return obtainConnectionFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
CciLocalTransactionObject txObject = new CciLocalTransactionObject();
|
||||
ConnectionHolder conHolder =
|
||||
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainConnectionFactory());
|
||||
txObject.setConnectionHolder(conHolder);
|
||||
return txObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
|
||||
// Consider a pre-bound connection as transaction.
|
||||
return txObject.hasConnectionHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
|
||||
ConnectionFactory connectionFactory = obtainConnectionFactory();
|
||||
Connection con = null;
|
||||
|
||||
try {
|
||||
con = connectionFactory.getConnection();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Acquired Connection [" + con + "] for local CCI transaction");
|
||||
}
|
||||
|
||||
ConnectionHolder connectionHolder = new ConnectionHolder(con);
|
||||
connectionHolder.setSynchronizedWithTransaction(true);
|
||||
|
||||
con.getLocalTransaction().begin();
|
||||
int timeout = determineTimeout(definition);
|
||||
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
connectionHolder.setTimeoutInSeconds(timeout);
|
||||
}
|
||||
|
||||
txObject.setConnectionHolder(connectionHolder);
|
||||
TransactionSynchronizationManager.bindResource(connectionFactory, connectionHolder);
|
||||
}
|
||||
catch (NotSupportedException ex) {
|
||||
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
|
||||
throw new CannotCreateTransactionException("CCI Connection does not support local transactions", ex);
|
||||
}
|
||||
catch (LocalTransactionException ex) {
|
||||
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
|
||||
throw new CannotCreateTransactionException("Could not begin local CCI transaction", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
|
||||
throw new TransactionSystemException("Unexpected failure on begin of CCI local transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doSuspend(Object transaction) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
|
||||
txObject.setConnectionHolder(null);
|
||||
return TransactionSynchronizationManager.unbindResource(obtainConnectionFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
|
||||
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
|
||||
TransactionSynchronizationManager.bindResource(obtainConnectionFactory(), conHolder);
|
||||
}
|
||||
|
||||
protected boolean isRollbackOnly(Object transaction) throws TransactionException {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
|
||||
return txObject.getConnectionHolder().isRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction();
|
||||
Connection con = txObject.getConnectionHolder().getConnection();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing CCI local transaction on Connection [" + con + "]");
|
||||
}
|
||||
try {
|
||||
con.getLocalTransaction().commit();
|
||||
}
|
||||
catch (LocalTransactionException ex) {
|
||||
throw new TransactionSystemException("Could not commit CCI local transaction", ex);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new TransactionSystemException("Unexpected failure on commit of CCI local transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction();
|
||||
Connection con = txObject.getConnectionHolder().getConnection();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back CCI local transaction on Connection [" + con + "]");
|
||||
}
|
||||
try {
|
||||
con.getLocalTransaction().rollback();
|
||||
}
|
||||
catch (LocalTransactionException ex) {
|
||||
throw new TransactionSystemException("Could not roll back CCI local transaction", ex);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new TransactionSystemException("Unexpected failure on rollback of CCI local transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Setting CCI local transaction [" + txObject.getConnectionHolder().getConnection() +
|
||||
"] rollback-only");
|
||||
}
|
||||
txObject.getConnectionHolder().setRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
|
||||
ConnectionFactory connectionFactory = obtainConnectionFactory();
|
||||
|
||||
// Remove the connection holder from the thread.
|
||||
TransactionSynchronizationManager.unbindResource(connectionFactory);
|
||||
txObject.getConnectionHolder().clear();
|
||||
|
||||
Connection con = txObject.getConnectionHolder().getConnection();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Releasing CCI Connection [" + con + "] after transaction");
|
||||
}
|
||||
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CCI local transaction object, representing a ConnectionHolder.
|
||||
* Used as transaction object by CciLocalTransactionManager.
|
||||
* @see ConnectionHolder
|
||||
*/
|
||||
private static class CciLocalTransactionObject {
|
||||
|
||||
@Nullable
|
||||
private ConnectionHolder connectionHolder;
|
||||
|
||||
public void setConnectionHolder(@Nullable ConnectionHolder connectionHolder) {
|
||||
this.connectionHolder = connectionHolder;
|
||||
}
|
||||
|
||||
public ConnectionHolder getConnectionHolder() {
|
||||
Assert.state(this.connectionHolder != null, "No ConnectionHolder available");
|
||||
return this.connectionHolder;
|
||||
}
|
||||
|
||||
public boolean hasConnectionHolder() {
|
||||
return (this.connectionHolder != null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper class that provides static methods for obtaining CCI Connections
|
||||
* from a {@link javax.resource.cci.ConnectionFactory}. Includes special
|
||||
* support for Spring-managed transactional Connections, e.g. managed
|
||||
* by {@link CciLocalTransactionManager} or
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager}.
|
||||
*
|
||||
* <p>Used internally by {@link org.springframework.jca.cci.core.CciTemplate},
|
||||
* Spring's CCI operation objects and the {@link CciLocalTransactionManager}.
|
||||
* Can also be used directly in application code.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #getConnection
|
||||
* @see #releaseConnection
|
||||
* @see CciLocalTransactionManager
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class ConnectionFactoryUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ConnectionFactoryUtils.class);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions
|
||||
* into the Spring hierarchy of unchecked generic data access exceptions, simplifying
|
||||
* calling code and making any exception that is thrown more meaningful.
|
||||
* <p>Is aware of a corresponding Connection bound to the current thread, for example
|
||||
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
|
||||
* if transaction synchronization is active (e.g. if in a JTA transaction).
|
||||
* @param cf the ConnectionFactory to obtain Connection from
|
||||
* @return a CCI Connection from the given ConnectionFactory
|
||||
* @throws org.springframework.jca.cci.CannotGetCciConnectionException
|
||||
* if the attempt to get a Connection failed
|
||||
* @see #releaseConnection
|
||||
*/
|
||||
public static Connection getConnection(ConnectionFactory cf)
|
||||
throws org.springframework.jca.cci.CannotGetCciConnectionException {
|
||||
|
||||
return getConnection(cf, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions
|
||||
* into the Spring hierarchy of unchecked generic data access exceptions, simplifying
|
||||
* calling code and making any exception that is thrown more meaningful.
|
||||
* <p>Is aware of a corresponding Connection bound to the current thread, for example
|
||||
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
|
||||
* if transaction synchronization is active (e.g. if in a JTA transaction).
|
||||
* @param cf the ConnectionFactory to obtain Connection from
|
||||
* @param spec the ConnectionSpec for the desired Connection (may be {@code null}).
|
||||
* Note: If this is specified, a new Connection will be obtained for every call,
|
||||
* without participating in a shared transactional Connection.
|
||||
* @return a CCI Connection from the given ConnectionFactory
|
||||
* @throws org.springframework.jca.cci.CannotGetCciConnectionException
|
||||
* if the attempt to get a Connection failed
|
||||
* @see #releaseConnection
|
||||
*/
|
||||
public static Connection getConnection(ConnectionFactory cf, @Nullable ConnectionSpec spec)
|
||||
throws org.springframework.jca.cci.CannotGetCciConnectionException {
|
||||
try {
|
||||
if (spec != null) {
|
||||
Assert.notNull(cf, "No ConnectionFactory specified");
|
||||
return cf.getConnection(spec);
|
||||
}
|
||||
else {
|
||||
return doGetConnection(cf);
|
||||
}
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new org.springframework.jca.cci.CannotGetCciConnectionException("Could not get CCI Connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually obtain a CCI Connection from the given ConnectionFactory.
|
||||
* Same as {@link #getConnection}, but throwing the original ResourceException.
|
||||
* <p>Is aware of a corresponding Connection bound to the current thread, for example
|
||||
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
|
||||
* if transaction synchronization is active (e.g. if in a JTA transaction).
|
||||
* <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}.
|
||||
* @param cf the ConnectionFactory to obtain Connection from
|
||||
* @return a CCI Connection from the given ConnectionFactory
|
||||
* @throws ResourceException if thrown by CCI API methods
|
||||
* @see #doReleaseConnection
|
||||
*/
|
||||
public static Connection doGetConnection(ConnectionFactory cf) throws ResourceException {
|
||||
Assert.notNull(cf, "No ConnectionFactory specified");
|
||||
|
||||
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf);
|
||||
if (conHolder != null) {
|
||||
return conHolder.getConnection();
|
||||
}
|
||||
|
||||
logger.debug("Opening CCI Connection");
|
||||
Connection con = cf.getConnection();
|
||||
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
conHolder = new ConnectionHolder(con);
|
||||
conHolder.setSynchronizedWithTransaction(true);
|
||||
TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, cf));
|
||||
TransactionSynchronizationManager.bindResource(cf, conHolder);
|
||||
}
|
||||
|
||||
return con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given JCA CCI Connection is transactional, that is,
|
||||
* bound to the current thread by Spring's transaction facilities.
|
||||
* @param con the Connection to check
|
||||
* @param cf the ConnectionFactory that the Connection was obtained from
|
||||
* (may be {@code null})
|
||||
* @return whether the Connection is transactional
|
||||
*/
|
||||
public static boolean isConnectionTransactional(Connection con, @Nullable ConnectionFactory cf) {
|
||||
if (cf == null) {
|
||||
return false;
|
||||
}
|
||||
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf);
|
||||
return (conHolder != null && conHolder.getConnection() == con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given Connection, obtained from the given ConnectionFactory,
|
||||
* if it is not managed externally (that is, not bound to the thread).
|
||||
* @param con the Connection to close if necessary
|
||||
* (if this is {@code null}, the call will be ignored)
|
||||
* @param cf the ConnectionFactory that the Connection was obtained from
|
||||
* (can be {@code null})
|
||||
* @see #getConnection
|
||||
*/
|
||||
public static void releaseConnection(@Nullable Connection con, @Nullable ConnectionFactory cf) {
|
||||
try {
|
||||
doReleaseConnection(con, cf);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
logger.debug("Could not close CCI Connection", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// We don't trust the CCI driver: It might throw RuntimeException or Error.
|
||||
logger.debug("Unexpected exception on closing CCI Connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually close the given Connection, obtained from the given ConnectionFactory.
|
||||
* Same as {@link #releaseConnection}, but throwing the original ResourceException.
|
||||
* <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}.
|
||||
* @param con the Connection to close if necessary
|
||||
* (if this is {@code null}, the call will be ignored)
|
||||
* @param cf the ConnectionFactory that the Connection was obtained from
|
||||
* (can be {@code null})
|
||||
* @throws ResourceException if thrown by JCA CCI methods
|
||||
* @see #doGetConnection
|
||||
*/
|
||||
public static void doReleaseConnection(@Nullable Connection con, @Nullable ConnectionFactory cf)
|
||||
throws ResourceException {
|
||||
|
||||
if (con == null || isConnectionTransactional(con, cf)) {
|
||||
return;
|
||||
}
|
||||
con.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for resource cleanup at the end of a non-native CCI transaction
|
||||
* (e.g. when participating in a JTA transaction).
|
||||
*/
|
||||
private static class ConnectionSynchronization
|
||||
extends ResourceHolderSynchronization<ConnectionHolder, ConnectionFactory> {
|
||||
|
||||
public ConnectionSynchronization(ConnectionHolder connectionHolder, ConnectionFactory connectionFactory) {
|
||||
super(connectionHolder, connectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseResource(ConnectionHolder resourceHolder, ConnectionFactory resourceKey) {
|
||||
releaseConnection(resourceHolder.getConnection(), resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import javax.resource.cci.Connection;
|
||||
|
||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
|
||||
/**
|
||||
* Resource holder wrapping a CCI {@link Connection}.
|
||||
* {@link CciLocalTransactionManager} binds instances of this class to the thread,
|
||||
* for a given {@link javax.resource.cci.ConnectionFactory}.
|
||||
*
|
||||
* <p>Note: This is an SPI class, not intended to be used by applications.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see CciLocalTransactionManager
|
||||
* @see ConnectionFactoryUtils
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConnectionHolder extends ResourceHolderSupport {
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
|
||||
public ConnectionHolder(Connection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
||||
public Connection getConnection() {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory},
|
||||
* applying the given ConnectionSpec to every standard {@code getConnection()}
|
||||
* call, that is, implicitly invoking {@code getConnection(ConnectionSpec)}
|
||||
* on the target. All other methods simply delegate to the corresponding methods
|
||||
* of the target ConnectionFactory.
|
||||
*
|
||||
* <p>Can be used to proxy a target JNDI ConnectionFactory that does not have a
|
||||
* ConnectionSpec configured. Client code can work with the ConnectionFactory
|
||||
* without passing in a ConnectionSpec on every {@code getConnection()} call.
|
||||
*
|
||||
* <p>In the following example, client code can simply transparently work with
|
||||
* the preconfigured "myConnectionFactory", implicitly accessing
|
||||
* "myTargetConnectionFactory" with the specified user credentials.
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="myTargetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
|
||||
* <property name="jndiName" value="java:comp/env/cci/mycf"/>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="myConnectionFactory" class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
|
||||
* <property name="targetConnectionFactory" ref="myTargetConnectionFactory"/>
|
||||
* <property name="connectionSpec">
|
||||
* <bean class="your.resource.adapter.ConnectionSpecImpl">
|
||||
* <property name="username" value="myusername"/>
|
||||
* <property name="password" value="mypassword"/>
|
||||
* </bean>
|
||||
* </property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* <p>If the "connectionSpec" is empty, this proxy will simply delegate to the
|
||||
* standard {@code getConnection()} method of the target ConnectionFactory.
|
||||
* This can be used to keep a UserCredentialsConnectionFactoryAdapter bean definition
|
||||
* just for the <i>option</i> of implicitly passing in a ConnectionSpec if the
|
||||
* particular target ConnectionFactory requires it.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #getConnection
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class ConnectionSpecConnectionFactoryAdapter extends DelegatingConnectionFactory {
|
||||
|
||||
@Nullable
|
||||
private ConnectionSpec connectionSpec;
|
||||
|
||||
private final ThreadLocal<ConnectionSpec> threadBoundSpec =
|
||||
new NamedThreadLocal<>("Current CCI ConnectionSpec");
|
||||
|
||||
|
||||
/**
|
||||
* Set the ConnectionSpec that this adapter should use for retrieving Connections.
|
||||
* Default is none.
|
||||
*/
|
||||
public void setConnectionSpec(ConnectionSpec connectionSpec) {
|
||||
this.connectionSpec = connectionSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a ConnectionSpec for this proxy and the current thread.
|
||||
* The given ConnectionSpec will be applied to all subsequent
|
||||
* {@code getConnection()} calls on this ConnectionFactory proxy.
|
||||
* <p>This will override any statically specified "connectionSpec" property.
|
||||
* @param spec the ConnectionSpec to apply
|
||||
* @see #removeConnectionSpecFromCurrentThread
|
||||
*/
|
||||
public void setConnectionSpecForCurrentThread(ConnectionSpec spec) {
|
||||
this.threadBoundSpec.set(spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any ConnectionSpec for this proxy from the current thread.
|
||||
* A statically specified ConnectionSpec applies again afterwards.
|
||||
* @see #setConnectionSpecForCurrentThread
|
||||
*/
|
||||
public void removeConnectionSpecFromCurrentThread() {
|
||||
this.threadBoundSpec.remove();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether there is currently a thread-bound ConnectionSpec,
|
||||
* using it if available, falling back to the statically specified
|
||||
* "connectionSpec" property else.
|
||||
* @see #doGetConnection
|
||||
*/
|
||||
@Override
|
||||
public final Connection getConnection() throws ResourceException {
|
||||
ConnectionSpec threadSpec = this.threadBoundSpec.get();
|
||||
if (threadSpec != null) {
|
||||
return doGetConnection(threadSpec);
|
||||
}
|
||||
else {
|
||||
return doGetConnection(this.connectionSpec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to the {@code getConnection(ConnectionSpec)}
|
||||
* method of the target ConnectionFactory, passing in the specified user credentials.
|
||||
* If the specified username is empty, it will simply delegate to the standard
|
||||
* {@code getConnection()} method of the target ConnectionFactory.
|
||||
* @param spec the ConnectionSpec to apply
|
||||
* @return the Connection
|
||||
* @see javax.resource.cci.ConnectionFactory#getConnection(javax.resource.cci.ConnectionSpec)
|
||||
* @see javax.resource.cci.ConnectionFactory#getConnection()
|
||||
*/
|
||||
protected Connection doGetConnection(@Nullable ConnectionSpec spec) throws ResourceException {
|
||||
ConnectionFactory connectionFactory = getTargetConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
|
||||
return (spec != null ? connectionFactory.getConnection(spec) : connectionFactory.getConnection());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.Reference;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
import javax.resource.cci.ResourceAdapterMetaData;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* CCI {@link ConnectionFactory} implementation that delegates all calls
|
||||
* to a given target {@link ConnectionFactory}.
|
||||
*
|
||||
* <p>This class is meant to be subclassed, with subclasses overriding only
|
||||
* those methods (such as {@link #getConnection()}) that should not simply
|
||||
* delegate to the target {@link ConnectionFactory}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #getConnection
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class DelegatingConnectionFactory implements ConnectionFactory, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private ConnectionFactory targetConnectionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Set the target ConnectionFactory that this ConnectionFactory should delegate to.
|
||||
*/
|
||||
public void setTargetConnectionFactory(@Nullable ConnectionFactory targetConnectionFactory) {
|
||||
this.targetConnectionFactory = targetConnectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target ConnectionFactory that this ConnectionFactory should delegate to.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getTargetConnectionFactory() {
|
||||
return this.targetConnectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the target {@code ConnectionFactory} for actual use (never {@code null}).
|
||||
* @since 5.0
|
||||
*/
|
||||
protected ConnectionFactory obtainTargetConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = getTargetConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (getTargetConnectionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'targetConnectionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws ResourceException {
|
||||
return obtainTargetConnectionFactory().getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException {
|
||||
return obtainTargetConnectionFactory().getConnection(connectionSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecordFactory getRecordFactory() throws ResourceException {
|
||||
return obtainTargetConnectionFactory().getRecordFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceAdapterMetaData getMetaData() throws ResourceException {
|
||||
return obtainTargetConnectionFactory().getMetaData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reference getReference() throws NamingException {
|
||||
return obtainTargetConnectionFactory().getReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReference(Reference reference) {
|
||||
obtainTargetConnectionFactory().setReference(reference);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import javax.resource.NotSupportedException;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.IndexedRecord;
|
||||
import javax.resource.cci.MappedRecord;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
|
||||
/**
|
||||
* Implementation of the CCI RecordFactory interface that always throws
|
||||
* NotSupportedException.
|
||||
*
|
||||
* <p>Useful as a placeholder for a RecordFactory argument (for example as
|
||||
* defined by the RecordCreator callback), in particular when the connector's
|
||||
* {@code ConnectionFactory.getRecordFactory()} implementation happens to
|
||||
* throw NotSupportedException early rather than throwing the exception from
|
||||
* RecordFactory's methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.4
|
||||
* @see org.springframework.jca.cci.core.RecordCreator#createRecord(javax.resource.cci.RecordFactory)
|
||||
* @see org.springframework.jca.cci.core.CciTemplate#getRecordFactory(javax.resource.cci.ConnectionFactory)
|
||||
* @see javax.resource.cci.ConnectionFactory#getRecordFactory()
|
||||
* @see javax.resource.NotSupportedException
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public class NotSupportedRecordFactory implements RecordFactory {
|
||||
|
||||
@Override
|
||||
public MappedRecord createMappedRecord(String name) throws ResourceException {
|
||||
throw new NotSupportedException("The RecordFactory facility is not supported by the connector");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexedRecord createIndexedRecord(String name) throws ResourceException {
|
||||
throw new NotSupportedException("The RecordFactory facility is not supported by the connector");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import javax.resource.NotSupportedException;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A CCI ConnectionFactory adapter that returns the same Connection on all
|
||||
* {@code getConnection} calls, and ignores calls to
|
||||
* {@code Connection.close()}.
|
||||
*
|
||||
* <p>Useful for testing and standalone environments, to keep using the same
|
||||
* Connection for multiple CciTemplate calls, without having a pooling
|
||||
* ConnectionFactory, also spanning any number of transactions.
|
||||
*
|
||||
* <p>You can either pass in a CCI Connection directly, or let this
|
||||
* factory lazily create a Connection via a given target ConnectionFactory.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #getConnection()
|
||||
* @see javax.resource.cci.Connection#close()
|
||||
* @see org.springframework.jca.cci.core.CciTemplate
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class SingleConnectionFactory extends DelegatingConnectionFactory implements DisposableBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/** Wrapped Connection. */
|
||||
@Nullable
|
||||
private Connection target;
|
||||
|
||||
/** Proxy Connection. */
|
||||
@Nullable
|
||||
private Connection connection;
|
||||
|
||||
/** Synchronization monitor for the shared Connection. */
|
||||
private final Object connectionMonitor = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SingleConnectionFactory for bean-style usage.
|
||||
* @see #setTargetConnectionFactory
|
||||
*/
|
||||
public SingleConnectionFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new SingleConnectionFactory that always returns the
|
||||
* given Connection.
|
||||
* @param target the single Connection
|
||||
*/
|
||||
public SingleConnectionFactory(Connection target) {
|
||||
Assert.notNull(target, "Target Connection must not be null");
|
||||
this.target = target;
|
||||
this.connection = getCloseSuppressingConnectionProxy(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new SingleConnectionFactory that always returns a single
|
||||
* Connection which it will lazily create via the given target
|
||||
* ConnectionFactory.
|
||||
* @param targetConnectionFactory the target ConnectionFactory
|
||||
*/
|
||||
public SingleConnectionFactory(ConnectionFactory targetConnectionFactory) {
|
||||
Assert.notNull(targetConnectionFactory, "Target ConnectionFactory must not be null");
|
||||
setTargetConnectionFactory(targetConnectionFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure a Connection or ConnectionFactory has been set.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (this.connection == null && getTargetConnectionFactory() == null) {
|
||||
throw new IllegalArgumentException("Connection or 'targetConnectionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws ResourceException {
|
||||
synchronized (this.connectionMonitor) {
|
||||
if (this.connection == null) {
|
||||
initConnection();
|
||||
}
|
||||
return this.connection;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException {
|
||||
throw new NotSupportedException(
|
||||
"SingleConnectionFactory does not support custom ConnectionSpec");
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the underlying Connection.
|
||||
* The provider of this ConnectionFactory needs to care for proper shutdown.
|
||||
* <p>As this bean implements DisposableBean, a bean factory will
|
||||
* automatically invoke this on destruction of its cached singletons.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
resetConnection();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the single underlying Connection.
|
||||
* <p>Closes and reinitializes the Connection if an underlying
|
||||
* Connection is present already.
|
||||
* @throws javax.resource.ResourceException if thrown by CCI API methods
|
||||
*/
|
||||
public void initConnection() throws ResourceException {
|
||||
if (getTargetConnectionFactory() == null) {
|
||||
throw new IllegalStateException(
|
||||
"'targetConnectionFactory' is required for lazily initializing a Connection");
|
||||
}
|
||||
synchronized (this.connectionMonitor) {
|
||||
if (this.target != null) {
|
||||
closeConnection(this.target);
|
||||
}
|
||||
this.target = doCreateConnection();
|
||||
prepareConnection(this.target);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Established shared CCI Connection: " + this.target);
|
||||
}
|
||||
this.connection = getCloseSuppressingConnectionProxy(this.target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the underlying shared Connection, to be reinitialized on next access.
|
||||
*/
|
||||
public void resetConnection() {
|
||||
synchronized (this.connectionMonitor) {
|
||||
if (this.target != null) {
|
||||
closeConnection(this.target);
|
||||
}
|
||||
this.target = null;
|
||||
this.connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a CCI Connection via this template's ConnectionFactory.
|
||||
* @return the new CCI Connection
|
||||
* @throws javax.resource.ResourceException if thrown by CCI API methods
|
||||
*/
|
||||
protected Connection doCreateConnection() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = getTargetConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
|
||||
return connectionFactory.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given Connection before it is exposed.
|
||||
* <p>The default implementation is empty. Can be overridden in subclasses.
|
||||
* @param con the Connection to prepare
|
||||
*/
|
||||
protected void prepareConnection(Connection con) throws ResourceException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given Connection.
|
||||
* @param con the Connection to close
|
||||
*/
|
||||
protected void closeConnection(Connection con) {
|
||||
try {
|
||||
con.close();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.warn("Could not close shared CCI Connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given Connection with a proxy that delegates every method call to it
|
||||
* but suppresses close calls. This is useful for allowing application code to
|
||||
* handle a special framework Connection just like an ordinary Connection from a
|
||||
* CCI ConnectionFactory.
|
||||
* @param target the original Connection to wrap
|
||||
* @return the wrapped Connection
|
||||
*/
|
||||
protected Connection getCloseSuppressingConnectionProxy(Connection target) {
|
||||
return (Connection) Proxy.newProxyInstance(
|
||||
Connection.class.getClassLoader(),
|
||||
new Class<?>[] {Connection.class},
|
||||
new CloseSuppressingInvocationHandler(target));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invocation handler that suppresses close calls on CCI Connections.
|
||||
*/
|
||||
private static final class CloseSuppressingInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final Connection target;
|
||||
|
||||
private CloseSuppressingInvocationHandler(Connection target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
switch (method.getName()) {
|
||||
case "equals":
|
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0]);
|
||||
case "hashCode":
|
||||
// Use hashCode of Connection proxy.
|
||||
return System.identityHashCode(proxy);
|
||||
case "close":
|
||||
// Handle close method: don't pass the call on.
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return method.invoke(this.target, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.cci.connection;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Proxy for a target CCI {@link javax.resource.cci.ConnectionFactory}, adding
|
||||
* awareness of Spring-managed transactions. Similar to a transactional JNDI
|
||||
* ConnectionFactory as provided by a Java EE server.
|
||||
*
|
||||
* <p>Data access code that should remain unaware of Spring's data access support
|
||||
* can work with this proxy to seamlessly participate in Spring-managed transactions.
|
||||
* Note that the transaction manager, for example the {@link CciLocalTransactionManager},
|
||||
* still needs to work with underlying ConnectionFactory, <i>not</i> with this proxy.
|
||||
*
|
||||
* <p><b>Make sure that TransactionAwareConnectionFactoryProxy is the outermost
|
||||
* ConnectionFactory of a chain of ConnectionFactory proxies/adapters.</b>
|
||||
* TransactionAwareConnectionFactoryProxy can delegate either directly to the
|
||||
* target connection pool or to some intermediate proxy/adapter like
|
||||
* {@link ConnectionSpecConnectionFactoryAdapter}.
|
||||
*
|
||||
* <p>Delegates to {@link ConnectionFactoryUtils} for automatically participating in
|
||||
* thread-bound transactions, for example managed by {@link CciLocalTransactionManager}.
|
||||
* {@code getConnection} calls and {@code close} calls on returned Connections
|
||||
* will behave properly within a transaction, i.e. always operate on the transactional
|
||||
* Connection. If not within a transaction, normal ConnectionFactory behavior applies.
|
||||
*
|
||||
* <p>This proxy allows data access code to work with the plain JCA CCI API and still
|
||||
* participate in Spring-managed transactions, similar to CCI code in a Java EE/JTA
|
||||
* environment. However, if possible, use Spring's ConnectionFactoryUtils, CciTemplate or
|
||||
* CCI operation objects to get transaction participation even without a proxy for
|
||||
* the target ConnectionFactory, avoiding the need to define such a proxy in the first place.
|
||||
*
|
||||
* <p><b>NOTE:</b> This ConnectionFactory proxy needs to return wrapped Connections
|
||||
* in order to handle close calls properly. Therefore, the returned Connections cannot
|
||||
* be cast to a native CCI Connection type or to a connection pool implementation type.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see javax.resource.cci.ConnectionFactory#getConnection
|
||||
* @see javax.resource.cci.Connection#close
|
||||
* @see ConnectionFactoryUtils#doGetConnection
|
||||
* @see ConnectionFactoryUtils#doReleaseConnection
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class TransactionAwareConnectionFactoryProxy extends DelegatingConnectionFactory {
|
||||
|
||||
/**
|
||||
* Create a new TransactionAwareConnectionFactoryProxy.
|
||||
* @see #setTargetConnectionFactory
|
||||
*/
|
||||
public TransactionAwareConnectionFactoryProxy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TransactionAwareConnectionFactoryProxy.
|
||||
* @param targetConnectionFactory the target ConnectionFactory
|
||||
*/
|
||||
public TransactionAwareConnectionFactoryProxy(ConnectionFactory targetConnectionFactory) {
|
||||
setTargetConnectionFactory(targetConnectionFactory);
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delegate to ConnectionFactoryUtils for automatically participating in Spring-managed
|
||||
* transactions. Throws the original ResourceException, if any.
|
||||
* @return a transactional Connection if any, a new one else
|
||||
* @see org.springframework.jca.cci.connection.ConnectionFactoryUtils#doGetConnection
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection() throws ResourceException {
|
||||
ConnectionFactory targetConnectionFactory = obtainTargetConnectionFactory();
|
||||
Connection con = ConnectionFactoryUtils.doGetConnection(targetConnectionFactory);
|
||||
return getTransactionAwareConnectionProxy(con, targetConnectionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given Connection with a proxy that delegates every method call to it
|
||||
* but delegates {@code close} calls to ConnectionFactoryUtils.
|
||||
* @param target the original Connection to wrap
|
||||
* @param cf the ConnectionFactory that the Connection came from
|
||||
* @return the wrapped Connection
|
||||
* @see javax.resource.cci.Connection#close()
|
||||
* @see ConnectionFactoryUtils#doReleaseConnection
|
||||
*/
|
||||
protected Connection getTransactionAwareConnectionProxy(Connection target, ConnectionFactory cf) {
|
||||
return (Connection) Proxy.newProxyInstance(
|
||||
Connection.class.getClassLoader(),
|
||||
new Class<?>[] {Connection.class},
|
||||
new TransactionAwareInvocationHandler(target, cf));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invocation handler that delegates close calls on CCI Connections
|
||||
* to ConnectionFactoryUtils for being aware of thread-bound transactions.
|
||||
*/
|
||||
private static class TransactionAwareInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final Connection target;
|
||||
|
||||
private final ConnectionFactory connectionFactory;
|
||||
|
||||
public TransactionAwareInvocationHandler(Connection target, ConnectionFactory cf) {
|
||||
this.target = target;
|
||||
this.connectionFactory = cf;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// Invocation on Connection interface coming in...
|
||||
|
||||
switch (method.getName()) {
|
||||
case "equals":
|
||||
// Only consider equal when proxies are identical.
|
||||
return (proxy == args[0]);
|
||||
case "hashCode":
|
||||
// Use hashCode of Connection proxy.
|
||||
return System.identityHashCode(proxy);
|
||||
case "getLocalTransaction":
|
||||
if (ConnectionFactoryUtils.isConnectionTransactional(this.target, this.connectionFactory)) {
|
||||
throw new javax.resource.spi.IllegalStateException(
|
||||
"Local transaction handling not allowed within a managed transaction");
|
||||
}
|
||||
return this.target.getLocalTransaction();
|
||||
case "close":
|
||||
// Handle close method: only close if not within a transaction.
|
||||
ConnectionFactoryUtils.doReleaseConnection(this.target, this.connectionFactory);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Invoke method on target Connection.
|
||||
try {
|
||||
return method.invoke(this.target, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Provides a utility class for easy ConnectionFactory access,
|
||||
* a PlatformTransactionManager for local CCI transactions,
|
||||
* and various simple ConnectionFactory proxies/adapters.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.cci.connection;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.cci.core;
|
||||
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.Record;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of CCI operations on an EIS.
|
||||
* Implemented by CciTemplate. Not often used, but a useful option
|
||||
* to enhance testability, as it can easily be mocked or stubbed.
|
||||
*
|
||||
* <p>Alternatively, the standard CCI infrastructure can be mocked.
|
||||
* However, mocking this interface constitutes significantly less work.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see CciTemplate
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public interface CciOperations {
|
||||
|
||||
/**
|
||||
* Execute a request on an EIS with CCI, implemented as callback action
|
||||
* working on a CCI Connection. This allows for implementing arbitrary
|
||||
* data access operations, within Spring's managed CCI environment:
|
||||
* that is, participating in Spring-managed transactions and converting
|
||||
* JCA ResourceExceptions into Spring's DataAccessException hierarchy.
|
||||
* <p>The callback action can return a result object, for example a
|
||||
* domain object or a collection of domain objects.
|
||||
* @param action the callback object that specifies the action
|
||||
* @return the result object returned by the action, if any
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(ConnectionCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a request on an EIS with CCI, implemented as callback action
|
||||
* working on a CCI Interaction. This allows for implementing arbitrary
|
||||
* data access operations on a single Interaction, within Spring's managed
|
||||
* CCI environment: that is, participating in Spring-managed transactions
|
||||
* and converting JCA ResourceExceptions into Spring's DataAccessException
|
||||
* hierarchy.
|
||||
* <p>The callback action can return a result object, for example a
|
||||
* domain object or a collection of domain objects.
|
||||
* @param action the callback object that specifies the action
|
||||
* @return the result object returned by the action, if any
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(InteractionCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the specified interaction on an EIS with CCI.
|
||||
* @param spec the CCI InteractionSpec instance that defines
|
||||
* the interaction (connector-specific)
|
||||
* @param inputRecord the input record
|
||||
* @return the output record
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the specified interaction on an EIS with CCI.
|
||||
* @param spec the CCI InteractionSpec instance that defines
|
||||
* the interaction (connector-specific)
|
||||
* @param inputRecord the input record
|
||||
* @param outputRecord the output record
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the specified interaction on an EIS with CCI.
|
||||
* @param spec the CCI InteractionSpec instance that defines
|
||||
* the interaction (connector-specific)
|
||||
* @param inputCreator object that creates the input record to use
|
||||
* @return the output record
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the specified interaction on an EIS with CCI.
|
||||
* @param spec the CCI InteractionSpec instance that defines
|
||||
* the interaction (connector-specific)
|
||||
* @param inputRecord the input record
|
||||
* @param outputExtractor object to convert the output record to a result object
|
||||
* @return the output data extracted with the RecordExtractor object
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the specified interaction on an EIS with CCI.
|
||||
* @param spec the CCI InteractionSpec instance that defines
|
||||
* the interaction (connector-specific)
|
||||
* @param inputCreator object that creates the input record to use
|
||||
* @param outputExtractor object to convert the output record to a result object
|
||||
* @return the output data extracted with the RecordExtractor object
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
<T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor)
|
||||
throws DataAccessException;
|
||||
|
||||
}
|
||||
@@ -1,461 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.core;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.resource.NotSupportedException;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
import javax.resource.cci.IndexedRecord;
|
||||
import javax.resource.cci.Interaction;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.MappedRecord;
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
import javax.resource.cci.ResultSet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <b>This is the central class in the CCI core package.</b>
|
||||
* It simplifies the use of CCI and helps to avoid common errors.
|
||||
* It executes core CCI workflow, leaving application code to provide parameters
|
||||
* to CCI and extract results. This class executes EIS queries or updates,
|
||||
* catching ResourceExceptions and translating them to the generic exception
|
||||
* hierarchy defined in the {@code org.springframework.dao} package.
|
||||
*
|
||||
* <p>Code using this class can pass in and receive {@link javax.resource.cci.Record}
|
||||
* instances, or alternatively implement callback interfaces for creating input
|
||||
* Records and extracting result objects from output Records (or CCI ResultSets).
|
||||
*
|
||||
* <p>Can be used within a service implementation via direct instantiation
|
||||
* with a ConnectionFactory reference, or get prepared in an application context
|
||||
* and given to services as bean reference. Note: The ConnectionFactory should
|
||||
* always be configured as a bean in the application context, in the first case
|
||||
* given to the service directly, in the second case to the prepared template.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see RecordCreator
|
||||
* @see RecordExtractor
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public class CciTemplate implements CciOperations {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@Nullable
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
@Nullable
|
||||
private ConnectionSpec connectionSpec;
|
||||
|
||||
@Nullable
|
||||
private RecordCreator outputRecordCreator;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new CciTemplate for bean usage.
|
||||
* <p>Note: The ConnectionFactory has to be set before using the instance.
|
||||
* @see #setConnectionFactory
|
||||
*/
|
||||
public CciTemplate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new CciTemplate, given a ConnectionFactory to obtain Connections from.
|
||||
* Note: This will trigger eager initialization of the exception translator.
|
||||
* @param connectionFactory the JCA ConnectionFactory to obtain Connections from
|
||||
*/
|
||||
public CciTemplate(ConnectionFactory connectionFactory) {
|
||||
setConnectionFactory(connectionFactory);
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new CciTemplate, given a ConnectionFactory to obtain Connections from.
|
||||
* Note: This will trigger eager initialization of the exception translator.
|
||||
* @param connectionFactory the JCA ConnectionFactory to obtain Connections from
|
||||
* @param connectionSpec the CCI ConnectionSpec to obtain Connections for
|
||||
* (may be {@code null})
|
||||
*/
|
||||
public CciTemplate(ConnectionFactory connectionFactory, @Nullable ConnectionSpec connectionSpec) {
|
||||
setConnectionFactory(connectionFactory);
|
||||
if (connectionSpec != null) {
|
||||
setConnectionSpec(connectionSpec);
|
||||
}
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the CCI ConnectionFactory to obtain Connections from.
|
||||
*/
|
||||
public void setConnectionFactory(@Nullable ConnectionFactory connectionFactory) {
|
||||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CCI ConnectionFactory used by this template.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionFactory getConnectionFactory() {
|
||||
return this.connectionFactory;
|
||||
}
|
||||
|
||||
private ConnectionFactory obtainConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No ConnectionFactory set");
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CCI ConnectionSpec that this template instance is
|
||||
* supposed to obtain Connections for.
|
||||
*/
|
||||
public void setConnectionSpec(@Nullable ConnectionSpec connectionSpec) {
|
||||
this.connectionSpec = connectionSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CCI ConnectionSpec used by this template, if any.
|
||||
*/
|
||||
@Nullable
|
||||
public ConnectionSpec getConnectionSpec() {
|
||||
return this.connectionSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a RecordCreator that should be used for creating default output Records.
|
||||
* <p>Default is none: When no explicit output Record gets passed into an
|
||||
* {@code execute} method, CCI's {@code Interaction.execute} variant
|
||||
* that returns an output Record will be called.
|
||||
* <p>Specify a RecordCreator here if you always need to call CCI's
|
||||
* {@code Interaction.execute} variant with a passed-in output Record.
|
||||
* Unless there is an explicitly specified output Record, CciTemplate will
|
||||
* then invoke this RecordCreator to create a default output Record instance.
|
||||
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
|
||||
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
|
||||
*/
|
||||
public void setOutputRecordCreator(@Nullable RecordCreator creator) {
|
||||
this.outputRecordCreator = creator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a RecordCreator that should be used for creating default output Records.
|
||||
*/
|
||||
@Nullable
|
||||
public RecordCreator getOutputRecordCreator() {
|
||||
return this.outputRecordCreator;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (getConnectionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'connectionFactory' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a template derived from this template instance,
|
||||
* inheriting the ConnectionFactory and other settings but
|
||||
* overriding the ConnectionSpec used for obtaining Connections.
|
||||
* @param connectionSpec the CCI ConnectionSpec that the derived template
|
||||
* instance is supposed to obtain Connections for
|
||||
* @return the derived template instance
|
||||
* @see #setConnectionSpec
|
||||
*/
|
||||
public CciTemplate getDerivedTemplate(ConnectionSpec connectionSpec) {
|
||||
CciTemplate derived = new CciTemplate(obtainConnectionFactory(), connectionSpec);
|
||||
RecordCreator recordCreator = getOutputRecordCreator();
|
||||
if (recordCreator != null) {
|
||||
derived.setOutputRecordCreator(recordCreator);
|
||||
}
|
||||
return derived;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
ConnectionFactory connectionFactory = obtainConnectionFactory();
|
||||
Connection con = org.springframework.jca.cci.connection.ConnectionFactoryUtils.getConnection(
|
||||
connectionFactory, getConnectionSpec());
|
||||
try {
|
||||
return action.doInConnection(con, connectionFactory);
|
||||
}
|
||||
catch (NotSupportedException ex) {
|
||||
throw new org.springframework.jca.cci.CciOperationNotSupportedException(
|
||||
"CCI operation not supported by connector", ex);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new DataAccessResourceFailureException("CCI operation failed", ex);
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
throw new org.springframework.jca.cci.InvalidResultSetAccessException(
|
||||
"Parsing of CCI ResultSet failed", ex);
|
||||
}
|
||||
finally {
|
||||
org.springframework.jca.cci.connection.ConnectionFactoryUtils.releaseConnection(
|
||||
con, getConnectionFactory());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T execute(final InteractionCallback<T> action) throws DataAccessException {
|
||||
Assert.notNull(action, "Callback object must not be null");
|
||||
return execute((ConnectionCallback<T>) (connection, connectionFactory) -> {
|
||||
Interaction interaction = connection.createInteraction();
|
||||
try {
|
||||
return action.doInInteraction(interaction, connectionFactory);
|
||||
}
|
||||
finally {
|
||||
closeInteraction(interaction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException {
|
||||
return doExecute(spec, inputRecord, null, new SimpleRecordExtractor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) throws DataAccessException {
|
||||
doExecute(spec, inputRecord, outputRecord, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException {
|
||||
Record output = doExecute(spec, createRecord(inputCreator), null, new SimpleRecordExtractor());
|
||||
Assert.state(output != null, "Invalid output record");
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor)
|
||||
throws DataAccessException {
|
||||
|
||||
return doExecute(spec, inputRecord, null, outputExtractor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor)
|
||||
throws DataAccessException {
|
||||
|
||||
return doExecute(spec, createRecord(inputCreator), null, outputExtractor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the specified interaction on an EIS with CCI.
|
||||
* All other interaction execution methods go through this.
|
||||
* @param spec the CCI InteractionSpec instance that defines
|
||||
* the interaction (connector-specific)
|
||||
* @param inputRecord the input record
|
||||
* @param outputRecord output record (can be {@code null})
|
||||
* @param outputExtractor object to convert the output record to a result object
|
||||
* @return the output data extracted with the RecordExtractor object
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
@Nullable
|
||||
protected <T> T doExecute(
|
||||
final InteractionSpec spec, final Record inputRecord, @Nullable final Record outputRecord,
|
||||
@Nullable final RecordExtractor<T> outputExtractor) throws DataAccessException {
|
||||
|
||||
return execute((InteractionCallback<T>) (interaction, connectionFactory) -> {
|
||||
Record outputRecordToUse = outputRecord;
|
||||
try {
|
||||
if (outputRecord != null || getOutputRecordCreator() != null) {
|
||||
// Use the CCI execute method with output record as parameter.
|
||||
if (outputRecord == null) {
|
||||
RecordFactory recordFactory = getRecordFactory(connectionFactory);
|
||||
outputRecordToUse = getOutputRecordCreator().createRecord(recordFactory);
|
||||
}
|
||||
interaction.execute(spec, inputRecord, outputRecordToUse);
|
||||
}
|
||||
else {
|
||||
outputRecordToUse = interaction.execute(spec, inputRecord);
|
||||
}
|
||||
return (outputExtractor != null ? outputExtractor.extractData(outputRecordToUse) : null);
|
||||
}
|
||||
finally {
|
||||
if (outputRecordToUse instanceof ResultSet) {
|
||||
closeResultSet((ResultSet) outputRecordToUse);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an indexed Record through the ConnectionFactory's RecordFactory.
|
||||
* @param name the name of the record
|
||||
* @return the Record
|
||||
* @throws DataAccessException if creation of the Record failed
|
||||
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory)
|
||||
* @see javax.resource.cci.RecordFactory#createIndexedRecord(String)
|
||||
*/
|
||||
public IndexedRecord createIndexedRecord(String name) throws DataAccessException {
|
||||
try {
|
||||
RecordFactory recordFactory = getRecordFactory(obtainConnectionFactory());
|
||||
return recordFactory.createIndexedRecord(name);
|
||||
}
|
||||
catch (NotSupportedException ex) {
|
||||
throw new org.springframework.jca.cci.RecordTypeNotSupportedException(
|
||||
"Creation of indexed Record not supported by connector", ex);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new org.springframework.jca.cci.CannotCreateRecordException(
|
||||
"Creation of indexed Record failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mapped Record from the ConnectionFactory's RecordFactory.
|
||||
* @param name record name
|
||||
* @return the Record
|
||||
* @throws DataAccessException if creation of the Record failed
|
||||
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory)
|
||||
* @see javax.resource.cci.RecordFactory#createMappedRecord(String)
|
||||
*/
|
||||
public MappedRecord createMappedRecord(String name) throws DataAccessException {
|
||||
try {
|
||||
RecordFactory recordFactory = getRecordFactory(obtainConnectionFactory());
|
||||
return recordFactory.createMappedRecord(name);
|
||||
}
|
||||
catch (NotSupportedException ex) {
|
||||
throw new org.springframework.jca.cci.RecordTypeNotSupportedException(
|
||||
"Creation of mapped Record not supported by connector", ex);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new org.springframework.jca.cci.CannotCreateRecordException(
|
||||
"Creation of mapped Record failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given RecordCreator, converting JCA ResourceExceptions
|
||||
* to Spring's DataAccessException hierarchy.
|
||||
* @param recordCreator the RecordCreator to invoke
|
||||
* @return the created Record
|
||||
* @throws DataAccessException if creation of the Record failed
|
||||
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory)
|
||||
* @see RecordCreator#createRecord(javax.resource.cci.RecordFactory)
|
||||
*/
|
||||
protected Record createRecord(RecordCreator recordCreator) throws DataAccessException {
|
||||
try {
|
||||
RecordFactory recordFactory = getRecordFactory(obtainConnectionFactory());
|
||||
return recordCreator.createRecord(recordFactory);
|
||||
}
|
||||
catch (NotSupportedException ex) {
|
||||
throw new org.springframework.jca.cci.RecordTypeNotSupportedException(
|
||||
"Creation of the desired Record type not supported by connector", ex);
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new org.springframework.jca.cci.CannotCreateRecordException(
|
||||
"Creation of the desired Record failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a RecordFactory for the given ConnectionFactory.
|
||||
* <p>Default implementation returns the connector's RecordFactory if
|
||||
* available, falling back to a NotSupportedRecordFactory placeholder.
|
||||
* This allows to invoke a RecordCreator callback with a non-null
|
||||
* RecordFactory reference in any case.
|
||||
* @param connectionFactory the CCI ConnectionFactory
|
||||
* @return the CCI RecordFactory for the ConnectionFactory
|
||||
* @throws ResourceException if thrown by CCI methods
|
||||
* @see org.springframework.jca.cci.connection.NotSupportedRecordFactory
|
||||
*/
|
||||
protected RecordFactory getRecordFactory(ConnectionFactory connectionFactory) throws ResourceException {
|
||||
try {
|
||||
return connectionFactory.getRecordFactory();
|
||||
}
|
||||
catch (NotSupportedException ex) {
|
||||
return new org.springframework.jca.cci.connection.NotSupportedRecordFactory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the given CCI Interaction and ignore any thrown exception.
|
||||
* This is useful for typical finally blocks in manual CCI code.
|
||||
* @param interaction the CCI Interaction to close
|
||||
* @see javax.resource.cci.Interaction#close()
|
||||
*/
|
||||
private void closeInteraction(@Nullable Interaction interaction) {
|
||||
if (interaction != null) {
|
||||
try {
|
||||
interaction.close();
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
logger.trace("Could not close CCI Interaction", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// We don't trust the CCI driver: It might throw RuntimeException or Error.
|
||||
logger.trace("Unexpected exception on closing CCI Interaction", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given CCI ResultSet and ignore any thrown exception.
|
||||
* This is useful for typical finally blocks in manual CCI code.
|
||||
* @param resultSet the CCI ResultSet to close
|
||||
* @see javax.resource.cci.ResultSet#close()
|
||||
*/
|
||||
private void closeResultSet(@Nullable ResultSet resultSet) {
|
||||
if (resultSet != null) {
|
||||
try {
|
||||
resultSet.close();
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
logger.trace("Could not close CCI ResultSet", ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// We don't trust the CCI driver: It might throw RuntimeException or Error.
|
||||
logger.trace("Unexpected exception on closing CCI ResultSet", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class SimpleRecordExtractor implements RecordExtractor<Record> {
|
||||
|
||||
@Override
|
||||
public Record extractData(Record record) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.core;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Generic callback interface for code that operates on a CCI Connection.
|
||||
* Allows to execute any number of operations on a single Connection,
|
||||
* using any type and number of Interaction.
|
||||
*
|
||||
* <p>This is particularly useful for delegating to existing data access code
|
||||
* that expects a Connection to work on and throws ResourceException. For newly
|
||||
* written code, it is strongly recommended to use CciTemplate's more specific
|
||||
* {@code execute} variants.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @param <T> the result type
|
||||
* @see CciTemplate#execute(ConnectionCallback)
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record)
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface ConnectionCallback<T> {
|
||||
|
||||
/**
|
||||
* Gets called by {@code CciTemplate.execute} with an active CCI Connection.
|
||||
* Does not need to care about activating or closing the Connection, or handling
|
||||
* transactions.
|
||||
* <p>If called without a thread-bound CCI transaction (initiated by
|
||||
* CciLocalTransactionManager), the code will simply get executed on the CCI
|
||||
* Connection with its transactional semantics. If CciTemplate is configured
|
||||
* to use a JTA-aware ConnectionFactory, the CCI Connection and thus the callback
|
||||
* code will be transactional if a JTA transaction is active.
|
||||
* <p>Allows for returning a result object created within the callback, i.e.
|
||||
* a domain object or a collection of domain objects. Note that there's special
|
||||
* support for single step actions: see the {@code CciTemplate.execute}
|
||||
* variants. A thrown RuntimeException is treated as application exception:
|
||||
* it gets propagated to the caller of the template.
|
||||
* @param connection active CCI Connection
|
||||
* @param connectionFactory the CCI ConnectionFactory that the Connection was
|
||||
* created with (gives access to RecordFactory and ResourceAdapterMetaData)
|
||||
* @return a result object, or {@code null} if none
|
||||
* @throws ResourceException if thrown by a CCI method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws SQLException if thrown by a ResultSet method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws DataAccessException in case of custom exceptions
|
||||
* @see javax.resource.cci.ConnectionFactory#getRecordFactory()
|
||||
* @see javax.resource.cci.ConnectionFactory#getMetaData()
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
|
||||
*/
|
||||
@Nullable
|
||||
T doInConnection(Connection connection, ConnectionFactory connectionFactory)
|
||||
throws ResourceException, SQLException, DataAccessException;
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.core;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.Interaction;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Generic callback interface for code that operates on a CCI Interaction.
|
||||
* Allows to execute any number of operations on a single Interaction, for
|
||||
* example a single execute call or repeated execute calls with varying
|
||||
* parameters.
|
||||
*
|
||||
* <p>This is particularly useful for delegating to existing data access code
|
||||
* that expects an Interaction to work on and throws ResourceException. For newly
|
||||
* written code, it is strongly recommended to use CciTemplate's more specific
|
||||
* {@code execute} variants.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @param <T> the result type
|
||||
* @see CciTemplate#execute(InteractionCallback)
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record)
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface InteractionCallback<T> {
|
||||
|
||||
/**
|
||||
* Gets called by {@code CciTemplate.execute} with an active CCI Interaction.
|
||||
* Does not need to care about activating or closing the Interaction, or
|
||||
* handling transactions.
|
||||
* <p>If called without a thread-bound CCI transaction (initiated by
|
||||
* CciLocalTransactionManager), the code will simply get executed on the CCI
|
||||
* Interaction with its transactional semantics. If CciTemplate is configured
|
||||
* to use a JTA-aware ConnectionFactory, the CCI Interaction and thus the callback
|
||||
* code will be transactional if a JTA transaction is active.
|
||||
* <p>Allows for returning a result object created within the callback, i.e.
|
||||
* a domain object or a collection of domain objects. Note that there's special
|
||||
* support for single step actions: see the {@code CciTemplate.execute}
|
||||
* variants. A thrown RuntimeException is treated as application exception:
|
||||
* it gets propagated to the caller of the template.
|
||||
* @param interaction active CCI Interaction
|
||||
* @param connectionFactory the CCI ConnectionFactory that the Connection was
|
||||
* created with (gives access to RecordFactory and ResourceAdapterMetaData)
|
||||
* @return a result object, or {@code null} if none
|
||||
* @throws ResourceException if thrown by a CCI method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws SQLException if thrown by a ResultSet method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws DataAccessException in case of custom exceptions
|
||||
* @see javax.resource.cci.ConnectionFactory#getRecordFactory()
|
||||
* @see javax.resource.cci.ConnectionFactory#getMetaData()
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
|
||||
*/
|
||||
@Nullable
|
||||
T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
|
||||
throws ResourceException, SQLException, DataAccessException;
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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
|
||||
*
|
||||
* https://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.cci.core;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Callback interface for creating a CCI Record instance,
|
||||
* usually based on the passed-in CCI RecordFactory.
|
||||
*
|
||||
* <p>Used for input Record creation in CciTemplate. Alternatively,
|
||||
* Record instances can be passed into CciTemplate's corresponding
|
||||
* {@code execute} methods directly, either instantiated manually
|
||||
* or created through CciTemplate's Record factory methods.
|
||||
*
|
||||
* <P>Also used for creating default output Records in CciTemplate.
|
||||
* This is useful when the JCA connector needs an explicit output Record
|
||||
* instance, but no output Records should be passed into CciTemplate's
|
||||
* {@code execute} methods.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator)
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
|
||||
* @see CciTemplate#createIndexedRecord(String)
|
||||
* @see CciTemplate#createMappedRecord(String)
|
||||
* @see CciTemplate#setOutputRecordCreator(RecordCreator)
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface RecordCreator {
|
||||
|
||||
/**
|
||||
* Create a CCI Record instance, usually based on the passed-in CCI RecordFactory.
|
||||
* <p>For use as <i>input</i> creator with CciTemplate's {@code execute} methods,
|
||||
* this method should create a <i>populated</i> Record instance. For use as
|
||||
* <i>output</i> Record creator, it should return an <i>empty</i> Record instance.
|
||||
* @param recordFactory the CCI RecordFactory (never {@code null}, but not guaranteed to be
|
||||
* supported by the connector: its create methods might throw NotSupportedException)
|
||||
* @return the Record instance
|
||||
* @throws ResourceException if thrown by a CCI method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws DataAccessException in case of custom exceptions
|
||||
*/
|
||||
Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException;
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.core;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Record;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Callback interface for extracting a result object from a CCI Record instance.
|
||||
*
|
||||
* <p>Used for output object creation in CciTemplate. Alternatively, output
|
||||
* Records can also be returned to client code as-is. In case of a CCI ResultSet
|
||||
* as execution result, you will almost always want to implement a RecordExtractor,
|
||||
* to be able to read the ResultSet in a managed fashion, with the CCI Connection
|
||||
* still open while reading the ResultSet.
|
||||
*
|
||||
* <p>Implementations of this interface perform the actual work of extracting
|
||||
* results, but don't need to worry about exception handling. ResourceExceptions
|
||||
* will be caught and handled correctly by the CciTemplate class.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @param <T> the result type
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, Record, RecordExtractor)
|
||||
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
|
||||
* @see javax.resource.cci.ResultSet
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface RecordExtractor<T> {
|
||||
|
||||
/**
|
||||
* Process the data in the given Record, creating a corresponding result object.
|
||||
* @param record the Record to extract data from
|
||||
* (possibly a CCI ResultSet)
|
||||
* @return an arbitrary result object, or {@code null} if none
|
||||
* (the extractor will typically be stateful in the latter case)
|
||||
* @throws ResourceException if thrown by a CCI method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws SQLException if thrown by a ResultSet method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @throws DataAccessException in case of custom exceptions
|
||||
* @see javax.resource.cci.ResultSet
|
||||
*/
|
||||
@Nullable
|
||||
T extractData(Record record) throws ResourceException, SQLException, DataAccessException;
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Provides the core JCA CCI support, based on CciTemplate
|
||||
* and its associated callback interfaces.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.cci.core;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.core.support;
|
||||
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
|
||||
import org.springframework.dao.support.DaoSupport;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Convenient super class for CCI-based data access objects.
|
||||
*
|
||||
* <p>Requires a {@link javax.resource.cci.ConnectionFactory} to be set,
|
||||
* providing a {@link org.springframework.jca.cci.core.CciTemplate} based
|
||||
* on it to subclasses through the {@link #getCciTemplate()} method.
|
||||
*
|
||||
* <p>This base class is mainly intended for CciTemplate usage but can
|
||||
* also be used when working with a Connection directly or when using
|
||||
* {@code org.springframework.jca.cci.object} classes.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setConnectionFactory
|
||||
* @see #getCciTemplate
|
||||
* @see org.springframework.jca.cci.core.CciTemplate
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class CciDaoSupport extends DaoSupport {
|
||||
|
||||
@Nullable
|
||||
private org.springframework.jca.cci.core.CciTemplate cciTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Set the ConnectionFactory to be used by this DAO.
|
||||
*/
|
||||
public final void setConnectionFactory(ConnectionFactory connectionFactory) {
|
||||
if (this.cciTemplate == null || connectionFactory != this.cciTemplate.getConnectionFactory()) {
|
||||
this.cciTemplate = createCciTemplate(connectionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a CciTemplate for the given ConnectionFactory.
|
||||
* Only invoked if populating the DAO with a ConnectionFactory reference!
|
||||
* <p>Can be overridden in subclasses to provide a CciTemplate instance
|
||||
* with different configuration, or a custom CciTemplate subclass.
|
||||
* @param connectionFactory the CCI ConnectionFactory to create a CciTemplate for
|
||||
* @return the new CciTemplate instance
|
||||
* @see #setConnectionFactory(javax.resource.cci.ConnectionFactory)
|
||||
*/
|
||||
protected org.springframework.jca.cci.core.CciTemplate createCciTemplate(ConnectionFactory connectionFactory) {
|
||||
return new org.springframework.jca.cci.core.CciTemplate(connectionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ConnectionFactory used by this DAO.
|
||||
*/
|
||||
@Nullable
|
||||
public final ConnectionFactory getConnectionFactory() {
|
||||
return (this.cciTemplate != null ? this.cciTemplate.getConnectionFactory() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CciTemplate for this DAO explicitly,
|
||||
* as an alternative to specifying a ConnectionFactory.
|
||||
*/
|
||||
public final void setCciTemplate(org.springframework.jca.cci.core.CciTemplate cciTemplate) {
|
||||
this.cciTemplate = cciTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CciTemplate for this DAO,
|
||||
* pre-initialized with the ConnectionFactory or set explicitly.
|
||||
*/
|
||||
@Nullable
|
||||
public final org.springframework.jca.cci.core.CciTemplate getCciTemplate() {
|
||||
return this.cciTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void checkDaoConfig() {
|
||||
if (this.cciTemplate == null) {
|
||||
throw new IllegalArgumentException("'connectionFactory' or 'cciTemplate' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain a CciTemplate derived from the main template instance,
|
||||
* inheriting the ConnectionFactory and other settings but
|
||||
* overriding the ConnectionSpec used for obtaining Connections.
|
||||
* @param connectionSpec the CCI ConnectionSpec that the returned
|
||||
* template instance is supposed to obtain Connections for
|
||||
* @return the derived template instance
|
||||
* @see org.springframework.jca.cci.core.CciTemplate#getDerivedTemplate(javax.resource.cci.ConnectionSpec)
|
||||
*/
|
||||
protected final org.springframework.jca.cci.core.CciTemplate getCciTemplate(ConnectionSpec connectionSpec) {
|
||||
org.springframework.jca.cci.core.CciTemplate cciTemplate = getCciTemplate();
|
||||
Assert.state(cciTemplate != null, "No CciTemplate set");
|
||||
return cciTemplate.getDerivedTemplate(connectionSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a CCI Connection, either from the current transaction or a new one.
|
||||
* @return the CCI Connection
|
||||
* @throws org.springframework.jca.cci.CannotGetCciConnectionException
|
||||
* if the attempt to get a Connection failed
|
||||
* @see org.springframework.jca.cci.connection.ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory)
|
||||
*/
|
||||
protected final Connection getConnection() throws org.springframework.jca.cci.CannotGetCciConnectionException {
|
||||
ConnectionFactory connectionFactory = getConnectionFactory();
|
||||
Assert.state(connectionFactory != null, "No ConnectionFactory set");
|
||||
return org.springframework.jca.cci.connection.ConnectionFactoryUtils.getConnection(connectionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given CCI Connection, created via this bean's ConnectionFactory,
|
||||
* if it isn't bound to the thread.
|
||||
* @param con the Connection to close
|
||||
* @see org.springframework.jca.cci.connection.ConnectionFactoryUtils#releaseConnection
|
||||
*/
|
||||
protected final void releaseConnection(Connection con) {
|
||||
org.springframework.jca.cci.connection.ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.cci.core.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.Streamable;
|
||||
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* CCI Record implementation for a COMMAREA, holding a byte array.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see org.springframework.jca.cci.object.MappingCommAreaOperation
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class CommAreaRecord implements Record, Streamable {
|
||||
|
||||
private byte[] bytes = new byte[0];
|
||||
|
||||
private String recordName = "";
|
||||
|
||||
private String recordShortDescription = "";
|
||||
|
||||
|
||||
/**
|
||||
* Create a new CommAreaRecord.
|
||||
* @see #read(java.io.InputStream)
|
||||
*/
|
||||
public CommAreaRecord() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CommAreaRecord.
|
||||
* @param bytes the bytes to fill the record with
|
||||
*/
|
||||
public CommAreaRecord(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setRecordName(String recordName) {
|
||||
this.recordName = recordName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return this.recordName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecordShortDescription(String recordShortDescription) {
|
||||
this.recordShortDescription = recordShortDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRecordShortDescription() {
|
||||
return this.recordShortDescription;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void read(InputStream in) throws IOException {
|
||||
this.bytes = FileCopyUtils.copyToByteArray(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(OutputStream out) throws IOException {
|
||||
out.write(this.bytes);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return this.bytes;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
return new CommAreaRecord(this.bytes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Classes supporting the {@code org.springframework.jca.cci.core} package.
|
||||
* Contains a DAO base class for CciTemplate usage.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.cci.core.support;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.cci.object;
|
||||
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class for EIS operation objects that work with the CCI API.
|
||||
* Encapsulates a CCI ConnectionFactory and a CCI InteractionSpec.
|
||||
*
|
||||
* <p>Works with a CciTemplate instance underneath. EIS operation objects
|
||||
* are an alternative to working with a CciTemplate directly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #setConnectionFactory
|
||||
* @see #setInteractionSpec
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class EisOperation implements InitializingBean {
|
||||
|
||||
private org.springframework.jca.cci.core.CciTemplate cciTemplate =
|
||||
new org.springframework.jca.cci.core.CciTemplate();
|
||||
|
||||
@Nullable
|
||||
private InteractionSpec interactionSpec;
|
||||
|
||||
|
||||
/**
|
||||
* Set the CciTemplate to be used by this operation.
|
||||
* Alternatively, specify a CCI ConnectionFactory.
|
||||
* @see #setConnectionFactory
|
||||
*/
|
||||
public void setCciTemplate(org.springframework.jca.cci.core.CciTemplate cciTemplate) {
|
||||
Assert.notNull(cciTemplate, "CciTemplate must not be null");
|
||||
this.cciTemplate = cciTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CciTemplate used by this operation.
|
||||
*/
|
||||
public org.springframework.jca.cci.core.CciTemplate getCciTemplate() {
|
||||
return this.cciTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CCI ConnectionFactory to be used by this operation.
|
||||
*/
|
||||
public void setConnectionFactory(ConnectionFactory connectionFactory) {
|
||||
this.cciTemplate.setConnectionFactory(connectionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CCI InteractionSpec for this operation.
|
||||
*/
|
||||
public void setInteractionSpec(@Nullable InteractionSpec interactionSpec) {
|
||||
this.interactionSpec = interactionSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CCI InteractionSpec for this operation.
|
||||
*/
|
||||
@Nullable
|
||||
public InteractionSpec getInteractionSpec() {
|
||||
return this.interactionSpec;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
this.cciTemplate.afterPropertiesSet();
|
||||
|
||||
if (this.interactionSpec == null) {
|
||||
throw new IllegalArgumentException("InteractionSpec is required");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.object;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
/**
|
||||
* EIS operation object for access to COMMAREA records.
|
||||
* Subclass of the generic MappingRecordOperation class.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @since 1.2
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class MappingCommAreaOperation extends MappingRecordOperation {
|
||||
|
||||
/**
|
||||
* Create a new MappingCommAreaQuery.
|
||||
* @see #setConnectionFactory
|
||||
* @see #setInteractionSpec
|
||||
*/
|
||||
public MappingCommAreaOperation() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MappingCommAreaQuery.
|
||||
* @param connectionFactory the ConnectionFactory to use to obtain connections
|
||||
* @param interactionSpec specification to configure the interaction
|
||||
*/
|
||||
public MappingCommAreaOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
|
||||
super(connectionFactory, interactionSpec);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected final Record createInputRecord(RecordFactory recordFactory, Object inObject) {
|
||||
try {
|
||||
return new org.springframework.jca.cci.core.support.CommAreaRecord(objectToBytes(inObject));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new DataRetrievalFailureException("I/O exception during bytes conversion", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Object extractOutputData(Record record) throws DataAccessException {
|
||||
org.springframework.jca.cci.core.support.CommAreaRecord commAreaRecord =
|
||||
(org.springframework.jca.cci.core.support.CommAreaRecord) record;
|
||||
try {
|
||||
return bytesToObject(commAreaRecord.toByteArray());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new DataRetrievalFailureException("I/O exception during bytes conversion", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method used to convert an object into COMMAREA bytes.
|
||||
* @param inObject the input data
|
||||
* @return the COMMAREA's bytes
|
||||
* @throws IOException if thrown by I/O methods
|
||||
* @throws DataAccessException if conversion failed
|
||||
*/
|
||||
protected abstract byte[] objectToBytes(Object inObject) throws IOException, DataAccessException;
|
||||
|
||||
/**
|
||||
* Method used to convert the COMMAREA's bytes to an object.
|
||||
* @param bytes the COMMAREA's bytes
|
||||
* @return the output data
|
||||
* @throws IOException if thrown by I/O methods
|
||||
* @throws DataAccessException if conversion failed
|
||||
*/
|
||||
protected abstract Object bytesToObject(byte[] bytes) throws IOException, DataAccessException;
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.object;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* EIS operation object that expects mapped input and output objects,
|
||||
* converting to and from CCI Records.
|
||||
*
|
||||
* <p>Concrete subclasses must implement the abstract
|
||||
* {@code createInputRecord(RecordFactory, Object)} and
|
||||
* {@code extractOutputData(Record)} methods, to create an input
|
||||
* Record from an object and to convert an output Record into an object,
|
||||
* respectively.
|
||||
*
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @see #createInputRecord(javax.resource.cci.RecordFactory, Object)
|
||||
* @see #extractOutputData(javax.resource.cci.Record)
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class MappingRecordOperation extends EisOperation {
|
||||
|
||||
/**
|
||||
* Constructor that allows use as a JavaBean.
|
||||
*/
|
||||
public MappingRecordOperation() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor with ConnectionFactory and specifications
|
||||
* (connection and interaction).
|
||||
* @param connectionFactory the ConnectionFactory to use to obtain connections
|
||||
*/
|
||||
public MappingRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
|
||||
getCciTemplate().setConnectionFactory(connectionFactory);
|
||||
setInteractionSpec(interactionSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a RecordCreator that should be used for creating default output Records.
|
||||
* <p>Default is none: CCI's {@code Interaction.execute} variant
|
||||
* that returns an output Record will be called.
|
||||
* <p>Specify a RecordCreator here if you always need to call CCI's
|
||||
* {@code Interaction.execute} variant with a passed-in output Record.
|
||||
* This RecordCreator will then be invoked to create a default output Record instance.
|
||||
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
|
||||
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
|
||||
* @see org.springframework.jca.cci.core.CciTemplate#setOutputRecordCreator
|
||||
*/
|
||||
public void setOutputRecordCreator(org.springframework.jca.cci.core.RecordCreator creator) {
|
||||
getCciTemplate().setOutputRecordCreator(creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the interaction encapsulated by this operation object.
|
||||
* @param inputObject the input data, to be converted to a Record
|
||||
* by the {@code createInputRecord} method
|
||||
* @return the output data extracted with the {@code extractOutputData} method
|
||||
* @throws DataAccessException if there is any problem
|
||||
* @see #createInputRecord
|
||||
* @see #extractOutputData
|
||||
*/
|
||||
@Nullable
|
||||
public Object execute(Object inputObject) throws DataAccessException {
|
||||
InteractionSpec interactionSpec = getInteractionSpec();
|
||||
Assert.state(interactionSpec != null, "No InteractionSpec set");
|
||||
return getCciTemplate().execute(
|
||||
interactionSpec, new RecordCreatorImpl(inputObject), new RecordExtractorImpl());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to generate an input Record
|
||||
* from an input object passed into the {@code execute} method.
|
||||
* @param inputObject the passed-in input object
|
||||
* @return the CCI input Record
|
||||
* @throws ResourceException if thrown by a CCI method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @see #execute(Object)
|
||||
*/
|
||||
protected abstract Record createInputRecord(RecordFactory recordFactory, Object inputObject)
|
||||
throws ResourceException, DataAccessException;
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to convert the Record returned
|
||||
* by CCI execution into a result object for the {@code execute} method.
|
||||
* @param outputRecord the Record returned by CCI execution
|
||||
* @return the result object
|
||||
* @throws ResourceException if thrown by a CCI method, to be auto-converted
|
||||
* to a DataAccessException
|
||||
* @see #execute(Object)
|
||||
*/
|
||||
protected abstract Object extractOutputData(Record outputRecord)
|
||||
throws ResourceException, SQLException, DataAccessException;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of RecordCreator that calls the enclosing
|
||||
* class's {@code createInputRecord} method.
|
||||
*/
|
||||
protected class RecordCreatorImpl implements org.springframework.jca.cci.core.RecordCreator {
|
||||
|
||||
private final Object inputObject;
|
||||
|
||||
public RecordCreatorImpl(Object inObject) {
|
||||
this.inputObject = inObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException {
|
||||
return createInputRecord(recordFactory, this.inputObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of RecordExtractor that calls the enclosing
|
||||
* class's {@code extractOutputData} method.
|
||||
*/
|
||||
protected class RecordExtractorImpl implements org.springframework.jca.cci.core.RecordExtractor<Object> {
|
||||
|
||||
@Override
|
||||
public Object extractData(Record record) throws ResourceException, SQLException, DataAccessException {
|
||||
return extractOutputData(record);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.cci.object;
|
||||
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.Record;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* EIS operation object that accepts a passed-in CCI input Record
|
||||
* and returns a corresponding CCI output Record.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2
|
||||
* @deprecated as of 5.3, in favor of specific data access APIs
|
||||
* (or native CCI usage if there is no alternative)
|
||||
*/
|
||||
@Deprecated
|
||||
public class SimpleRecordOperation extends EisOperation {
|
||||
|
||||
/**
|
||||
* Constructor that allows use as a JavaBean.
|
||||
*/
|
||||
public SimpleRecordOperation() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor with ConnectionFactory and specifications
|
||||
* (connection and interaction).
|
||||
* @param connectionFactory the ConnectionFactory to use to obtain connections
|
||||
*/
|
||||
public SimpleRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
|
||||
getCciTemplate().setConnectionFactory(connectionFactory);
|
||||
setInteractionSpec(interactionSpec);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the CCI interaction encapsulated by this operation object.
|
||||
* <p>This method will call CCI's {@code Interaction.execute} variant
|
||||
* that returns an output Record.
|
||||
* @param inputRecord the input record
|
||||
* @return the output record
|
||||
* @throws DataAccessException if there is any problem
|
||||
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
|
||||
*/
|
||||
@Nullable
|
||||
public Record execute(Record inputRecord) throws DataAccessException {
|
||||
InteractionSpec interactionSpec = getInteractionSpec();
|
||||
Assert.state(interactionSpec != null, "No InteractionSpec set");
|
||||
return getCciTemplate().execute(interactionSpec, inputRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the CCI interaction encapsulated by this operation object.
|
||||
* <p>This method will call CCI's {@code Interaction.execute} variant
|
||||
* with a passed-in output Record.
|
||||
* @param inputRecord the input record
|
||||
* @param outputRecord the output record
|
||||
* @throws DataAccessException if there is any problem
|
||||
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
|
||||
*/
|
||||
public void execute(Record inputRecord, Record outputRecord) throws DataAccessException {
|
||||
InteractionSpec interactionSpec = getInteractionSpec();
|
||||
Assert.state(interactionSpec != null, "No InteractionSpec set");
|
||||
getCciTemplate().execute(interactionSpec, inputRecord, outputRecord);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* The classes in this package represent EIS operations as threadsafe,
|
||||
* reusable objects. This higher level of CCI abstraction depends on the
|
||||
* lower-level abstraction in the {@code org.springframework.jca.cci.core} package.
|
||||
* Exceptions thrown are as in the {@code org.springframework.dao} package,
|
||||
* meaning that code using this package does not need to worry about error handling.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.cci.object;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* This package contains Spring's support for the Common Client Interface (CCI),
|
||||
* as defined by the J2EE Connector Architecture. It is conceptually similar
|
||||
* to the {@code org.springframework.jdbc} package, providing the same
|
||||
* levels of data access abstraction.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.cci;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to be
|
||||
* notified of the BootstrapContext (typically determined by the
|
||||
* {@link ResourceAdapterApplicationContext}) that it runs in.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 2.5
|
||||
* @see javax.resource.spi.BootstrapContext
|
||||
*/
|
||||
public interface BootstrapContextAware extends Aware {
|
||||
|
||||
/**
|
||||
* Set the BootstrapContext that this object runs in.
|
||||
* <p>Invoked after population of normal bean properties but before an init
|
||||
* callback like InitializingBean's {@code afterPropertiesSet} or a
|
||||
* custom init-method. Invoked after ApplicationContextAware's
|
||||
* {@code setApplicationContext}.
|
||||
* @param bootstrapContext the BootstrapContext object to be used by this object
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext
|
||||
*/
|
||||
void setBootstrapContext(BootstrapContext bootstrapContext);
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
|
||||
* implementation that passes the BootstrapContext to beans that implement
|
||||
* the {@link BootstrapContextAware} interface.
|
||||
*
|
||||
* <p>{@link ResourceAdapterApplicationContext} automatically registers
|
||||
* this processor with its underlying bean factory.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see BootstrapContextAware
|
||||
*/
|
||||
class BootstrapContextAwareProcessor implements BeanPostProcessor {
|
||||
|
||||
@Nullable
|
||||
private final BootstrapContext bootstrapContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new BootstrapContextAwareProcessor for the given context.
|
||||
*/
|
||||
public BootstrapContextAwareProcessor(@Nullable BootstrapContext bootstrapContext) {
|
||||
this.bootstrapContext = bootstrapContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (this.bootstrapContext != null && bean instanceof BootstrapContextAware) {
|
||||
((BootstrapContextAware) bean).setBootstrapContext(this.bootstrapContext);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
import javax.resource.spi.work.WorkManager;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.context.ApplicationContext} implementation
|
||||
* for a JCA ResourceAdapter. Needs to be initialized with the JCA
|
||||
* {@link javax.resource.spi.BootstrapContext}, passing it on to
|
||||
* Spring-managed beans that implement {@link BootstrapContextAware}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see SpringContextResourceAdapter
|
||||
* @see BootstrapContextAware
|
||||
*/
|
||||
public class ResourceAdapterApplicationContext extends GenericApplicationContext {
|
||||
|
||||
private final BootstrapContext bootstrapContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ResourceAdapterApplicationContext for the given BootstrapContext.
|
||||
* @param bootstrapContext the JCA BootstrapContext that the ResourceAdapter
|
||||
* has been started with
|
||||
*/
|
||||
public ResourceAdapterApplicationContext(BootstrapContext bootstrapContext) {
|
||||
Assert.notNull(bootstrapContext, "BootstrapContext must not be null");
|
||||
this.bootstrapContext = bootstrapContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
beanFactory.addBeanPostProcessor(new BootstrapContextAwareProcessor(this.bootstrapContext));
|
||||
beanFactory.ignoreDependencyInterface(BootstrapContextAware.class);
|
||||
beanFactory.registerResolvableDependency(BootstrapContext.class, this.bootstrapContext);
|
||||
|
||||
// JCA WorkManager resolved lazily - may not be available.
|
||||
beanFactory.registerResolvableDependency(WorkManager.class,
|
||||
(ObjectFactory<WorkManager>) this.bootstrapContext::getWorkManager);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.context;
|
||||
|
||||
import javax.resource.NotSupportedException;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.spi.ActivationSpec;
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
import javax.resource.spi.ResourceAdapter;
|
||||
import javax.resource.spi.ResourceAdapterInternalException;
|
||||
import javax.resource.spi.endpoint.MessageEndpointFactory;
|
||||
import javax.transaction.xa.XAResource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* JCA 1.7 {@link javax.resource.spi.ResourceAdapter} implementation
|
||||
* that loads a Spring {@link org.springframework.context.ApplicationContext},
|
||||
* starting and stopping Spring-managed beans as part of the ResourceAdapter's
|
||||
* lifecycle.
|
||||
*
|
||||
* <p>Ideal for application contexts that do not need any HTTP entry points
|
||||
* but rather just consist of message endpoints and scheduled jobs etc.
|
||||
* Beans in such a context may use application server resources such as the
|
||||
* JTA transaction manager and JNDI-bound JDBC DataSources and JMS
|
||||
* ConnectionFactory instances, and may also register with the platform's
|
||||
* JMX server - all through Spring's standard transaction management and
|
||||
* JNDI and JMX support facilities.
|
||||
*
|
||||
* <p>If the need for scheduling asynchronous work arises, consider using
|
||||
* Spring's {@link org.springframework.jca.work.WorkManagerTaskExecutor}
|
||||
* as a standard bean definition, to be injected into application beans
|
||||
* through dependency injection. This WorkManagerTaskExecutor will automatically
|
||||
* use the JCA WorkManager from the BootstrapContext that has been provided
|
||||
* to this ResourceAdapter.
|
||||
*
|
||||
* <p>The JCA {@link javax.resource.spi.BootstrapContext} may also be
|
||||
* accessed directly, through application components that implement the
|
||||
* {@link BootstrapContextAware} interface. When deployed using this
|
||||
* ResourceAdapter, the BootstrapContext is guaranteed to be passed on
|
||||
* to such components.
|
||||
*
|
||||
* <p>This ResourceAdapter is to be defined in a "META-INF/ra.xml" file
|
||||
* within a Java EE ".rar" deployment unit like as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <connector xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
* xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee https://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
|
||||
* version="1.5">
|
||||
* <vendor-name>Spring Framework</vendor-name>
|
||||
* <eis-type>Spring Connector</eis-type>
|
||||
* <resourceadapter-version>1.0</resourceadapter-version>
|
||||
* <resourceadapter>
|
||||
* <resourceadapter-class>org.springframework.jca.context.SpringContextResourceAdapter</resourceadapter-class>
|
||||
* <config-property>
|
||||
* <config-property-name>ContextConfigLocation</config-property-name>
|
||||
* <config-property-type>java.lang.String</config-property-type>
|
||||
* <config-property-value>META-INF/applicationContext.xml</config-property-value>
|
||||
* </config-property>
|
||||
* </resourceadapter>
|
||||
* </connector></pre>
|
||||
*
|
||||
* Note that "META-INF/applicationContext.xml" is the default context config
|
||||
* location, so it doesn't have to specified unless you intend to specify
|
||||
* different/additional config files. So in the default case, you may remove
|
||||
* the entire {@code config-property} section above.
|
||||
*
|
||||
* <p><b>For simple deployment needs, all you need to do is the following:</b>
|
||||
* Package all application classes into a RAR file (which is just a standard
|
||||
* JAR file with a different file extension), add all required library jars
|
||||
* into the root of the RAR archive, add a "META-INF/ra.xml" deployment
|
||||
* descriptor as shown above as well as the corresponding Spring XML bean
|
||||
* definition file(s) (typically "META-INF/applicationContext.xml"),
|
||||
* and drop the resulting RAR file into your application server's
|
||||
* deployment directory!
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see #setContextConfigLocation
|
||||
* @see #loadBeanDefinitions
|
||||
* @see ResourceAdapterApplicationContext
|
||||
*/
|
||||
public class SpringContextResourceAdapter implements ResourceAdapter {
|
||||
|
||||
/**
|
||||
* Any number of these characters are considered delimiters between
|
||||
* multiple context config paths in a single String value.
|
||||
* @see #setContextConfigLocation
|
||||
*/
|
||||
public static final String CONFIG_LOCATION_DELIMITERS = ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS;
|
||||
|
||||
/**
|
||||
* The default {@code applicationContext.xml} location.
|
||||
*/
|
||||
public static final String DEFAULT_CONTEXT_CONFIG_LOCATION = "META-INF/applicationContext.xml";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private String contextConfigLocation = DEFAULT_CONTEXT_CONFIG_LOCATION;
|
||||
|
||||
@Nullable
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Set the location of the context configuration files, within the
|
||||
* resource adapter's deployment unit. This can be a delimited
|
||||
* String that consists of multiple resource location, separated
|
||||
* by commas, semicolons, whitespace, or line breaks.
|
||||
* <p>This can be specified as "ContextConfigLocation" config
|
||||
* property in the {@code ra.xml} deployment descriptor.
|
||||
* <p>The default is "classpath:META-INF/applicationContext.xml".
|
||||
*/
|
||||
public void setContextConfigLocation(String contextConfigLocation) {
|
||||
this.contextConfigLocation = contextConfigLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specified context configuration files.
|
||||
*/
|
||||
protected String getContextConfigLocation() {
|
||||
return this.contextConfigLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link StandardEnvironment}.
|
||||
* <p>Subclasses may override this method in order to supply
|
||||
* a custom {@link ConfigurableEnvironment} implementation.
|
||||
*/
|
||||
protected ConfigurableEnvironment createEnvironment() {
|
||||
return new StandardEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation loads a Spring ApplicationContext through the
|
||||
* {@link #createApplicationContext} template method.
|
||||
*/
|
||||
@Override
|
||||
public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Starting SpringContextResourceAdapter with BootstrapContext: " + bootstrapContext);
|
||||
}
|
||||
this.applicationContext = createApplicationContext(bootstrapContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Spring ApplicationContext for the given JCA BootstrapContext.
|
||||
* <p>The default implementation builds a {@link ResourceAdapterApplicationContext}
|
||||
* and delegates to {@link #loadBeanDefinitions} for actually parsing the
|
||||
* specified configuration files.
|
||||
* @param bootstrapContext this ResourceAdapter's BootstrapContext
|
||||
* @return the Spring ApplicationContext instance
|
||||
*/
|
||||
protected ConfigurableApplicationContext createApplicationContext(BootstrapContext bootstrapContext) {
|
||||
ResourceAdapterApplicationContext applicationContext =
|
||||
new ResourceAdapterApplicationContext(bootstrapContext);
|
||||
|
||||
// Set ResourceAdapter's ClassLoader as bean class loader.
|
||||
applicationContext.setClassLoader(getClass().getClassLoader());
|
||||
|
||||
// Extract individual config locations.
|
||||
String[] configLocations =
|
||||
StringUtils.tokenizeToStringArray(getContextConfigLocation(), CONFIG_LOCATION_DELIMITERS);
|
||||
|
||||
loadBeanDefinitions(applicationContext, configLocations);
|
||||
applicationContext.refresh();
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the bean definitions into the given registry,
|
||||
* based on the specified configuration files.
|
||||
* @param registry the registry to load into
|
||||
* @param configLocations the parsed config locations
|
||||
* @see #setContextConfigLocation
|
||||
*/
|
||||
protected void loadBeanDefinitions(BeanDefinitionRegistry registry, String[] configLocations) {
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(configLocations);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation closes the Spring ApplicationContext.
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
logger.debug("Stopping SpringContextResourceAdapter");
|
||||
if (this.applicationContext != null) {
|
||||
this.applicationContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation always throws a NotSupportedException.
|
||||
*/
|
||||
@Override
|
||||
public void endpointActivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec)
|
||||
throws ResourceException {
|
||||
|
||||
throw new NotSupportedException("SpringContextResourceAdapter does not support message endpoints");
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation does nothing.
|
||||
*/
|
||||
@Override
|
||||
public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation always returns {@code null}.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof SpringContextResourceAdapter &&
|
||||
ObjectUtils.nullSafeEquals(getContextConfigLocation(),
|
||||
((SpringContextResourceAdapter) other).getContextConfigLocation())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getContextConfigLocation());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Integration package that allows for deploying a Spring application context
|
||||
* as a JCA 1.7 compliant RAR file.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.context;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -18,15 +18,15 @@ 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 jakarta.resource.ResourceException;
|
||||
import jakarta.resource.spi.ApplicationServerInternalException;
|
||||
import jakarta.resource.spi.UnavailableException;
|
||||
import jakarta.resource.spi.endpoint.MessageEndpoint;
|
||||
import jakarta.resource.spi.endpoint.MessageEndpointFactory;
|
||||
import jakarta.transaction.Transaction;
|
||||
import jakarta.transaction.TransactionManager;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base implementation of the JCA 1.7
|
||||
* {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface,
|
||||
* {@link jakarta.resource.spi.endpoint.MessageEndpointFactory} interface,
|
||||
* providing transaction management capabilities as well as ClassLoader
|
||||
* exposure for endpoint invocations.
|
||||
*
|
||||
@@ -68,7 +68,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF
|
||||
* 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}.
|
||||
* interface, or a plain {@link jakarta.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
|
||||
@@ -86,7 +86,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF
|
||||
else {
|
||||
throw new IllegalArgumentException("Transaction manager [" + transactionManager +
|
||||
"] is neither a [org.springframework.transaction.jta.TransactionFactory} nor a " +
|
||||
"[javax.transaction.TransactionManager]");
|
||||
"[jakarta.transaction.TransactionManager]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
package org.springframework.jca.endpoint;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.spi.UnavailableException;
|
||||
import javax.resource.spi.endpoint.MessageEndpoint;
|
||||
import javax.transaction.xa.XAResource;
|
||||
|
||||
import jakarta.resource.ResourceException;
|
||||
import jakarta.resource.spi.UnavailableException;
|
||||
import jakarta.resource.spi.endpoint.MessageEndpoint;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
@@ -32,10 +32,10 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Generic implementation of the JCA 1.7
|
||||
* {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface,
|
||||
* {@link jakarta.resource.spi.endpoint.MessageEndpointFactory} interface,
|
||||
* providing transaction management capabilities for any kind of message
|
||||
* listener object (e.g. {@link javax.jms.MessageListener} objects or
|
||||
* {@link javax.resource.cci.MessageListener} objects.
|
||||
* listener object (e.g. {@link jakarta.jms.MessageListener} objects or
|
||||
* {@link jakarta.resource.cci.MessageListener} objects.
|
||||
*
|
||||
* <p>Uses AOP proxies for concrete endpoint instances, simply wrapping
|
||||
* the specified message listener object and exposing all of its implemented
|
||||
@@ -44,7 +44,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* <p>Typically used with Spring's {@link GenericMessageEndpointManager},
|
||||
* but not tied to it. As a consequence, this endpoint factory could
|
||||
* also be used with programmatic endpoint management on a native
|
||||
* {@link javax.resource.spi.ResourceAdapter} instance.
|
||||
* {@link jakarta.resource.spi.ResourceAdapter} instance.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
@@ -60,8 +60,8 @@ public class GenericMessageEndpointFactory extends AbstractMessageEndpointFactor
|
||||
|
||||
/**
|
||||
* Specify the message listener object that the endpoint should expose
|
||||
* (e.g. a {@link javax.jms.MessageListener} objects or
|
||||
* {@link javax.resource.cci.MessageListener} implementation).
|
||||
* (e.g. a {@link jakarta.jms.MessageListener} objects or
|
||||
* {@link jakarta.resource.cci.MessageListener} implementation).
|
||||
*/
|
||||
public void setMessageListener(Object messageListener) {
|
||||
this.messageListener = messageListener;
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.springframework.jca.endpoint;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.spi.ActivationSpec;
|
||||
import javax.resource.spi.ResourceAdapter;
|
||||
import javax.resource.spi.endpoint.MessageEndpointFactory;
|
||||
import jakarta.resource.ResourceException;
|
||||
import jakarta.resource.spi.ActivationSpec;
|
||||
import jakarta.resource.spi.ResourceAdapter;
|
||||
import jakarta.resource.spi.endpoint.MessageEndpointFactory;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -48,7 +48,7 @@ import org.springframework.util.Assert;
|
||||
* <property name="activationSpec">
|
||||
* <bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
|
||||
* <property name="destination" value="myQueue"/>
|
||||
* <property name="destinationType" value="javax.jms.Queue"/>
|
||||
* <property name="destinationType" value="jakarta.jms.Queue"/>
|
||||
* </bean>
|
||||
* </property>
|
||||
* </bean></pre>
|
||||
@@ -56,7 +56,7 @@ import org.springframework.util.Assert;
|
||||
* In this example, Spring's own {@link GenericMessageEndpointFactory} is used
|
||||
* to point to a standard message listener object that happens to be supported
|
||||
* by the specified target ResourceAdapter: in this case, a JMS
|
||||
* {@link javax.jms.MessageListener} object as supported by the ActiveMQ
|
||||
* {@link jakarta.jms.MessageListener} object as supported by the ActiveMQ
|
||||
* message broker, defined as a Spring bean:
|
||||
*
|
||||
* <pre class="code">
|
||||
@@ -84,7 +84,7 @@ import org.springframework.util.Assert;
|
||||
* For a different target resource, the configuration would simply point to a
|
||||
* different ResourceAdapter and a different ActivationSpec object (which are
|
||||
* both specific to the resource provider), and possibly a different message
|
||||
* listener (e.g. a CCI {@link javax.resource.cci.MessageListener} for a
|
||||
* listener (e.g. a CCI {@link jakarta.resource.cci.MessageListener} for a
|
||||
* resource adapter which is based on the JCA Common Client Interface).
|
||||
*
|
||||
* <p>The asynchronous execution strategy can be customized through the
|
||||
@@ -97,7 +97,7 @@ import org.springframework.util.Assert;
|
||||
* as built by the specified MessageEndpointFactory. {@link GenericMessageEndpointFactory}
|
||||
* supports XA transaction participation through its "transactionManager" property,
|
||||
* typically with a Spring {@link org.springframework.transaction.jta.JtaTransactionManager}
|
||||
* or a plain {@link javax.transaction.TransactionManager} implementation specified there.
|
||||
* or a plain {@link jakarta.transaction.TransactionManager} implementation specified there.
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean class="org.springframework.jca.endpoint.GenericMessageEndpointManager">
|
||||
@@ -111,7 +111,7 @@ import org.springframework.util.Assert;
|
||||
* <property name="activationSpec">
|
||||
* <bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
|
||||
* <property name="destination" value="myQueue"/>
|
||||
* <property name="destinationType" value="javax.jms.Queue"/>
|
||||
* <property name="destinationType" value="jakarta.jms.Queue"/>
|
||||
* </bean>
|
||||
* </property>
|
||||
* </bean>
|
||||
@@ -133,7 +133,7 @@ import org.springframework.util.Assert;
|
||||
* <property name="activationSpec">
|
||||
* <bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
|
||||
* <property name="destination" value="myQueue"/>
|
||||
* <property name="destinationType" value="javax.jms.Queue"/>
|
||||
* <property name="destinationType" value="jakarta.jms.Queue"/>
|
||||
* <property name="useRAManagedTransaction" value="true"/>
|
||||
* </bean>
|
||||
* </property>
|
||||
@@ -141,10 +141,10 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see javax.resource.spi.ResourceAdapter#endpointActivation
|
||||
* @see javax.resource.spi.ResourceAdapter#endpointDeactivation
|
||||
* @see javax.resource.spi.endpoint.MessageEndpointFactory
|
||||
* @see javax.resource.spi.ActivationSpec
|
||||
* @see jakarta.resource.spi.ResourceAdapter#endpointActivation
|
||||
* @see jakarta.resource.spi.ResourceAdapter#endpointDeactivation
|
||||
* @see jakarta.resource.spi.endpoint.MessageEndpointFactory
|
||||
* @see jakarta.resource.spi.ActivationSpec
|
||||
*/
|
||||
public class GenericMessageEndpointManager implements SmartLifecycle, InitializingBean, DisposableBean {
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.jca.support;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.spi.ConnectionManager;
|
||||
import javax.resource.spi.ManagedConnectionFactory;
|
||||
import jakarta.resource.ResourceException;
|
||||
import jakarta.resource.spi.ConnectionManager;
|
||||
import jakarta.resource.spi.ManagedConnectionFactory;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -29,13 +29,13 @@ import org.springframework.lang.Nullable;
|
||||
* a local JCA connection factory in "non-managed" mode (as defined by the
|
||||
* Java Connector Architecture specification). This is a direct alternative
|
||||
* to a {@link org.springframework.jndi.JndiObjectFactoryBean} definition that
|
||||
* obtains a connection factory handle from a Java EE server's naming environment.
|
||||
* obtains a connection factory handle from a Jakarta EE server's naming environment.
|
||||
*
|
||||
* <p>The type of the connection factory is dependent on the actual connector:
|
||||
* the connector can either expose its native API (such as a JDBC
|
||||
* {@link javax.sql.DataSource} or a JMS {@link javax.jms.ConnectionFactory})
|
||||
* {@link javax.sql.DataSource} or a JMS {@link jakarta.jms.ConnectionFactory})
|
||||
* or follow the standard Common Client Interface (CCI), as defined by the JCA spec.
|
||||
* The exposed interface in the CCI case is {@link javax.resource.cci.ConnectionFactory}.
|
||||
* The exposed interface in the CCI case is {@link jakarta.resource.cci.ConnectionFactory}.
|
||||
*
|
||||
* <p>In order to use this FactoryBean, you must specify the connector's
|
||||
* {@link #setManagedConnectionFactory "managedConnectionFactory"} (usually
|
||||
@@ -46,7 +46,7 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* <p><b>NOTE:</b> In non-managed mode, a connector is not deployed on an
|
||||
* application server, or more specifically not interacting with an application
|
||||
* server. Consequently, it cannot use a Java EE server's system contracts:
|
||||
* server. Consequently, it cannot use a Jakarta EE server's system contracts:
|
||||
* connection management, transaction management, and security management.
|
||||
* A custom ConnectionManager implementation has to be used for applying those
|
||||
* services in conjunction with a standalone transaction coordinator etc.
|
||||
@@ -65,8 +65,8 @@ import org.springframework.lang.Nullable;
|
||||
* @since 1.2
|
||||
* @see #setManagedConnectionFactory
|
||||
* @see #setConnectionManager
|
||||
* @see javax.resource.cci.ConnectionFactory
|
||||
* @see javax.resource.cci.Connection#getLocalTransaction
|
||||
* @see jakarta.resource.cci.ConnectionFactory
|
||||
* @see jakarta.resource.cci.Connection#getLocalTransaction
|
||||
* @see org.springframework.jca.cci.connection.CciLocalTransactionManager
|
||||
*/
|
||||
public class LocalConnectionFactoryBean implements FactoryBean<Object>, InitializingBean {
|
||||
@@ -91,11 +91,11 @@ public class LocalConnectionFactoryBean implements FactoryBean<Object>, Initiali
|
||||
* EntityManagerFactory.
|
||||
* <p>Note that the ManagerConnectionFactory implementation might expect
|
||||
* a reference to its JCA 1.7 ResourceAdapter, expressed through the
|
||||
* {@link javax.resource.spi.ResourceAdapterAssociation} interface.
|
||||
* {@link jakarta.resource.spi.ResourceAdapterAssociation} interface.
|
||||
* Simply inject the corresponding ResourceAdapter instance into its
|
||||
* "resourceAdapter" bean property in this case, before passing the
|
||||
* ManagerConnectionFactory into this LocalConnectionFactoryBean.
|
||||
* @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory()
|
||||
* @see jakarta.resource.spi.ManagedConnectionFactory#createConnectionFactory()
|
||||
*/
|
||||
public void setManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory) {
|
||||
this.managedConnectionFactory = managedConnectionFactory;
|
||||
@@ -107,7 +107,7 @@ public class LocalConnectionFactoryBean implements FactoryBean<Object>, Initiali
|
||||
* <p>A ConnectionManager implementation for local usage is often
|
||||
* included with a JCA connector. Such an included ConnectionManager
|
||||
* might be set as default, with no need to explicitly specify one.
|
||||
* @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager)
|
||||
* @see jakarta.resource.spi.ManagedConnectionFactory#createConnectionFactory(jakarta.resource.spi.ConnectionManager)
|
||||
*/
|
||||
public void setConnectionManager(ConnectionManager connectionManager) {
|
||||
this.connectionManager = connectionManager;
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
package org.springframework.jca.support;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
import javax.resource.spi.ResourceAdapter;
|
||||
import javax.resource.spi.XATerminator;
|
||||
import javax.resource.spi.work.WorkManager;
|
||||
import jakarta.resource.ResourceException;
|
||||
import jakarta.resource.spi.BootstrapContext;
|
||||
import jakarta.resource.spi.ResourceAdapter;
|
||||
import jakarta.resource.spi.XATerminator;
|
||||
import jakarta.resource.spi.work.WorkManager;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -30,8 +30,8 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.FactoryBean} that bootstraps
|
||||
* the specified JCA 1.7 {@link javax.resource.spi.ResourceAdapter},
|
||||
* starting it with a local {@link javax.resource.spi.BootstrapContext}
|
||||
* the specified JCA 1.7 {@link jakarta.resource.spi.ResourceAdapter},
|
||||
* starting it with a local {@link jakarta.resource.spi.BootstrapContext}
|
||||
* and exposing it for bean references. It will also stop the ResourceAdapter
|
||||
* on context shutdown. This corresponds to 'non-managed' bootstrap in a
|
||||
* local environment, according to the JCA 1.7 specification.
|
||||
@@ -45,8 +45,8 @@ import org.springframework.lang.Nullable;
|
||||
* @see #setResourceAdapter
|
||||
* @see #setBootstrapContext
|
||||
* @see #setWorkManager
|
||||
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
|
||||
* @see javax.resource.spi.ResourceAdapter#stop()
|
||||
* @see jakarta.resource.spi.ResourceAdapter#start(jakarta.resource.spi.BootstrapContext)
|
||||
* @see jakarta.resource.spi.ResourceAdapter#stop()
|
||||
*/
|
||||
public class ResourceAdapterFactoryBean implements FactoryBean<ResourceAdapter>, InitializingBean, DisposableBean {
|
||||
|
||||
@@ -114,7 +114,7 @@ public class ResourceAdapterFactoryBean implements FactoryBean<ResourceAdapter>,
|
||||
|
||||
/**
|
||||
* Builds the BootstrapContext and starts the ResourceAdapter with it.
|
||||
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
|
||||
* @see jakarta.resource.spi.ResourceAdapter#start(jakarta.resource.spi.BootstrapContext)
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws ResourceException {
|
||||
@@ -147,7 +147,7 @@ public class ResourceAdapterFactoryBean implements FactoryBean<ResourceAdapter>,
|
||||
|
||||
/**
|
||||
* Stops the ResourceAdapter.
|
||||
* @see javax.resource.spi.ResourceAdapter#stop()
|
||||
* @see jakarta.resource.spi.ResourceAdapter#stop()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
@@ -18,18 +18,18 @@ package org.springframework.jca.support;
|
||||
|
||||
import java.util.Timer;
|
||||
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
import javax.resource.spi.UnavailableException;
|
||||
import javax.resource.spi.XATerminator;
|
||||
import javax.resource.spi.work.WorkContext;
|
||||
import javax.resource.spi.work.WorkManager;
|
||||
import javax.transaction.TransactionSynchronizationRegistry;
|
||||
import jakarta.resource.spi.BootstrapContext;
|
||||
import jakarta.resource.spi.UnavailableException;
|
||||
import jakarta.resource.spi.XATerminator;
|
||||
import jakarta.resource.spi.work.WorkContext;
|
||||
import jakarta.resource.spi.work.WorkManager;
|
||||
import jakarta.transaction.TransactionSynchronizationRegistry;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple implementation of the JCA 1.7 {@link javax.resource.spi.BootstrapContext}
|
||||
* Simple implementation of the JCA 1.7 {@link jakarta.resource.spi.BootstrapContext}
|
||||
* interface, used for bootstrapping a JCA ResourceAdapter in a local environment.
|
||||
*
|
||||
* <p>Delegates to the given WorkManager and XATerminator, if any. Creates simple
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
|
||||
* @see jakarta.resource.spi.ResourceAdapter#start(jakarta.resource.spi.BootstrapContext)
|
||||
* @see ResourceAdapterFactoryBean
|
||||
*/
|
||||
public class SimpleBootstrapContext implements BootstrapContext {
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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
|
||||
*
|
||||
* https://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.work;
|
||||
|
||||
import javax.resource.spi.work.Work;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple Work adapter that delegates to a given Runnable.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see javax.resource.spi.work.Work
|
||||
* @see Runnable
|
||||
*/
|
||||
public class DelegatingWork implements Work {
|
||||
|
||||
private final Runnable delegate;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new DelegatingWork.
|
||||
* @param delegate the Runnable implementation to delegate to
|
||||
*/
|
||||
public DelegatingWork(Runnable delegate) {
|
||||
Assert.notNull(delegate, "Delegate must not be null");
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the wrapped Runnable implementation.
|
||||
*/
|
||||
public final Runnable getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delegates execution to the underlying Runnable.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
this.delegate.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation is empty, since we expect the Runnable
|
||||
* to terminate based on some specific shutdown signal.
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.work;
|
||||
|
||||
import javax.resource.spi.work.ExecutionContext;
|
||||
import javax.resource.spi.work.Work;
|
||||
import javax.resource.spi.work.WorkAdapter;
|
||||
import javax.resource.spi.work.WorkCompletedException;
|
||||
import javax.resource.spi.work.WorkEvent;
|
||||
import javax.resource.spi.work.WorkException;
|
||||
import javax.resource.spi.work.WorkListener;
|
||||
import javax.resource.spi.work.WorkManager;
|
||||
import javax.resource.spi.work.WorkRejectedException;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.core.task.TaskRejectedException;
|
||||
import org.springframework.core.task.TaskTimeoutException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple JCA 1.7 {@link javax.resource.spi.work.WorkManager} implementation that
|
||||
* delegates to a Spring {@link org.springframework.core.task.TaskExecutor}.
|
||||
* Provides simple task execution including start timeouts, but without support
|
||||
* for a JCA ExecutionContext (i.e. without support for imported transactions).
|
||||
*
|
||||
* <p>Uses a {@link org.springframework.core.task.SyncTaskExecutor} for {@link #doWork}
|
||||
* calls and a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
|
||||
* for {@link #startWork} and {@link #scheduleWork} calls, by default.
|
||||
* These default task executors can be overridden through configuration.
|
||||
*
|
||||
* <p><b>NOTE: This WorkManager does not provide thread pooling by default!</b>
|
||||
* Specify a {@link org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor}
|
||||
* (or any other thread-pooling TaskExecutor) as "asyncTaskExecutor" in order to
|
||||
* achieve actual thread pooling.
|
||||
*
|
||||
* <p>This WorkManager automatically detects a specified
|
||||
* {@link org.springframework.core.task.AsyncTaskExecutor} implementation
|
||||
* and uses its extended timeout functionality where appropriate.
|
||||
* JCA WorkListeners are fully supported in any case.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see #setSyncTaskExecutor
|
||||
* @see #setAsyncTaskExecutor
|
||||
*/
|
||||
public class SimpleTaskWorkManager implements WorkManager {
|
||||
|
||||
@Nullable
|
||||
private TaskExecutor syncTaskExecutor = new SyncTaskExecutor();
|
||||
|
||||
@Nullable
|
||||
private AsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor();
|
||||
|
||||
|
||||
/**
|
||||
* Specify the TaskExecutor to use for <i>synchronous</i> work execution
|
||||
* (i.e. {@link #doWork} calls).
|
||||
* <p>Default is a {@link org.springframework.core.task.SyncTaskExecutor}.
|
||||
*/
|
||||
public void setSyncTaskExecutor(TaskExecutor syncTaskExecutor) {
|
||||
this.syncTaskExecutor = syncTaskExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the TaskExecutor to use for <i>asynchronous</i> work execution
|
||||
* (i.e. {@link #startWork} and {@link #scheduleWork} calls).
|
||||
* <p>This will typically (but not necessarily) be an
|
||||
* {@link org.springframework.core.task.AsyncTaskExecutor} implementation.
|
||||
* Default is a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}.
|
||||
*/
|
||||
public void setAsyncTaskExecutor(AsyncTaskExecutor asyncTaskExecutor) {
|
||||
this.asyncTaskExecutor = asyncTaskExecutor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void doWork(Work work) throws WorkException {
|
||||
doWork(work, WorkManager.INDEFINITE, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWork(Work work, long startTimeout, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener)
|
||||
throws WorkException {
|
||||
|
||||
Assert.state(this.syncTaskExecutor != null, "No 'syncTaskExecutor' set");
|
||||
executeWork(this.syncTaskExecutor, work, startTimeout, false, executionContext, workListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long startWork(Work work) throws WorkException {
|
||||
return startWork(work, WorkManager.INDEFINITE, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long startWork(Work work, long startTimeout, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener)
|
||||
throws WorkException {
|
||||
|
||||
Assert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
|
||||
return executeWork(this.asyncTaskExecutor, work, startTimeout, true, executionContext, workListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleWork(Work work) throws WorkException {
|
||||
scheduleWork(work, WorkManager.INDEFINITE, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleWork(Work work, long startTimeout, @Nullable ExecutionContext executionContext, @Nullable WorkListener workListener)
|
||||
throws WorkException {
|
||||
|
||||
Assert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
|
||||
executeWork(this.asyncTaskExecutor, work, startTimeout, false, executionContext, workListener);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the given Work on the specified TaskExecutor.
|
||||
* @param taskExecutor the TaskExecutor to use
|
||||
* @param work the Work to execute
|
||||
* @param startTimeout the time duration within which the Work is supposed to start
|
||||
* @param blockUntilStarted whether to block until the Work has started
|
||||
* @param executionContext the JCA ExecutionContext for the given Work
|
||||
* @param workListener the WorkListener to clal for the given Work
|
||||
* @return the time elapsed from Work acceptance until start of execution
|
||||
* (or -1 if not applicable or not known)
|
||||
* @throws WorkException if the TaskExecutor did not accept the Work
|
||||
*/
|
||||
protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout, boolean blockUntilStarted,
|
||||
@Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException {
|
||||
|
||||
if (executionContext != null && executionContext.getXid() != null) {
|
||||
throw new WorkException("SimpleTaskWorkManager does not supported imported XIDs: " + executionContext.getXid());
|
||||
}
|
||||
WorkListener workListenerToUse = workListener;
|
||||
if (workListenerToUse == null) {
|
||||
workListenerToUse = new WorkAdapter();
|
||||
}
|
||||
|
||||
boolean isAsync = (taskExecutor instanceof AsyncTaskExecutor);
|
||||
DelegatingWorkAdapter workHandle = new DelegatingWorkAdapter(work, workListenerToUse, !isAsync);
|
||||
try {
|
||||
if (isAsync) {
|
||||
((AsyncTaskExecutor) taskExecutor).execute(workHandle, startTimeout);
|
||||
}
|
||||
else {
|
||||
taskExecutor.execute(workHandle);
|
||||
}
|
||||
}
|
||||
catch (TaskTimeoutException ex) {
|
||||
WorkException wex = new WorkRejectedException("TaskExecutor rejected Work because of timeout: " + work, ex);
|
||||
wex.setErrorCode(WorkException.START_TIMED_OUT);
|
||||
workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
|
||||
throw wex;
|
||||
}
|
||||
catch (TaskRejectedException ex) {
|
||||
WorkException wex = new WorkRejectedException("TaskExecutor rejected Work: " + work, ex);
|
||||
wex.setErrorCode(WorkException.INTERNAL);
|
||||
workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
|
||||
throw wex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
WorkException wex = new WorkException("TaskExecutor failed to execute Work: " + work, ex);
|
||||
wex.setErrorCode(WorkException.INTERNAL);
|
||||
throw wex;
|
||||
}
|
||||
if (isAsync) {
|
||||
workListenerToUse.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
|
||||
}
|
||||
|
||||
if (blockUntilStarted) {
|
||||
long acceptanceTime = System.currentTimeMillis();
|
||||
synchronized (workHandle.monitor) {
|
||||
try {
|
||||
while (!workHandle.started) {
|
||||
workHandle.monitor.wait();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
return (System.currentTimeMillis() - acceptanceTime);
|
||||
}
|
||||
else {
|
||||
return WorkManager.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Work adapter that supports start timeouts and WorkListener callbacks
|
||||
* for a given Work that it delegates to.
|
||||
*/
|
||||
private static class DelegatingWorkAdapter implements Work {
|
||||
|
||||
private final Work work;
|
||||
|
||||
private final WorkListener workListener;
|
||||
|
||||
private final boolean acceptOnExecution;
|
||||
|
||||
public final Object monitor = new Object();
|
||||
|
||||
public boolean started = false;
|
||||
|
||||
public DelegatingWorkAdapter(Work work, WorkListener workListener, boolean acceptOnExecution) {
|
||||
this.work = work;
|
||||
this.workListener = workListener;
|
||||
this.acceptOnExecution = acceptOnExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.acceptOnExecution) {
|
||||
this.workListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, this.work, null));
|
||||
}
|
||||
synchronized (this.monitor) {
|
||||
this.started = true;
|
||||
this.monitor.notify();
|
||||
}
|
||||
this.workListener.workStarted(new WorkEvent(this, WorkEvent.WORK_STARTED, this.work, null));
|
||||
try {
|
||||
this.work.run();
|
||||
}
|
||||
catch (RuntimeException | Error ex) {
|
||||
this.workListener.workCompleted(
|
||||
new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(ex)));
|
||||
throw ex;
|
||||
}
|
||||
this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
this.work.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.work;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.resource.spi.BootstrapContext;
|
||||
import javax.resource.spi.work.ExecutionContext;
|
||||
import javax.resource.spi.work.Work;
|
||||
import javax.resource.spi.work.WorkException;
|
||||
import javax.resource.spi.work.WorkListener;
|
||||
import javax.resource.spi.work.WorkManager;
|
||||
import javax.resource.spi.work.WorkRejectedException;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.core.task.TaskDecorator;
|
||||
import org.springframework.core.task.TaskRejectedException;
|
||||
import org.springframework.core.task.TaskTimeoutException;
|
||||
import org.springframework.jca.context.BootstrapContextAware;
|
||||
import org.springframework.jndi.JndiLocatorSupport;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.SchedulingException;
|
||||
import org.springframework.scheduling.SchedulingTaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
import org.springframework.util.concurrent.ListenableFutureTask;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.core.task.TaskExecutor} implementation
|
||||
* that delegates to a JCA 1.7 WorkManager, implementing the
|
||||
* {@link javax.resource.spi.work.WorkManager} interface.
|
||||
*
|
||||
* <p>This is mainly intended for use within a JCA ResourceAdapter implementation,
|
||||
* but may also be used in a standalone environment, delegating to a locally
|
||||
* embedded WorkManager implementation (such as Geronimo's).
|
||||
*
|
||||
* <p>Also implements the JCA 1.7 WorkManager interface itself, delegating all
|
||||
* calls to the target WorkManager. Hence, a caller can choose whether it wants
|
||||
* to talk to this executor through the Spring TaskExecutor interface or the
|
||||
* WorkManager interface.
|
||||
*
|
||||
* <p>This adapter is also capable of obtaining a JCA WorkManager from JNDI.
|
||||
* This is for example appropriate on the Geronimo application server, where
|
||||
* WorkManager GBeans (e.g. Geronimo's default "DefaultWorkManager" GBean)
|
||||
* can be linked into the Java EE environment through "gbean-ref" entries
|
||||
* in the {@code geronimo-web.xml} deployment descriptor.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see #setWorkManager
|
||||
* @see javax.resource.spi.work.WorkManager#scheduleWork
|
||||
*/
|
||||
public class WorkManagerTaskExecutor extends JndiLocatorSupport
|
||||
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, BootstrapContextAware, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private WorkManager workManager;
|
||||
|
||||
@Nullable
|
||||
private String workManagerName;
|
||||
|
||||
private boolean blockUntilStarted = false;
|
||||
|
||||
private boolean blockUntilCompleted = false;
|
||||
|
||||
@Nullable
|
||||
private WorkListener workListener;
|
||||
|
||||
@Nullable
|
||||
private TaskDecorator taskDecorator;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new WorkManagerTaskExecutor, expecting bean-style configuration.
|
||||
* @see #setWorkManager
|
||||
*/
|
||||
public WorkManagerTaskExecutor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new WorkManagerTaskExecutor for the given WorkManager.
|
||||
* @param workManager the JCA WorkManager to delegate to
|
||||
*/
|
||||
public WorkManagerTaskExecutor(WorkManager workManager) {
|
||||
setWorkManager(workManager);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify the JCA WorkManager instance to delegate to.
|
||||
*/
|
||||
public void setWorkManager(WorkManager workManager) {
|
||||
Assert.notNull(workManager, "WorkManager must not be null");
|
||||
this.workManager = workManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JNDI name of the JCA WorkManager.
|
||||
* <p>This can either be a fully qualified JNDI name,
|
||||
* or the JNDI name relative to the current environment
|
||||
* naming context if "resourceRef" is set to "true".
|
||||
* @see #setWorkManager
|
||||
* @see #setResourceRef
|
||||
*/
|
||||
public void setWorkManagerName(String workManagerName) {
|
||||
this.workManagerName = workManagerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the JCA BootstrapContext that contains the
|
||||
* WorkManager to delegate to.
|
||||
*/
|
||||
@Override
|
||||
public void setBootstrapContext(BootstrapContext bootstrapContext) {
|
||||
Assert.notNull(bootstrapContext, "BootstrapContext must not be null");
|
||||
this.workManager = bootstrapContext.getWorkManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to let {@link #execute} block until the work
|
||||
* has been actually started.
|
||||
* <p>Uses the JCA {@code startWork} operation underneath,
|
||||
* instead of the default {@code scheduleWork}.
|
||||
* @see javax.resource.spi.work.WorkManager#startWork
|
||||
* @see javax.resource.spi.work.WorkManager#scheduleWork
|
||||
*/
|
||||
public void setBlockUntilStarted(boolean blockUntilStarted) {
|
||||
this.blockUntilStarted = blockUntilStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to let {@link #execute} block until the work
|
||||
* has been completed.
|
||||
* <p>Uses the JCA {@code doWork} operation underneath,
|
||||
* instead of the default {@code scheduleWork}.
|
||||
* @see javax.resource.spi.work.WorkManager#doWork
|
||||
* @see javax.resource.spi.work.WorkManager#scheduleWork
|
||||
*/
|
||||
public void setBlockUntilCompleted(boolean blockUntilCompleted) {
|
||||
this.blockUntilCompleted = blockUntilCompleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a JCA WorkListener to apply, if any.
|
||||
* <p>This shared WorkListener instance will be passed on to the
|
||||
* WorkManager by all {@link #execute} calls on this TaskExecutor.
|
||||
*/
|
||||
public void setWorkListener(@Nullable WorkListener workListener) {
|
||||
this.workListener = workListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable}
|
||||
* about to be executed.
|
||||
* <p>Note that such a decorator is not necessarily being applied to the
|
||||
* user-supplied {@code Runnable}/{@code Callable} but rather to the actual
|
||||
* execution callback (which may be a wrapper around the user-supplied task).
|
||||
* <p>The primary use case is to set some execution context around the task's
|
||||
* invocation, or to provide some monitoring/statistics for task execution.
|
||||
* <p><b>NOTE:</b> Exception handling in {@code TaskDecorator} implementations
|
||||
* is limited to plain {@code Runnable} execution via {@code execute} calls.
|
||||
* In case of {@code #submit} calls, the exposed {@code Runnable} will be a
|
||||
* {@code FutureTask} which does not propagate any exceptions; you might
|
||||
* have to cast it and call {@code Future#get} to evaluate exceptions.
|
||||
* @since 4.3
|
||||
*/
|
||||
public void setTaskDecorator(TaskDecorator taskDecorator) {
|
||||
this.taskDecorator = taskDecorator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws NamingException {
|
||||
if (this.workManager == null) {
|
||||
if (this.workManagerName != null) {
|
||||
this.workManager = lookup(this.workManagerName, WorkManager.class);
|
||||
}
|
||||
else {
|
||||
this.workManager = getDefaultWorkManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a default WorkManager to delegate to.
|
||||
* Called if no explicit WorkManager or WorkManager JNDI name has been specified.
|
||||
* <p>The default implementation returns a {@link SimpleTaskWorkManager}.
|
||||
* Can be overridden in subclasses.
|
||||
*/
|
||||
protected WorkManager getDefaultWorkManager() {
|
||||
return new SimpleTaskWorkManager();
|
||||
}
|
||||
|
||||
private WorkManager obtainWorkManager() {
|
||||
Assert.state(this.workManager != null, "No WorkManager specified");
|
||||
return this.workManager;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Implementation of the Spring SchedulingTaskExecutor interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
execute(task, TIMEOUT_INDEFINITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
Work work = new DelegatingWork(this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
|
||||
try {
|
||||
if (this.blockUntilCompleted) {
|
||||
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) {
|
||||
obtainWorkManager().doWork(work, startTimeout, null, this.workListener);
|
||||
}
|
||||
else {
|
||||
obtainWorkManager().doWork(work);
|
||||
}
|
||||
}
|
||||
else if (this.blockUntilStarted) {
|
||||
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) {
|
||||
obtainWorkManager().startWork(work, startTimeout, null, this.workListener);
|
||||
}
|
||||
else {
|
||||
obtainWorkManager().startWork(work);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) {
|
||||
obtainWorkManager().scheduleWork(work, startTimeout, null, this.workListener);
|
||||
}
|
||||
else {
|
||||
obtainWorkManager().scheduleWork(work);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WorkRejectedException ex) {
|
||||
if (WorkException.START_TIMED_OUT.equals(ex.getErrorCode())) {
|
||||
throw new TaskTimeoutException("JCA WorkManager rejected task because of timeout: " + task, ex);
|
||||
}
|
||||
else {
|
||||
throw new TaskRejectedException("JCA WorkManager rejected task: " + task, ex);
|
||||
}
|
||||
}
|
||||
catch (WorkException ex) {
|
||||
throw new SchedulingException("Could not schedule task on JCA WorkManager", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
FutureTask<Object> future = new FutureTask<>(task, null);
|
||||
execute(future, TIMEOUT_INDEFINITE);
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
FutureTask<T> future = new FutureTask<>(task);
|
||||
execute(future, TIMEOUT_INDEFINITE);
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<?> submitListenable(Runnable task) {
|
||||
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
|
||||
execute(future, TIMEOUT_INDEFINITE);
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
|
||||
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
|
||||
execute(future, TIMEOUT_INDEFINITE);
|
||||
return future;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Implementation of the JCA WorkManager interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void doWork(Work work) throws WorkException {
|
||||
obtainWorkManager().doWork(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener)
|
||||
throws WorkException {
|
||||
|
||||
obtainWorkManager().doWork(work, delay, executionContext, workListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long startWork(Work work) throws WorkException {
|
||||
return obtainWorkManager().startWork(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long startWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener)
|
||||
throws WorkException {
|
||||
|
||||
return obtainWorkManager().startWork(work, delay, executionContext, workListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleWork(Work work) throws WorkException {
|
||||
obtainWorkManager().scheduleWork(work);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener)
|
||||
throws WorkException {
|
||||
|
||||
obtainWorkManager().scheduleWork(work, delay, executionContext, workListener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Convenience classes for scheduling based on the JCA WorkManager facility,
|
||||
* as supported within ResourceAdapters.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.jca.work;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -86,8 +86,8 @@ public interface TransactionDefinition {
|
||||
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
|
||||
* on all transaction managers. This in particular applies to
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager},
|
||||
* which requires the {@code javax.transaction.TransactionManager} to be
|
||||
* made available it to it (which is server-specific in standard Java EE).
|
||||
* which requires the {@code jakarta.transaction.TransactionManager} to be
|
||||
* made available it to it (which is server-specific in standard Jakarta EE).
|
||||
* <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
|
||||
* transaction synchronizations. Existing synchronizations will be suspended
|
||||
* and resumed appropriately.
|
||||
@@ -101,8 +101,8 @@ public interface TransactionDefinition {
|
||||
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
|
||||
* on all transaction managers. This in particular applies to
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager},
|
||||
* which requires the {@code javax.transaction.TransactionManager} to be
|
||||
* made available it to it (which is server-specific in standard Java EE).
|
||||
* which requires the {@code jakarta.transaction.TransactionManager} to be
|
||||
* made available it to it (which is server-specific in standard Jakarta EE).
|
||||
* <p>Note that transaction synchronization is <i>not</i> available within a
|
||||
* {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
|
||||
* will be suspended and resumed appropriately.
|
||||
|
||||
@@ -37,8 +37,8 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* <p>This class reads Spring's JDK 1.5+ {@link Transactional} annotation and
|
||||
* exposes corresponding transaction attributes to Spring's transaction infrastructure.
|
||||
* Also supports JTA 1.2's {@link javax.transaction.Transactional} and EJB3's
|
||||
* {@link javax.ejb.TransactionAttribute} annotation (if present).
|
||||
* Also supports JTA 1.2's {@link jakarta.transaction.Transactional} and EJB3's
|
||||
* {@link jakarta.ejb.TransactionAttribute} annotation (if present).
|
||||
* This class may also serve as base class for a custom TransactionAttributeSource,
|
||||
* or get customized through {@link TransactionAnnotationParser} strategies.
|
||||
*
|
||||
@@ -62,8 +62,8 @@ public class AnnotationTransactionAttributeSource extends AbstractFallbackTransa
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
|
||||
jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
|
||||
ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
|
||||
jta12Present = ClassUtils.isPresent("jakarta.transaction.Transactional", classLoader);
|
||||
ejb3Present = ClassUtils.isPresent("jakarta.ejb.TransactionAttribute", classLoader);
|
||||
}
|
||||
|
||||
private final boolean publicMethodsOnly;
|
||||
@@ -74,7 +74,7 @@ public class AnnotationTransactionAttributeSource extends AbstractFallbackTransa
|
||||
/**
|
||||
* Create a default AnnotationTransactionAttributeSource, supporting
|
||||
* public methods that carry the {@code Transactional} annotation
|
||||
* or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
|
||||
* or the EJB3 {@link jakarta.ejb.TransactionAttribute} annotation.
|
||||
*/
|
||||
public AnnotationTransactionAttributeSource() {
|
||||
this(true);
|
||||
@@ -83,7 +83,7 @@ public class AnnotationTransactionAttributeSource extends AbstractFallbackTransa
|
||||
/**
|
||||
* Create a custom AnnotationTransactionAttributeSource, supporting
|
||||
* public methods that carry the {@code Transactional} annotation
|
||||
* or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
|
||||
* or the EJB3 {@link jakarta.ejb.TransactionAttribute} annotation.
|
||||
* @param publicMethodsOnly whether to support public methods that carry
|
||||
* the {@code Transactional} annotation only (typically for use
|
||||
* with proxy-based AOP), or protected/private methods as well
|
||||
|
||||
@@ -19,8 +19,8 @@ package org.springframework.transaction.annotation;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
import javax.ejb.ApplicationException;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
import jakarta.ejb.ApplicationException;
|
||||
import jakarta.ejb.TransactionAttributeType;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -28,7 +28,7 @@ import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
/**
|
||||
* Strategy implementation for parsing EJB3's {@link javax.ejb.TransactionAttribute}
|
||||
* Strategy implementation for parsing EJB3's {@link jakarta.ejb.TransactionAttribute}
|
||||
* annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
@@ -39,13 +39,13 @@ public class Ejb3TransactionAnnotationParser implements TransactionAnnotationPar
|
||||
|
||||
@Override
|
||||
public boolean isCandidateClass(Class<?> targetClass) {
|
||||
return AnnotationUtils.isCandidateClass(targetClass, javax.ejb.TransactionAttribute.class);
|
||||
return AnnotationUtils.isCandidateClass(targetClass, jakarta.ejb.TransactionAttribute.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
|
||||
javax.ejb.TransactionAttribute ann = element.getAnnotation(javax.ejb.TransactionAttribute.class);
|
||||
jakarta.ejb.TransactionAttribute ann = element.getAnnotation(jakarta.ejb.TransactionAttribute.class);
|
||||
if (ann != null) {
|
||||
return parseTransactionAnnotation(ann);
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class Ejb3TransactionAnnotationParser implements TransactionAnnotationPar
|
||||
}
|
||||
}
|
||||
|
||||
public TransactionAttribute parseTransactionAnnotation(javax.ejb.TransactionAttribute ann) {
|
||||
public TransactionAttribute parseTransactionAnnotation(jakarta.ejb.TransactionAttribute ann) {
|
||||
return new Ejb3TransactionAttribute(ann.value());
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
/**
|
||||
* Strategy implementation for parsing JTA 1.2's {@link javax.transaction.Transactional} annotation.
|
||||
* Strategy implementation for parsing JTA 1.2's {@link jakarta.transaction.Transactional} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
@@ -41,14 +41,14 @@ public class JtaTransactionAnnotationParser implements TransactionAnnotationPars
|
||||
|
||||
@Override
|
||||
public boolean isCandidateClass(Class<?> targetClass) {
|
||||
return AnnotationUtils.isCandidateClass(targetClass, javax.transaction.Transactional.class);
|
||||
return AnnotationUtils.isCandidateClass(targetClass, jakarta.transaction.Transactional.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
|
||||
element, javax.transaction.Transactional.class);
|
||||
element, jakarta.transaction.Transactional.class);
|
||||
if (attributes != null) {
|
||||
return parseTransactionAnnotation(attributes);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class JtaTransactionAnnotationParser implements TransactionAnnotationPars
|
||||
}
|
||||
}
|
||||
|
||||
public TransactionAttribute parseTransactionAnnotation(javax.transaction.Transactional ann) {
|
||||
public TransactionAttribute parseTransactionAnnotation(jakarta.transaction.Transactional ann) {
|
||||
return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ public enum Propagation {
|
||||
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
|
||||
* on all transaction managers. This in particular applies to
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager},
|
||||
* which requires the {@code javax.transaction.TransactionManager} to be
|
||||
* made available to it (which is server-specific in standard Java EE).
|
||||
* which requires the {@code jakarta.transaction.TransactionManager} to be
|
||||
* made available to it (which is server-specific in standard Jakarta EE).
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
|
||||
*/
|
||||
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
|
||||
@@ -73,8 +73,8 @@ public enum Propagation {
|
||||
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
|
||||
* on all transaction managers. This in particular applies to
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager},
|
||||
* which requires the {@code javax.transaction.TransactionManager} to be
|
||||
* made available to it (which is server-specific in standard Java EE).
|
||||
* which requires the {@code jakarta.transaction.TransactionManager} to be
|
||||
* made available to it (which is server-specific in standard Jakarta EE).
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
|
||||
*/
|
||||
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
|
||||
|
||||
@@ -25,8 +25,8 @@ import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
* Strategy interface for parsing known transaction annotation types.
|
||||
* {@link AnnotationTransactionAttributeSource} delegates to such
|
||||
* parsers for supporting specific annotation types such as Spring's own
|
||||
* {@link Transactional}, JTA 1.2's {@link javax.transaction.Transactional}
|
||||
* or EJB3's {@link javax.ejb.TransactionAttribute}.
|
||||
* {@link Transactional}, JTA 1.2's {@link jakarta.transaction.Transactional}
|
||||
* or EJB3's {@link jakarta.ejb.TransactionAttribute}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
|
||||
@@ -57,7 +57,7 @@ public class TransactionManagementConfigurationSelector extends AdviceModeImport
|
||||
}
|
||||
|
||||
private String determineTransactionAspectClass() {
|
||||
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
|
||||
return (ClassUtils.isPresent("jakarta.transaction.Transactional", getClass().getClassLoader()) ?
|
||||
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
|
||||
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public @interface Transactional {
|
||||
* a transaction rollback.
|
||||
* <p>This can be a substring of a fully qualified class name, with no wildcard
|
||||
* support at present. For example, a value of {@code "ServletException"} would
|
||||
* match {@code javax.servlet.ServletException} and its subclasses.
|
||||
* match {@code jakarta.servlet.ServletException} and its subclasses.
|
||||
* <p><b>NB:</b> Consider carefully how specific the pattern is and whether
|
||||
* to include package information (which isn't mandatory). For example,
|
||||
* {@code "Exception"} will match nearly anything and will probably hide other
|
||||
|
||||
@@ -65,7 +65,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
if ("aspectj".equals(mode)) {
|
||||
// mode="aspectj"
|
||||
registerTransactionAspect(element, parserContext);
|
||||
if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
|
||||
if (ClassUtils.isPresent("jakarta.transaction.Transactional", getClass().getClassLoader())) {
|
||||
registerJtaTransactionAspect(element, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -21,23 +21,20 @@ import org.w3c.dom.Element;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
/**
|
||||
* Parser for the <tx:jta-transaction-manager/> XML configuration element,
|
||||
* autodetecting WebLogic and WebSphere servers and exposing the corresponding
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager} subclass.
|
||||
* Parser for the <tx:jta-transaction-manager/> XML configuration element.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Christian Dupuis
|
||||
* @since 2.5
|
||||
* @see org.springframework.transaction.jta.WebLogicJtaTransactionManager
|
||||
* @see org.springframework.transaction.jta.WebSphereUowTransactionManager
|
||||
*/
|
||||
public class JtaTransactionManagerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return JtaTransactionManagerFactoryBean.resolveJtaTransactionManagerClassName();
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return JtaTransactionManager.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,62 +16,23 @@
|
||||
|
||||
package org.springframework.transaction.config;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A {@link FactoryBean} equivalent to the <tx:jta-transaction-manager/> XML element,
|
||||
* autodetecting WebLogic and WebSphere servers and exposing the corresponding
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager} subclass.
|
||||
* A {@link FactoryBean} equivalent to the <tx:jta-transaction-manager/> XML element.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1.1
|
||||
* @see org.springframework.transaction.jta.WebLogicJtaTransactionManager
|
||||
* @see org.springframework.transaction.jta.WebSphereUowTransactionManager
|
||||
* @deprecated as of 6.0, in favor of a straight {@link JtaTransactionManager} definition
|
||||
*/
|
||||
@Deprecated
|
||||
public class JtaTransactionManagerFactoryBean implements FactoryBean<JtaTransactionManager>, InitializingBean {
|
||||
|
||||
private static final String WEBLOGIC_JTA_TRANSACTION_MANAGER_CLASS_NAME =
|
||||
"org.springframework.transaction.jta.WebLogicJtaTransactionManager";
|
||||
|
||||
private static final String WEBSPHERE_TRANSACTION_MANAGER_CLASS_NAME =
|
||||
"org.springframework.transaction.jta.WebSphereUowTransactionManager";
|
||||
|
||||
private static final String JTA_TRANSACTION_MANAGER_CLASS_NAME =
|
||||
"org.springframework.transaction.jta.JtaTransactionManager";
|
||||
|
||||
|
||||
private static final boolean weblogicPresent;
|
||||
|
||||
private static final boolean webspherePresent;
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = JtaTransactionManagerFactoryBean.class.getClassLoader();
|
||||
weblogicPresent = ClassUtils.isPresent("weblogic.transaction.UserTransaction", classLoader);
|
||||
webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", classLoader);
|
||||
}
|
||||
|
||||
|
||||
private final JtaTransactionManager transactionManager;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public JtaTransactionManagerFactoryBean() {
|
||||
String className = resolveJtaTransactionManagerClassName();
|
||||
try {
|
||||
Class<? extends JtaTransactionManager> clazz = (Class<? extends JtaTransactionManager>)
|
||||
ClassUtils.forName(className, JtaTransactionManagerFactoryBean.class.getClassLoader());
|
||||
this.transactionManager = BeanUtils.instantiateClass(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException("Failed to load JtaTransactionManager class: " + className, ex);
|
||||
}
|
||||
}
|
||||
private final JtaTransactionManager transactionManager = new JtaTransactionManager();
|
||||
|
||||
|
||||
@Override
|
||||
@@ -95,17 +56,4 @@ public class JtaTransactionManagerFactoryBean implements FactoryBean<JtaTransact
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static String resolveJtaTransactionManagerClassName() {
|
||||
if (weblogicPresent) {
|
||||
return WEBLOGIC_JTA_TRANSACTION_MANAGER_CLASS_NAME;
|
||||
}
|
||||
else if (webspherePresent) {
|
||||
return WEBSPHERE_TRANSACTION_MANAGER_CLASS_NAME;
|
||||
}
|
||||
else {
|
||||
return JTA_TRANSACTION_MANAGER_CLASS_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class RollbackRuleAttribute implements Serializable{
|
||||
* for the given {@code exceptionName}.
|
||||
* <p>This can be a substring, with no wildcard support at present. A value
|
||||
* of "ServletException" would match
|
||||
* {@code javax.servlet.ServletException} and subclasses, for example.
|
||||
* {@code jakarta.servlet.ServletException} and subclasses, for example.
|
||||
* <p><b>NB:</b> Consider carefully how specific the pattern is, and
|
||||
* whether to include package information (which is not mandatory). For
|
||||
* example, "Exception" will match nearly anything, and will probably hide
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.springframework.transaction.jta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import jakarta.transaction.Status;
|
||||
import jakarta.transaction.Synchronization;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -23,17 +23,18 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.transaction.HeuristicMixedException;
|
||||
import javax.transaction.HeuristicRollbackException;
|
||||
import javax.transaction.InvalidTransactionException;
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.TransactionSynchronizationRegistry;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import jakarta.transaction.HeuristicMixedException;
|
||||
import jakarta.transaction.HeuristicRollbackException;
|
||||
import jakarta.transaction.InvalidTransactionException;
|
||||
import jakarta.transaction.NotSupportedException;
|
||||
import jakarta.transaction.RollbackException;
|
||||
import jakarta.transaction.Status;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.Transaction;
|
||||
import jakarta.transaction.TransactionManager;
|
||||
import jakarta.transaction.TransactionSynchronizationRegistry;
|
||||
import jakarta.transaction.UserTransaction;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
@@ -56,7 +57,7 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* {@link org.springframework.transaction.PlatformTransactionManager} implementation
|
||||
* for JTA, delegating to a backend JTA provider. This is typically used to delegate
|
||||
* to a Java EE server's transaction coordinator, but may also be configured with a
|
||||
* to a Jakarta EE server's transaction coordinator, but may also be configured with a
|
||||
* local JTA provider which is embedded within the application.
|
||||
*
|
||||
* <p>This transaction manager is appropriate for handling distributed transactions,
|
||||
@@ -67,8 +68,8 @@ import org.springframework.util.StringUtils;
|
||||
* HibernateTransactionManager is appropriate, for example.
|
||||
*
|
||||
* <p><b>For typical JTA transactions (REQUIRED, SUPPORTS, MANDATORY, NEVER), a plain
|
||||
* JtaTransactionManager definition is all you need, portable across all Java EE servers.</b>
|
||||
* This corresponds to the functionality of the JTA UserTransaction, for which Java EE
|
||||
* JtaTransactionManager definition is all you need, portable across all Jakarta EE servers.</b>
|
||||
* This corresponds to the functionality of the JTA UserTransaction, for which Jakarta EE
|
||||
* specifies a standard JNDI name ("java:comp/UserTransaction"). There is no need to
|
||||
* configure a server-specific TransactionManager lookup for this kind of JTA usage.
|
||||
*
|
||||
@@ -77,26 +78,17 @@ import org.springframework.util.StringUtils;
|
||||
* autodetected by JtaTransactionManager, provided that the "autodetectTransactionManager"
|
||||
* flag is set to "true" (which it is by default).
|
||||
*
|
||||
* <p>Note: Support for the JTA TransactionManager interface is not required by Java EE.
|
||||
* Almost all Java EE servers expose it, but do so as extension to EE. There might be some
|
||||
* <p>Note: Support for the JTA TransactionManager interface is not required by Jakarta EE.
|
||||
* Almost all Jakarta EE servers expose it, but do so as extension to EE. There might be some
|
||||
* issues with compatibility, despite the TransactionManager interface being part of JTA.
|
||||
* As a consequence, Spring provides various vendor-specific PlatformTransactionManagers,
|
||||
* which are recommended to be used if appropriate: {@link WebLogicJtaTransactionManager}
|
||||
* and {@link WebSphereUowTransactionManager}. For all other Java EE servers, the
|
||||
* standard JtaTransactionManager is sufficient.
|
||||
*
|
||||
* <p>This pure JtaTransactionManager class supports timeouts but not per-transaction
|
||||
* isolation levels. Custom subclasses may override the {@link #doJtaBegin} method for
|
||||
* specific JTA extensions in order to provide this functionality; Spring includes a
|
||||
* corresponding {@link WebLogicJtaTransactionManager} class for WebLogic Server. Such
|
||||
* adapters for specific Java EE transaction coordinators may also expose transaction
|
||||
* names for monitoring; with standard JTA, transaction names will simply be ignored.
|
||||
* specific JTA extensions in order to provide this functionality. Such adapters for
|
||||
* specific Jakarta EE transaction coordinators may also expose transaction names for
|
||||
* monitoring; with standard JTA, transaction names will simply be ignored.
|
||||
*
|
||||
* <p><b>Consider using Spring's {@code tx:jta-transaction-manager} configuration
|
||||
* element for automatically picking the appropriate JTA platform transaction manager
|
||||
* (automatically detecting WebLogic and WebSphere).</b>
|
||||
*
|
||||
* <p>JTA 1.1 adds the TransactionSynchronizationRegistry facility, as public Java EE 5
|
||||
* <p>JTA 1.1 adds the TransactionSynchronizationRegistry facility, as public Jakarta EE
|
||||
* API in addition to the standard JTA UserTransaction handle. As of Spring 2.5, this
|
||||
* JtaTransactionManager autodetects the TransactionSynchronizationRegistry and uses
|
||||
* it for registering Spring-managed synchronizations when participating in an existing
|
||||
@@ -108,21 +100,20 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 24.03.2003
|
||||
* @see javax.transaction.UserTransaction
|
||||
* @see javax.transaction.TransactionManager
|
||||
* @see javax.transaction.TransactionSynchronizationRegistry
|
||||
* @see jakarta.transaction.UserTransaction
|
||||
* @see jakarta.transaction.TransactionManager
|
||||
* @see jakarta.transaction.TransactionSynchronizationRegistry
|
||||
* @see #setUserTransactionName
|
||||
* @see #setUserTransaction
|
||||
* @see #setTransactionManagerName
|
||||
* @see #setTransactionManager
|
||||
* @see WebLogicJtaTransactionManager
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements TransactionFactory, InitializingBean, Serializable {
|
||||
|
||||
/**
|
||||
* Default JNDI location for the JTA UserTransaction. Many Java EE servers
|
||||
* Default JNDI location for the JTA UserTransaction. Many Jakarta EE servers
|
||||
* also provide support for the JTA TransactionManager interface there.
|
||||
* @see #setUserTransactionName
|
||||
* @see #setAutodetectTransactionManager
|
||||
@@ -141,7 +132,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
"java:pm/TransactionManager", "java:/TransactionManager"};
|
||||
|
||||
/**
|
||||
* Standard Java EE 5 JNDI location for the JTA TransactionSynchronizationRegistry.
|
||||
* Standard Jakarta EE JNDI location for the JTA TransactionSynchronizationRegistry.
|
||||
* Autodetected when available.
|
||||
*/
|
||||
public static final String DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME =
|
||||
@@ -265,7 +256,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
|
||||
/**
|
||||
* Set the JTA UserTransaction to use as direct reference.
|
||||
* <p>Typically just used for local JTA setups; in a Java EE environment,
|
||||
* <p>Typically just used for local JTA setups; in a Jakarta EE environment,
|
||||
* the UserTransaction will always be fetched from JNDI.
|
||||
* @see #setUserTransactionName
|
||||
* @see #setAutodetectUserTransaction
|
||||
@@ -284,7 +275,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
|
||||
/**
|
||||
* Set the JNDI name of the JTA UserTransaction.
|
||||
* <p>Note that the UserTransaction will be autodetected at the Java EE
|
||||
* <p>Note that the UserTransaction will be autodetected at the Jakarta EE
|
||||
* default location "java:comp/UserTransaction" if not specified explicitly.
|
||||
* @see #DEFAULT_USER_TRANSACTION_NAME
|
||||
* @see #setUserTransaction
|
||||
@@ -296,7 +287,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
|
||||
/**
|
||||
* Set whether to autodetect the JTA UserTransaction at its default
|
||||
* JNDI location "java:comp/UserTransaction", as specified by Java EE.
|
||||
* JNDI location "java:comp/UserTransaction", as specified by Jakarta EE.
|
||||
* Will proceed without UserTransaction if none found.
|
||||
* <p>Default is "true", autodetecting the UserTransaction unless
|
||||
* it has been specified explicitly. Turn this flag off to allow for
|
||||
@@ -381,7 +372,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* <p>A TransactionSynchronizationRegistry allows for interposed registration
|
||||
* of transaction synchronizations, as an alternative to the regular registration
|
||||
* methods on the JTA TransactionManager API. Also, it is an official part of the
|
||||
* Java EE 5 platform, in contrast to the JTA TransactionManager itself.
|
||||
* Jakarta EE platform, in contrast to the JTA TransactionManager itself.
|
||||
* <p>Note that the TransactionSynchronizationRegistry will be autodetected in JNDI and
|
||||
* also from the UserTransaction/TransactionManager object if implemented there as well.
|
||||
* @see #setTransactionSynchronizationRegistryName
|
||||
@@ -402,7 +393,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
/**
|
||||
* Set the JNDI name of the JTA 1.1 TransactionSynchronizationRegistry.
|
||||
* <p>Note that the TransactionSynchronizationRegistry will be autodetected
|
||||
* at the Java EE 5 default location "java:comp/TransactionSynchronizationRegistry"
|
||||
* at the Jakarta EE default location "java:comp/TransactionSynchronizationRegistry"
|
||||
* if not specified explicitly.
|
||||
* @see #DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME
|
||||
*/
|
||||
@@ -741,7 +732,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
/**
|
||||
* Find the JTA 1.1 TransactionSynchronizationRegistry through autodetection:
|
||||
* checking whether the UserTransaction object or TransactionManager object
|
||||
* implements it, and checking Java EE 5's standard JNDI location.
|
||||
* implements it, and checking Jakarta EE's standard JNDI location.
|
||||
* <p>The default implementation simply returns {@code null}.
|
||||
* @param ut the JTA UserTransaction object
|
||||
* @param tm the JTA TransactionManager object
|
||||
@@ -834,7 +825,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* <p>JTA implementations might support nested transactions via further
|
||||
* {@code UserTransaction.begin()} invocations, but never support savepoints.
|
||||
* @see #doBegin
|
||||
* @see javax.transaction.UserTransaction#begin()
|
||||
* @see jakarta.transaction.UserTransaction#begin()
|
||||
*/
|
||||
@Override
|
||||
protected boolean useSavepointForNestedTransaction() {
|
||||
@@ -874,8 +865,8 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* @see #applyIsolationLevel
|
||||
* @see #applyTimeout
|
||||
* @see JtaTransactionObject#getUserTransaction()
|
||||
* @see javax.transaction.UserTransaction#setTransactionTimeout
|
||||
* @see javax.transaction.UserTransaction#begin
|
||||
* @see jakarta.transaction.UserTransaction#setTransactionTimeout
|
||||
* @see jakarta.transaction.UserTransaction#begin
|
||||
*/
|
||||
protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition)
|
||||
throws NotSupportedException, SystemException {
|
||||
@@ -918,7 +909,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* @throws SystemException if thrown by the JTA implementation
|
||||
* @see #doJtaBegin
|
||||
* @see JtaTransactionObject#getUserTransaction()
|
||||
* @see javax.transaction.UserTransaction#setTransactionTimeout(int)
|
||||
* @see jakarta.transaction.UserTransaction#setTransactionTimeout(int)
|
||||
*/
|
||||
protected void applyTimeout(JtaTransactionObject txObject, int timeout) throws SystemException {
|
||||
if (timeout > TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
@@ -948,7 +939,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* @return the suspended JTA Transaction object
|
||||
* @throws SystemException if thrown by JTA methods
|
||||
* @see #getTransactionManager()
|
||||
* @see javax.transaction.TransactionManager#suspend()
|
||||
* @see jakarta.transaction.TransactionManager#suspend()
|
||||
*/
|
||||
protected Object doJtaSuspend(JtaTransactionObject txObject) throws SystemException {
|
||||
if (getTransactionManager() == null) {
|
||||
@@ -984,7 +975,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* @throws InvalidTransactionException if thrown by JTA methods
|
||||
* @throws SystemException if thrown by JTA methods
|
||||
* @see #getTransactionManager()
|
||||
* @see javax.transaction.TransactionManager#resume(javax.transaction.Transaction)
|
||||
* @see jakarta.transaction.TransactionManager#resume(jakarta.transaction.Transaction)
|
||||
*/
|
||||
protected void doJtaResume(@Nullable JtaTransactionObject txObject, Object suspendedTransaction)
|
||||
throws InvalidTransactionException, SystemException {
|
||||
@@ -1144,8 +1135,8 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
|
||||
* @throws RollbackException if thrown by JTA methods
|
||||
* @throws SystemException if thrown by JTA methods
|
||||
* @see #getTransactionManager()
|
||||
* @see javax.transaction.Transaction#registerSynchronization
|
||||
* @see javax.transaction.TransactionSynchronizationRegistry#registerInterposedSynchronization
|
||||
* @see jakarta.transaction.Transaction#registerSynchronization
|
||||
* @see jakarta.transaction.TransactionSynchronizationRegistry#registerInterposedSynchronization
|
||||
*/
|
||||
protected void doRegisterAfterCompletionWithJtaTransaction(
|
||||
JtaTransactionObject txObject, List<TransactionSynchronization> synchronizations)
|
||||
|
||||
@@ -16,16 +16,16 @@
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.UserTransaction;
|
||||
import jakarta.transaction.Status;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.UserTransaction;
|
||||
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.SmartTransactionObject;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||
|
||||
/**
|
||||
* JTA transaction object, representing a {@link javax.transaction.UserTransaction}.
|
||||
* JTA transaction object, representing a {@link jakarta.transaction.UserTransaction}.
|
||||
* Used as transaction object by Spring's {@link JtaTransactionManager}.
|
||||
*
|
||||
* <p>Note: This is an SPI class, not intended to be used by applications.
|
||||
@@ -33,7 +33,7 @@ import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see JtaTransactionManager
|
||||
* @see javax.transaction.UserTransaction
|
||||
* @see jakarta.transaction.UserTransaction
|
||||
*/
|
||||
public class JtaTransactionObject implements SmartTransactionObject {
|
||||
|
||||
|
||||
@@ -16,21 +16,22 @@
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.HeuristicMixedException;
|
||||
import javax.transaction.HeuristicRollbackException;
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.xa.XAResource;
|
||||
|
||||
import jakarta.transaction.HeuristicMixedException;
|
||||
import jakarta.transaction.HeuristicRollbackException;
|
||||
import jakarta.transaction.RollbackException;
|
||||
import jakarta.transaction.Synchronization;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.Transaction;
|
||||
import jakarta.transaction.TransactionManager;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapter for a managed JTA Transaction handle, taking a JTA
|
||||
* {@link javax.transaction.TransactionManager} reference and creating
|
||||
* a JTA {@link javax.transaction.Transaction} handle for it.
|
||||
* {@link jakarta.transaction.TransactionManager} reference and creating
|
||||
* a JTA {@link jakarta.transaction.Transaction} handle for it.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.2
|
||||
|
||||
@@ -16,25 +16,25 @@
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
import jakarta.transaction.NotSupportedException;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.Transaction;
|
||||
import jakarta.transaction.TransactionManager;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link TransactionFactory} strategy interface,
|
||||
* simply wrapping a standard JTA {@link javax.transaction.TransactionManager}.
|
||||
* simply wrapping a standard JTA {@link jakarta.transaction.TransactionManager}.
|
||||
*
|
||||
* <p>Does not support transaction names; simply ignores any specified name.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see javax.transaction.TransactionManager#setTransactionTimeout(int)
|
||||
* @see javax.transaction.TransactionManager#begin()
|
||||
* @see javax.transaction.TransactionManager#getTransaction()
|
||||
* @see jakarta.transaction.TransactionManager#setTransactionTimeout(int)
|
||||
* @see jakarta.transaction.TransactionManager#begin()
|
||||
* @see jakarta.transaction.TransactionManager#getTransaction()
|
||||
*/
|
||||
public class SimpleTransactionFactory implements TransactionFactory {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import jakarta.transaction.Status;
|
||||
import jakarta.transaction.Synchronization;
|
||||
import jakarta.transaction.TransactionManager;
|
||||
import jakarta.transaction.UserTransaction;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -30,7 +29,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapter that implements the JTA {@link javax.transaction.Synchronization}
|
||||
* Adapter that implements the JTA {@link jakarta.transaction.Synchronization}
|
||||
* interface delegating to an underlying Spring
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronization}.
|
||||
*
|
||||
@@ -40,7 +39,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see javax.transaction.Transaction#registerSynchronization
|
||||
* @see jakarta.transaction.Transaction#registerSynchronization
|
||||
* @see org.springframework.transaction.support.TransactionSynchronization
|
||||
*/
|
||||
public class SpringJtaSynchronizationAdapter implements Synchronization {
|
||||
@@ -82,9 +81,7 @@ public class SpringJtaSynchronizationAdapter implements Synchronization {
|
||||
@Nullable UserTransaction jtaUserTransaction) {
|
||||
|
||||
this(springSynchronization);
|
||||
if (jtaUserTransaction != null && !jtaUserTransaction.getClass().getName().startsWith("weblogic.")) {
|
||||
this.jtaTransaction = jtaUserTransaction;
|
||||
}
|
||||
this.jtaTransaction = jtaUserTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,9 +101,7 @@ public class SpringJtaSynchronizationAdapter implements Synchronization {
|
||||
TransactionSynchronization springSynchronization, @Nullable TransactionManager jtaTransactionManager) {
|
||||
|
||||
this(springSynchronization);
|
||||
if (jtaTransactionManager != null && !jtaTransactionManager.getClass().getName().startsWith("weblogic.")) {
|
||||
this.jtaTransaction = new UserTransactionAdapter(jtaTransactionManager);
|
||||
}
|
||||
this.jtaTransaction = new UserTransactionAdapter(jtaTransactionManager);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import jakarta.transaction.NotSupportedException;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.Transaction;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Strategy interface for creating JTA {@link javax.transaction.Transaction}
|
||||
* Strategy interface for creating JTA {@link jakarta.transaction.Transaction}
|
||||
* objects based on specified transactional characteristics.
|
||||
*
|
||||
* <p>The default implementation, {@link SimpleTransactionFactory}, simply
|
||||
* wraps a standard JTA {@link javax.transaction.TransactionManager}.
|
||||
* wraps a standard JTA {@link jakarta.transaction.TransactionManager}.
|
||||
* This strategy interface allows for more sophisticated implementations
|
||||
* that adapt to vendor-specific JTA extensions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see javax.transaction.TransactionManager#getTransaction()
|
||||
* @see jakarta.transaction.TransactionManager#getTransaction()
|
||||
* @see SimpleTransactionFactory
|
||||
* @see JtaTransactionManager
|
||||
*/
|
||||
@@ -58,8 +58,8 @@ public interface TransactionFactory {
|
||||
* {@link org.springframework.jca.endpoint.AbstractMessageEndpointFactory}
|
||||
* in order to differentiate between invalid configuration and valid
|
||||
* ResourceAdapter-managed transactions.
|
||||
* @see javax.resource.spi.ResourceAdapter#endpointActivation
|
||||
* @see javax.resource.spi.endpoint.MessageEndpointFactory#isDeliveryTransacted
|
||||
* @see jakarta.resource.spi.ResourceAdapter#endpointActivation
|
||||
* @see jakarta.resource.spi.endpoint.MessageEndpointFactory#isDeliveryTransacted
|
||||
*/
|
||||
boolean supportsResourceAdapterManagedTransactions();
|
||||
|
||||
|
||||
@@ -16,20 +16,20 @@
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.HeuristicMixedException;
|
||||
import javax.transaction.HeuristicRollbackException;
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
import jakarta.transaction.HeuristicMixedException;
|
||||
import jakarta.transaction.HeuristicRollbackException;
|
||||
import jakarta.transaction.NotSupportedException;
|
||||
import jakarta.transaction.RollbackException;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.TransactionManager;
|
||||
import jakarta.transaction.UserTransaction;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapter for a JTA UserTransaction handle, taking a JTA
|
||||
* {@link javax.transaction.TransactionManager} reference and creating
|
||||
* a JTA {@link javax.transaction.UserTransaction} handle for it.
|
||||
* {@link jakarta.transaction.TransactionManager} reference and creating
|
||||
* a JTA {@link jakarta.transaction.UserTransaction} handle for it.
|
||||
*
|
||||
* <p>The JTA UserTransaction interface is an exact subset of the JTA
|
||||
* TransactionManager interface. Unfortunately, it does not serve as
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.transaction.jta;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.transaction.InvalidTransactionException;
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Special {@link JtaTransactionManager} variant for BEA WebLogic (9.0 and higher).
|
||||
* Supports the full power of Spring's transaction definitions on WebLogic's
|
||||
* transaction coordinator, <i>beyond standard JTA</i>: transaction names,
|
||||
* per-transaction isolation levels, and proper resuming of transactions in all cases.
|
||||
*
|
||||
* <p>Uses WebLogic's special {@code begin(name)} method to start a JTA transaction,
|
||||
* in order to make <b>Spring-driven transactions visible in WebLogic's transaction
|
||||
* monitor</b>. In case of Spring's declarative transactions, the exposed name will
|
||||
* (by default) be the fully-qualified class name + "." + method name.
|
||||
*
|
||||
* <p>Supports a <b>per-transaction isolation level</b> through WebLogic's corresponding
|
||||
* JTA transaction property "ISOLATION LEVEL". This will apply the specified isolation
|
||||
* level (e.g. ISOLATION_SERIALIZABLE) to all JDBC Connections that participate in the
|
||||
* given transaction.
|
||||
*
|
||||
* <p>Invokes WebLogic's special {@code forceResume} method if standard JTA resume
|
||||
* failed, to <b>also resume if the target transaction was marked rollback-only</b>.
|
||||
* If you're not relying on this feature of transaction suspension in the first
|
||||
* place, Spring's standard JtaTransactionManager will behave properly too.
|
||||
*
|
||||
* <p>By default, the JTA UserTransaction and TransactionManager handles are
|
||||
* fetched directly from WebLogic's {@code TransactionHelper}. This can be
|
||||
* overridden by specifying "userTransaction"/"userTransactionName" and
|
||||
* "transactionManager"/"transactionManagerName", passing in existing handles
|
||||
* or specifying corresponding JNDI locations to look up.
|
||||
*
|
||||
* <p><b>NOTE: This JtaTransactionManager is intended to refine specific transaction
|
||||
* demarcation behavior on Spring's side. It will happily co-exist with independently
|
||||
* configured WebLogic transaction strategies in your persistence provider, with no
|
||||
* need to specifically connect those setups in any way.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1
|
||||
* @see org.springframework.transaction.TransactionDefinition#getName
|
||||
* @see org.springframework.transaction.TransactionDefinition#getIsolationLevel
|
||||
* @see weblogic.transaction.UserTransaction#begin(String)
|
||||
* @see weblogic.transaction.Transaction#setProperty
|
||||
* @see weblogic.transaction.TransactionManager#forceResume
|
||||
* @see weblogic.transaction.TransactionHelper
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class WebLogicJtaTransactionManager extends JtaTransactionManager {
|
||||
|
||||
private static final String USER_TRANSACTION_CLASS_NAME = "weblogic.transaction.UserTransaction";
|
||||
|
||||
private static final String CLIENT_TRANSACTION_MANAGER_CLASS_NAME = "weblogic.transaction.ClientTransactionManager";
|
||||
|
||||
private static final String TRANSACTION_CLASS_NAME = "weblogic.transaction.Transaction";
|
||||
|
||||
private static final String TRANSACTION_HELPER_CLASS_NAME = "weblogic.transaction.TransactionHelper";
|
||||
|
||||
private static final String ISOLATION_LEVEL_KEY = "ISOLATION LEVEL";
|
||||
|
||||
|
||||
private boolean weblogicUserTransactionAvailable;
|
||||
|
||||
@Nullable
|
||||
private Method beginWithNameMethod;
|
||||
|
||||
@Nullable
|
||||
private Method beginWithNameAndTimeoutMethod;
|
||||
|
||||
private boolean weblogicTransactionManagerAvailable;
|
||||
|
||||
@Nullable
|
||||
private Method forceResumeMethod;
|
||||
|
||||
@Nullable
|
||||
private Method setPropertyMethod;
|
||||
|
||||
@Nullable
|
||||
private Object transactionHelper;
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws TransactionSystemException {
|
||||
super.afterPropertiesSet();
|
||||
loadWebLogicTransactionClasses();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected UserTransaction retrieveUserTransaction() throws TransactionSystemException {
|
||||
Object helper = loadWebLogicTransactionHelper();
|
||||
try {
|
||||
logger.trace("Retrieving JTA UserTransaction from WebLogic TransactionHelper");
|
||||
Method getUserTransactionMethod = helper.getClass().getMethod("getUserTransaction");
|
||||
return (UserTransaction) getUserTransactionMethod.invoke(this.transactionHelper);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new TransactionSystemException(
|
||||
"WebLogic's TransactionHelper.getUserTransaction() method failed", ex.getTargetException());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not invoke WebLogic's TransactionHelper.getUserTransaction() method", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected TransactionManager retrieveTransactionManager() throws TransactionSystemException {
|
||||
Object helper = loadWebLogicTransactionHelper();
|
||||
try {
|
||||
logger.trace("Retrieving JTA TransactionManager from WebLogic TransactionHelper");
|
||||
Method getTransactionManagerMethod = helper.getClass().getMethod("getTransactionManager");
|
||||
return (TransactionManager) getTransactionManagerMethod.invoke(this.transactionHelper);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new TransactionSystemException(
|
||||
"WebLogic's TransactionHelper.getTransactionManager() method failed", ex.getTargetException());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not invoke WebLogic's TransactionHelper.getTransactionManager() method", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object loadWebLogicTransactionHelper() throws TransactionSystemException {
|
||||
Object helper = this.transactionHelper;
|
||||
if (helper == null) {
|
||||
try {
|
||||
Class<?> transactionHelperClass = getClass().getClassLoader().loadClass(TRANSACTION_HELPER_CLASS_NAME);
|
||||
Method getTransactionHelperMethod = transactionHelperClass.getMethod("getTransactionHelper");
|
||||
helper = getTransactionHelperMethod.invoke(null);
|
||||
this.transactionHelper = helper;
|
||||
logger.trace("WebLogic TransactionHelper found");
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new TransactionSystemException(
|
||||
"WebLogic's TransactionHelper.getTransactionHelper() method failed", ex.getTargetException());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not initialize WebLogicJtaTransactionManager because WebLogic API classes are not available",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
private void loadWebLogicTransactionClasses() throws TransactionSystemException {
|
||||
try {
|
||||
Class<?> userTransactionClass = getClass().getClassLoader().loadClass(USER_TRANSACTION_CLASS_NAME);
|
||||
this.weblogicUserTransactionAvailable = userTransactionClass.isInstance(getUserTransaction());
|
||||
if (this.weblogicUserTransactionAvailable) {
|
||||
this.beginWithNameMethod = userTransactionClass.getMethod("begin", String.class);
|
||||
this.beginWithNameAndTimeoutMethod = userTransactionClass.getMethod("begin", String.class, int.class);
|
||||
logger.debug("Support for WebLogic transaction names available");
|
||||
}
|
||||
else {
|
||||
logger.debug("Support for WebLogic transaction names not available");
|
||||
}
|
||||
|
||||
// Obtain WebLogic ClientTransactionManager interface.
|
||||
Class<?> transactionManagerClass =
|
||||
getClass().getClassLoader().loadClass(CLIENT_TRANSACTION_MANAGER_CLASS_NAME);
|
||||
logger.trace("WebLogic ClientTransactionManager found");
|
||||
|
||||
this.weblogicTransactionManagerAvailable = transactionManagerClass.isInstance(getTransactionManager());
|
||||
if (this.weblogicTransactionManagerAvailable) {
|
||||
Class<?> transactionClass = getClass().getClassLoader().loadClass(TRANSACTION_CLASS_NAME);
|
||||
this.forceResumeMethod = transactionManagerClass.getMethod("forceResume", Transaction.class);
|
||||
this.setPropertyMethod = transactionClass.getMethod("setProperty", String.class, Serializable.class);
|
||||
logger.debug("Support for WebLogic forceResume available");
|
||||
}
|
||||
else {
|
||||
logger.debug("Support for WebLogic forceResume not available");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not initialize WebLogicJtaTransactionManager because WebLogic API classes are not available",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
private TransactionManager obtainTransactionManager() {
|
||||
TransactionManager tm = getTransactionManager();
|
||||
Assert.state(tm != null, "No TransactionManager set");
|
||||
return tm;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition)
|
||||
throws NotSupportedException, SystemException {
|
||||
|
||||
int timeout = determineTimeout(definition);
|
||||
|
||||
// Apply transaction name (if any) to WebLogic transaction.
|
||||
if (this.weblogicUserTransactionAvailable && definition.getName() != null) {
|
||||
try {
|
||||
if (timeout > TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
/*
|
||||
weblogic.transaction.UserTransaction wut = (weblogic.transaction.UserTransaction) ut;
|
||||
wut.begin(definition.getName(), timeout);
|
||||
*/
|
||||
Assert.state(this.beginWithNameAndTimeoutMethod != null, "WebLogic JTA API not initialized");
|
||||
this.beginWithNameAndTimeoutMethod.invoke(txObject.getUserTransaction(), definition.getName(), timeout);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
weblogic.transaction.UserTransaction wut = (weblogic.transaction.UserTransaction) ut;
|
||||
wut.begin(definition.getName());
|
||||
*/
|
||||
Assert.state(this.beginWithNameMethod != null, "WebLogic JTA API not initialized");
|
||||
this.beginWithNameMethod.invoke(txObject.getUserTransaction(), definition.getName());
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new TransactionSystemException(
|
||||
"WebLogic's UserTransaction.begin() method failed", ex.getTargetException());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not invoke WebLogic's UserTransaction.begin() method", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No WebLogic UserTransaction available or no transaction name specified
|
||||
// -> standard JTA begin call.
|
||||
applyTimeout(txObject, timeout);
|
||||
txObject.getUserTransaction().begin();
|
||||
}
|
||||
|
||||
// Specify isolation level, if any, through corresponding WebLogic transaction property.
|
||||
if (this.weblogicTransactionManagerAvailable) {
|
||||
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
|
||||
try {
|
||||
Transaction tx = obtainTransactionManager().getTransaction();
|
||||
Integer isolationLevel = definition.getIsolationLevel();
|
||||
/*
|
||||
weblogic.transaction.Transaction wtx = (weblogic.transaction.Transaction) tx;
|
||||
wtx.setProperty(ISOLATION_LEVEL_KEY, isolationLevel);
|
||||
*/
|
||||
Assert.state(this.setPropertyMethod != null, "WebLogic JTA API not initialized");
|
||||
this.setPropertyMethod.invoke(tx, ISOLATION_LEVEL_KEY, isolationLevel);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new TransactionSystemException(
|
||||
"WebLogic's Transaction.setProperty(String, Serializable) method failed", ex.getTargetException());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not invoke WebLogic's Transaction.setProperty(String, Serializable) method", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
applyIsolationLevel(txObject, definition.getIsolationLevel());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doJtaResume(@Nullable JtaTransactionObject txObject, Object suspendedTransaction)
|
||||
throws InvalidTransactionException, SystemException {
|
||||
|
||||
try {
|
||||
obtainTransactionManager().resume((Transaction) suspendedTransaction);
|
||||
}
|
||||
catch (InvalidTransactionException ex) {
|
||||
if (!this.weblogicTransactionManagerAvailable) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Standard JTA resume threw InvalidTransactionException: " + ex.getMessage() +
|
||||
" - trying WebLogic JTA forceResume");
|
||||
}
|
||||
/*
|
||||
weblogic.transaction.TransactionManager wtm =
|
||||
(weblogic.transaction.TransactionManager) getTransactionManager();
|
||||
wtm.forceResume(suspendedTransaction);
|
||||
*/
|
||||
try {
|
||||
Assert.state(this.forceResumeMethod != null, "WebLogic JTA API not initialized");
|
||||
this.forceResumeMethod.invoke(getTransactionManager(), suspendedTransaction);
|
||||
}
|
||||
catch (InvocationTargetException ex2) {
|
||||
throw new TransactionSystemException(
|
||||
"WebLogic's TransactionManager.forceResume(Transaction) method failed", ex2.getTargetException());
|
||||
}
|
||||
catch (Exception ex2) {
|
||||
throw new TransactionSystemException(
|
||||
"Could not access WebLogic's TransactionManager.forceResume(Transaction) method", ex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction createTransaction(@Nullable String name, int timeout) throws NotSupportedException, SystemException {
|
||||
if (this.weblogicUserTransactionAvailable && name != null) {
|
||||
try {
|
||||
if (timeout >= 0) {
|
||||
Assert.state(this.beginWithNameAndTimeoutMethod != null, "WebLogic JTA API not initialized");
|
||||
this.beginWithNameAndTimeoutMethod.invoke(getUserTransaction(), name, timeout);
|
||||
}
|
||||
else {
|
||||
Assert.state(this.beginWithNameMethod != null, "WebLogic JTA API not initialized");
|
||||
this.beginWithNameMethod.invoke(getUserTransaction(), name);
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
if (ex.getTargetException() instanceof NotSupportedException) {
|
||||
throw (NotSupportedException) ex.getTargetException();
|
||||
}
|
||||
else if (ex.getTargetException() instanceof SystemException) {
|
||||
throw (SystemException) ex.getTargetException();
|
||||
}
|
||||
else if (ex.getTargetException() instanceof RuntimeException) {
|
||||
throw (RuntimeException) ex.getTargetException();
|
||||
}
|
||||
else {
|
||||
throw new SystemException(
|
||||
"WebLogic's begin() method failed with an unexpected error: " + ex.getTargetException());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new SystemException("Could not invoke WebLogic's UserTransaction.begin() method: " + ex);
|
||||
}
|
||||
return new ManagedTransactionAdapter(obtainTransactionManager());
|
||||
}
|
||||
|
||||
else {
|
||||
// No name specified - standard JTA is sufficient.
|
||||
return super.createTransaction(name, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,423 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.transaction.jta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import com.ibm.websphere.uow.UOWSynchronizationRegistry;
|
||||
import com.ibm.wsspi.uow.UOWAction;
|
||||
import com.ibm.wsspi.uow.UOWActionException;
|
||||
import com.ibm.wsspi.uow.UOWException;
|
||||
import com.ibm.wsspi.uow.UOWManager;
|
||||
import com.ibm.wsspi.uow.UOWManagerFactory;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.InvalidTimeoutException;
|
||||
import org.springframework.transaction.NestedTransactionNotSupportedException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.SmartTransactionObject;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* WebSphere-specific PlatformTransactionManager implementation that delegates
|
||||
* to a {@link com.ibm.wsspi.uow.UOWManager} instance, obtained from WebSphere's
|
||||
* JNDI environment. This allows Spring to leverage the full power of the WebSphere
|
||||
* transaction coordinator, including transaction suspension, in a manner that is
|
||||
* perfectly compliant with officially supported WebSphere API.
|
||||
*
|
||||
* <p>The {@link CallbackPreferringPlatformTransactionManager} interface
|
||||
* implemented by this class indicates that callers should preferably pass in
|
||||
* a {@link TransactionCallback} through the {@link #execute} method, which
|
||||
* will be handled through the callback-based WebSphere UOWManager API instead
|
||||
* of through standard JTA API (UserTransaction / TransactionManager). This avoids
|
||||
* the use of the non-public {@code javax.transaction.TransactionManager}
|
||||
* API on WebSphere, staying within supported WebSphere API boundaries.
|
||||
*
|
||||
* <p>This transaction manager implementation derives from Spring's standard
|
||||
* {@link JtaTransactionManager}, inheriting the capability to support programmatic
|
||||
* transaction demarcation via {@code getTransaction} / {@code commit} /
|
||||
* {@code rollback} calls through a JTA UserTransaction handle, for callers
|
||||
* that do not use the TransactionCallback-based {@link #execute} method. However,
|
||||
* transaction suspension is <i>not</i> supported in this {@code getTransaction}
|
||||
* style (unless you explicitly specify a {@link #setTransactionManager} reference,
|
||||
* despite the official WebSphere recommendations). Use the {@link #execute} style
|
||||
* for any code that might require transaction suspension.
|
||||
*
|
||||
* <p>This transaction manager is compatible with WebSphere 6.1.0.9 and above.
|
||||
* The default JNDI location for the UOWManager is "java:comp/websphere/UOWManager".
|
||||
* If the location happens to differ according to your WebSphere documentation,
|
||||
* simply specify the actual location through this transaction manager's
|
||||
* "uowManagerName" bean property.
|
||||
*
|
||||
* <p><b>NOTE: This JtaTransactionManager is intended to refine specific transaction
|
||||
* demarcation behavior on Spring's side. It will happily co-exist with independently
|
||||
* configured WebSphere transaction strategies in your persistence provider, with no
|
||||
* need to specifically connect those setups in any way.</b>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see #setUowManager
|
||||
* @see #setUowManagerName
|
||||
* @see com.ibm.wsspi.uow.UOWManager
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class WebSphereUowTransactionManager extends JtaTransactionManager
|
||||
implements CallbackPreferringPlatformTransactionManager {
|
||||
|
||||
/**
|
||||
* Default JNDI location for the WebSphere UOWManager.
|
||||
* @see #setUowManagerName
|
||||
*/
|
||||
public static final String DEFAULT_UOW_MANAGER_NAME = "java:comp/websphere/UOWManager";
|
||||
|
||||
|
||||
@Nullable
|
||||
private UOWManager uowManager;
|
||||
|
||||
@Nullable
|
||||
private String uowManagerName;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new WebSphereUowTransactionManager.
|
||||
*/
|
||||
public WebSphereUowTransactionManager() {
|
||||
setAutodetectTransactionManager(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new WebSphereUowTransactionManager for the given UOWManager.
|
||||
* @param uowManager the WebSphere UOWManager to use as direct reference
|
||||
*/
|
||||
public WebSphereUowTransactionManager(UOWManager uowManager) {
|
||||
this();
|
||||
this.uowManager = uowManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the WebSphere UOWManager to use as direct reference.
|
||||
* <p>Typically just used for test setups; in a Java EE environment,
|
||||
* the UOWManager will always be fetched from JNDI.
|
||||
* @see #setUserTransactionName
|
||||
*/
|
||||
public void setUowManager(UOWManager uowManager) {
|
||||
this.uowManager = uowManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JNDI name of the WebSphere UOWManager.
|
||||
* The default "java:comp/websphere/UOWManager" is used if not set.
|
||||
* @see #DEFAULT_USER_TRANSACTION_NAME
|
||||
* @see #setUowManager
|
||||
*/
|
||||
public void setUowManagerName(String uowManagerName) {
|
||||
this.uowManagerName = uowManagerName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws TransactionSystemException {
|
||||
initUserTransactionAndTransactionManager();
|
||||
|
||||
// Fetch UOWManager handle from JNDI, if necessary.
|
||||
if (this.uowManager == null) {
|
||||
if (this.uowManagerName != null) {
|
||||
this.uowManager = lookupUowManager(this.uowManagerName);
|
||||
}
|
||||
else {
|
||||
this.uowManager = lookupDefaultUowManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the WebSphere UOWManager in JNDI via the configured name.
|
||||
* @param uowManagerName the JNDI name of the UOWManager
|
||||
* @return the UOWManager object
|
||||
* @throws TransactionSystemException if the JNDI lookup failed
|
||||
* @see #setJndiTemplate
|
||||
* @see #setUowManagerName
|
||||
*/
|
||||
protected UOWManager lookupUowManager(String uowManagerName) throws TransactionSystemException {
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Retrieving WebSphere UOWManager from JNDI location [" + uowManagerName + "]");
|
||||
}
|
||||
return getJndiTemplate().lookup(uowManagerName, UOWManager.class);
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
throw new TransactionSystemException(
|
||||
"WebSphere UOWManager is not available at JNDI location [" + uowManagerName + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the WebSphere UOWManager from the default JNDI location
|
||||
* "java:comp/websphere/UOWManager".
|
||||
* @return the UOWManager object
|
||||
* @throws TransactionSystemException if the JNDI lookup failed
|
||||
* @see #setJndiTemplate
|
||||
*/
|
||||
protected UOWManager lookupDefaultUowManager() throws TransactionSystemException {
|
||||
try {
|
||||
logger.debug("Retrieving WebSphere UOWManager from default JNDI location [" + DEFAULT_UOW_MANAGER_NAME + "]");
|
||||
return getJndiTemplate().lookup(DEFAULT_UOW_MANAGER_NAME, UOWManager.class);
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
logger.debug("WebSphere UOWManager is not available at default JNDI location [" +
|
||||
DEFAULT_UOW_MANAGER_NAME + "] - falling back to UOWManagerFactory lookup");
|
||||
return UOWManagerFactory.getUOWManager();
|
||||
}
|
||||
}
|
||||
|
||||
private UOWManager obtainUOWManager() {
|
||||
Assert.state(this.uowManager != null, "No UOWManager set");
|
||||
return this.uowManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers the synchronizations as interposed JTA Synchronization on the UOWManager.
|
||||
*/
|
||||
@Override
|
||||
protected void doRegisterAfterCompletionWithJtaTransaction(
|
||||
JtaTransactionObject txObject, List<TransactionSynchronization> synchronizations) {
|
||||
|
||||
obtainUOWManager().registerInterposedSynchronization(new JtaAfterCompletionSynchronization(synchronizations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} since WebSphere ResourceAdapters (as exposed in JNDI)
|
||||
* implicitly perform transaction enlistment if the MessageEndpointFactory's
|
||||
* {@code isDeliveryTransacted} method returns {@code true}.
|
||||
* In that case we'll simply skip the {@link #createTransaction} call.
|
||||
* @see javax.resource.spi.endpoint.MessageEndpointFactory#isDeliveryTransacted
|
||||
* @see org.springframework.jca.endpoint.AbstractMessageEndpointFactory
|
||||
* @see TransactionFactory#createTransaction
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsResourceAdapterManagedTransactions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T execute(@Nullable TransactionDefinition definition, TransactionCallback<T> callback)
|
||||
throws TransactionException {
|
||||
|
||||
// Use defaults if no transaction definition given.
|
||||
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
|
||||
|
||||
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
|
||||
}
|
||||
|
||||
UOWManager uowManager = obtainUOWManager();
|
||||
int pb = def.getPropagationBehavior();
|
||||
boolean existingTx = (uowManager.getUOWStatus() != UOWSynchronizationRegistry.UOW_STATUS_NONE &&
|
||||
uowManager.getUOWType() != UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION);
|
||||
|
||||
int uowType = UOWSynchronizationRegistry.UOW_TYPE_GLOBAL_TRANSACTION;
|
||||
boolean joinTx = false;
|
||||
boolean newSynch = false;
|
||||
|
||||
if (existingTx) {
|
||||
if (pb == TransactionDefinition.PROPAGATION_NEVER) {
|
||||
throw new IllegalTransactionStateException(
|
||||
"Transaction propagation 'never' but existing transaction found");
|
||||
}
|
||||
if (pb == TransactionDefinition.PROPAGATION_NESTED) {
|
||||
throw new NestedTransactionNotSupportedException(
|
||||
"Transaction propagation 'nested' not supported for WebSphere UOW transactions");
|
||||
}
|
||||
if (pb == TransactionDefinition.PROPAGATION_SUPPORTS ||
|
||||
pb == TransactionDefinition.PROPAGATION_REQUIRED ||
|
||||
pb == TransactionDefinition.PROPAGATION_MANDATORY) {
|
||||
joinTx = true;
|
||||
newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
else if (pb == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
|
||||
uowType = UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION;
|
||||
newSynch = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
else {
|
||||
newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pb == TransactionDefinition.PROPAGATION_MANDATORY) {
|
||||
throw new IllegalTransactionStateException(
|
||||
"Transaction propagation 'mandatory' but no existing transaction found");
|
||||
}
|
||||
if (pb == TransactionDefinition.PROPAGATION_SUPPORTS ||
|
||||
pb == TransactionDefinition.PROPAGATION_NOT_SUPPORTED ||
|
||||
pb == TransactionDefinition.PROPAGATION_NEVER) {
|
||||
uowType = UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION;
|
||||
newSynch = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
else {
|
||||
newSynch = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
}
|
||||
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
if (debug) {
|
||||
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
|
||||
}
|
||||
SuspendedResourcesHolder suspendedResources = (!joinTx ? suspend(null) : null);
|
||||
UOWActionAdapter<T> action = null;
|
||||
try {
|
||||
boolean actualTransaction = (uowType == UOWManager.UOW_TYPE_GLOBAL_TRANSACTION);
|
||||
if (actualTransaction && def.getTimeout() > TransactionDefinition.TIMEOUT_DEFAULT) {
|
||||
uowManager.setUOWTimeout(uowType, def.getTimeout());
|
||||
}
|
||||
if (debug) {
|
||||
logger.debug("Invoking WebSphere UOW action: type=" + uowType + ", join=" + joinTx);
|
||||
}
|
||||
action = new UOWActionAdapter<>(def, callback, actualTransaction, !joinTx, newSynch, debug);
|
||||
uowManager.runUnderUOW(uowType, joinTx, action);
|
||||
if (debug) {
|
||||
logger.debug("Returned from WebSphere UOW action: type=" + uowType + ", join=" + joinTx);
|
||||
}
|
||||
return action.getResult();
|
||||
}
|
||||
catch (UOWException | UOWActionException ex) {
|
||||
TransactionSystemException tse =
|
||||
new TransactionSystemException("UOWManager transaction processing failed", ex);
|
||||
Throwable appEx = action.getException();
|
||||
if (appEx != null) {
|
||||
logger.error("Application exception overridden by rollback exception", appEx);
|
||||
tse.initApplicationException(appEx);
|
||||
}
|
||||
throw tse;
|
||||
}
|
||||
finally {
|
||||
if (suspendedResources != null) {
|
||||
resume(null, suspendedResources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapter that executes the given Spring transaction within the WebSphere UOWAction shape.
|
||||
*/
|
||||
private class UOWActionAdapter<T> implements UOWAction, SmartTransactionObject {
|
||||
|
||||
private final TransactionDefinition definition;
|
||||
|
||||
private final TransactionCallback<T> callback;
|
||||
|
||||
private final boolean actualTransaction;
|
||||
|
||||
private final boolean newTransaction;
|
||||
|
||||
private final boolean newSynchronization;
|
||||
|
||||
private boolean debug;
|
||||
|
||||
@Nullable
|
||||
private T result;
|
||||
|
||||
@Nullable
|
||||
private Throwable exception;
|
||||
|
||||
public UOWActionAdapter(TransactionDefinition definition, TransactionCallback<T> callback,
|
||||
boolean actualTransaction, boolean newTransaction, boolean newSynchronization, boolean debug) {
|
||||
|
||||
this.definition = definition;
|
||||
this.callback = callback;
|
||||
this.actualTransaction = actualTransaction;
|
||||
this.newTransaction = newTransaction;
|
||||
this.newSynchronization = newSynchronization;
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
UOWManager uowManager = obtainUOWManager();
|
||||
DefaultTransactionStatus status = prepareTransactionStatus(
|
||||
this.definition, (this.actualTransaction ? this : null),
|
||||
this.newTransaction, this.newSynchronization, this.debug, null);
|
||||
try {
|
||||
this.result = this.callback.doInTransaction(status);
|
||||
triggerBeforeCommit(status);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
this.exception = ex;
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back on application exception from transaction callback", ex);
|
||||
}
|
||||
uowManager.setRollbackOnly();
|
||||
}
|
||||
finally {
|
||||
if (status.isLocalRollbackOnly()) {
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Transaction callback has explicitly requested rollback");
|
||||
}
|
||||
uowManager.setRollbackOnly();
|
||||
}
|
||||
triggerBeforeCompletion(status);
|
||||
if (status.isNewSynchronization()) {
|
||||
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
|
||||
TransactionSynchronizationManager.clear();
|
||||
if (!synchronizations.isEmpty()) {
|
||||
uowManager.registerInterposedSynchronization(new JtaAfterCompletionSynchronization(synchronizations));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getResult() {
|
||||
if (this.exception != null) {
|
||||
ReflectionUtils.rethrowRuntimeException(this.exception);
|
||||
}
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Throwable getException() {
|
||||
return this.exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return obtainUOWManager().getRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
TransactionSynchronizationUtils.triggerFlush();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1152,8 +1152,8 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
|
||||
* @see DefaultTransactionStatus#isLocalRollbackOnly()
|
||||
* @see org.springframework.transaction.TransactionStatus#setRollbackOnly()
|
||||
* @see org.springframework.transaction.UnexpectedRollbackException
|
||||
* @see javax.transaction.UserTransaction#commit()
|
||||
* @see javax.transaction.RollbackException
|
||||
* @see jakarta.transaction.UserTransaction#commit()
|
||||
* @see jakarta.transaction.RollbackException
|
||||
*/
|
||||
protected boolean shouldCommitOnGlobalRollbackOnly() {
|
||||
return false;
|
||||
|
||||
@@ -36,8 +36,8 @@ public interface SmartTransactionObject extends Flushable {
|
||||
/**
|
||||
* Return whether the transaction is internally marked as rollback-only.
|
||||
* Can, for example, check the JTA UserTransaction.
|
||||
* @see javax.transaction.UserTransaction#getStatus
|
||||
* @see javax.transaction.Status#STATUS_MARKED_ROLLBACK
|
||||
* @see jakarta.transaction.UserTransaction#getStatus
|
||||
* @see jakarta.transaction.Status#STATUS_MARKED_ROLLBACK
|
||||
*/
|
||||
boolean isRollbackOnly();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user