Connection properties along with JDBC URL for oracle thin driver - jdbc

How to supply DB connection properties along with JDBC URL when we used Oracle thin driver

Oracle has a very good documentation on that point.
It boils down to:
Create a Properties file, add the connection properties you need and add them into your call to
getConnection(String URL, Properties info);
Given your comment, you could try the following - but I could find no documentation that this connection property is actually available on the thin driver. This document that points to that driver suggests it's part of the deprecated weblogic oracle driver.
Properties p = new Properties();
p.setProperty ("user", youruser);
p.setProperty ("password", yourpass);
p.setProperty("EnableCancelTimeout", "true");
Connection con = DriverManager.getConnection(jdbc:oracle:thin:#<host>:1521:<SID>), p);

Related

Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Invalid Oracle URL specified

I am getting this error when running my spring boot application. It is a CRUD API that I am trying to connect to my table data in SQL developer. I would really appreciate some help.
Application Properties
spring.datasource.url = jdbc:oracle:DIP:#localhost:1521:orcl
spring.datasource.username = DIP
spring.datasource.password = DIP
spring.datasource.driver-class-name = oracle.jdbc.driver.OracleDriver
server.port = 8080
Code That Generated Exception
private EmployeeDAO dao;
#BeforeEach
void setUp() throws Exception {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:oracle:DIP:#localhost:1521:orcl");
dataSource.setUsername("DIP");
dataSource.setPassword("DIP");
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dao = new EmployeeDAO(new JdbcTemplate(dataSource));
}
Oracle Driver System Path Pom.xml
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>2.3.0</version>
<scope>system</scope>
<systemPath>C:/ojdbc8.jar</systemPath>
</dependency>
The connection URL looks odd to me.
The part of the connection URL after jdbc:oracle: specifies which type of Oracle JDBC driver to use, as there's more than one of them. The only possible values this can take are thin, oci (or oci8?) and kprb (according to the Oracle JDBC driver documentation). In your code, you've set this to DIP, which appears to also be the username you are using.
I've never had any need to use kprb (in fact I didn't even know about it until today), and I haven't used oci in years. thin is the type of driver I use most often and would be the type of driver I would recommend you try to use.
Try replacing DIP in your connection URL with thin, i.e. jdbc:oracle:thin:#localhost:1521:orcl.
Note that this URL appears twice in your code, once in your properties file and once in what appears to be a test class. You will presumably need to change it in both.

Is there a way to overcome DSRA9010E "'setReadOnly' is not supported on the WebSphere" exception?

our application is using Spring for TX management and is marking certain transactions as readonly. When deploying our application on websphere (8.5.5.3) with a Oracle JDBC Connection we are getting exceptions like the following:
Caused by: java.sql.SQLException: DSRA9010E: 'setReadOnly' is not supported on the WebSphere java.sql.Connection implementation.
at com.ibm.ws.rsadapter.spi.InternalOracleDataStoreHelper.setReadOnly(InternalOracleDataStoreHelper.java:371)
at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.setReadOnly(WSJdbcConnection.java:3646)
at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.getTargetConnection(LazyConnectionDataSourceProxy.java:410)
at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.invoke(LazyConnectionDataSourceProxy.java:376)
at com.sun.proxy.$Proxy476.getMetaData(Unknown Source)
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:619)
at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:239)
at com.sun.proxy.$Proxy476.getMetaData(Unknown Source)
I know what websphere is trying to tell me but I was wondering if there is a way to disable this check so that Connection.setReadonly calls are just ignored instead of throwing an exception.
Of course I could also change the application to not use readonly transactions but that would be much more complicated.
Try to unwrap the connection object like this:
Context ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup("jdbc/OracleDS");
Connection conn = ds.getConnection();
if (conn.isWrapperFor(oracle.jdbc.OracleConnection.class)) {
// Returns an object that implements the given interface to
// allow access to non-standard methods, or standard methods
// not exposed by the proxy.
oracle.jdbc.OracleConnection oraCon = conn.unwrap(oracle.jdbc.OracleConnection.class);
// Do some Oracle-specific work here.
oraCon.setReadOnly(readOnly);
....
}
conn.close();
See WebSphere Application Server and the JDBC 4.0 Wrapper Pattern
Oracle JDBC (12c onwards; perhaps 11g as well?) can be tricky to use with readonly -
according to https://marschall.github.io/2017/01/28/oracle-read-only.html:
Calling Connection.setReadOnly(true) with the 12c driver no longer establishes a read only transaction
This means that Spring (before version 4.3.7) also struggles to set read only transactions with Oracle JDBC (see previous link).
To overcome this, you need to manually include SET TRANSACTION READ ONLY in your SQL, instead of relying on Spring's #Transactional(readOnly=true).
However, from Spring 4.3.7, the transaction now acts correctly, and so you should no longer see this issue (https://github.com/spring-projects/spring-framework/issues/19774)

websphere datasource connection properties

In websphere 8.5, If I have an XA Datasource with a URL as below
jdbc:oracle:thin:#ip:port:SID
How can I add connection properties related to encoding so that the URL becomes as below:
jdbc:oracle:thin:#ip:port:SID?useUnicode=no&characterEncoding=ISO-8859-1&characterSetResults=ISO-8859-6
Oracle JDBC driver gets user locale and country from JVM, therefore you might try adding the following parameters into JVM arguments (this is an example for locale=Arabic, Country=United Arab Emirates,):
-Duser.language=ar -Duser.country=AE

how to change Java code to access database using JDBC after creating JDBC connection pool in GlassFish?

I'm new to JDBC. I've installed GlassFish 3.1.1 on Centos 6.2 and need to use it with an application that connects to an Oracle 11G database on another server. I've read through the documentation for GlassFish and think I understand how to create a JDBC connection pool as well as a JDBC resource. My question is, how do I use this information when coding the java middle-tier to connect to the database?
Currently (with just GlassFish install and no JDBC configuration), I am relying on the CentOS enviroment variables for java (such as CLASSPATH) to allow the web application to use the JDBC drivers. However, I'm getting the following error:
java.lang.NoClassDefFoundError: oracle/jdbc/pool/OracleDataSource
Thus, my attempt to create a JDBC connection pool and resource in GlassFish (so the app can use the JDBC driver). My java file starts out:
import java.sql.*;
import oracle.jdbc.*;
import oracle.jdbc.pool.OracleDataSource;
class JDBCexample {
public static void main(String args[]) throws SQLException {
Connection conn;
Statement stmt;
ResultSet rset;
String query;
String sqlString;
String person_firstName;
String person_lastName;
String person_email;
int person_salary;
// connect to database
OracleDataSource ds = new OracleDataSource();
ds.setURL("jdbc:oracle:thin:myID/myPWD#192.168.0.1:1521:mySID");
conn = ds.getConnection();
// read something in database
stmt = conn.createStatement();
query = "SELECT first_name, last_name, email, salary FROM HR.Employees where rownum < 6";
rset = stmt.executeQuery(query);
while (rset.next()) {
person_firstName = rset.getString("first_name");
person_lastName = rset.getString("last_name");
person_email = rset.getString("email");
person_salary = rset.getInt("salary");
System.out.format(person_firstName + " " + person_lastName + " " + person_email + " %d%n", person_salary)
}
and so on...
QUESTION: How would I change the above code after I create a JDBC Connection Pool (named: myPool) and a JDBC Resource (named: myDBPool)? If it matters, I'm using Oracle 11.2, CentOS 6.2, GlassFish 3.1.1 with mod_jk and fronted by Apache 2.2 webserver, JDK 1.6. I don't have any clustering or load-balancing.
UPDATE 1: I thought this link was a good reference (see section titled: "Creating a Data Source Instance, Registering with JNDI, and Connecting"). But when I modify the above Java file as follows (just preparing the java file; haven't touched GlassFish yet),
// Add These:
import javax.naming.Context;
import javax.naming.InitialContext;
// Change from this:
// connect to database
OracleDataSource ds = new OracleDataSource();
ds.setURL("jdbc:oracle:thin:myID/myPWD#192.168.0.1:1521:mySID");
conn = ds.getConnection();
// To this:
// connect to database
Context ctext = new InitialContext();
OracleDataSource ds = (OracleDataSource)ctext.lookup("jdbc/myDBPool");
conn = ds.getConnection();
I get the errors:
JitterClass.java:67: unreported exception javax.naming.NamingException; must be caught or declared to be thrown
Context ctext = new InitialContext();
^
JitterClass.java:68: unreported exception javax.naming.NamingException; must be caught or declared to be thrown
OracleDataSource ds = (OracleDataSource)ctext.lookup("jdbc/myDBPool");
^
UPDATE 2: I cleared those compile errors using cyril's comments below (to throw all exceptions). Then I created JDBC Connection Pool and JDBC Resource, and the Ping was successful. So then I run the application from the client and observe the following error:
java.lang.ClassCastException : com.sun.gjc.spi.jdbc40.DataSource40 cannot be cast to oracle.jdbc.pool.OracleDataSource
At this point, if I add an include javax.sql.DataSource to the program, and change this line:
OracleDataSource ds = (OracleDataSource)ctext.lookup("jdbc/myDBPool");
to become this line:
DataSource ds = (DataSource)ctext.lookup("jdbc/myDBPool");
it compiles without errors. But now I'm confused... aren't we supposed to be using OracleDataSource here? Or, does GlassFish somehow implement OracleDataSource since I do see a setting for this connection pool for Datasource Classname set to oracle.jdbc.pool.OracleDataSource (?). Hoping someone can explain this.
Do pings on your connection pool work?
If not, check your pool configuration w/ http://docs.oracle.com/cd/E18930_01/html/821-2416/beamw.html#beanh
Once pings work and the JDBC Resource is configured, you should be able to access it in your app code through JNDI:
InitialContext context = new InitialContext();
DataSource ds = (DataSource) context.lookup("jdbc/myDBPool"); // or whatever name you used when creating the resource
conn = ds.getConnection();
Hope it helps,
RESPONSE TO UPDATE 1:
That's just the compiler telling you to formally catch or declare a checked exception which may be thrown by JNDI.
For testing purposes, the easiest way out of this (and future errors like this) is to just widen your method signature to throw all exceptions, i.e.:
public static void main(String args[]) throws /*SQL*/Exception {
RESPONSE TO UPDATE 2:
There's no reason to cast JDBC interfaces down to Oracle implementations unless you need to access any custom feature not specified in the JDBC spec. The purpose of a DataSource is to be a factory for Connections, whose API is defined in the JDBC interface, so that should be all you need. When you define a connection pool and resource in GlassFish, the app server is adding value by wrapping the JDBC driver classes and proxying them seamlessly for you as long as you stick to import java.sql.*. No need for oracle imports :) The main advantage being that if you ever decide to switch to MySQL or some other data store later on, your code is then portable and doesn't need any change.
To add to cyril's good answer:
Instead of the JNDI lookup, you can also use Resource Injection to set up your DataSource:
#Resource(name = "jdbc/Your_DB_Res")
private DataSource ds;
On startup, the application server will then inject the JDBC ressource. This section of Java EE Tutorial has more on that matter.
By using resource injection, you can reduce the amount of boilerplate code. This article introduces the concepts.
Besides adding the driver to your classpath, you should try adding the appserv-rt.jar file to your project's build path (the jar is located in Glassfish's lib directory). If you don't want to include all the other jars you should first create a library containing the appserv-rt jar and then add it to your project's build path.

How to use HSQLDB as a datasource in Websphere Application Server?

I try to set up a local development infrastructure and I want to use HSQLDB as a datasource with my WAS 6.1. I already know that I have to use Apache DBCP to get a connection pooling, but I'm stuck when my application tries to get the first connection.
What I've done
In WAS I created a JDBC provider with the class org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS and removed everything from the classpath input field. Then I put commons-dbcp.jar, commons-pool.jar and hsqldb.jar in MYAPPSERVERDIRECTORY/lib/ext.
Then I created a new datasource with that provider. I added the following custom properties:
driver=org.hsqldb.jdbc.JDBCDriver
url=jdbc:hsqldb:file:///C:/mydatabase.db;shutdown=true
user=SA
password=
My Problem
When I run my application and the first connection to the database is made, I get the following exception:
---- Begin backtrace for Nested Throwables
java.sql.SQLException: No suitable driverDSRA0010E: SQL-Status = 08001, Fehlercode = 0
at java.sql.DriverManager.getConnection(DriverManager.java:592)
at java.sql.DriverManager.getConnection(DriverManager.java:196)
at org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS.getPooledConnection(DriverAdapterCPDS.java:205)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper$1.run(InternalGenericDataStoreHelper.java:918)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper.getPooledConnection(InternalGenericDataStoreHelper.java:955)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.getPooledConnection(WSRdbDataSource.java:1437)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.createManagedConnection(WSManagedConnectionFactoryImpl.java:1089)
at com.ibm.ejs.j2c.FreePool.createManagedConnectionWithMCWrapper(FreePool.java:1837)
at com.ibm.ejs.j2c.FreePool.createOrWaitForConnection(FreePool.java:1568)
at com.ibm.ejs.j2c.PoolManager.reserve(PoolManager.java:2338)
at com.ibm.ejs.j2c.ConnectionManager.allocateMCWrapper(ConnectionManager.java:909)
at com.ibm.ejs.j2c.ConnectionManager.allocateConnection(ConnectionManager.java:599)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:439)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:408)
Any tips on this? I suspect I'm using a wrong class from hsqldb, or maybe my JDBC url is wrong...
In the example given in BDCP docs, the org.hsqldb.jdbcDriver class is used as the driver. The org.hsqldb.jdbc.JDBCDriver is supported only in HSQLDB 2.x, but the other class is supported by all versions of HSQLDB.

Resources