I try to connect a web application which runs on a tomcat 8 to an oracle database. Both of them run as Docker containers:
docker-compose.yml:
version: "3"
services:
appweb:
build: ./app
image: "servlet-search-app:0.1"
ports:
- "8888:8080"
links:
- appdb
environment:
- DATA_SOURCE_NAME="jdbc:oracle:thin:#appdb:1521/XE"
appdb:
build: ./db
image: "servlet-search-db:0.1"
ports:
- "49160:22"
- "1521:1521"
- "8889:8080"
Dockerfile of my oracle DB image (build: ./db):
FROM wnameless/oracle-xe-11g
ADD createUser.sql /docker-entrypoint-initdb.d/
ENV ORACLE_ALLOW_REMOTE=true
Dockerfile of the tomcat image (build: ./app)
FROM tomcat:8.0.20-jre8
COPY servlet.war /usr/local/tomcat/webapps/
COPY ojdbc14-1.0.jar /usr/local/tomcat/lib/
So the app starts up as expected but throws an exception when trying to connect to the database:
java.lang.IllegalStateException: java.sql.SQLException: Io exception: Invalid connection string format, a valid format is: "host:port:sid"
org.se.lab.ui.ControllerServlet.createConnection(ControllerServlet.java:115)
org.se.lab.ui.ControllerServlet.handleSearch(ControllerServlet.java:78)
org.se.lab.ui.ControllerServlet.doPost(ControllerServlet.java:53)
org.se.lab.ui.ControllerServlet.doGet(ControllerServlet.java:38)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Now the issue seems obvious, however when I fix the DATA_SOURCE_NAME string to:
DATA_SOURCE_NAME="jdbc:oracle:thin:#appdb:1521:XE"
I get the following exception:
java.lang.IllegalStateException: java.sql.SQLException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
The Connection descriptor used by the client was:
appdb:1521:XE"
org.se.lab.ui.ControllerServlet.createConnection(ControllerServlet.java:115)
org.se.lab.ui.ControllerServlet.handleSearch(ControllerServlet.java:78)
org.se.lab.ui.ControllerServlet.doPost(ControllerServlet.java:53)
org.se.lab.ui.ControllerServlet.doGet(ControllerServlet.java:38)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Now I tried to find out which one of them should actually work. Thus, I started only the DB container:
docker build -t dbtest .
docker run -it -d --rm -p 1521:1521 --name dbtest dbtest
docker inspect dbtest | grep IPAddress
>> "IPAddress": "172.17.0.4"
Next, I try to connect with sqlplus:
sqlplus system/oracle#172.17.0.4:1521/XE # works
sqlplus system/oracle#172.17.0.4:1521:XE #ERROR: ORA-12545: Connect failed because target host or object does not exist
So what's the problem? Due to the link in the docker-compose file, the tomcat container can resolve "appdb" to the container's IP.
Here's the code which should establish the connection:
protected Connection createConnection() {
String datasource = System.getenv("DATA_SOURCE_NAME");
try {
// debug
InetAddress address = null;
try {
address = InetAddress.getByName("appdb");
System.out.println(address); // resolves in appdb/10.0.0.2
System.out.println(address.getHostAddress()); // resolves in 10.0.0.2
} catch (UnknownHostException e) {
e.printStackTrace();
}
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection(datasource, "system", "oracle");
} catch (SQLException | ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
Lastly here's the tnsnames.ora file:
cat $ORACLE_HOME/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File:
XE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = fcffb044d69d)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)
Thanks!
The oracle default listener resolved the configured host to the wrong IP address:
vim $ORACLE_HOME/network/admin/listener.ora:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0/xe)
(PROGRAM = extproc)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE))
(ADDRESS = (PROTOCOL = TCP)(HOST = f4c4a3638c11)(PORT = 1521))
)
)
DEFAULT_SERVICE_LISTENER = (XE)
The HOST value is the Docker container id. If we look at /etc/hosts it is set up correctly for the service link in the docker-compose link:
10.0.0.5 f4c4a3638c11
It gets also resolved correctly from the tomcat container
ping f4c4a3638c11
PING f4c4a3638c11 (10.0.0.5): 56 data bytes
...
If I try to connect with an IP address of the other interface, which is the docker interface from the host system, the connection from the web application to the database works
String datasource = "jdbc:oracle:thin:#172.17.0.4:1521:XE";
So the solution is to configure the listener to listen to the correct IP address
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.5)(PORT = 1521))
Now this connection string works:
jdbc:oracle:thin:#appdb:1521:XE
I will report this behavior to wnameless/oracle-xe-11g as a bug
Sorry, this is not a definitive answer. Let's treat it as long comment :)
Your setup is quite complex for me to recreate however your error message is intriguing:
The Connection descriptor used by the client was:
appdb:1521:XE"
...
It looks like the environment value was chopped to appdb:1521:XE. How about if you try hard-coding:
String datasource = "jdbc:oracle:thin:#appdb:1521/XE";
If that works, then probably need to somehow escape your docker DATA_SOURCE_NAME environment variable.
I could be completely wrong but I think it is worth a try.
Related
I have a docker compose file:
version: '3.3'
services:
bifrost:
image: ivorytoast3853/bifrost
container_name: bifrost-app
ports:
- "8084:8084"
thor:
image: ivorytoast3853/thor
container_name: thor-app
ports:
- "8085:8084"
loki:
image: ivorytoast3853/loki
container_name: loki-app
ports:
- "8086:8084"
Which is meant to test a ZeroMQ app.
Bifrost: Broker
Thor: Server
Loki: Client
I am using the exact code from ZeroMQ's start guide (and when I start it locally -- without Docker it works (Loki sends messages to Thor through the Bifrost)).
For reference, the 3 files are:
LOKI
try (ZContext context = new ZContext()) {
ZMQ.Socket requester = context.createSocket(SocketType.REQ);
boolean didConnect = requester.connect("tcp://0.0.0.0:5559");
log.info("Loki connected to the bifrost: " + didConnect);
for (int request_nbr = 0; request_nbr < 10; request_nbr++) {
requester.send("One", 0);
String reply = requester.recvStr(0);
System.out.println("Received reply " + request_nbr + " [" + reply + "]");
}
}
Thor
try (ZContext context = new ZContext()) {
ZMQ.Socket responder = context.createSocket(SocketType.REP);
boolean didConnect = responder.connect("tcp://0.0.0.0:5560");
log.info("Thor connected to the bifrost: " + didConnect);
while (!Thread.currentThread().isInterrupted()) {
String string = responder.recvStr(0);
System.out.printf("Received request: [%s]\n", string);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
responder.send("You sent me: " + string);
}
}
Bifrost
while (true) {
try (ZContext context = new ZContext()) {
ZMQ.Socket frontend = context.createSocket(SocketType.ROUTER);
ZMQ.Socket backend = context.createSocket(SocketType.DEALER);
frontend.bind("tcp://*:5559");
backend.bind("tcp://*:5560");
log.info("Started Bifrost to connect Loki and Thor");
ZMQ.Poller items = context.createPoller(2);
items.register(frontend, ZMQ.Poller.POLLIN);
items.register(backend, ZMQ.Poller.POLLIN);
boolean more = false;
byte[] message;
while (!Thread.currentThread().isInterrupted()) {
items.poll();
if (items.pollin(0)) {
while (true) {
message = frontend.recv(0);
more = frontend.hasReceiveMore();
backend.send(message, more ? ZMQ.SNDMORE : 0);
if (!more) {
break;
}
}
}
if (items.pollin(1)) {
while (true) {
message = backend.recv(0);
more = backend.hasReceiveMore();
frontend.send(message, more ? ZMQ.SNDMORE : 0);
if (!more) {
break;
}
}
}
}
}
}
Am I doing something wrong with the Docker compose file? I know Docker compose creates a network automatically...
Thanks!
Turns out I was not internalizing fundamental ideas of docker and containers as a whole.
The Problem
I was trying to connect to: "tcp://0.0.0.0:5560" from Loki/Thor to Bifrost.
Why is that a problem?
It is a problem because unlike starting all 3 spring boot applications on the same computer (with the same IP), I am starting each spring application in its OWN docker container -- which has its OWN UNIQUE IP. Therefore, I cannot say to Loki/Thor to "on this computer (IP), connect to Bifrost." -- since Bifrost lies on a completely separate IP address.
How did I fix it:
I changed the docker-compose file for Bifrost to contain a network alias:
image: ivorytoast3853/bifrost
container_name: bifrost-app
networks:
my-net:
aliases:
- queue
All this does is allow me to say, "if I give you the hostname of "queue", please connect to the IP address of the container that the Bifrost application is found on."
Then, all I had to do is change the host:port string in Loki and Thor to reflect the following:
responder.connect("tcp://queue:5560");
Hope this helps anyone who comes across a similar issue (or lack of understanding in my case)
<Edited>
I'm an intermediate Java programmer currently working with Java and MySQL to create an app. I'm using Xampp and the PHPMYAdmin that comes with it.
The server is on 127.0.0.1 without any routers,Wifi systems or network.My app is also on 127.0.0.1
Everytime I try to connect to MySQL using Java, this message is displayed:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link
failure The last packet sent successfully to the server was 0 milliseconds
ago.The driver has not received any packets from the server.
But the MySQL server is running alright. When I log into PHPMYAdmin, these
errors are shown:
#2002 - Only one usage of each socket address (protocol/network
address/port)
is normally permitted.
— The server is not responding (or the local server's socket is not
correctly configured).
mysqli_real_connect(): (HY000/2002): Only one usage of each socket
address
(protocol/network address/port) is normally permitted.
Connection for controluser as defined in your configuration failed.
mysqli_real_connect(): (HY000/2002): Only one usage of each socket
address
(protocol/network address/port) is normally permitted.
Retry to connect
Warning in .\libraries\dbi\DBIMysqli.php#629
mysqli_real_escape_string() expects parameter 1 to be mysqli, boolean
given
Backtrace
.\libraries\dbi\DBIMysqli.php#629: mysqli_real_escape_string(
boolean false,
string 'root',
)
.\libraries\DatabaseInterface.php#2670: PMA\libraries\dbi\DBIMysqli-
>escapeString(
boolean false,
string 'root',
)
.\libraries\Menu.php#142: PMA\libraries\DatabaseInterface-
>escapeString(string 'root')
.\libraries\Menu.php#110: PMA\libraries\Menu->_getAllowedTabs(string
'server')
.\libraries\Menu.php#83: PMA\libraries\Menu->_getMenu()
.\libraries\Response.php#316: PMA\libraries\Menu->getHash()
.\libraries\Response.php#441: PMA\libraries\Response->_ajaxResponse()
PMA\libraries\Response::response()
Warning in .\libraries\dbi\DBIMysqli.php#629
mysqli_real_escape_string() expects parameter 1 to be mysqli, boolean
given
Backtrace
.\libraries\dbi\DBIMysqli.php#629: mysqli_real_escape_string(
boolean false,
string 'root',
)
.\libraries\DatabaseInterface.php#2670: PMA\libraries\dbi\DBIMysqli-
>escapeString(
boolean false,
string 'root',
)
.\libraries\Menu.php#142: PMA\libraries\DatabaseInterface-
>escapeString(string
'root')
.\libraries\Menu.php#110: PMA\libraries\Menu->_getAllowedTabs(string
'server')
.\libraries\Menu.php#71: PMA\libraries\Menu->_getMenu()
.\libraries\Response.php#327: PMA\libraries\Menu->getDisplay()
.\libraries\Response.php#441: PMA\libraries\Response->_ajaxResponse()
PMA\libraries\Response::response()
the mysql my.ini file:
[mysqld]
port= 3306
socket = "E:/xampp/mysql/mysql.sock"
basedir = "E:/xampp/mysql"
tmpdir = "E:/xampp/tmp"
datadir = "E:/xampp/mysql/data"
pid_file = "mysql.pid"
# enable-named-pipe
key_buffer = 16M
max_allowed_packet = 1M
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
log_error = "mysql_error.log"
plugin_dir = "E:/xampp/mysql/lib/plugin/"
innodb_data_home_dir = "E:/xampp/mysql/data"
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = "E:/xampp/mysql/data"
innodb_buffer_pool_size = 16M
innodb_additional_mem_pool_size = 2M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
[isamchk]
key_buffer = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[myisamchk]
key_buffer = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
And heres how I connect to Java:
try{
Class.forName("java.sql.DriverManager");
Connection conn=
(Connection)DriverManager.getConnection("jdbc:mysql://
localhost:3306/","root","mypassword");
Statement stmt=(Statement)conn.createStatement();
}
catch(Exception e){/*handling*/}
I am facing a problem connecting my java application to an oracle database using oracle wallet as password store.
To isolate the problem I made a small Main class as follow:
public static void main(String[] args) {
Connection conn;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
System.setProperty("oracle.net.tns_admin", "c:\\tns");
OracleDataSource ds = new OracleDataSource();
Properties props = new Properties();
System.setProperty("oracle.net.wallet_location", "c:/wallet2");
ds.setConnectionProperties(props);
ds.setURL("jdbc:oracle:thin:/#XE2");
Provider p;
p = new OraclePKIProvider();
Security.insertProviderAt(p, 3);
conn = ds.getConnection();
} catch (SQLException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
in the directory c:\tns I've the following files:
sqlnet.ora
tnsnames.ora
this is the listing for sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES = (NTS)
names.directory_path = TNSNAMES
SQLNET.WALLET_OVERRIDE = TRUE
#WALLET_LOCATION = (SOURCE=(METHOD=FILE)METHOD_DATA=(DIRECTORY=c:\wallet))
WALLET_LOCATION = (SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=c:/wallet)))
that for the tnsnames
...
XE2 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
In c:\wallet2 there are the following files:
cwallet.sso
ewallet.p12
the file was previously generated with orapki and there is my entry named XE2 with the correct credential. When I run the code I get the following exception
Could not open wallet. java.io.IOException: Could not open wallet. Check password
enabling the oracle trace I can see these lines:
mar 02, 2017 3:57:00 PM oracle.jdbc.driver.DatabaseError findMessage
TRACE_30: Enter: "ORA-17168", java.io.IOException: Could not open wallet. java.io.IOException: Could not open wallet. Check password
mar 02, 2017 3:57:00 PM oracle.jdbc.driver.Message11 msg
TRACE_30: 72B6CBCC Enter: "ORA-17168", java.io.IOException: Could not open wallet. java.io.IOException: Could not open wallet. Check password
mar 02, 2017 3:57:00 PM oracle.jdbc.driver.Message11 msg
TRACE_30: 72B6CBCC Exit [0.066509ms]
and
mar 02, 2017 3:57:00 PM oracle.jdbc.driver.PhysicalConnection getSecretStoreCredentials
GRAVE: Throwing SQLException: 168java.io.IOException: Could not open wallet. java.io.IOException: Could not open wallet. Check password
Anyone can help me?
Thanks for reading.
r.
This is very old topic .
-TNS_ADMIN should point to the wallet location ( C:\wallet2 )
-in tnsnames.ora wallet_location is C:\wallet2 not c:/walet as you have
I think that your ewallet.p12 file is protected by password.
You need do setup the oracle.net.wallet_password property with the password:
System.setProperty("oracle.net.wallet_password", "PASSWORD");
If the password is specified, the driver looks for the p12 file, otherwise it uses the sso file.
SQLNET.AUTHENTICATION_SERVICES = (NTS)
That should that be TNS instead of NTS.
This question already has answers here:
java.lang.NoClassDefFoundError: com/google/common/util/concurrent/FutureFallback
(4 answers)
Closed 6 years ago.
I am trying to connect to cassandra using Java (Hadoop2), but it is throwing the below error
Connecting to IP Address 127.0.0.1:9042...
16/04/12 10:35:13 INFO core.NettyUtil: Found Netty's native epoll transport in the classpath, using it
Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.util.concurrent.Futures.withFallback(Lcom/google/common /util/concurrent/ListenableFuture;Lcom/google/common/util/concurrent /FutureFallback;Ljava/util/concurrent/Executor;)Lcom/google/common/util/concurrent/ListenableFuture;
at com.datastax.driver.core.Connection.initAsync(Connection.java:177)
at com.datastax.driver.core.Connection$Factory.open(Connection.java:731)
at com.datastax.driver.core.ControlConnection.tryConnect(ControlConnection.java:251)
at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:199)
at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:77)
at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1414)
at com.datastax.driver.core.Cluster.getMetadata(Cluster.java:393)
at cassandra.CassandraConnector.connect(CassandraConnector.java:42)
at cassandra.Main.main(Main.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.main(RunJar.java:212)
Please see the cassandra environment details::
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.5 | CQL spec 3.3.1 | Native protocol v4]
Jars i am using::
cassandra-driver-core-3.0.0.jar
guava-19.0.jar
netty-all-4.1.0.CR7.jar
I have tried other jars( guava >=16.01 ,netty-all-4.0...,cassandra-driver-core-2.2.0). but always it is throwing more or less similar error.
please see below the code snippet used for establishing connection:
public void connect(final String node, final int port)
{
this.cluster = Cluster.builder().addContactPoint(node).withPort(port)
.build();
final Metadata metadata = cluster.getMetadata();
ProtocolVersion myCurrentVersion = cluster.getConfiguration()
.getProtocolOptions()
.getProtocolVersion();
System.out.println(myCurrentVersion);
out.printf("Connected to cluster: %s\n", metadata.getClusterName());
for (final Host host : metadata.getAllHosts())
{
out.printf("Datacenter: %s; Host: %s; Rack: %s\n",
host.getDatacenter(), host.getAddress(), host.getRack());
}
session = cluster.connect();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
final CassandraConnector client = new CassandraConnector();
final String ipAddress = args.length > 0 ? args[0] : "127.0.0.1";
final int port = args.length > 1 ? Integer.parseInt(args[1]) : 9042;
out.println("Connecting to IP Address " + ipAddress + ":" + port + "...");
client.connect(ipAddress, port);
client.close();
}
I think it might be because of some version conflict, but unable to find the correct version.
Have checked some other similar posts and tried the solutions (using different jars) but could not resolve the issue
Any help will be highly appreciated.
Yes.You are correct.This issue occurs due to the version conflict.
I will recommend you to use guava Jar and remove other unnecessary Jars.
Also please have a look at this answer, it might help you.
I have a requirement for my java application to connect to an Oracle database (10 and 11g) using the Oracle wallet for the DB credentials.
My issue is when connecting trying to connect to the database i get:
java.sql.SQLException: could not resolve the connect identifier "mydb".
sqlnet.ora looks like the following:
AUTOMATIC_IPC = OFF
TRACE_LEVEL_CLIENT = OFF
names.directory_path = (TNSNAMES)
names.default_domain = world
names.default_zone = world
WALLET_LOCATION =
(SOURCE =
(METHOD = FILE)
(METHOD_DATA =
(DIRECTORY = <wallet location C:....>)
)
)
SQLNET.WALLET_OVERRIDE = TRUE
SSL_CLIENT_AUTHENTICATION = FALSESSL_VERSION = 0
And my tnsnames.ora entry looks like:
mydb.WORLD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP) (Host = <HOST>)
(Port = <PORT>))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = <DB_SERVICES>)
(INSTANCE_NAME = mydb)
)
)
and my wallet entry is setup as follows:
mkstore -wrl C:\oracle\wallet -createCredential mydb username "password"
Java application connection string as follows:
jdbc:oracle:thin:/#mydb
Now the connection works if the .world is removed from the entry in tnsnames.ora, but from my understanding that is what the names.default_domain = world should pass to the tnsnames.ora lookup, is that correct? if so then why isn't this being set?
I can connect to sqlplus in dos fine by using sqlplus /#mydb
Thanks