Skip to content

fix(recovery): Change initialiseConnection() in XAResourceRecoveryHelper #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.lang.reflect.Modifier;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.DataSource;
Expand All @@ -30,14 +29,15 @@
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.xa.XAResource;

import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule;
import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory;
import org.apache.tomcat.dbcp.dbcp2.managed.BasicManagedDataSource;

import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule;
import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper;

public final class PoolingDataSourceFactory {

private static final Log log = LogFactory.getLog(PoolingDataSourceFactory.class);
Expand Down Expand Up @@ -71,39 +71,49 @@ private void initialiseConnection() throws SQLException {
// This will allow us to ensure that each recovery cycle gets a fresh connection
// It might be better to close at the end of the recovery pass to free up the connection but
// we don't have a hook
if (connection == null) {
final String user = properties.getProperty(PROP_USERNAME);
final String password = properties.getProperty(PROP_PASSWORD);

if (user != null && password != null) {
connection = xaDataSource.getXAConnection(user, password);
} else {
connection = xaDataSource.getXAConnection();
if (connection != null) {
try {
log.debug("XAResourceRecoveryHelper : Detected a connection during XARecovery" + connection + " attempting to close it properly & generating a new one");
connection.close();

} catch (Exception e) {
log.debug("XAResourceRecoveryHelper : The connection could not close properly, generating a new one", e);
} finally {
connection = null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I am reading this correctly then every call to getXAResources() will return a fresh connection. I'm not sure who calls it, but I am assuming it is called by the narayana recovery module, which means that each recovery pass will get a fresh resource. I am unclear about the performance impact but safety is more important than performance. On this basis I will confer my approval.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think you are right.

}
connection.addConnectionEventListener(new ConnectionEventListener() {
@Override
public void connectionClosed(ConnectionEvent event) {
log.warn("The connection was closed: " + connection);
synchronized (lock) {
connection = null;
}
}

final String user = properties.getProperty(PROP_USERNAME);
final String password = properties.getProperty(PROP_PASSWORD);

if (user != null && password != null) {
connection = xaDataSource.getXAConnection(user, password);
} else {
connection = xaDataSource.getXAConnection();
}
connection.addConnectionEventListener(new ConnectionEventListener() {
@Override
public void connectionClosed(ConnectionEvent event) {
log.warn("The connection was closed: " + connection);
synchronized (lock) {
connection = null;
}
}

@Override
public void connectionErrorOccurred(ConnectionEvent event) {
log.warn("A connection error occurred: " + connection);
synchronized (lock) {
try {
connection.close();
} catch (SQLException e) {
// Ignore
log.warn("Could not close failing connection: " + connection);
}
connection = null;
@Override
public void connectionErrorOccurred(ConnectionEvent event) {
log.warn("A connection error occurred: " + connection);
synchronized (lock) {
try {
connection.close();
} catch (SQLException e) {
// Ignore
log.warn("Could not close failing connection: " + connection);
}
connection = null;
}
});
}
}
});
}
};
}
Expand Down