How to solve the jboss + oracle problem: "the network adapter could not stablish the connection"? - oracle

I'm using Oracle 10.2.0.4 server and we are testing Java Application Servers in order to chose the most appropriate for our needs. So far we managed to get OpenEJB and GlassFish working, but not JBoss.
We have a simple fat Java client connecting to a simple EJB 3.0 (stateless session bean), which in turn, tries to perform a simple SQL query using an oracle data source. This same setup has already worked with Apache's OpenEJB and Sun's Glashfish. However, we couldn't make it work with either Jboss 5.1.0.GA or Jboss-6.0.0.20100721-M4 (the latest milestone).
Jboss deploys the EJB without errors and the EJB can indeed be reached by the client. However, when the EJB tries to get a connection from the Oracle data source it fails with:
11:04:34,837 INFO [STDOUT] oracleDS=org.jboss.resource.adapter.jdbc.WrapperDataSource#63d587bf
11:04:45,110 WARN [org.jboss.resource.connectionmanager.JBossManagedConnectionPool] Throwable while attempting to get a new connection: null: org.jboss.resource.JBossResourceException: Could not create connection; - nested throwable: (java.sql.SQLException: I/O Exception: The Network Adapter could not establish the connection)
at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:225) [:6.0.0.20100721-M4]
at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.createManagedConnection(LocalManagedConnectionFactory.java:195) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.createConnectionEventListener(InternalManagedConnectionPool.java:643) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.getConnection(InternalManagedConnectionPool.java:267) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.JBossManagedConnectionPool$BasePool.getConnection(JBossManagedConnectionPool.java:747) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.BaseConnectionManager2.getManagedConnection(BaseConnectionManager2.java:403) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.TxConnectionManager.getManagedConnection(TxConnectionManager.java:413) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:496) [:6.0.0.20100721-M4]
at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941) [:6.0.0.20100721-M4]
at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) [:6.0.0.20100721-M4]
at test.ejb.Business.getResults(Business.java:184) [:]
The data source configuration file oracle-ds.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>oracleDS</jndi-name>
<connection-url>jdbc:oracle:thin:#192.168.10.20:1521:ODB</connection-url>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<user-name>myusername</user-name>
<password>mypassword</password>
<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
<metadata>
<type-mapping>Oracle9i</type-mapping>
</metadata>
<min-pool-size>0</min-pool-size>
<max-pool-size>20</max-pool-size>
<idle-timeout-minutes>0</idle-timeout-minutes>
</local-tx-datasource>
</datasources>
The relevant parts of the EJB are:
#Stateless
public class Business implements BusinessRemote {
#Resource(name = "oracleDS",mappedName="java:oracleDS")
private DataSource oracleDS;
public String validateEJB(String value) {
return value + "ok";
}
public String[] getResults() {
String[] result = null;
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
//Fails here
con = oracleDS.getConnection();
I have already played with different values for the #Resource tag, different Oracle JDBC drivers (currently we are using ojdbc14.jar and orai18n.jar. The connection works either directly or through OpenEJB.
Does anybody have a hint of what might be wrong?
Thanks

The problem lies on an invisible versionning conflict of the drivers. You have to make absolutely sure that both oracle JARs come from the same version and also that there are no other Oracle JARs in the CLASSPATH.

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.

IIB is not finding the jdbc driver

I have created a JDBCProvider service in an IBM integration bus (IIB v10) in Windows called TESTDDBB, which is also the name of the database. I have a JavaCompute node where I'm trying to generate a connection to call an oracle function
TESTDDBB
connectionUrlFormat='jdbc:oracle:thin:#x.x.x.x:1521:TESTDDBB;'
connectionUrlFormatAttr1=''
connectionUrlFormatAttr2=''
connectionUrlFormatAttr3=''
connectionUrlFormatAttr4=''
connectionUrlFormatAttr5=''
databaseName='TESTDDBB'
databaseSchemaNames='PROM'
databaseType='Oracle'
databaseVersion='11.2.0.4.0'
description='default_Description'
environmentParms='default_none'
jarsURL='C:\jdbc\lib'
jdbcProviderXASupport='true'
maxConnectionPoolSize='200'
portNumber='1521'
securityIdentity='devCredentials'
serverName='x.x.x.x'
type4DatasourceClassName='oracle.jdbc.xa.client.OracleXADataSource'
type4DriverClassName='oracle.jdbc.OracleDriver'
useDeployedJars='true'
public class GetUserData_JavaCompute extends MbJavaComputeNode {
public void evaluate(MbMessageAssembly inAssembly) throws MbException {
...
Connection conn = getJDBCType4Connection("TESTDDBB",JDBC_TransactionType.MB_TRANSACTION_AUTO);
try(CallableStatement callableStmt = conn.prepareCall("{ ? = call PROM.pkg_prop_2.getUserData(?)}");) {
...
}
...
}
}
The problem is that when IIB tried to get the conenction, it isn't finding the datasource java class
...
com.ibm.broker.jdbctype4.jdbcdbasemgr.JDBCType4Connection#-53d4c850.createXAConnection 'java.lang.ClassNotFoundException: oracle.jdbc.xa.client.OracleXADataSource at java.net.URLClassLoader.findClass(URLClassLoader.java:609) at com.ibm.broker.classloading.JavaResourceClassLoader.findClass(JavaResourceClassLoader.java:181) at com.ibm.broker.classloading.SharedClassLoader.findClass(SharedClassLoader.java:215) at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:925)
...
I have the ojdbc6.jar driver in the folder C:\jdbc\lib and deployed in a shared library in the integration server, library that is referenced by the RESTAPI app that contains the JavaCompute node. What am I missing? I have tried using useDeployedJars true and false, and jarsURL also with 'C:\jdbc\lib\ojdbc6' without success. Where are the common libraries of the integration server in windows?
From one side you can place the jar to root of you java source folder and connect this jar to Integration Toolkit. This give you ability to use this jar. From other side you can configure JDBC provider for Integration node and use created alias in getJDBCType4Connection call. More information about working with databases from JavaCompute you can see here 1

EJB3 & Websphere Application Server 7: NoClassDefFoundError on Remote EJB

I have been trying all day to connect to a Remote EJB on a Websphere Application Server 7. This configuration is necessary for project specific reasons. Its goal is to connect two applications together that are on independent EAR but on the same server.
I have been trying to access a dummy method that does not have any parameters.
The lookup URL is the one copied from the EJB deployment on my local server and it complies with EJB3.0 IBM specifications according to the information here.
I have seen several other posts on stackoverflow related to EJB Remote issues in WAS (but I cannot link all threads because of my user limitations) but they do not resolve or are not the same as my problem.
Local EJB invocation works fine.
Here is the implementation. I do not use any specific IBM WAS libraries in the imports:
The class that is connecting to the Remote EJB:
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL, "iiop://localhost:2809");
Context ctx = new InitialContext(env);
Object object = ctx.lookup("ejb/<component-id>#<package.qualified.interface>");
RemoteInterface interface = (RemoteInterface)javax.rmi.PortableRemoteObject.narrow(object, RemoteInterface.class);
String sResponse = (String)interface.dummy();
The definition of the remote interface is:
#Remote
public interface RemoteInterface {
public String dummy() throws Exception;
}
And my implementation is:
#Override
public String dummy() throws Exception {
return "string";
}
Environment information:
Websphere Application Server 7
JDK 1.6
EJB 3.0
EAR 5.0
Maybe someone can give me some pointers on what to do next.

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.

JBoss JDBC MBean Prevent Startup If Server Not Found

During JBoss startup I have a Persistence Manager that depends on a JDBC connection (DefaultDS). The JDBC connection starts fine whether or not it can actually connect to the database so when the Persistence Manager starts it thinks it has a connection. Then it blows up because it cannot connect to the database and never starts. This prevents my DestinationManager from starting and causes all kinds of headache.
Is there a way to make MBeans that depend on the JDBC connection not start unless the JDBC connection can actually connect to the database? As an alternative, is there a way to make the JDBC connection depend on an MBean that is only active while the database can be connected to?
tl;dr; All I need is for my MBeans/DestinationManager to wait until the database (DefaultDS) is available before booting.
Please comment if you need more info about the enviornment.
JBoss version 4.2.3
Database: MsSql
If I understand the issue correctly, you're having a problem because even though the DefaultDS data source reports that it has started, since it has not acquired any connections, you don't necessarily know that connections can be made .
Unfortunately, even with the prefill option enabled, the datasource service will still start normally even if it cannot make a connection.
Your best bet is to implement a ServiceMBean that checks an actual connection from the datasource before it reports being started. For this example, we'll call it org.bob.ConnChecker and will deployed using the ObjectName org.bob:service=ConnChecker.
Your deployment descriptor should look something like this:
<mbean code="org.bob.ConnChecker" name="jboss.mq:service=DestinationManager">
<depends optional-attribute-name="DataSource">jboss.jca:name=DefaultDS,service=ManagedConnectionPool</depends>
</mbean>
So your service will not be started until the data source has started. Your service will not start unless it can get a connection. Now you just have to add org.bob:service=ConnChecker as a dependency of the DestinationManager:
jboss.mq:service=MessageCache
jboss.mq:service=PersistenceManager
jboss.mq:service=StateManager
jboss.mq:service=ThreadPool
jboss:service=Naming
org.bob:service=ConnChecker
The code for ConnChecker will look something like this:
....
import org.jboss.system.ServiceMBeanSupport;
....
public class ConnChecker extends ServiceMBeanSupport implements ConnCheckerMBean {
/** The ObjectName of the data source */
protected ObjectName dataSourceObjectName = null;
/** The Datasource reference */
protected DataSource dataSource = null;
/**
* Called by JBoss when the dataSource has started
* #throws Exception This will happen if the dataSource cannot provide a connection
* #see org.jboss.system.ServiceMBeanSupport#startService()
*/
public void startService() throws Exception {
Connection conn = null;
try {
// Get the JNDI name from the DataSource Pool MBean
String jndiName = (String)server.getAttribute(dataSourceObjectName, "PoolJndiName");
// Get a ref to the DataSource from JNDI
lookupDataSource(jndiName);
// Try getting a connection
conn = dataSource.getConnection();
// If we get here, we successfully got a connection and this service will report being Started
} finally {
if(conn!=null) try { conn.close(); } catch (Exception e) {}
}
}
/**
* Configures the service's DataSource ObjectName
* #param dataSourceObjectName The ObjectName of the connection pool
*/
public void setDataSource(ObjectName dataSourceObjectName) {
this.dataSourceObjectName = dataSourceObjectName;
}
/**
* Acquires a reference to the data source from JNDI
* #param jndiName The JNDI binding name of the data source
* #throws NamingException
*/
protected void lookupDataSource(String jndiName) throws NamingException {
dataSource = (DataSource)new InitialContext().lookup(jndiName);
}
}
The code for ConnCheckerMBean looks like this:
....
import org.jboss.system.ServiceMBeanSupport;
....
public interface ConnCheckerMBean extends ServiceMBean {
public void setDataSource(ObjectName dataSourceObjectName);
}
So you will still get errors if connections cannot be made to the database, but the DestinationManager will not start, and hopefully that will be better than the headaches you're having now.
So there is no way to have a bunch of beans just "waiting" and still
allow Jboss to boot all the way up?
Not in any standard fashion. The JBoss boot cycle either runs through to completion or reports a dependency failure. The process is sequential and single-threaded (until JBoss 7).
What you could do (and I only briefly tested this) is:
Re-implement the ConnChecker to run its connection test in a separate thread. It will be considered started as soon as that thread is spawned.
Pull out all the XML config files for services you want to depend on ConnChecker (I guess this would be all JMS deployment XML) files into another directory outside of deploy, say for example /jboss/server/bob/late-deploy.
Since the late-service files are now not in the URLDeploymentScanner's list of paths, they will not be deployed as part of the default deployment process.
The trick to getting the late-service files to deploy is that your new ConnChecker will happily spin, waiting to get a connection (and might possibly timeout and stop right there) but when it does successfully acquire a connection, it will execute code that looks like this:
import javax.management.*;
.....
// The JBoss URL Deployment Scanner MBean ObjectName
ObjectName on = new ObjectName("jboss.deployment:flavor=URL,type=DeploymentScanner");
// server is the JBossMBean server. ServiceMBeans automatically have this reference.
server.invoke(on, "addURL", new Object[]{new URL("file:/jboss/server/bob/late-deploy")}, new String[]{String.class.getName});
So what this does is tell the deployment scanner "start looking in this directory too" and a couple of seconds later, your late-services will deploy, hopefully error free. Additionally, since you added the late-service at runtime (and therefore non-persistently), when the server restarts, the deployment scanner will be reverted back to it's original configuration, waiting for ConnChecker to add new URLs to it.
Just make sure that the deployer has ScanEnabled set to true and that the ScanPeriod is low enough that you get the required response time to deploy your late-services once the JDBC connection is made. That MBean configuration is in
<jboss-home>/server/<server-name>/conf/jboss-service.xml
Look for this:
<mbean code="org.jboss.deployment.scanner.URLDeploymentScanner"
name="jboss.deployment:type=DeploymentScanner,flavor=URL">
....
<!-- Frequency in milliseconds to rescan the URLs for changes -->
<attribute name="ScanPeriod">5000</attribute>
<!-- A flag to disable the scans -->
<attribute name="ScanEnabled">true</attribute>
....
</mbean>

Resources