Accessing attributes of resource from context.xml in program - java

Is there a way in java to access the values of the resource tag given in the context.xml from the program?
<Context ...>
...
<Resource name="jdbc/EmployeeDB" auth="Container"
type="javax.sql.DataSource" username="dbusername" password="dbpassword"
driverClassName="org.hsql.jdbcDriver" url="jdbc:HypersonicSQL:database"
maxActive="8" maxIdle="4"/>
...
</Context>
I know that we can get the the datasource the following way:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)
envCtx.lookup("jdbc/EmployeeDB");
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();
But is there a way to print the userName and password in the program that i give in the resource tag?

You can try to cast it to actual implementation of the resource (print out the name with .getClass().getName()) and use the methods provided there. For example tomcat's BasicDataSource has getPassword getUser methods.

Related

JNDI Lookup with Resource annotation always NULL

I've got a WebApp with Tomcat 10, Java11 using Jersey3.
I defined a ConnectionPool in my context.xml for handling the connection to my OracleDB and now I'm trying to access the DataSource within my controller through a #Resource annotation. This should invoke a JNDI-lookup. Unfortunately, I always get a NPE as it seems not to find the resource while running... What am I doing wrong? Or what would the correct mappedName / lookup be?
#Path("/data")
public class DataController {
#Context
ServletContext context;
#Resource(lookup = "java:/jdbc/myDB") //also tried java:/comp/env/jdbc/myDB and mappedName="jdbc/myDB"
protected DataSource ds; //always null
<Context name="myapp">
<Resource type="javax.sql.DataSource"
name="jdbc/myDB"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#//localhost:1521/orcl"
username="xy"
password="xy"/>
According to the tutorials, a ref-link is optional when I define the resource directly in the context.xml.
Thanks for any input!
This link is about jboss, but would seem relevant to you too. It says that according to the specification, Resource annotation to do JNDI lookups would only work with EJBs, so it wouldn't work for your case.
A workaround is to do the programmatic way to see if your datasource is working:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource bean = (DataSource ) envCtx.lookup("jdbc/myDB");
If you can find your datasource you can then try to optimize to avoid "manual" lookup above.

How to switch between two databses, based on user request in Java web application?

I am using Spring restful web services in my project, here I have two categories of users
1) secondary (Student studying class between 6 to 10th)
2) inter (Student studying class between 11th and 12th).
In each URI, we specify the user type, for example see below:
(http://localhost:8080/TestProject/login/secondary/authenticate)
For above request, I need to fetch the data from 'secondary' d.b tables.
Similarly for other user type request, need to communicate with other d.b(Inter).
In 'DAO' class:
NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(
getDataSource());
jdbcTemplate.getJdbcOperations().execute(
"SET SCHEMA " + **UriUtils.getSchema()**);
In above UriUtils.getSchema(), method returns the 'DataBase' name.
private DataSource getDataSource() {
String db = UriUtils.getDataBaseName();
DataSource dataSource = null;
try {
InitialContext initialContext = new InitialContext();
Context environmentContext = (Context) initialContext
.lookup("java:comp/env");
dataSource = (DataSource) environmentContext.lookup(db);
} catch (NamingException e) {
logger.error(e.getMessage());
logger.info(db + " resource is not available in server.xml file");
e.printStackTrace();
}
return dataSource;
}
In Tomcat server I configured the connection pooling.
server.xml
<Resource auth="Container" driverClassName="org.postgresql.Driver"
logAbandoned="true" maxActive="20" maxIdle="10" maxWait="-1"
name="secondary" password="admin" removeAbandoned="true"
removeAbandonedTimeout="90" type="javax.sql.DataSource"
url="jdbc:postgresql://localhost:5432/postgres?currentSchema=secondary"
username="postgres" />
<Resource auth="Container" driverClassName="org.postgresql.Driver"
logAbandoned="true" maxActive="20" maxIdle="10" maxWait="-1"
name="inter" password="admin" removeAbandoned="true"
removeAbandonedTimeout="90" type="javax.sql.DataSource"
url="jdbc:postgresql://localhost:5432/postgres?currentSchema=inter"
username="postgres" />
context.xml
<ResourceLink name="secondary" global="secondary"
type="org.postgresql.Driver" />
<ResourceLink name="inter" global="inter"
type="org.postgresql.Driver" />
Is loading the datasource object every time is a good practice ?
Please suggest if any better approach is available.
Is loading the datasource object every time is a good practice ?
NO, IMV.
Define two datasources (secondaryDS, interDS) as spring beans default to singleton, and inject corresponding datasource to JDBCTemplateclass as per your requirement.
You do not loading database every time. Lookup operation is not loading database. It is OK perform lookup on every request. Also I do not see two databases in your sample. You have two data sources over one postgresql database. You can use one data source and perform SET SCHEMA on each client request for schema switching.

How to get username from connection pool declaration at runtime

My connection pool is declared in context.xml of tomcat server as follows :
<Resource name="jdbc/codesign" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#abc.fjd.com"
username="tiger" password="tiger123" maxActive="30" maxIdle="10"
poolPreparedStatements="true" maxOpenPreparedStatements="100"
validationQuery="SELECT SYSDATE FROM DUAL" maxWait="10000"/>
I am initializing datasource in usual way as :
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
ds = (DataSource) envContext.lookup("jdbc/codesign");
What I want is to access the username ("tiger" in this case) at runtime. I am not seeing any such method in javax.sql.DataSource class. And when I try to get schema from connection using
Connection conn = DataSourceConnectionPool.getConnection()
conn.getSchema();
I get following error :
java.lang.AbstractMethodError: org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.getSchema()
And I get the same error if unwrap the connection first :
conn.unwrap(OracleConnection.class).getSchema()
java.lang.AbstractMethodError: oracle.jdbc.driver.OracleConnection.getSchema()
Is ther a way to get schema name or username from datasource or Connection?
If you are using Tomcat, your DataSoruce implementation is most likely BasicDataSource https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.html
You can cast your ds to BasicDataSource, and access the user by getUsername().
But of course try first to print the db.getClass().getName() to see what is the actual implementation.

TomEE Exception when trying to access datasource from JAX-WS

I have class called ConnectionManager
public class ConnectionManager{
public static getDBConnection()
{
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mydb");
return ds.getConnection();
}
}
When it tried to call this class from jsp page, servlet, jax-rs restful service, it just works fine.
However, I go the following exception when i try to call ConnectionManager.getDBConnection() from JAX-WS web service:
Name [comp/env/jdbc/mydb] is not bound in this Context. Unable to find [comp].
Please note that i defined the Resource inside TomEE_HOME/conf/context.xml:
<Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"
username="user" password="pass"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://10.x.x.x:xxxx;databaseName=MyDBName"/>
Please advice.

How to store string values in context.xml

I'd like to store connection URLs in a JNDI binding for my Tomcat application. Since Tomcat uses context.xml for JNDI resource defining, I need to figure out the propert way to store a String (or multiple strings for multiple connections) in context.xml.
My reason for doing this is so that I can define different strings for different environments, and load them through JNDI.
Usually, I see entries like so:
<Context ...>
<Resource name="someName" auth="Container"
type="someFullyQualifiedClassName"
description="Some description."/>
</Context>
Is it really just as simple as:
<Context ...>
<Resource name="myConnectionURL" auth="Container"
type="java.lang.String"
description="A connection URL string."/>
</Context>
If so, where do I actually store the String value?!?! And if it's not correct, then what is the proper way for me to store, for instance, "amqp:5272//blah.example.com&param1=4" in context.xml so I could then look it up like so:
Context ctx = new InitialContext();
String connectionURL = (String)ctx.lookup("myConnectionURL");
Thanks in advance!
You can use an Environmenttag:
<Context>
<Environment name="myConnectionURL" value="amqp:5272//blah.example.com&param1=4" type="java.lang.String"/>
</Context>
And you can read it almost as you specified in the question:
InitialContext initialContext = new InitialContext();
Context environmentContext = (Context) initialContext.lookup("java:/comp/env");
String connectionURL = (String) environmentContext.lookup("myConnectionURL");
This is much the same as using a Parameter tag, but without the need for a ServletContext.
You can configure named values that will be made visible to the web application as servlet context initialization parameters by nesting elements inside this element. For example, you can create an initialization parameter like this:
<Context>
...
<Parameter name="companyName" value="My Company, Incorporated"
override="false"/>
...
</Context>
This is equivalent to the inclusion of the following element in the web application deployment descriptor (/WEB-INF/web.xml):
<context-param>
<param-name>companyName</param-name>
<param-value>My Company, Incorporated</param-value>
</context-param>
Your java code looks like this
ServletContext sc = getServletContext();
String companyName = sc.getInitParameter("companyName");
Please see the reference http://tomcat.apache.org/tomcat-7.0-doc/config/context.html

Categories