Este es un escenario curioso: tienes un programa en java que se conecta a una base de datos Oracle usando direcciones IP, pero no se puede conectar a la base de datos aún si usas exactamente la misma cadena de conexión en tnsnames y puedes conectarte a esa base de datos usando el cliente SQL/Plus.
Pero empecemos desde el principio, cuando no tienes ningún problema (porque el nombre del servidor de bases de datos Oracle tiene un nombre de dominio calificado y se puede resolver):
Como puedes ver, hay tres diferentes cadenas de conexión definidas en este archivo tnsnames: una con un FQDN como conexión dedicada, una con una dirección IP como conexión compartida, y la última con una dirección IP como conexión dedicada. Ahora pruebas el nombre del servidor e intentas conectarte usando estos tres servicios:
Todo estuvo bien como se esperaba, y aún este diminuto y util programa de prueba de java está trabajando:
Pero que pasa cuando el nombre del servidor ya no se puede resolver? Como cuando se comentan las líneas de nameserver en /etc/resolv.conf:
Como se esperaba, la primer cadena de conexión que usa el nombre del servidor no esta funcionando, pero las otras dos que usan direcciones IP aún funcionan. Por lo tanto, el programa de java tiene que funcionar también, correcto?
Ese no es el caso. De acuerdo a la nota de Metalink de Oracle 139775.1, cuando tratas de conectarte a un servicio de Oracle por medio de una conexión dedicada usando java, la cadena de conexión tiene direcciones IP en lugar de nombres de dominio calificados, y esas direcciones IP no se pueden resolver en la máquina cliente, obtendrás un mensaje de error Network Adapter Could not Establish Connection, aún si desde ese cliente puedes alcanzar la base de datos usando un cliente SQL/Plus. En este ejemplo el mensaje de error es diferente, supongo que porque estoy usando Oracle 10g XE.
Más información:
Io exception: The Network Adapter could not establish the connection
NL Exception trying to connect to 10g RAC w/JDBC
Pero empecemos desde el principio, cuando no tienes ningún problema (porque el nombre del servidor de bases de datos Oracle tiene un nombre de dominio calificado y se puede resolver):
oracle@test:~$ cd $ORACLE_HOME/network/admin
oracle@test:~/app/oracle/product/10.2.0/server/network/admin$ cat tnsnames.ora
# tnsnames.ora Network Configuration File:
XE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = hera.localdomain)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
XE2 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.108.76)(PORT = 1521))
(CONNECT_DATA =
(SERVER = SHARED)
(SERVICE_NAME = XE)
)
)
XE3 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.108.76)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
Como puedes ver, hay tres diferentes cadenas de conexión definidas en este archivo tnsnames: una con un FQDN como conexión dedicada, una con una dirección IP como conexión compartida, y la última con una dirección IP como conexión dedicada. Ahora pruebas el nombre del servidor e intentas conectarte usando estos tres servicios:
oracle@test:~$ ping hera
PING hera.localdomain (192.168.108.76) 56(84) bytes of data.
64 bytes from hera.localdomain (192.168.108.76): icmp_req=1 ttl=64 time=8.34 ms
64 bytes from hera.localdomain (192.168.108.76): icmp_req=2 ttl=64 time=3.58 ms
--- hera.localdomain ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 3.589/5.964/8.340/2.376 ms
oracle@test:~$ sqlplus hr/hr@xe
SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 15:44:16 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
oracle@test:~$ sqlplus hr/hr@xe2
SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 15:44:21 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
oracle@test:~$ sqlplus hr/hr@xe3
SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 15:44:26 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Todo estuvo bien como se esperaba, y aún este diminuto y util programa de prueba de java está trabajando:
oracle@test:~$ cat OracleJdbcExample.java |grep jdbc
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.108.76)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)))";
oracle@test:~$ javac -g OracleJdbcExample.java
oracle@test:~$ export CLASSPATH=$CLASSPATH:/usr/lib/oracle/MyJDBC/ojdbc6.jar
oracle@test:~$ java OracleJdbcExample
Current Date from Oracle : 2013-05-15 16:06:08
done
Pero que pasa cuando el nombre del servidor ya no se puede resolver? Como cuando se comentan las líneas de nameserver en /etc/resolv.conf:
oracle@test:/etc# ping hera
ping: unknown host hera
oracle@test:~$ sqlplus hr/hr@xe
SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 16:02:25 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
ERROR:
ORA-12560: TNS:protocol adapter error
Enter user-name:
oracle@test:~$ sqlplus hr/hr@xe2
SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 16:02:44 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
oracle@test:~$ sqlplus hr/hr@xe3
SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 16:02:50 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Como se esperaba, la primer cadena de conexión que usa el nombre del servidor no esta funcionando, pero las otras dos que usan direcciones IP aún funcionan. Por lo tanto, el programa de java tiene que funcionar también, correcto?
oracle@test:~$ java OracleJdbcExample
Exception in thread "main" java.sql.SQLRecoverableException: IO Error: Connection reset
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:421)
at oracle.jdbc.driver.PhysicalConnection.(PhysicalConnection.java:531)
at oracle.jdbc.driver.T4CConnection.(T4CConnection.java:221)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:503)
at java.sql.DriverManager.getConnection(DriverManager.java:582)
at java.sql.DriverManager.getConnection(DriverManager.java:154)
at OracleJdbcExample.main(OracleJdbcExample.java:25)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:96)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at oracle.net.ns.DataPacket.send(DataPacket.java:199)
at oracle.net.ns.NetOutputStream.flush(NetOutputStream.java:211)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:227)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:175)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:100)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:85)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:122)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:78)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1179)
at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1155)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:279)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:366)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:752)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:359)
... 7 more
Ese no es el caso. De acuerdo a la nota de Metalink de Oracle 139775.1, cuando tratas de conectarte a un servicio de Oracle por medio de una conexión dedicada usando java, la cadena de conexión tiene direcciones IP en lugar de nombres de dominio calificados, y esas direcciones IP no se pueden resolver en la máquina cliente, obtendrás un mensaje de error Network Adapter Could not Establish Connection, aún si desde ese cliente puedes alcanzar la base de datos usando un cliente SQL/Plus. En este ejemplo el mensaje de error es diferente, supongo que porque estoy usando Oracle 10g XE.
Más información:
Io exception: The Network Adapter could not establish the connection
NL Exception trying to connect to 10g RAC w/JDBC