-----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-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org