Runtime exception while creating Blob - java

Trying to create BLOB object using BLOB.createTemporary(connection, false, BLOB.DURATION_SESSION) ,But getting Class Cast Exception
java.lang.ClassCastException:
org.apache.commons.dbcp.cpdsadapter.ConnectionImpl cannot be cast to
oracle.jdbc.OracleConnection.
I tried following suggestions but still same error .Apache Commons DBCP connection object problem, Thread: ClassCastException in org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
Some one please suggest me to resolve this issue.

The Oracle BLOB.createTemporary() method expects the Connection parameter to be a oracle.jdbc.OracleConnection object, but connections from Tomcat are managed by DBCP, so the connection is wrapped in a DBCP class (org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper).
You either need to unwrap it to get the real Oracle connection object, or stop using the Oracle BLOB.
Just use the JDBC methods: Blob blob = connection.createBlob()
Update
The JDBC Blob is an interface. There are no implementing classes in the JDK, so you'll always get a DBMS specific implementation. If needed, you can cast to OracleBlob, which is also an interface, that provides additional Oracle-specific methods.
Interesting javadoc for OracleBlob:
Generally any new code should avoid the direct use of the class BLOB. For variable declarations use the interface Blob or this interface as required. Instead of the static methods BLOB.createTemporary(java.sql.Connection, boolean, int) and BLOB.empty_lob() please use Connection.createBlob() and BLOB.getEmptyBLOB() respectively.

Related

"SQLException: Unwrap error" with JDBI and PGJDBC-NG Postgres Driver

I'm using JDBI to connect to my Postgres db. This has been working fine. Today I decided to try replacing the native Postgres driver with PGJDBC-NG driver. Everything is fine until I try my first simple query:
jdbi.useExtension(FooDao.class, dao -> {
dao.insert(e);
});
This unfortunately results in:
org.jdbi.v3.core.ConnectionException: java.sql.SQLException: Unwrap error
Debugging into the app I find the exception occurs in the customizeHandle method of JDBI's PostgresPlugin class:
#Override
public Handle customizeHandle(Handle handle) {
PGConnection pgConnection = Unchecked.supplier(() -> handle.getConnection().unwrap(PGConnection.class)).get();
return handle.configure(PostgresTypes.class, pt -> pt.addTypesToConnection(pgConnection));
}
The exception is thrown on the first line, in the unwrap method. The problem it seems is that with the new driver, getConnection returns an instance of PGDirectConnection, which is not assignable from PGConnection, as the unwrap method call specifies.
Is there a work-around for this? I'm thinking I could just extend PostgresPlugin and override the implementation of customizeHandle to unwrap using PGDirectConnection but I'd prefer not to if possible.
Edit: Ugh, can't override customizeHandle because PostgresTypes.addTypesToConnection isn't public.
The PostgresPlugin JDBI is querying for PGConnection directly; which is a class only available in the standard driver. So until it's altered to work with NG, it won't.
Although, according to the docs...
The plugin configures mappings for the Java 8 java.time types like Instant or Duration, InetAddress, UUID, typed enums, and hstore.
but none of this is necessary because PGJDBC-NG supports all of these types natively!
Solution
Don't use the PostgresPlugin

How can I map a PostgreSQL varchar[] (array column) to a List<String> in Java using Hibernate?

I have a column in PostgreSQL 9.6 of type "character varying[]" which is essentially an array of strings. I am using Dropwizard with Hibernate to handle the database connection. Normally I just need to provide an annotation to define the data type, however, Hibernate is complaining about the deserialization of a varchar[] type. How do I map this to a List in Java?
I have tried implement my own UserType extended class to handle the (de)serialization with no luck. Any help would be most appreciated.
UPDATE:
I took a look at this link posted by #Waqas and I was able to at least create a type that extends UserType to implement the mapping of varchar[] to String[] in Java.
Some differences in my implementation:
In the nullSafeSet() and nullSafeGet() methods that need to be implemented (#Override), I had to use a (newer?) class called SharedSessionContractImplementor from org.hibernate.engine.spi instead of the (older?) class SessionImplementor.
When I implemented this change and added the #Type annotation to my column mapping (in my entity data class) my runtime was complaining about an #Override that apparently wasn't valid for a certain HibernateBundle class (error below). Even though maven built the jar without any issues and I only have Java 1.8 installed on my machine (OpenSuse). P.S. I am using Dropwizard 1.2 and I took the declaration of the HibernateBundle straight from their documentation. Nevertheless, I deleted the #Override annotation and it works now. Not sure why, or how, but it does.
Error as promised:
INFO [2017-11-08 22:39:06,220] org.eclipse.jetty.util.log: Logging initialized #1137ms to org.eclipse.jetty.util.log.Slf4jLog
INFO [2017-11-08 22:39:06,310] io.dropwizard.server.DefaultServerFactory: Registering jersey handler with root path prefix: /
INFO [2017-11-08 22:39:06,312] io.dropwizard.server.DefaultServerFactory: Registering admin handler with root path prefix: /
java.lang.Error: Unresolved compilation problem:
The method getDataSourceFactory(ApplicationConfiguration) of type new HibernateBundle<ApplicationConfiguration>(){} must override a superclass method
at com.tksoft.food.Application$1.getDataSourceFactory(Application.java:24)
at com.tksoft.food.Application$1.getDataSourceFactory(Application.java:1)
at io.dropwizard.hibernate.HibernateBundle.run(HibernateBundle.java:61)
at io.dropwizard.hibernate.HibernateBundle.run(HibernateBundle.java:15)
at io.dropwizard.setup.Bootstrap.run(Bootstrap.java:200)
at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:42)
at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:85)
at io.dropwizard.cli.Cli.run(Cli.java:75)
at io.dropwizard.Application.run(Application.java:93)
at com.tksoft.food.Application.main(Application.java:30)
Any way, this has left me super confused, but it is working so I am happy :) (for now). I just have to figure out if I can map it to a List instead of an array :/

Java JMS to access database

I have having this problem with Java JMS when I am sending a queue to other systems and also planning to access the database to store some pictures.
I am facing this error with the compiler:
reference to connection is ambiguous,both interface
java.sql.Connection in java.sql and interface and interface javax.jms
Connection in javax.jms match Connection connection = null;
It should be quite a simple tweak to the code but I am not sure how. Any ideas?
You have to user the fully qualified class name, that is, java.sql.Connection or javax.jms.Connection. Otherwise the compiler doesn't know which connection interface you are referring to.

Unable to use multiple ebean databases in Play 2

We are setting up a slightly complicated project using Play Framework 2.0.3.
We need to access several databases (pre-existing) and would like to do it using the frameworks built-in facilities (ie. EBean).
We tried to create all model classes within the "models" package, and then map each class with its FQN to the corresponding EBean property in the application.conf:
ebean.firstDB="models.ClassA,models.ClassB,models.ClassC"
ebean.secondDB="models.ClassD"
ebean.thirdDB="models.ClassE,models.ClassF"
This doesn't seem to work:
PersistenceException: Error with [models.SomeClass] It has not been enhanced but it's superClass [class play.db.ebean.Model] is? (You are not allowed to mix enhancement in a single inheritance hierarchy) marker[play.db.ebean.Model] className[models.SomeClass]
We checked and re-checked and the configuration is OK!
We then tried to use a different Java package for each database model classes and map them accordingly in the application.conf:
ebean.firstDB = "packageA.*"
ebean.secondDB = "packageB.*"
ebean.thirdDB = "packageC.*"
This works fine when reading information from the database, but when you try to save/update objects we get:
PersistenceException: The default EbeanServer has not been defined? This is normally set via the ebean.datasource.default property. Otherwise it should be registered programatically via registerServer()
Any ideas?
Thanks!
Ricardo
You have to specify in your query which database you want to access.
For example, if you want to retrieve all users from your secondDB :
// Get access to your secondDB
EbeanServer secondDB = Ebean.getServer("secondDB");
// Get all users in secondDB
List<User> userList = secondDB.find(User.class).findList();
When using save(), delete(), update() or refresh(), you have to specify the Ebean server, for instance for the save() method:
classA.save("firstDB");
I have encounter the same problem and waste a whole day to investigate into it,finally I have got it.
1.define named eabean server
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost:3306/db1"
db.default.user=root
db.default.password=123456
db.aux.driver=com.mysql.jdbc.Driver
db.aux.url="jdbc:mysql://localhost:3306/db2"
db.aux.user=root
db.aux.password=123456
now you have two ebean server [default] and [aux] at run time.
2.app conf file
ebean.default="models.*"
ebean.aux= "secondary.*"
Now entiies under package models.* configured to [default] server and entities under package secondary.* configured to [aux] server. I think this may related to java class enhancement or something. You don't need to separate Entities into different packages, but if entities of different ebean servers are under same package, it may cause weird trouble and exceptions.
When using you model, save/delete/update related method should add server name as parameter
Student s = new Student(); s.save("aux");
When use finder,you should define your finder as
public static Finder find = new Finder("aux",Long.class,Student.class);
Might not be the same case, I ran to this SomeClass not enhanced PersistenceException with Play 2.1.0,
and only what was missing was a public declaration in SomeClass model class that I had forgotten..
In Play 2.1.0 the error message was a little different:
PersistenceException: java.lang.IllegalStateException: Class [class play.db.ebean.Model] is enhanced and [class models.Address] is not - (you can not mix!!)
This solved my issue with saving to my db table and resolving the error:
"javax.persistence.PersistenceException: The default EbeanServer has not been defined ? This is normally set via the ebean.datasource.default property. Otherwise it should be registered programatically via registerServer()"

Is the DriverManager concept in JDBC based on the provider design pattern

In JDBC we use the
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
method to load the object in memory. Then when we use the DriverManager class to get a connection to the Sql Server, the DriverManager automatically uses the appropriate drivers from the set of drivers loaded in memory. Can the DriverManager concept be compared with the Provider design pattern used in .net ? If not, then what exactly do we mean by
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
method and why don't we create the object of the sql server driver class using the new keyword ?
Class.forName("XXXDriver") invokes static block of XXXDriver.
Usually the static block invokes DriverManager.registerDriver(new XXXDriver()) to register itself to DriverManager.
Something like:
public class XXXDriver implements Driver{
static{
//Be invoked by Class.forName("XXXDriver")
DriverManager.registerDriver(new XXXDriver())
}
...
}
Unfortunately I don't know about the provider pattern in .Net. But here is what that Class.forName() magic is for.
You don't instantiate the class via newInstance(). forName() is enough. (Ok, I see the reason for instance creation in BalusC's answer.)
The JDBC specification mandates that every JDBC driver registers itself with DriverManager.registerDriver(). This is done via a static block that gets executed when the class is loaded. Class loading is initiated via Class.forName().

Categories