tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <>
Subject Re: Runtime Cloning of DataSource for Different DB?
Date Mon, 19 Dec 2016 18:24:51 GMT
Hash: SHA256


On 12/16/16 3:39 PM, Jerry Malcolm wrote:
> On 6/27/2016 4:35 PM, Jerry Malcolm wrote:
>> Mark,
>> On 6/27/2016 1:07 PM, Mark Thomas wrote:
>>> On 27/06/2016 17:44, Jerry Malcolm wrote:
>>>> I'm assuming that context.lookup(...) simply locates the
>>>> "jdbc/myDB" <Resource> tag in the context.xml file, pulls all
>>>> of the parms out of that tag, creates a DataSource object
>>>> utilizing the parms, and returns it.    If that's the case,
>>>> couldn't I create a variation/subclass of the Context object
>>>> that modifies the url parm that it found in the resource tag
>>>> and puts the desired db name into the url before constructing
>>>> the DataSource?
>>> Sure.
>>> You need to implement the appropriate factory and then specify
>>> your factory class explicitly in the Resource element using the
>>> factory attribute.
>>> You probably want to start here for ideas on how to code up
>>> your factory: 
or for a more specific example:
> Mark, It's been several months since we corresponded on this
> thread.  I've been working on other aspects of the project. But the
> time has arrived that I have to get this working.  Refresher.... I
> want to have one generic  <resource..... url="dbURL/%dbName%">.
> When I need an instance, I pass a dbname to the factory and it
> builds the correct URL substituting the desired dbName into the
> URL.
> I have coded a subclass of BasicDataSourceFactory that has a new 
> getInstance( databaseName ) method on it.  All I'm doing there is 
> getting the URL property from the common/generic <Resource> tag
> and appending databaseName to the URL, then calling the parent 
> createDataSource( properties ) method.  I believe that will do what
> I need.  Plus it compiles successfully.
> Where I'm falling apart now is defining the resource tag(s) and 
> successfully coding the request to get an instance.   Normally when
> I reference a "<resource>" tag in my code [ ds = 
> (DataSource)envContext.lookup( dataSourceName );  ] the lookup 
> apparently uses the default datasourcefactory and returns a
> datasource. Fine.  But now I want to tell it use my subclass
> factory instead, and I need to pass a parameter (the db name) in.
> So I 'think' I need to get an instance of MyDataSourceFactory, then
> call my new method on it.  But how do I tell "envContext.lookup()"
> that I want to use my own factory and my own custom method (with
> the additional parameter) to get the instance from the factory?
> Or.... do I use "envContext.lookup() to lookup and give me an
> instance of my FACTORY, and then simply call my method on my 
> factory to get the ds?  Either way, I'm hitting wall on how to do
> it.

It's all in the configuration; your code shouldn't have to do anything.

<Resource factory="fully.qualified.MyDataSourceFactory"
     ... [ all shared configuration] ...

NOTE: I have no idea if this is the right code here, but conceptually
it sounds like what you are trying to do.

package fully.qualified;
public class MyDataSourceFactory {
  public void setDBName(String name) { ... };
  public static String getDBName() { ... };
  public Object createDataSource(Properties props) {
    String dbURL = getURL().replaceAll("%dbName%", getDBName());

    props.put("url", dbURL");
    return super.createDataSource(props);

I think that's all you're looking for.

It occurs to me that your *code* might need to provide the dbname to
the factory. In that case you might have to provide some environmental
context for this. Maybe a ThreadLocal.

<Resource factory="fully.qualified.MyDataSourceFactory"
     ... [ all shared configuration] ...

[The "unsharable" scope means that every call to ctx.lookup() will
return a new pooled DataSource. That means you don't want to use JNDI
as your application's stash for the DataSource... you're going to want
to store it instead in e.g. the application scope.]

package fully.qualified;
public class MyDataSourceFactory {
  public ThreadLocal<String> dbName = new ThreadLocal<String>();
  public Object createDataSource(Properties props) {
    String dbURL = getURL().replaceAll("%dbName%", dbName.get());

    props.put("url", dbURL");
    return super.createDataSource(props);

// client code
DataSource dx = ctx.lookup(jndiPath);

I'm not sure if the servlet spec or Tomcat provide any guarantees
about the current thread being used to call the factory's
createDataSource method, but I don't see a reason why Tomcat would use
another thread for that purpose.

- -chris
Comment: GPGTools -
Comment: Using GnuPG with Thunderbird -


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message