Re: DBCP, Oracle9i Blob/Clob broken

2005-03-31 Thread Martin Kalén
Danilo Tommasina wrote:
we just upgraded to OJB 1.0.2, the fixes in Oracle9i platform work like 
a charm
many, many thanks again for the great work to everybody that contributed.
Hi Danilo,
 that's great to hear! Thank you for contributing valuable feedback,
code suggestions and for reporting back to the list.
Cheers,
 Martin
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-31 Thread Danilo Tommasina
Hi Martin,
we just upgraded to OJB 1.0.2, the fixes in Oracle9i platform work like a charm
many, many thanks again for the great work to everybody that contributed.
bye
danilo
Nice work,
many thanks.
cheers
danilo

Danilo Tommasina wrote:
I ended up implementing a custom DBCP connection factory that is 
using a BasicDataSource instead of a PooledDataSource. Since the 
documentation of the DBCP stuff is really ugly I didn't find out what 
the difference really is between the PooledDataSource and the 
BasicDataSource. Fact is that with the BasicDataSource based 
implementation the problem with the MAX_OPEN_CURSORS is solved, 
because a fixed-size PreparedStatement cache is used.

I had a look in DBCP CVS and the BasicDataSource is really only a 
specialiced implementation of PooledDataSource with more user-friendly 
getter/setters. It will use AbandonedObjectPool or GenericObjectPool 
for connection "storage".

With PooledDataSource you can choose any underlying pool you want and 
just supply a factory that could eg return your own pool 
implementations. (But you have no "nice" setter like setMaxIdle, since 
you can't rely on any specifics on the object pool.)

I think it makes sence to keep PooledDataSource in OJB, which enables 
the configuration to be more generic in OJB1.1.

However, I was able to work around the MAX_OPEN_CURSORS error by 
adding a check in the default DBCP connection factory: if platform is 
Oracle9i then don't use DBCP PreparedStatement caching. After fixing 
so that the factory calls initializeJdbcConnection properly, this 
allows the Oracle9i platform impl to manage the statement caching.

Note that it is necessary to implement/override also the 
releaseAllResources() method for closing the pooled connections on 
application shutdown.

This is now fixed in the DBCP factory in CVS.
These changes are only in OJB_1_0_RELEASE branch yet, I will now merge 
them with head.

Regards,
 Martin
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-16 Thread Danilo Tommasina
Nice work,
many thanks.
cheers
danilo

Danilo Tommasina wrote:
I ended up implementing a custom DBCP connection factory that is using 
a BasicDataSource instead of a PooledDataSource. Since the 
documentation of the DBCP stuff is really ugly I didn't find out what 
the difference really is between the PooledDataSource and the 
BasicDataSource. Fact is that with the BasicDataSource based 
implementation the problem with the MAX_OPEN_CURSORS is solved, 
because a fixed-size PreparedStatement cache is used.

I had a look in DBCP CVS and the BasicDataSource is really only a 
specialiced implementation of PooledDataSource with more user-friendly 
getter/setters. It will use AbandonedObjectPool or GenericObjectPool for 
connection "storage".

With PooledDataSource you can choose any underlying pool you want and 
just supply a factory that could eg return your own pool 
implementations. (But you have no "nice" setter like setMaxIdle, since 
you can't rely on any specifics on the object pool.)

I think it makes sence to keep PooledDataSource in OJB, which enables 
the configuration to be more generic in OJB1.1.

However, I was able to work around the MAX_OPEN_CURSORS error by adding 
a check in the default DBCP connection factory: if platform is Oracle9i 
then don't use DBCP PreparedStatement caching. After fixing so that the 
factory calls initializeJdbcConnection properly, this allows the 
Oracle9i platform impl to manage the statement caching.

Note that it is necessary to implement/override also the 
releaseAllResources() method for closing the pooled connections on 
application shutdown.

This is now fixed in the DBCP factory in CVS.
These changes are only in OJB_1_0_RELEASE branch yet, I will now merge 
them with head.

Regards,
 Martin
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-16 Thread Martin Kalén
Danilo Tommasina wrote:
I ended up implementing a custom DBCP connection factory that is using a 
BasicDataSource instead of a PooledDataSource. Since the documentation 
of the DBCP stuff is really ugly I didn't find out what the difference 
really is between the PooledDataSource and the BasicDataSource. Fact is 
that with the BasicDataSource based implementation the problem with the 
MAX_OPEN_CURSORS is solved, because a fixed-size PreparedStatement cache 
is used.
I had a look in DBCP CVS and the BasicDataSource is really only a 
specialiced implementation of PooledDataSource with more user-friendly 
getter/setters. It will use AbandonedObjectPool or GenericObjectPool for 
connection "storage".

With PooledDataSource you can choose any underlying pool you want and 
just supply a factory that could eg return your own pool 
implementations. (But you have no "nice" setter like setMaxIdle, since 
you can't rely on any specifics on the object pool.)

I think it makes sence to keep PooledDataSource in OJB, which enables 
the configuration to be more generic in OJB1.1.

However, I was able to work around the MAX_OPEN_CURSORS error by adding 
a check in the default DBCP connection factory: if platform is Oracle9i 
then don't use DBCP PreparedStatement caching. After fixing so that the 
factory calls initializeJdbcConnection properly, this allows the 
Oracle9i platform impl to manage the statement caching.

Note that it is necessary to implement/override also the 
releaseAllResources() method for closing the pooled connections on 
application shutdown.
This is now fixed in the DBCP factory in CVS.
These changes are only in OJB_1_0_RELEASE branch yet, I will now merge 
them with head.

Regards,
 Martin
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-15 Thread Martin Kalén
Danilo Tommasina wrote:
There is a problem with using Oracle and the default DBCP connection 
factory, since PreparedStatement caching in DBCP will "eat" all your 
Oracle cursors rather quickly. See the release notes for a work-around 
(set PSPoolFactory==null). In OJB 1.1 the configuration mechanism will 
be a bit more flexible so you will probably not see any new connection 
factories in the 1.0.x line of releases.
Dang, I spent a couple on days on this issue last week, I didn't saw the 
release notes...
They were not there last week so you didn't miss out. ;) I did not have 
the time to do extensive testing of the DBCP stuff until now and several 
of the regression tests will catch if cursors are leaking.

I ended up implementing a custom DBCP connection factory that is using a 
BasicDataSource instead of a PooledDataSource. Since the documentation 
of the DBCP stuff is really ugly I didn't find out what the difference 
really is between the PooledDataSource and the BasicDataSource. Fact is 
that with the BasicDataSource based implementation the problem with the 
MAX_OPEN_CURSORS is solved, because a fixed-size PreparedStatement cache 
is used.
Interesting! Thank you for your code, I will review it and the DBCP 
factory again after the release of OJB1.0.2.

Regards,
 Martin
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-15 Thread Danilo Tommasina
Hi again,
That's perfectly right -- yesterday I added a recursive generic 
unwrap-function to the default Oracle9i platform that will try to unwrap 
Connection and PreparedStatement objects until and Oracle-compatible 
class is found.

Current implementation knows about Oracle10g, Commons DBCP, P6Spy and 
BEA WebLogic.
wow really nice...
There is a problem with using Oracle and the default DBCP connection 
factory, since PreparedStatement caching in DBCP will "eat" all your 
Oracle cursors rather quickly. See the release notes for a work-around 
(set PSPoolFactory==null). In OJB 1.1 the configuration mechanism will 
be a bit more flexible so you will probably not see any new connection 
factories in the 1.0.x line of releases.
Dang, I spent a couple on days on this issue last week, I didn't saw the release notes...
I ended up implementing a custom DBCP connection factory that is using a BasicDataSource instead of a PooledDataSource. Since the documentation of the DBCP stuff is really ugly I 
didn't find out what the difference really is between the PooledDataSource and the BasicDataSource. Fact is that with the BasicDataSource based implementation the problem with the 
MAX_OPEN_CURSORS is solved, because a fixed-size PreparedStatement cache is used.

below the code we are using:
Sorry, I didn't took out the code specific to our application, static calls to ORSConfiguration. are used to load stuff from our config. files and could be replaced by 
constants or values loaded from OJB config, calls to ORSLogger.SYSTEM. are used for our internal logging routines.
Note that it is necessary to implement/override also the releaseAllResources() method for closing the pooled connections on application shutdown.


public class ORSConnFactDBCPImpl extends ConnectionFactoryDBCPImpl {
private BasicDataSource pooledDs = null;
/** Creates a new instance of ORSConnFactDBCPImpl */
public ORSConnFactDBCPImpl() {}
/** Overrides ConnectionFactoryDBCPImpl.createConnectionFactory( 
JdbcConnectionDescriptor jcd ) */
protected org.apache.commons.dbcp.ConnectionFactory 
createConnectionFactory( JdbcConnectionDescriptor jcd ) {
// This is custom code for setting custom JDBC driver 
attributes/properties
// adding support for extracting the attributes from the 
JdbcConnectionDescriptor
// would be the required implementation of (my) feature request:
// OJB298 (Setting custom JDBC driver tuning options trough 
jdbc-connection-descriptor)
Properties connProp = ORSConfiguration.getJDBCDriverOptions();
// Add user and password
connProp.put( "user", jcd.getUserName() );
connProp.put( "password", jcd.getPassWord() );
return new DriverManagerConnectionFactory( super.getDbURL( jcd ), 
connProp );
}
/**
 * Override this method to setup your own pool
 */
protected DataSource setupPool( JdbcConnectionDescriptor jcd ) {
ORSLogger.SYSTEM.debug( "Creating new ORS DBCP connection pool" );
try {
ClassHelper.newInstance( jcd.getDriver() );
} catch ( InstantiationException e ){
ORSLogger.SYSTEM.fatal( "Unable to instantiate the driver class: " + 
jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e );
} catch (IllegalAccessException e ) {
ORSLogger.SYSTEM.fatal( "IllegalAccessException while instantiating the driver 
class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e );
} catch (ClassNotFoundException e ) {
ORSLogger.SYSTEM.fatal( "Could not find the driver class : " + 
jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e );
}
// get the configuration for the connection pool
GenericObjectPool.Config conf = 
jcd.getConnectionPoolDescriptor().getObjectPoolConfig();
this.pooledDs = new BasicDataSource();
// Init using the data from connection descriptor in repository.xml
this.pooledDs.setDefaultAutoCommit( jcd.getUseAutoCommit() != 
JdbcConnectionDescriptor.AUTO_COMMIT_SET_FALSE );
this.pooledDs.setDriverClassName( jcd.getDriver() );
this.pooledDs.setMaxActive( conf.maxActive );
this.pooledDs.setMaxIdle( conf.maxIdle );
this.pooledDs.setMaxWait( conf.maxWait );
this.pooledDs.setMinEvictableIdleTimeMillis( 
conf.minEvictableIdleTimeMillis );
this.pooledDs.setMinIdle( conf.minIdle );
this.pooledDs.setNumTestsPerEvictionRun( conf.numTestsPerEvictionRun );
this.pooledDs.setPassword( jcd.getPassWord() );
this.pooledDs.setTestOnBorrow( conf.testOnBorrow );
this.pooledDs.setTestOnReturn( conf.testOnReturn );
this.pooledDs.setTestWhileIdle( conf.testWhileIdle );
this.pooledDs.setTimeBetweenEvictionRunsMillis( 
conf.timeBetweenEvictionRunsMillis );
this.pooledDs.setUrl( super.getDbURL( jcd ) );
this.pooledDs.setUsername( jcd.getUserName() );
this.pooledDs.setValidationQuery( 
jcd

Re: DBCP, Oracle9i Blob/Clob broken

2005-03-15 Thread Martin Kalén
Danilo Tommasina wrote:
I found out that there is the method getInnermostDelegate() on the DBCP 
DelegatingPreparedStatement calling this will return the original 
PreparedStatement independently on how many hierarchies of wrappers DBCP 
is using.
That's perfectly right -- yesterday I added a recursive generic 
unwrap-function to the default Oracle9i platform that will try to unwrap 
Connection and PreparedStatement objects until and Oracle-compatible 
class is found.

Current implementation knows about Oracle10g, Commons DBCP, P6Spy and 
BEA WebLogic.

It's easy to add new methods to the array of known names/argument types.
So for the first time ever the Oracle9i platform could handle large CLOB 
and BLOB using both P6Spy and DBCP (which will render the Connection 
"superwrapped" in multiple wrappers).

There is a problem with using Oracle and the default DBCP connection 
factory, since PreparedStatement caching in DBCP will "eat" all your 
Oracle cursors rather quickly. See the release notes for a work-around 
(set PSPoolFactory==null). In OJB 1.1 the configuration mechanism will 
be a bit more flexible so you will probably not see any new connection 
factories in the 1.0.x line of releases.

Another issue is the "accesToUnderlyingConnection" in DBCP which can 
stop the large LOB-support from working. This will also not be set 
explicitly in 1.0.x since that requires a new connection factory impl or 
hardcoding a new configuration attribute. In OJB1.1 a generic 
name/value-approach till make it easier to pass implementation-specific 
parameters to the connection factories. However, I made some testing 
with the shipped DBCP v1.1 and I was able to unwrap the Connection by 
default (which has not been the case with previous versions).

Ok I didn't think at the runtime dependencies, following code uses 
reflection and avoids these external dependencies (maybe you already 
implemented it like this)

PreparedStatement innerPS;
try
{
Method delgGetter = ClassHelper.getMethod( ps, 
"getInnermostDelegate", null );
innerPS = ( delgGetter != null ) ? (PreparedStatement) 
delgGetter.invoke( ps, null ) : ps;
} catch ( Exception ignore ) {
innerPS = ps;
}
Yes, that's pretty much exactly how the code in CVS looks now (although 
the method name/type are parametrized to try multiple options).

Testing of the new functionality is appreciated; either check out from 
CVS on OJB_1_0_RELEASE branch or wait a few days until OJB1.0.2 is 
released. (Vote has already passed, we are just holding off while 
investigating an issue in the ODMG.)

Regards,
 Martin
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-15 Thread Danilo Tommasina
Hi Martin,
thank you for your answer.
I found out that there is the method getInnermostDelegate() on the DBCP DelegatingPreparedStatement calling this will return the original PreparedStatement independently on how 
many hierarchies of wrappers DBCP is using.

I reviewed your suggested DBCP-fix and this will not make it into
the default Oracle9i platform, as the imports would add a DBCP run-time 
dependency when using OJB and Oracle9i platform (which is not currently 
the case and would apply even for users that don't want DBCP).

I will try to make a more flexible support for all types of wrapped 
conenctions using reflection calls. If this is not possible your code could 
always extend the default platform and make a new "PlatformDbcpOracle9iImp",
but this would be my personal last choice...

Ok I didn't think at the runtime dependencies, following code uses 
reflection and avoids these external dependencies (maybe you already 
implemented it like this)
PreparedStatement innerPS;
try
{
Method delgGetter = ClassHelper.getMethod( ps, "getInnermostDelegate", null 
);
innerPS = ( delgGetter != null ) ? (PreparedStatement) delgGetter.invoke( 
ps, null ) : ps;
} catch ( Exception ignore ) {
innerPS = ps;
}
where ps is the 'potentially' wrappped PreparedStatement and innerPS is the 
original unwrapped PreparedStatement on which the setBLOB/CLOB methods can be 
called.
bye
danilo
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: DBCP, Oracle9i Blob/Clob broken

2005-03-14 Thread Martin Kalén
Danilo Tommasina  risksys.com> writes:
> When using the Oracle9i platform storing Blobs/Clobs does not work when using
> the DBCP connection factory
> (org.apache.ojb.broker.accesslayer.ConnectionFactoryDBCPImpl)

Hi Danilo,
 thank you for your patch and suggestions.

Unfortunately this is true not only for DBCP, but all types of wrapped
connections (eg in managed environments like BEA WebLogic).

And as you so carefully spotted, using P6Spy will render the same problem.

BLOB/CLOB is only one out of two known issues with wrapped connections. The
other one is batching and the 2k/4k BLOB/CLOB length limits with the 
oracle:thin driver.

If you select batch-mode=true these annoying limits will reappear,
even if using PlatformOracle9iImpl. (Another item on the TODO-list.)


Previously there has been a special platform added to circument the
wrapped connection problem (PlatformWLOracle9iImpl for WebLogic),
but this solution is IMHO also not satisfactory due to code duplication 
and too many platforms.

I reviewed your suggested DBCP-fix and this will not make it into
the default Oracle9i platform, as the imports would add a DBCP run-time 
dependency when using OJB and Oracle9i platform (which is not currently 
the case and would apply even for users that don't want DBCP).

I will try to make a more flexible support for all types of wrapped 
conenctions using reflection calls. If this is not possible your code could 
always extend the default platform and make a new "PlatformDbcpOracle9iImp",
but this would be my personal last choice...

> And one more side notice: why the Oracle and Sybase (and maybe other) 
> platforms are not configured to use SQL92 syntax?

Often this is simply because one developer adds a new platform method 
and do not have access to all RDBMS that OJB support, and therefore have 
to make a "qualified guess" for good defaults. If no-one using a specific 
platform yells this can go unnoticed for some time...

> At least in Sybase there are less limitations on outer joins 
> when using this syntax and it should be granted that you get same results on 
> all platform when using the SQL92.

Agreed. Since Oracle9i passes all regression tests regardless of ORACLE/SQL92 
join syntax I added your suggestion to CVS (for both 1.0.x branch and HEAD).

The upcoming OJB 1.0.2 release will use SQL92 join syntax for 
the Oracle9i platform.

(Sybase is unknown territory for me.)

Regards,
 Martin


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



DBCP, Oracle9i Blob/Clob broken

2005-03-03 Thread Danilo Tommasina
Hi,
I just saw another post about Oracle 9i and Blobs, so if somebody is going to 
get a look into it, here is some more:
When using the Oracle9i platform storing Blobs/Clobs does not work when using 
the DBCP connection factory 
(org.apache.ojb.broker.accesslayer.ConnectionFactoryDBCPImpl)
This is because of the code in PlatformOracle9iImpl:
methodSetBlob = ClassHelper.getMethod( ps, "setBLOB", new Class [] { 
Integer.TYPE, blobClass } );
The problem is that when using the DBCP connection factory the variable 'ps' 
does not contain an instance of proprietary OraclePreparedStatement with the 
proprietary setBLOB method.
It is first necessary to extract the OraclePreparedStatemnt from the 'DBCP 
PreparedStatemnt stack' until we reach the original statement.
Furthermore the Connection object bound to the OraclePreparedStatement must be 
used and not the one bound to the DBCP PreparedStatement.
And one more side notice: why the Oracle and Sybase (and maybe other) platforms are not configured to use SQL92 syntax? At least in Sybase there are less limitations on outer joins 
when using this syntax and it should be granted that you get same results on all platform when using the SQL92.

Below the code of the Platform implementation that we are using for Oracle 9i, configured for SQL92 syntax and with the workaround for the DBCP connection factory.
The code is ugly and may break if the DBCP API is modified, however I do not really see any better solution. (Maybe a recursive loop until the getDelegate() method can be found per 
reflection?)

Note that if p6spy is beeing used, the code will also not work, because the 
setBLOB method is also not available in the p6spy PreparedStatement wrapper.
And sorry for a couple of weeks more I'll be unable to post any test-cases.

public class PlatformANSIOracle9iImpl extends PlatformOracle9iImpl {
/** Creates a new instance of PlatformOracle9iImpl */
public PlatformANSIOracle9iImpl() {
super();
}
/** Get join syntax type for this RDBMS - one on of the constants from
 * JoinSyntaxType interface
 * @return SQL92_NOPAREN_JOIN_SYNTAX
 */
public byte getJoinSyntaxType() {
return SQL92_NOPAREN_JOIN_SYNTAX;
}
/** @see Platform#setObjectForStatement */
public void setObjectForStatement( PreparedStatement ps, int index, Object 
value, int sqlType ) throws SQLException {
boolean blobHandlingSupported = false;
boolean clobHandlingSupported = false;
Method methodSetBlob = null;
Method methodSetClob = null;
PreparedStatement innerPS;
if ( ps instanceof DelegatingPreparedStatement ) {
innerPS = (PreparedStatement) ((DelegatingPreparedStatement) 
ps).getDelegate();
if ( innerPS instanceof PoolablePreparedStatement ) {
innerPS = (PreparedStatement) ((PoolablePreparedStatement) 
innerPS).getDelegate();
}
} else {
innerPS = ps;
}
// Check for Oracle JDBC-driver LOB-support
if ( sqlType == Types.CLOB ) {
try {
Class clobClass = ClassHelper.getClass( "oracle.sql.CLOB", 
false );
methodSetClob = ClassHelper.getMethod( innerPS, "setCLOB", new 
Class [] { Integer.TYPE, clobClass } );
clobHandlingSupported = methodSetClob != null;
} catch ( Exception ignore ) {
// ignore it
}
} else if (sqlType == Types.BLOB ) {
try {
Class blobClass = ClassHelper.getClass( "oracle.sql.BLOB", 
false );
methodSetBlob = ClassHelper.getMethod( innerPS, "setBLOB", new 
Class [] { Integer.TYPE, blobClass } );
blobHandlingSupported = methodSetBlob != null;
} catch ( Exception ignore ) {
// ignore it
}
}
if ( clobHandlingSupported && ( value instanceof String ) ) {
try {
Object clob = Oracle9iLobHandler.createCLOBFromString( 
innerPS.getConnection(), (String) value);
methodSetClob.invoke( innerPS, new Object[] { new 
Integer(index), clob } );
} catch (Exception e) {
throw new SQLException( e.getLocalizedMessage() );
}
} else if ( blobHandlingSupported && ( value instanceof byte[] ) ) {
try {
Object blob = Oracle9iLobHandler.createBLOBFromByteArray( 
innerPS.getConnection(), (byte[]) value );
methodSetBlob.invoke( innerPS, new Object[] {new Integer( index 
), blob } );
} catch ( Exception e ) {
throw new SQLException( e.getLocalizedMessage() );
}
} else {
// Fall-through to superclass
super.setObjectForStatement( ps, index, value, sqlType );
}
}
}
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-