Re: Runtime Cloning of DataSource for Different DB?
-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" 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 . > 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 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 "" 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. 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. [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 dbName = new ThreadLocal(); 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
Re: Runtime Cloning of DataSource for Different DB?
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" 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/factory/ or for a more specific example: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/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 . 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 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 "" 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. Thanks. Jerry - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 6/29/2016 1:44 AM, Mark Thomas wrote: On 29/06/2016 05:12, Terence M. Bandoian wrote: On 6/28/2016 3:56 AM, Mark Thomas wrote: On 27/06/2016 22:35, 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" 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/factory/ or for a more specific example: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?view=annotate Mark Thanks so much. This looks doable. Just to make sure I have the big picture correct 1) I will define a new custom resource that returns a custom context object that I write. 2) On the tag for my custom context resource I can put all of the standard DataSource parms 3) I then call lookup() on this custom context passing the dbName in 4) This custom context will build an appropriate Reference object with all the parms, instantiate a BasicDataSourceFactory, and call getInstance(.) on the factory. When I need an instance of the datasource: Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); MyDataSourceContext dsContext = (MyDataSourceContext) envContext.lookup( "dsContext/myDSContext" ); DataSource myDS = (DataSource) dsContext.getInstance( "dbName" ); Am I getting close? Yes, but I don't think you want to use custom NamingContexts. I think there is a simpler way. 1. Write a custom DataSource factory that provides a getDataSource(...) method that allows you to pass in whatever per instance config you need. This DataSource factory will need to use bean style setters (like the example I linked to) to pick up the other config from the 2. Write a custom resource factory that returns an instance of your DataSource factory. 3. Add a context Resource element for your DataSource factory, remembering to use the factory element and specify the custom resource factory from 2. HTH, Mark If external configuration were not required, would there be a problem instantiating a DataSource directly and setting any required properties programmatically? Would any functionality be lost? The option of a global resource shared between multiple web apps is lost. You'd need a mechanism (a statics would work) to store and retrieve the DataSource. Also, if there were base properties set in a element, would there be a problem using a copy of the properties from that data source, modified as necessary, to instantiate a new DataSource? No, but you'd need to be careful since multiple requests for the same DataSource should return the same object. You'd need to be able to differentiate between a request for a new DataSourece and a previously created one. Mark Thanks! -Terence - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 29/06/2016 05:12, Terence M. Bandoian wrote: > On 6/28/2016 3:56 AM, Mark Thomas wrote: >> On 27/06/2016 22:35, 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" > 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/factory/ or for a more specific example: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?view=annotate Mark >>> Thanks so much. This looks doable. Just to make sure I have the big >>> picture correct >>> >>> 1) I will define a new custom resource that returns a custom context >>> object that I write. >>> 2) On the tag for my custom context resource I can put all of >>> the standard DataSource parms >>> 3) I then call lookup() on this custom context passing the dbName in >>> 4) This custom context will build an appropriate Reference object with >>> all the parms, instantiate a BasicDataSourceFactory, and call >>> getInstance(.) on the factory. >>> >>> When I need an instance of the datasource: >>> Context initContext = new InitialContext(); >>> Context envContext = >>> (Context)initContext.lookup("java:/comp/env"); >>> MyDataSourceContext dsContext = (MyDataSourceContext) >>> envContext.lookup( "dsContext/myDSContext" ); >>> DataSource myDS = (DataSource) dsContext.getInstance( >>> "dbName" ); >>> >>> Am I getting close? >> Yes, but I don't think you want to use custom NamingContexts. I think >> there is a simpler way. >> >> 1. Write a custom DataSource factory that provides a getDataSource(...) >> method that allows you to pass in whatever per instance config you need. >> This DataSource factory will need to use bean style setters (like the >> example I linked to) to pick up the other config from the >> >> 2. Write a custom resource factory that returns an instance of your >> DataSource factory. >> >> 3. Add a context Resource element for your DataSource factory, >> remembering to use the factory element and specify the custom resource >> factory from 2. >> >> HTH, >> >> Mark > > > If external configuration were not required, would there be a problem > instantiating a DataSource directly and setting any required properties > programmatically? Would any functionality be lost? The option of a global resource shared between multiple web apps is lost. You'd need a mechanism (a statics would work) to store and retrieve the DataSource. > Also, if there were base properties set in a element, would > there be a problem using a copy of the properties from that data source, > modified as necessary, to instantiate a new DataSource? No, but you'd need to be careful since multiple requests for the same DataSource should return the same object. You'd need to be able to differentiate between a request for a new DataSourece and a previously created one. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 6/28/2016 3:56 AM, Mark Thomas wrote: On 27/06/2016 22:35, 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" 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/factory/ or for a more specific example: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?view=annotate Mark Thanks so much. This looks doable. Just to make sure I have the big picture correct 1) I will define a new custom resource that returns a custom context object that I write. 2) On the tag for my custom context resource I can put all of the standard DataSource parms 3) I then call lookup() on this custom context passing the dbName in 4) This custom context will build an appropriate Reference object with all the parms, instantiate a BasicDataSourceFactory, and call getInstance(.) on the factory. When I need an instance of the datasource: Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); MyDataSourceContext dsContext = (MyDataSourceContext) envContext.lookup( "dsContext/myDSContext" ); DataSource myDS = (DataSource) dsContext.getInstance( "dbName" ); Am I getting close? Yes, but I don't think you want to use custom NamingContexts. I think there is a simpler way. 1. Write a custom DataSource factory that provides a getDataSource(...) method that allows you to pass in whatever per instance config you need. This DataSource factory will need to use bean style setters (like the example I linked to) to pick up the other config from the 2. Write a custom resource factory that returns an instance of your DataSource factory. 3. Add a context Resource element for your DataSource factory, remembering to use the factory element and specify the custom resource factory from 2. HTH, Mark If external configuration were not required, would there be a problem instantiating a DataSource directly and setting any required properties programmatically? Would any functionality be lost? Also, if there were base properties set in a element, would there be a problem using a copy of the properties from that data source, modified as necessary, to instantiate a new DataSource? -Terence Bandoian - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 27/06/2016 22:35, 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" >>> 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/factory/ >> >> or for a more specific example: >> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?view=annotate >> >> >> >> Mark >> > Thanks so much. This looks doable. Just to make sure I have the big > picture correct > > 1) I will define a new custom resource that returns a custom context > object that I write. > 2) On the tag for my custom context resource I can put all of > the standard DataSource parms > 3) I then call lookup() on this custom context passing the dbName in > 4) This custom context will build an appropriate Reference object with > all the parms, instantiate a BasicDataSourceFactory, and call > getInstance(.) on the factory. > > When I need an instance of the datasource: > Context initContext = new InitialContext(); > Context envContext = > (Context)initContext.lookup("java:/comp/env"); > MyDataSourceContext dsContext = (MyDataSourceContext) > envContext.lookup( "dsContext/myDSContext" ); > DataSource myDS = (DataSource) dsContext.getInstance( "dbName" ); > > Am I getting close? Yes, but I don't think you want to use custom NamingContexts. I think there is a simpler way. 1. Write a custom DataSource factory that provides a getDataSource(...) method that allows you to pass in whatever per instance config you need. This DataSource factory will need to use bean style setters (like the example I linked to) to pick up the other config from the 2. Write a custom resource factory that returns an instance of your DataSource factory. 3. Add a context Resource element for your DataSource factory, remembering to use the factory element and specify the custom resource factory from 2. HTH, Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 6/27/2016 1:07 AM, Jerry Malcolm wrote: On 6/26/2016 8:27 PM, David Kerber wrote: On 6/26/2016 1:32 AM, Jerry Malcolm wrote: I have a webapp that runs on a single host. It has one primary database. But it has many secondary databases. There is one secondary database for each of my clients that use my app. These client databases come and go regularly as clients signup and leave. I don't want to have to edit Tomcat conf files adding and deleting tags for the secondary databases and then have to bounce Tomcat several times a day as clients come onboard or leave. I have one tag for the primary database. The id/pw and everything else in the resource tag is the same for all of the databases. Is there a way to specify/override the url (i.e. the database name) at runtime to connect to whatever secondary database I need for the particular client? Or is there a way to clone a datasource for a different url/database? I still would like to use the one resource tag in the context.xml.default conf file to specify the id/pw for the secondary DBs. I'd prefer not to hardcode id/pw in the java code. But if that is the only option, I can do it. Hopefully there is some way to dynamically select the db in a datasource at runtime... (??) Suggestions? You can move your authentication code into your application, rather than having TC handle it. Then you can pick any database or data source you want. I know I can hardcode the connection in the code. But that is not going to provide connection pooling. That 's a huge performance hit. I really want the same capability I get with jdbc datasources, only without hardcoding hundreds of them in the conf files. You would need to handle your own pooling (which isn't particularly difficult), but there's certainly no need to hard-code anything. All of your db connection info can be in a "master" database, in Tomcat's configurations, or anywhere else that is accessible by your code. If you can build connection strings from login information, it would be super simple. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
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" 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/factory/ or for a more specific example: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?view=annotate Mark Thanks so much. This looks doable. Just to make sure I have the big picture correct 1) I will define a new custom resource that returns a custom context object that I write. 2) On the tag for my custom context resource I can put all of the standard DataSource parms 3) I then call lookup() on this custom context passing the dbName in 4) This custom context will build an appropriate Reference object with all the parms, instantiate a BasicDataSourceFactory, and call getInstance(.) on the factory. When I need an instance of the datasource: Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); MyDataSourceContext dsContext = (MyDataSourceContext) envContext.lookup( "dsContext/myDSContext" ); DataSource myDS = (DataSource) dsContext.getInstance( "dbName" ); Am I getting close? Thx. Jerry - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 27/06/2016 17:44, Jerry Malcolm wrote: > I'm assuming that context.lookup(...) simply locates the "jdbc/myDB" > 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/factory/ or for a more specific example: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java?view=annotate Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 6/27/2016 1:03 AM, Mark Eggers wrote: Jerry, On 6/26/2016 10:07 PM, Jerry Malcolm wrote: On 6/26/2016 8:27 PM, David Kerber wrote: On 6/26/2016 1:32 AM, Jerry Malcolm wrote: I have a webapp that runs on a single host. It has one primary database. But it has many secondary databases. There is one secondary database for each of my clients that use my app. These client databases come and go regularly as clients signup and leave. I don't want to have to edit Tomcat conf files adding and deleting tags for the secondary databases and then have to bounce Tomcat several times a day as clients come onboard or leave. I have one tag for the primary database. The id/pw and everything else in the resource tag is the same for all of the databases. Is there a way to specify/override the url (i.e. the database name) at runtime to connect to whatever secondary database I need for the particular client? Or is there a way to clone a datasource for a different url/database? I still would like to use the one resource tag in the context.xml.default conf file to specify the id/pw for the secondary DBs. I'd prefer not to hardcode id/pw in the java code. But if that is the only option, I can do it. Hopefully there is some way to dynamically select the db in a datasource at runtime... (??) Suggestions? You can move your authentication code into your application, rather than having TC handle it. Then you can pick any database or data source you want. I know I can hardcode the connection in the code. But that is not going to provide connection pooling. That 's a huge performance hit. I really want the same capability I get with jdbc datasources, only without hardcoding hundreds of them in the conf files. From what I remember of your environment, it's the following: 1. Monolithic web application 2. No WAR file 3. Much of the configuration is in Tomcat-wide locations To me (and I don't mean to sound harsh) this violates the software architecture principle of separating things that change from things that remain the same (speed of change being relative). This lack of separation leads to a lot of operational challenges (which you've written about in the past). In an ideal world, I'd use versioned WAR files and a CI / CD server (we use Jenkins) to manage the deployment. Keep context.xml in version control, and you end up with the potential for a zero down time update. There are a lot of wrinkles to the above solution that I could go over, but since this is not your architecture I won't fill up the mailing list with some likely scenarios. That being said, I can see three paths for you to go down. 1. Put everything into context.xml You'll have to edit it and upload the file. When context.xml is changed Tomcat will reload the web application. You'll experience some downtime, but with your current architecture I don't see an easy way around that. 2. Roll your own pools There are several JDBC connection libraries available. You would roll your own pool management, and then create an administrator application to add and delete pools. 3. Move to an application server Wildfly and Glassfish both have administrative interfaces that allow you to add and delete JNDI JDBC pools. Unfortunatly, the last time I tried Glassfish the interface to manage JNDI JDBC pools was broken. I don't know if they've fixed that yet. I've not worked with WildFly, but it appears to have an administrative interface with this capability. We're also looking at Elastic Beanstalk, but there are a lot of wrinkles we need to work out before deciding to move in that direction. . . . just my two cents /mde/ I'm not sure what you mean by 'monolithic'. I have 10 virtual hosts each with about 10 individual webapps. Everything is configured in individual \conf\Catalina\\context and web.xml files. I am not using WAR files. But only because when I change one jsp or one jar I don't want to have to wait 15 minutes for an entire WAR refresh over a slow internet link. But otherwise my architecture is identical to using WAR files. None of my configuration is in a Tomcat-wide location. But I'm not sure what any of this has to do with being able to create a DataSource using a variable for the database URL. If Wildfly and Glassfish can do it, it would seem that I would be able to do the same thing. I currently use three lines of code to get a DataSource: Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); DataSource ds = (DataSource)envContext.lookup( "jdbc/myDB" ); I'm assuming that context.lookup(...) simply locates the "jdbc/myDB" 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
Re: Runtime Cloning of DataSource for Different DB?
On Sun, Jun 26, 2016 at 11:07 PM, Jerry Malcolmwrote: > > On 6/26/2016 8:27 PM, David Kerber wrote: > >> On 6/26/2016 1:32 AM, Jerry Malcolm wrote: >> >>> I have a webapp that runs on a single host. It has one primary >>> database. But it has many secondary databases. There is one >>> secondary database for each of my clients that use my app. These >>> client databases come and go regularly as clients signup and leave. >>> I don't want to have to edit Tomcat conf files adding and deleting >>> tags for the secondary databases and then have to bounce >>> Tomcat several times a day as clients come onboard or leave. >>> >>> I have one tag for the primary database. The id/pw and >>> everything else in the resource tag is the same for all of the >>> databases. Is there a way to specify/override the url (i.e. the >>> database name) at runtime to connect to whatever secondary database I >>> need for the particular client? Or is there a way to clone a >>> datasource for a different url/database? I still would like to use >>> the one resource tag in the context.xml.default conf file to specify >>> the id/pw for the secondary DBs. I'd prefer not to hardcode id/pw in >>> the java code. But if that is the only option, I can do it. >>> >>> Hopefully there is some way to dynamically select the db in a >>> datasource at runtime... (??) Suggestions? >>> >> >> You can move your authentication code into your application, rather than >> having TC handle it. Then you can pick any database or data source you >> want. >> >> >> I know I can hardcode the connection in the code. But that is not going > to provide connection pooling. That 's a huge performance hit. I really > want the same capability I get with jdbc datasources, only without > hardcoding hundreds of them in the conf files. > > I seem to recall DBCP having a per-user pool data source feature, where you can pass different credentials to the same base Resource. Whether you can change the database too, i don't remember. You might want to check the docs or ask those guys a couple doors down. -Tony > - > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org > >
Re: Runtime Cloning of DataSource for Different DB?
Jerry, On 6/26/2016 10:07 PM, Jerry Malcolm wrote: > > On 6/26/2016 8:27 PM, David Kerber wrote: >> On 6/26/2016 1:32 AM, Jerry Malcolm wrote: >>> I have a webapp that runs on a single host. It has one primary >>> database. But it has many secondary databases. There is one >>> secondary database for each of my clients that use my app. These >>> client databases come and go regularly as clients signup and >>> leave. I don't want to have to edit Tomcat conf files adding and >>> deleting tags for the secondary databases and then >>> have to bounce Tomcat several times a day as clients come onboard >>> or leave. >>> >>> I have one tag for the primary database. The id/pw >>> and everything else in the resource tag is the same for all of >>> the databases. Is there a way to specify/override the url (i.e. >>> the database name) at runtime to connect to whatever secondary >>> database I need for the particular client? Or is there a way to >>> clone a datasource for a different url/database? I still would >>> like to use the one resource tag in the context.xml.default conf >>> file to specify the id/pw for the secondary DBs. I'd prefer not >>> to hardcode id/pw in the java code. But if that is the only >>> option, I can do it. >>> >>> Hopefully there is some way to dynamically select the db in a >>> datasource at runtime... (??) Suggestions? >> >> You can move your authentication code into your application, >> rather than having TC handle it. Then you can pick any database or >> data source you want. >> >> > I know I can hardcode the connection in the code. But that is not > going to provide connection pooling. That 's a huge performance hit. > I really want the same capability I get with jdbc datasources, only > without hardcoding hundreds of them in the conf files. From what I remember of your environment, it's the following: 1. Monolithic web application 2. No WAR file 3. Much of the configuration is in Tomcat-wide locations To me (and I don't mean to sound harsh) this violates the software architecture principle of separating things that change from things that remain the same (speed of change being relative). This lack of separation leads to a lot of operational challenges (which you've written about in the past). In an ideal world, I'd use versioned WAR files and a CI / CD server (we use Jenkins) to manage the deployment. Keep context.xml in version control, and you end up with the potential for a zero down time update. There are a lot of wrinkles to the above solution that I could go over, but since this is not your architecture I won't fill up the mailing list with some likely scenarios. That being said, I can see three paths for you to go down. 1. Put everything into context.xml You'll have to edit it and upload the file. When context.xml is changed Tomcat will reload the web application. You'll experience some downtime, but with your current architecture I don't see an easy way around that. 2. Roll your own pools There are several JDBC connection libraries available. You would roll your own pool management, and then create an administrator application to add and delete pools. 3. Move to an application server Wildfly and Glassfish both have administrative interfaces that allow you to add and delete JNDI JDBC pools. Unfortunatly, the last time I tried Glassfish the interface to manage JNDI JDBC pools was broken. I don't know if they've fixed that yet. I've not worked with WildFly, but it appears to have an administrative interface with this capability. We're also looking at Elastic Beanstalk, but there are a lot of wrinkles we need to work out before deciding to move in that direction. . . . just my two cents /mde/ signature.asc Description: OpenPGP digital signature
Re: Runtime Cloning of DataSource for Different DB?
On 6/26/2016 8:27 PM, David Kerber wrote: On 6/26/2016 1:32 AM, Jerry Malcolm wrote: I have a webapp that runs on a single host. It has one primary database. But it has many secondary databases. There is one secondary database for each of my clients that use my app. These client databases come and go regularly as clients signup and leave. I don't want to have to edit Tomcat conf files adding and deleting tags for the secondary databases and then have to bounce Tomcat several times a day as clients come onboard or leave. I have one tag for the primary database. The id/pw and everything else in the resource tag is the same for all of the databases. Is there a way to specify/override the url (i.e. the database name) at runtime to connect to whatever secondary database I need for the particular client? Or is there a way to clone a datasource for a different url/database? I still would like to use the one resource tag in the context.xml.default conf file to specify the id/pw for the secondary DBs. I'd prefer not to hardcode id/pw in the java code. But if that is the only option, I can do it. Hopefully there is some way to dynamically select the db in a datasource at runtime... (??) Suggestions? You can move your authentication code into your application, rather than having TC handle it. Then you can pick any database or data source you want. I know I can hardcode the connection in the code. But that is not going to provide connection pooling. That 's a huge performance hit. I really want the same capability I get with jdbc datasources, only without hardcoding hundreds of them in the conf files. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Runtime Cloning of DataSource for Different DB?
On 6/26/2016 1:32 AM, Jerry Malcolm wrote: I have a webapp that runs on a single host. It has one primary database. But it has many secondary databases. There is one secondary database for each of my clients that use my app. These client databases come and go regularly as clients signup and leave. I don't want to have to edit Tomcat conf files adding and deleting tags for the secondary databases and then have to bounce Tomcat several times a day as clients come onboard or leave. I have one tag for the primary database. The id/pw and everything else in the resource tag is the same for all of the databases. Is there a way to specify/override the url (i.e. the database name) at runtime to connect to whatever secondary database I need for the particular client? Or is there a way to clone a datasource for a different url/database? I still would like to use the one resource tag in the context.xml.default conf file to specify the id/pw for the secondary DBs. I'd prefer not to hardcode id/pw in the java code. But if that is the only option, I can do it. Hopefully there is some way to dynamically select the db in a datasource at runtime... (??) Suggestions? You can move your authentication code into your application, rather than having TC handle it. Then you can pick any database or data source you want. Thanks. Jerry - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Runtime Cloning of DataSource for Different DB?
I have a webapp that runs on a single host. It has one primary database. But it has many secondary databases. There is one secondary database for each of my clients that use my app. These client databases come and go regularly as clients signup and leave. I don't want to have to edit Tomcat conf files adding and deleting tags for the secondary databases and then have to bounce Tomcat several times a day as clients come onboard or leave. I have one tag for the primary database. The id/pw and everything else in the resource tag is the same for all of the databases. Is there a way to specify/override the url (i.e. the database name) at runtime to connect to whatever secondary database I need for the particular client? Or is there a way to clone a datasource for a different url/database? I still would like to use the one resource tag in the context.xml.default conf file to specify the id/pw for the secondary DBs. I'd prefer not to hardcode id/pw in the java code. But if that is the only option, I can do it. Hopefully there is some way to dynamically select the db in a datasource at runtime... (??) Suggestions? Thanks. Jerry - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org