Menu

#180 Inserting of clobs fails

v2.2.2
closed-fixed
None
5
2014-11-03
2008-06-04
Bustuila
No

Since version 2.2.2, the insert operation fails with clobs and Oracle:

java.lang.ClassCastException: java.lang.String cannot be cast to oracle.sql.CLOB
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:9229)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8843)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:9316)
at org.dbunit.dataset.datatype.ClobDataType.setSqlValue(ClobDataType.java:67)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.database.statement.AutomaticPreparedBatchStatement.addValue(AutomaticPreparedBatchStatement.java:63)
at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:201)
at org.dbunit.ant.Operation.execute(Operation.java:212)

The change that triggers this problem seems to come from this:

ClobDataType.getSqlValue(int column, ResultSet resultSet) contains
statement.setObject(column, typeCast(value), getSqlType());

where getSqlType() returns Types.CLOB -> 2005

In version 2.2.1, where it works, it was:
statement.setObject(column, typeCast(value), DataType.LONGVARCHAR.getSqlType());

where DataType.LONGVARCHAR.getSqlType() -> -1
the same as Types.LONGVARCHAR

Oracle driver: 10.2.0.2.0 and 10.2.0.4.0
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production

Discussion

1 2 > >> (Page 1 of 2)
  • Sébastien Le Callonnec

    • assigned_to: nobody --> slecallonnec
    • status: open --> pending
     
  • Sébastien Le Callonnec

    Logged In: YES
    user_id=1232035
    Originator: NO

    Hi there,

    Would you have a simple test case reproducing the issue? If you use an OracleConnection, OracleClobDataType should be used instead of the "normal" ClobDataType.

    Regards,
    Sébastien

     
  • Bustuila

    Bustuila - 2008-06-05

    Logged In: YES
    user_id=711602
    Originator: YES

    I've tried using OracleDataTypeFactory(with driver class oracle.jdbc.OracleDriver and oracle.jdbc.driver.OracleDriver), but it doesn't work:

    java.lang.ClassCastException: oracle.jdbc.driver.T4CConnection cannot be cast to oracle.jdbc.OracleConnection
    at oracle.sql.CLOB.createTemporary(CLOB.java:754)
    at oracle.sql.CLOB.createTemporary(CLOB.java:716)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.dbunit.ext.oracle.OracleClobDataType.getClob(OracleClobDataType.java:70)
    at org.dbunit.ext.oracle.OracleClobDataType.setSqlValue(OracleClobDataType.java:56)
    at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:62)
    at org.dbunit.database.statement.AutomaticPreparedBatchStatement.addValue(AutomaticPreparedBatchStatement.java:52)
    at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:177)
    at org.dbunit.ant.Operation.execute(Operation.java:183)

    I'll try and create a simple test case.

     
  • Bustuila

    Bustuila - 2008-06-05
    • status: pending --> open
     
  • Roberto Lo Giacco

    Logged In: YES
    user_id=57511
    Originator: NO

    Oviously the problem is OracleDataTypeFactory is not aware of the pure JDBC oracle driver and recognizes only the previous classes12.jar driver

    I suggest to introduce a new factory or patch the actual one to work with both (the latter seems a little bit harder to me)

     
  • Bustuila

    Bustuila - 2008-06-05

    Logged In: YES
    user_id=711602
    Originator: YES

    The thing I don't understand is why was the change that broke 2.2 was required...
    It worked perfectly fine.
    I've searched Hibernate sources for oracle.sql.CLOB and they don't seem to used it, so maybe it's not required at all.

     
  • Bustuila

    Bustuila - 2008-06-05

    Logged In: YES
    user_id=711602
    Originator: YES

    It seems it's because of the fix for 1806363

     
  • Sébastien Le Callonnec

    Logged In: YES
    user_id=1232035
    Originator: NO

    This fix was introduced because LONGVARCHAR was causing issues with other RSBMSes. Cf. https://sourceforge.net/tracker/?func=detail&atid=449491&aid=1806363&group_id=47439

    Given that we have an Oracle-specific data type, I think that fix is legitimate since the target is everything but Oracle. Now as Roberto indicated, the problem seems to be caused because the OracleDataTypeFactory should probably support T4CConnection along with OracleConnection.

    Regards,
    Sébastien.

     
  • Roberto Lo Giacco

    Logged In: YES
    user_id=57511
    Originator: NO

    I suggest rollback your dbunit version until we find out a solution or, in
    case you need some of the patches applied after the 2.2.1 release, you can
    rollback the commit relative to the #1806363 issue.

    Sorry for the inconvenience, we already know we should set up a multi
    rdbms integration test platform, but time and money are needed for such
    activities and we actually have none of them :\

     
  • Bustuila

    Bustuila - 2008-06-05

    Logged In: YES
    user_id=711602
    Originator: YES

    No problem... If I find the time, I'll try to fix it using your sugestions and provide a patch.

     
  • Sébastien Le Callonnec

    Logged In: YES
    user_id=1232035
    Originator: NO

    If you could still provide us with a test case reproducing the issue, that would help us investigate the problem, as I haven't been able to reproduce the issue so far.

    Thanks,
    Sébastien.

     
  • Bustuila

    Bustuila - 2008-06-06

    test project

     
  • Bustuila

    Bustuila - 2008-06-06

    Logged In: YES
    user_id=711602
    Originator: YES

    I've attached a project that demonstrates the problem.
    File Added: 1984596.zip

     
  • matthias g

    matthias g - 2008-06-07

    Logged In: YES
    user_id=1803108
    Originator: NO

    Hi all,

    I tried to reproduce the problem using your testcase and I got the same exception as you mentioned initially. I added the dataTypeFactory to the pom.xml and the test was green afterwards.

    ...
    <configuration>
    <driver>${driver}</driver>
    <url>${url}</url>
    <username>${username}</username>
    <password>${password}</password>
    <skip>${maven.test.skip}</skip>
    <dataTypeFactoryName>org.dbunit.ext.oracle.OracleDataTypeFactory</dataTypeFactoryName>
    </configuration>
    ...

    Note that if you want to set it in the java code you can do it as follows:

    ...
    DatabaseConnection dbConnection = new DatabaseConnection(jdbcConnection);
    dbConnection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new OracleDataTypeFactory());
    ...

    I also found that you might get into this problem when you work inside a Container (Tomcat or J2EE) while having the ojdbc.jar in your deployment artifact AND in the server lib dir. The cause are the ClassLoader strategies used by the container. See http://forums.oracle.com/forums/thread.jspa?threadID=554480&tstart=0 for further information.
    If this would be true (just speculating a bit) the cause could be that dbunit's OracleClobDataType uses "Class.forName("oracle.sql.CLOB")" instead of "connection.getClass().getClassLoader().loadClass("oracle.sql.CLOB")"

    Regards,
    mat

     
  • Sébastien Le Callonnec

    Logged In: YES
    user_id=1232035
    Originator: NO

    Hi Bustuila,

    Thanks a mil for that project, that really helps! If only all the bug reports were coming with these packages test cases, life would be so much easier!

    Also, apologies, I hadn't realised you were using dbunit through the maven plugin. As mat mentioned below, adding:

    <dataTypeFactoryName>org.dbunit.ext.oracle.OracleDataTypeFactory</dataTypeFactoryName>

    solves the problem for me too. Is that the case for you too, or is it what caused your second problem?:

    java.lang.ClassCastException: oracle.jdbc.driver.T4CConnection cannot be
    cast to oracle.jdbc.OracleConnection

    I haven't been able to reproduce that second issue, though (on Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product). Did you get this my tweaking your maven config?

    Regards,
    Sébastien.

     
  • Bustuila

    Bustuila - 2008-06-08

    Logged In: YES
    user_id=711602
    Originator: YES

    I'm glad the test project was useful, especially since I forgot to put the schema.sql in it...
    I don't run dbunit with the maven plugin in my work project, we're still using ant.
    I just used maven for this example, which indeed works after using the oracle datatype factory...
    I think the problem with the "oracle.jdbc.driver.T4CConnection cannot be cast to oracle.jdbc.OracleConnection" comes from the ant classloader, because I see before that another error:

    [taskdef] log4j:ERROR A "org.apache.log4j.xml.DOMConfigurator" object is not assignable to a "org.apache.log4j.spi.Configurator" variable.
    [taskdef] log4j:ERROR The class "org.apache.log4j.spi.Configurator" was loaded by
    [taskdef] log4j:ERROR [AntClassLoader[...]].
    [taskdef] log4j:ERROR Could not instantiate configurator [org.apache.log4j.xml.DOMConfigurator].

    Another thing... it seems that these newer Oracle drivers are using the standard way of working with lobs:
    http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14249/adlob_api_overview.htm

    "You can make changes to an entire persistent LOB, or to pieces of the beginning, middle, or end of a persistent LOB in Java by means of the JDBC API using the classes:

    oracle.sql.BLOB

    oracle.sql.CLOB

    These classes implement java.sql.Blob and java.sql.Clob interfaces according to the JDBC 3.0 specification, which has methods for LOB modification. They also include legacy Oracle proprietary methods for LOB modification. These legacy methods are marked as deprecated and may be removed in a future release.

    If you use JDK 1.4 or higher, then you can use variables typed java.sql.Blob and java.sql.Clob.

    The JDBC 3.0 methods are included in classes12.jar, so that they can be used in JDK 1.2 or 1.3, but since they are not part of the java.sql.Blob and java.sql.Clob interfaces in those JDK versions, you must use variables typed or cast to oracle.sql.BLOB or oracle.sql.CLOB."

    When using the application with the spring framework and hibernate, it has no problem in inserting and updating lobs with org.springframework.jdbc.support.lob.DefaultLobHandler, so I guess this is another hint that the new drivers are much improved and they can be used with the standard jdbc interfaces.
    I've tried using org.springframework.jdbc.support.lob.OracleLobHandler, but it needs another dependency(NativeJdbcExtractor), so, I was very hapy the default handler worked.

    So, I guess something could be improved in dbunit in detecting in some way that the standard interfaces can be used... spring framework seems to use java.sql.PreparedStatement.setClob(int i, Clob x) and maybe dbunit could do it too...

    And then, I will try to see what I workaround I can find to make ant not screw up things..

    Thanks for your help.

     
  • matthias g

    matthias g - 2008-06-08

    Logged In: YES
    user_id=1803108
    Originator: NO

    Hi Bustuila,

    Thanks a lot for the hints. I think chances are good that your second exception is a classloader issue since the dbunit ant task uses the AntClassLoader to load the db driver class.

    If you have a couple of minutes you could test this as follows:
    - Get dbunit trunk sources from repository
    - Replace one line in the file org.dbunit.ext.oracle.OracleClobDataType#getClob():
    <<<OLD line: Class aClobClass = Class.forName("oracle.sql.CLOB");
    >>>NEW line: Class aClobClass = connection.getClass().getClassLoader().loadClass("oracle.sql.CLOB");
    - Invoke "mvn install" in the dbunit trunk directory

    Then try using the newly created 2.3.0-SNAPSHOT version of dbunit.

    I think you are right in terms of checking and updating the oracle support in dbunit. It would be nice to start a discussion on how to do that (perhaps dbunit could introduce a new Oracle10DataTypeFactory that uses the newer JDBC API with java.sql.CLOB)

    Hope this helps.
    Regards,
    mat

     
  • Bustuila

    Bustuila - 2008-06-24

    Logged In: YES
    user_id=711602
    Originator: YES

    Hello,
    sorry for the long pause.
    It works with this change :-)

    I also had to modify org.dbunit.ant.Operation, to fix a NPE, in toString():

    replace result.append(", src=" + _src == null ? null : _src.getAbsolutePath());
    with result.append(", src=" + _src == null ? "null" : _src.getAbsolutePath());

    Thank you

     
  • matthias g

    matthias g - 2008-08-05

    Logged In: YES
    user_id=1803108
    Originator: NO

    Hi there,

    I committed the change on rev. 773/trunk for the upcoming 2.3.0 release. The change affects OracleNClobDataType/OracleClobDataType/OracleBlobDataType which now load the classes via the JDBC connection's classloader.

    Thanks again and regards,
    mat

     
  • matthias g

    matthias g - 2008-08-05
    • assigned_to: slecallonnec --> gommma
    • status: open --> closed-fixed
     
  • shai o

    shai o - 2008-08-06

    Logged In: YES
    user_id=2169370
    Originator: NO

    i tried the latest build from today
    the clob problem still occures

     
  • Paul P

    Paul P - 2010-03-11

    I am using the latest version of DBUnit (2.4.7), on Oracle 11GR2. I'm using Java 6 (1.6.0_15) and the latest version of Oracle's client jar (jdbc6.jar)

    I've been unable to successfully load any data referenced by a CLOB Oracle field from an XML file into the database.

    I've used all sorts of versions of the Oracle JDBC library / Hibernate library etc...I think the problem lies in DBUnit.
    I've tried: both FlatXmlDataSet and XmlDataset,
    I've tried both OracleDataTypeFactory , Oracle10DataTypeFactory and Oracle11DataTypeFactory found here: https://sourceforge.net/tracker/index.php?func=detail&aid=2010567&group_id=47439&atid=449494

    I'm fairly convinced that its a DBunit problem as reverting all the way down to DBunit 2.2.1 seems to fix the problem. Please let me know if you want any additional info.

    The exception being reported is: * Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to oracle.sql.CLOB

     
  • John MacEnri

    John MacEnri - 2010-05-12

    Hi,
    I also was hitting the same problem with v2.4.7 and latest Oracle JDBC driver. I took the easy way out and built 2.4.7 myself with the one line change shown in this bug, in the org.dbunit.dataset.datatype.ClobDataType.setSqlValue(...) method.
    Works fine now for Oracle CLOBs, but not sure it would work across other databases.

    In the comments there is a mention of the fix being applied to the v3 branch, but that does not seem to have appeared.

    John

     
1 2 > >> (Page 1 of 2)

Log in to post a comment.