I've abandon PerUserPoolDataSource and retreated to
org.apache.tomcat.jdbc.pool.DataSourceand multiple resource entries in
context.xml (probably even if I could make PerUser work).
I'm clearly missing a crucial piece. Here's my current full context.xml
<Context reloadable="true">
<Resource
name="jdbc/sgsdb"
url="jdbc:postgresql://localhost:5432/version4007"
driverClassName="org.postgresql.Driver"
type="org.apache.commons.dbcp2.datasources.PerUserPoolPoolDataSource"
factory="org.apache.tomcat.dbcp.dbcp2.datasources.PerUserPoolDataSourceFactory"
validationQuery="select 1"
testWhileIdle="false"
testOnBorrow="true"
testOnReturn="false"
validationInterval="30000"
timeBetweenEvictionRunsMillis="30000"
maxActive="50"
initialSize="5"
maxWait="10000"
removeAbandonedTimeout="60"
minEvictableIdleTimeMillis="30000"
minIdle="1"
maxIdle="5"
logAbandoned="true"
removeAbandoned="true"
username="x"
password="y"
/>
</Context>
My apologies for the noise.
On 1/9/21 8:10 PM, Rob Sargent wrote:
After many loops through this, I'm pretty certain my datasource
factory is simply never added to the context as per the SEVERE message.
Any other combinations of lookups generates a NamingException.
This verbose approach demonstrates that the key is in the map and it
is mapped to null.
InitialContext ic = new InitialContext();
Context sgsContext = (Context) ic.lookup("java:/comp/env");
Context jctx = (Context) sgsContext.lookup("jdbc");
dataSource = (PerUserPoolDataSource) jctx.lookup("sgsdb");
gets to the last line with a valid "jctx" but still returns null (and
NOT a NamingException)
// normally I would do just two lookups
//Context sgsContext = (Context) ic.lookup("java:/comp/env");
//dataSource = (PerUserPoolDataSource)
sgsContext.lookup("jdbc/sgsdb");
In NamingContextListener.addResource(ContextResource resorce)
(9.0.41), Lines 1011-1028
if (("javax.sql.DataSource".equals(ref.getClassName()) ||
"javax.sql.XADataSource".equals(ref.getClassName())) &&
resource.getSingleton()) {
Object actualResource =null;
try {
ObjectName on = createObjectName(resource);
actualResource =envCtx.lookup(resource.getName());
Registry.getRegistry(null,null).registerComponent(actualResource,on,null);
objectNames.put(resource.getName(),on);
}catch (Exception e) {
log.warn(sm.getString("naming.jmxRegistrationFailed", e));
}
// Bug 63210. DBCP2 DataSources require an explicit close.
This goes
// further and cleans up and AutoCloseable DataSource by default.
if (actualResourceinstanceof AutoCloseable &&
!resource.getCloseMethodConfigured()) {
resource.setCloseMethod("close");
}
}
The lookup setting actualResource (line 1017) returns null. This uses
the passed in resource which has name = "jdbc/sgsdb" and lookupName =
null. That no resource is found makes sense since it's being
registered and registerComponent refuses to register a null value.
I have no idea why the actualResource (a DataSource Factory) is not
available.
On 1/8/21 9:11 AM, Rob Sargent wrote:
I'm getting the following error message during startup
SEVERE: Cannot register null bean for
[Tomcat:type=DataSource,host=localhost,context=/sgs,class=javax.sql.DataSource,name="jdbc/sgsdb"]
with sgs/META-INF/context.xml as
<Context reloadable="true">
<Resource
name="jdbc/sgsdb"
url="jdbc:postgresql://localhost:5432/version4007"
driverClassName="org.postgresql.Driver"
// a dozen attribute elided.
type="javax.sql.DataSource"
classname="org.apache.tomcat.dbcp.dbcp.datasources.PerUserPoolDataSource"
factory="org.apache.commons.dbcp2.datasources.PerUserPoolDataSourceFactory"
/>
</Context>
and sgs/WEB-INF/web.xml as
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>SGSaaS</display-name>
<context-param>
<description>Enable debugging for the application</description>
<param-name>debug</param-name>
<param-value>true</param-value>
</context-param>
<env-entry>
<env-entry-name>databaseHost</env-entry-name>
<env-entry-value>${SGSSRVR_databaseHost}</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
<env-entry>
<env-entry-name>databasePort</env-entry-name>
<env-entry-value>${SGSSRVR_databasePort}</env-entry-value>
<env-entry-type>java.lang.Integer</env-entry-type>
</env-entry>
<env-entry>
<env-entry-name>roleExtension</env-entry-name>
<env-entry-value>${SGSSRVR_roleExtension}</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
<env-entry>
<env-entry-name>expansionStep</env-entry-name>
<env-entry-value>${SGSSRVR_expansionStep}</env-entry-value>
<env-entry-type>java.lang.Integer</env-entry-type>
</env-entry>
<resource-ref>
<description>Pointer to context datasource</description>
<res-ref-name>jdbc/sgsdb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
Deep down in NamingContextListen
actualResource =envCtx.lookup(resource.getName());
fails, setting actualResource to null and resource.getName() is
"jdbc/sgsdb"
I can get the env values (some of which are superfluous) in my app,
but I cannot get the DataSource I think because it isn't there.
I've tried (with castings removed for brevity)
ctx = initialContext.lookup("java:/comp/env");
dataSource = ctx.lookup("jdbc/sgsdb");
dataSource=initialContext.lookup("sgs/jdbc/sgsdb") //with and
without leading slash
and several permutations of these.
Where have a gone afoul of the XMLgod(s)?