Getting "ORA-01017: invalid username/password; logon denied" when trying to create a data source in Tomcat 6 - oracle

Been pulling my hair trying to set up a data source in in Tomcat for an application. The steps I've taken are
Create a META-INF/context.xml with the following content
<Context>
<Resource name="jdbc/mydb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#gpqa6.myserver.com:1526:gpqa6"
username="foo"
password="foobar"
maxActive="20"
maxIdle="30"
maxWait="-1" />
</Context>
Enter the following text in WEB-INF/web.xml
<resource-ref>
<description>Datasource</description>
<res-ref-name>jdbc/mydb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Using it in the code
public class MyServlet extends HttpServlet {
private DataSource ds;
public void init() {
try {
Context ctx = new InitialContext();
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mydb");
} catch (NamingException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//this is where the exception is thrown
Connection conn = ds.getConnection();
//...do stuff with the connection
}
But keep on getting the following error
"Encounter exception during mapping. Error: Cannot create PoolableConnectionFactory (ORA-01017: invalid username/password; logon denied
)
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (ORA-01017: invalid username/password; logon denied"
I know that the username and password are correct. Because the following code works
Class.forName("oracle.jdbc.OracleDriver").newInstance();
conn = DriverManager.getConnection(
"jdbc:oracle:thin:#gpqa6.myserver.com:1526:gpqa6", "foo", "foobar");
I've even tried to enter an invalid url but still get the same error. What's going on???
Also, does Tomcat have some way of testing the data source similar to WebLogic or Glassfish?

Now it's working. Seem like after I establish a connection with the following code
Class.forName("oracle.jdbc.OracleDriver").newInstance();
conn = DriverManager.getConnection(
"jdbc:oracle:thin:#gpqa6.myserver.com:1526:gpqa6", "foo", "foobar");
then switching back to using the data source, it's fine. Maybe it's a caching issue?
--Update--
It is a caching issue. Ijust have to delete the \conf\Catalina folder.
This link really helped.
http://pwu-developer.blogspot.com/2010/02/why-isnt-my-datasource-configuration.html

Related

Tomcat servlet configure JNDI

Good day, respective all!
My environment:
Tomcat 8.5 under windows 64-bit
All needed jars are placed into $CATALINA_HOME/lib
It is my first attempt to write servlet using ConnectionPool.
After "googling"I made an entry inside $CATALINA_HOME/conf/server.xml:
<context docbase="msgsend" path="/msgsend" reloadable="true">
<context docbase="ssr" path="/ssr" reloadable="true">
<Resource
name="jdbc/OrServlet"
auth="Container"
type="javax.sql.DataSource"
user="STERN"
username="STERN"
password="pwdxxx"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:STERN/pwdxxx#XEPDB1"
/>
</context>
I included following into WEb-INF/web.xml:
<resource-ref>
<description>just a test</description>
<res-ref-name>jdbc/OrServlet</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
When I try to connect to Oracle in traditional way:
try {
cn = DriverManager.getConnection(
"jdbc:oracle:thin:#XEPDB1", "STERN", "pwdxx");
}
catch (Exception e) { }
everything works fine.
But when I try to connect through context:
Connection cn = null;
DataSource ds = null;
try
{
Context initCtx = new InitialContext();
Context envCtx = (Context)initCtx.lookup("java:comp/env");
ds = (DataSource)envCtx.lookup("jdbc/OrServlet");
cn = ds.getConnection();
}
catch(NamingException n) {}
catch(SQLException s) {out.println(ds.getClass().getName()+" exception "+s);
;}
I get :
**exception java.sql.SQLException: Cannot create JDBC driver of class '' for connect URL 'null'**
and ds.getClass().getName() in exception handler returns:
org.apache.tomcat.dbcp.dbcp2.BasicDataSource
which is distinct from javax.sql.DataSource as declared in
and .
And it seems to me that ds = (DataSource)envCtx.lookup("jdbc/OrServlet")
doesn't wvwn try to look inside Resource section.
What I missed?
Any help will be very appreciated.
Regards,
Andrew.

Need Clarification on configuration of Oracle UCP

Requirement : Create a multi-tenant Application which should insert each tenants data into their respective PDBs based on the tenant id in the request. In other words each tenant or customer will have there own PDB in a CDB, all PDBs will have the same schema and based on then tenant Id in the request a datasource will be selected and the data would be inserted into that PDB.
Stack - spring boot 2.3.0.RELEASE, Oracle 18c, Connection pool - Oracle shared universal connection pool
UCP connection :
<ucp-properties>
<connection-pool
connection-pool-name="pool1"
connection-factory-class-name="oracle.jdbc.pool.OracleDataSource"
url="jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(HOST=localhost)(PORT=1521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=orcl.accounts.intern)))"
user="C##commonuser"
password="commonuser"
initial-pool-size="10"
min-pool-size="5"
max-pool-size="20"
connection-repurpose-threshold="13"
sql-for-validate-connection="select 1 from dual"
shared="true"
>
<connection-property name="oracle.jdbc.ReadTimeout" value="2000"/>
<connection-property name="oracle.net.OUTBOUND_CONNECT_TIMEOUT" value="2000"/>
<data-source data-source-name="pdbcust1" service="pdbcust1.accounts.intern" user="cust1" password="password"/>
<data-source data-source-name="pdbcust2" service="pdbcust2.accounts.intern" user="cust2" password="password"/>
</connection-pool>
</ucp-properties>
Spring datasource config class :
#Bean
public DataSource dataSource() throws SQLException {
System.setProperty("oracle.ucp.jdbc.xmlConfigFile", "file:/" + dbConfigProperties.getUcpConfigFile());
final AbstractRoutingDataSource dataSource = new MultitenantRoutingDataSource();
targetDataSources = new ConcurrentHashMap<>();
final PoolDataSource tenantDataSource1 = getTenantDataSource("pdbcust1", "cust1", "password");
final PoolDataSource tenantDataSource2 = getTenantDataSource("pdbcust2", "cust2", "password");
targetDataSources.put("pdbcust1", tenantDataSource1 );
targetDataSources.put("pdbcust2", tenantDataSource2 );
dataSource.setDefaultTargetDataSource(lTenantDataSource2);
lDataSource.setTargetDataSources(lTargetDataSources);
lDataSource.afterPropertiesSet();
return lDataSource;
}
private static PoolDataSource getTenantDataSource(final String tenantId, String username, String password) {
try {
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource(tenantId);
Properties prop = new Properties();
// prop.setProperty("user", username);
// prop.setProperty("password", password);
//pds.reconfigureDataSource(prop);
return pds;
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
Above configuration does not work and throws the following error when I fire a request with a tenant id :
java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:509) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:461) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1104) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:550) ~[ojdbc8-19.3.0.0.jar:19.3.0.
However if I uncomment the following lines in the above class and remove the username and password from the UCP file, it works:
prop.setProperty("user", username);
prop.setProperty("password", password);
pds.reconfigureDataSource(prop);
So my questions are :
Why does this happen?
The UCP config xmls xsd has a user and password field, how do we use it?
This page describes share pooling https://docs.oracle.com/middleware/12213/wls/JDBCA/shared_pooling_ds.htm#JDBCA-GUID-4B7DA858-327E-4CEA-A68C-376792D4A466
This has line : "This common user must exist in all PDBs that are connected to the sharing data sources"
What does it mean?
In order to use ucp shared pool feature, the database user must be same for all the datasources sharing a common pool of connection. So you should not use user and password under datasource element.
<data-source data-source-name="pdbcust1" service="pdbcust1.accounts.intern" />
<data-source data-source-name="pdbcust2" service="pdbcust2.accounts.intern"/>
If you have a requirement to use a different user for each pdb then shared pool is not an option. In that case you should define two different pools in the XML, one for each PDB, that means you should not set the shared=true in connection-pool element. Also, for non shared pools there is no need of using a common user at pool level, you can directly use pdb user, password and service name under pool element.
<ucp-properties>
<connection-pool
connection-pool-name="pool1"
connection-factory-class-name="oracle.jdbc.pool.OracleDataSource"
url="jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(HOST=localhost)(PORT=1521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=cust1.accounts.intern)))"
user="cust1"
password="cust1password"
initial-pool-size="10"
min-pool-size="5"
max-pool-size="20"
sql-for-validate-connection="select 1 from dual"
>
<connection-property name="oracle.jdbc.ReadTimeout" value="2000"/>
<connection-property name="oracle.net.OUTBOUND_CONNECT_TIMEOUT" value="2000"/>
<data-source data-source-name="pdbcust1" />
</connection-pool>
<connection-pool
connection-pool-name="pool2"
connection-factory-class-name="oracle.jdbc.pool.OracleDataSource"
url="jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(HOST=localhost)(PORT=1521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=pdbcust2.accounts.intern)))"
user="cust2"
password="cust2password"
initial-pool-size="10"
min-pool-size="5"
max-pool-size="20"
sql-for-validate-connection="select 1 from dual"
>
<connection-property name="oracle.jdbc.ReadTimeout" value="2000"/>
<connection-property name="oracle.net.OUTBOUND_CONNECT_TIMEOUT" value="2000"/>
<data-source data-source-name="pdbcust2" />
</connection-pool>
</ucp-properties>

JSR-352 with Liberty Profile - 'ORA-01002: fetch out of sequence'

I am experimenting with the JSR-352 implementation in the Liberty Profile and have been stumped by an 'ORA-01002: fetch out of sequence' error after my reader processes the first 10 items of my JDBC ResultSet. My chunk size is set to 100.
Here is my reader:
#Dependent
#Named("myItemReader")
public class MyItemReader extends AbstractItemReader {
#Resource(name="jdbc/somedb",shareable=false)
private DataSource lavDb;
private PreparedStatement stmt;
private ResultSet rs;
#Override
public void open(Serializable checkpoint) throws Exception {
Connection con = lavDb.getConnection();
con.setAutoCommit(false);
stmt = con.prepareStatement("select id from sometable",
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery();
}
#Override
public MyInputRecord readItem() throws Exception{
if(rs.next()){
return new MyInputRecord(rs.getInt(1));
}
return null;
}
#Override
public void close(){
try{
rs.close();
stmt.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
If the ResultSet processing occurs in the open() method then I do not encounter any errors.
Here is my batchPersistence configuration from my server.xml:
<dataSource id="oracle-wasadmin" jdbcDriverRef="wasoracledriver" jndiName="jdbc/wasoracledb" type="javax.sql.XADataSource">
<properties.oracle URL="${wasadmin.jdbcurl}" password="xxxxxx" user="yyyyyy"/>
<conionManager agedTimeout="1m" maxIdleTime="15m" maxPoolSize="25" minPoolSize="0"/>
</dataSource>
<jdbcDriver id="wasoracledriver" javax.sql.XADataSource="oracle.jdbc.xa.client.OracleXADataSource">
<library>
<fileset dir="${shared.resource.dir}/oracle" includes="*.jar"/>
</library>
</jdbcDriver>
Here is the error in the joblog:
com.ibm.jbatch.container.exception.BatchContainerRuntimeException: Failure in Read-Process-Write Loop
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeChunk(ChunkStepControllerImpl.java:702)
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeCoreStep(ChunkStepControllerImpl.java:792)
at com.ibm.jbatch.container.controller.impl.BaseStepControllerImpl.execute(BaseStepControllerImpl.java:292)
at com.ibm.jbatch.container.controller.impl.ExecutionTransitioner.doExecutionLoop(ExecutionTransitioner.java:118)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.executeCoreTransitionLoop(WorkUnitThreadControllerImpl.java:94)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.executeWorkUnit(WorkUnitThreadControllerImpl.java:155)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl$AbstractControllerHelper.runExecutionOnThread(WorkUnitThreadControllerImpl.java:480)
at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.runExecutionOnThread(WorkUnitThreadControllerImpl.java:90)
at com.ibm.jbatch.container.util.BatchWorkUnit.run(BatchWorkUnit.java:117)
at com.ibm.ws.context.service.serializable.ContextualRunnable.run(ContextualRunnable.java:80)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.sql.SQLException: ORA-01002: fetch out of sequence
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.readItem(ChunkStepControllerImpl.java:354)
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.readAndProcess(ChunkStepControllerImpl.java:245)
at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeChunk(ChunkStepControllerImpl.java:626)
... 14 more
Caused by: java.sql.SQLException: ORA-01002: fetch out of sequence
I have additional logs, etc, if they would be helpful. Thanks in advance.
Don't cache JDBC Statement or ResultSet instances across threads. The JDBC programming model does not support multi-threaded access, which is likely why you are running into this error. And also why it works fine from within the open method, which runs on a single thread. When using JDBC, it is okay to cache DataSource, but not Connection or anything beneath Connection. Let the application server manage pooling of Connections and Statements, which it does in a thread safe way.

Liferay portlet non-liferay JNDI data source null

For a Liferay 6.2 custom portlet accessing a non liferay Oracle database we are running into an issue where the data source returned is null.
We have configured the tomcat/conf/context.xml
<!-- Adding custom New non liferay datasource -->
<Resource name="jdbc/NewPool"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = dbservernameorip)(PORT = 9999))
(CONNECT_DATA = (SERVER = DEDICATED)
(SERVICE_NAME = dbSIDorservicename)))"
username="user"
password="pwd"
maxActive="35"
maxIdle="10"
maxWait="20000"
removeAbandoned="true"
logAbandoned="true"
minEvictableIdleTimeMillis="3600000"
timeBetweenEvictionRunsMillis="1800000"
testOnBorrow="true"
testOnReturn="false"
/>
The portlet web.xml contains:
<resource-ref>
<description>Oracle Datasource example</description>
<res-ref-name>jdbc/NewPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
The code for lookup is:
String JNDI = "jdbc/NewPool"
_log.debug("JNDI Name is: " + JNDI);
_log.debug("dataSource in dbConnect is :" + dataSource);
Context context = new InitialContext();
Context envContext = (Context)context.lookup("java:/comp/env");
_log.debug("envContext in dbConnect is :" + envContext);
try {
DataSource ds = (DataSource)envContext.lookup(JNDI);
Liferay can use the context.xml resource with a similar data source for the Liferay Oracle database successfully.
Is some other wiring needed for Liferay portlet to establish a connection to another database?
The same portlet code works on weblogic without the web.xml change. Similar JNDI data source lookup code and configuration works on vanilla tomcat (without liferay) and a plain war (non liferay portlet) file.
Update:
I have checked db connections on the server with netstat -an|grep dbport. this does not show an established connection.
I have also tried setting the portal.security.manager.strategy=none in portal-ext.properties. This did not work either.
Any insight is much appreciated as we are kind of stuck here.
Thanks!
I just stumbled over this thread in the Liferay Forum which basically says. oput this in your tomcat/conf/server.xml
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
<Resource name="jdbc/XXX" auth="Container" type="javax.sql.DataSource"
maxActive="20" maxIdle="10" maxWait="5000"
removeAbandoned="true" removeAbandonedTimeout="250" validationQuery="SELECT 1"
username="user2" password="pwd2"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/myOtherDb"/>
and this in your context.xml:
<ResourceLink name="jdbc/XXX" global="jdbc/XXX" type="javax.sql.DataSource">
It should do the trick. If you really asking WHY Liferay can find the jndi resource, but not your portlet:
I have no clue...
We also had some problems using the resource and pools. Since we have very few requests to handle and performance were not a concern for our scenario we used a JDBC connection directly without a pool and it's working fine (we are connecting to a MS Sql server)
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String url = "jdbc:jtds:sqlserver://host/dbname";
String driver = "net.sourceforge.jtds.jdbc.Driver";
String db_userName = PropsUtil.get("jdbc.default.username");
String db_password = PropsUtil.get("jdbc.default.password");
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, db_userName, db_password);
String sql = "SELECT * FROM Users";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
while(rs.next()){
// DO WHAT YOU WANT
return true;
}
rs.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
conn.close();
}catch(SQLException se){
}// do nothing
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try
And it's working fine. Username and password are configured in portal-ext.properties (We are using the same account used for liferay own db)
Hope this helps
I believe we found our issue. It seems like it was a typo.
All references to dataSource need to be changed to ds. There was a code changed. It turned out the the variable name was not changed to ds in code after the ds variable was declared during troubleshooting the issue.
String JNDI = "jdbc/NewPool"
_log.debug("JNDI Name is: " + JNDI);
_log.debug("dataSource in dbConnect is :" + ds);
Context context = new InitialContext();
Context envContext = (Context)context.lookup("java:/comp/env");
_log.debug("envContext in dbConnect is :" + envContext);
try {
DataSource ds = (DataSource)envContext.lookup(JNDI);
_log.debug("dataSource in dbConnect is :" + ds)
We need to test this out. I will post the results after the final test.

Configure DB Connection Pooling - Axis2 webservice

I'd like to know how to modify the server.xml file so all my webservices built on axis2 can talk to the DB using Connection Pooling. Each webservice has a different data source, one points to one instance of the DB and the other to another DB server. How do I specify the context that should be used by each service?
Thanks in advance,
Pojo
If you want to use connection pool in your project , Ensure that you have the following code set up for the Tomcat connection pooling to work in context.xml file:
1)Create file with name "context.xml" if it's not exist under directory "WebContent/META-INF/context.xml" with the following content:
For My Project , Please modify it with appropriate value :
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/dbcp" docBase="dbcp">
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
removeAbandoned="true" removeAbandonedTimeout="30" maxActive="80"
maxIdle="30" maxWait="10000" username="sontn" password="nhantien"
driverClassName="org.postgresql.Driver"
url = "jdbc:postgresql://localhost/group8" useUnicode="true"
characterEncoding="utf-8" characterSetResults="utf8"/>
</Context>
Or you can copy file : context.xml into directory "$Catalian\webapps\axis2\META-INF"
How can you get connection pool?
In your webservice method : create method getConnection() with following content:
public Connection getConnection() {
Connection connection = null;
try {
Context envCtx = (Context) new InitialContext().lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
connection = ds.getConnection();
}
catch (Exception e) {
System.out.println("Connection error: " + e.getMessage());
}
return connection;
}
Thanks

Resources