Skip to content
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

TopLinkTransactionManager unable to expose a TopLink transaction to JDBC access code [SPR-4382] #9061

Closed
spring-projects-issues opened this issue Jan 23, 2008 · 3 comments
Assignees
Labels
status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Marc Ludwig opened SPR-4382 and commented

(see http://forum.springframework.org/showthread.php?t=48968 for further info)

In Spring docs it states:
"TopLinkTransactionManager is capable of exposing a TopLink transaction to JDBC access code that accesses
the same JDBC DataSource, provided that TopLink works with JDBC in the backend and is thus able to expose
the underlying JDBC Connection. The DataSource to expose the transactions for needs to be specified
explicitly; it won't be autodetected."

In order to generate and call some anonymous PL/SQL blocks (to deal with Oracle associative arrays used in legacy code) we are using JdbcDaoSupport.
The rest of our app used TopLinkDaoSupport.

I saw in the documentation that Toplink transaction can be exposed to JDBC, but I think that this will never occur due to the SessionFactory creating a Proxy aound the Session, whilst checks within the ToplinkTransactionManager to retrieve the JDBCConnection assume a ClientSession.

Stepping through doBegin in TopLinkTransactionManager I think shows that a jdbcConnection will never be retrieved from a Writeable Toplink Client Session.

TopLinkTransactionManager.doBegin
Code:
if (!definition.isReadOnly()) {
logger.debug("Creating managed TopLink Session with active UnitOfWork for read-write transaction");
session = getSessionFactory().createManagedClientSession();
}

ServerSessionFactory.createManagedClientSession (in AbstractSessionFactory)
Code:
logger.debug("Creating managed TopLink client Session");
return (Session) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[] {Session.class},
new ManagedClientInvocationHandler(createClientSession()));

But later in TopLinkTransactionManager.doBegin it calls getJdbcConnection
Code:
if (!(session instanceof oracle.toplink.publicinterface.Session)) {
if (logger.isDebugEnabled()) {
logger.debug("TopLink Session [" + session +"] does not derive from [oracle.toplink.publicinterface.Session]");
}
return null;

Unless I'm mistaken (a big risk!), a writeable Toplink Session will never be able to provide the JDBC Connection to the JdbcDaoSupport, as it's an instance of Proxy (notSession).

Is this expected behaviour, meaning that the ToplinkTransactionManager.getJdbcConnection should be overridden to deal with the Proxy instance, or is it a bug within the Spring-Toplink Integration layer.

As always, many thanks for investigating.

Marc


Affects: 2.0.8, 2.5.1

Backported to: 2.0.9

@spring-projects-issues
Copy link
Collaborator Author

Marc Ludwig commented

Marten Deinum has more correctly diagnosed the issue: http://forum.springframework.org/showthread.php?t=48968

Quote:
You are mistaken.

If you look at the code for generating the proxy.

Code:
logger.debug("Creating managed TopLink client Session");
return (Session) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[] {Session.class},
new ManagedClientInvocationHandler(createClientSession()));It creates a proxy for the oracle.toplink.sessions.Session class, however the check is against 'oracle.toplink.publicinterface.Session' which is a different interface. Kind of weird imho. I guess with the current solution it isn't going to work, I suggest you register a JIRA for this.

@spring-projects-issues
Copy link
Collaborator Author

Marten Deinum commented

The code in the ToplinkTransactionManager.getJdbcConnection checks the given Session if it is an instance of oracle.toplink.publicinterface.Session. However the the createManagedClientSession of the AbstractSessionFactory is is creating a proxy for the oracle.toplink.sessions.Session. The test in the getJdbcConnection will thus always fail and the connection will never be shared.

I guess the code below is more correct for retrieving the jdbc connection used by Toplink.

[code]
protected Connection getJdbcConnection(Session session) {
UnitOfWork uow = session.getActiveUnitOfWork();
if (!(uow instanceof AbstractSession)) {
if (logger.isDebugEnabled()) {
logger.debug("TopLink Session [" + session +
"] does not derive from [oracle.toplink.internal.sessions.AbstractSession]");
}
return null;
}
Accessor accessor = ((oracle.toplink.internal.sessions.AbstractSession) uow).getAccessor();
if (!(accessor instanceof DatabaseAccessor)) {
if (logger.isDebugEnabled()) {
logger.debug("TopLink Accessor [" + accessor +
"] does not derive from [oracle.toplink.internal.databaseaccess.DatabaseAccessor]");
}
return null;
}
return ((DatabaseAccessor) accessor).getConnection();
}
[/code]

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Thanks for the report! I've fixed this for 2.5.2, keeping the oracle.toplink.publicinterface.Session check but this time on the "most specific Session" available: The UnitOfWork in case of a read-write transaction, and the plain Session in case of a read-only transaction. Previously our code always operated on the plain Session which only really worked with a read-only transaction...

This will be available in tonight's 2.5.2 snapshot (-382 or above; available from http://static.springframework.org/downloads/nightly/snapshot-download.php?project=SPR). Please give it a try and let us know whether it works for you...

Juergen

@spring-projects-issues spring-projects-issues added type: bug A general bug status: backported An issue that has been backported to maintenance branches labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 2.5.2 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants