tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <ch...@christopherschultz.net>
Subject Re: Runtime Cloning of DataSource for Different DB?
Date Mon, 19 Dec 2016 18:24:51 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Jerry,

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: 
>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/fac
tory/
>>>
>>>
>>>
>>> 
or for a more specific example:
>>> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbc
p/dbcp2/BasicDataSourceFactory.java?view=annotate
>>>
>>>
>>>
>>>
>>> 
Mark
>>> 
>> 
> 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"
     dbName="explicitDBname"
     ... [ 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"
     scope="Unshareable"
     ... [ 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
MyDataSourceFactory.dbName.set("explicitDBName");
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
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBCAAGBQJYWCXzAAoJEBzwKT+lPKRYZH8QALuuG0XTNaJg1qFJi0p25Bbx
Gp7UbIZqOiIpFAavs/pco8+knnas9deX5DLLS8/CfQWK0l9SByAuR+0ltOJa8oCp
KpQXBhBWiJEQggQ1j4Moii/KWLO4Rt0fVAv800fFZ4DVvAEytm5JNP9J1cT9vRJx
RucK9FgFnRi8tKTvhjP0LXly3myFPwr+gHciki7Sh5W8lrKAkSEmOBPZIRyNvFr7
hsKviZso5JQMIJ1433f6/IGs1mGevirhbUfjbProRUu/HadysLq37CvCzrS2m1N2
k5OywJZMlGYpgseGSligNuX44GtVE4q2xS4pJbPWlX1belptmEqvAS5NCOLbhZwp
RDpOxv+oEoktliuDEpEoyh0LSf1Ev1rMKuYkL4rLGiVvORoYn+cLWXvdVToiNQpC
J6/cX8hORGQ6pHjJfWU95T8PjqlzJvoqUBuWcXXA8IcbmFd1tzAhc1q4k+VYF8L5
//kNJVPf/NKdmJ8c7eyK8tWijIHqWHBUlvaZGLTcDlr5Di18qIFy5i6a1ogX/at+
HzOhGuh0GAZ0+AXSHPl1UGv8DwH65IVb9PvPdF+JHnUM8tFtupy9Ki8AcaCHd6XE
Ji5sD1uD1F3KaX+j2MnKFlg33Ju8OQSBfZ+kh5h/s0K+Y5sz1qB8LC5UeIj8vgDk
dl+En1iTtzOaNbCNZ1c/
=c8XU
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message