Re: Database configuration on web application startup
Yes, that should solve my problem. In this case, the application name would be the servlet context path? Another question: when the application is deployed in the server root url, which would be the app name? ROOT? Anyway, since this seems a small addition to an already existing heuristic, and is generally useful (not only for my case), I've registered an issue at https://issues.apache.org/jira/browse/OPENEJB-1027 Luis Fernando Planella Gonzalez lfpg@gmail.com http://freeit.inf.br Em Sexta-feira 22 Maio 2009, às 18:09:09, David Blevins escreveu: > > On May 22, 2009, at 11:13 AM, Luis Fernando Planella Gonzalez wrote: > > > * Several instances of the same application may be deployed in the > > same server. So, even that the user could create a data source in > > tomcat/conf/openejb.xml, he would have to change each application > > instance's META-INF/persistence.xml, which is packed inside a jar, > > inside another war. So, this is the showstopper. If weren't for > > this, it wouldn't be that bad to make the user set the data source > > in the tomcat file. > > Still reading the email, but just wanted to post some initial thoughts > on this point. We already don't require you to explicitly set the > data source names in the persistence.xml and will fill them in > automatically in some situations. Our current "guessing" algorithm > wouldn't help you, but we might be able to beef it up to allow for > more kinds of matching. Recently Karsten had a very similar > situation involving multiple persistence units and datasources to > match each: > > > http://www.nabble.com/Using-Multiple-PersistenceUnits-tp23520311p23534955.html > > I suggest there that we might be able to improve the datasource > matching we do for persistence.xml files to look for data sources that > use the persistence unit name when looking for them by the name listed > fails. That won't work for you as you have the same application > deployed several times and would need different datasources for each. > So as another fallback strategy we could maybe match my application > name. > > The algorithm for resolving the datasources for a persistence unit > would then look like this: > >Look for a datasource whose name matches: >1. the name set in or >2. the name of the persistence-unit >3. the name of the module name (i.e. war, ejb-jar, etc.) >4. the name of the app name (i.e. ear) > > Then you could simply leave the source> blank and configure a datasource for each application in your > openejb.xml file. > > Would something like that work for you? Seems like it would be a good > first step towards what you ultimately want and also a good solution > for Karsten. > > -David > >
Re: Database configuration on web application startup
On Sat, May 23, 2009 at 1:16 AM, David Blevins wrote: >> I'd rather avoid introducing any >> container-specific solutions unless they're really necessary. I think >> the closer we are to other ejb containers (likely application servers >> themselves) the better so people won't run into any issues during >> their production deployments. How is it handled by other app servers? >> GlassFish has a default datasource notion. What about JBAS or JOnAS or >> WLS? > > Right, as you point out the spec says "the format of these names and the > ability to specify the names are product specific" which makes it > unavoidably container specific. As far as I can see everyone has taken > their own approach (Geronimo uses the AbstractName of the db pool gbean, > JBoss uses the Jboss-specific jndi name of the datasource, etc. etc). Not > sure what we can do about that other than do our best to support the > situations people bring to us. I think it encourages us to use the Strategy design pattern with GeronimoDataSourceFormat, JBossDataSourceFormat and such, so they could be on/off to get as close to the production container as possible. Ideas? Hints? Jacek -- Jacek Laskowski Notatnik Projektanta Java EE - http://www.JacekLaskowski.pl
Re: Database configuration on web application startup
On May 22, 2009, at 2:45 PM, Jacek Laskowski wrote: Really interesting. Interesting indeed. Like global ejb names, but worse. I'd rather avoid introducing any container-specific solutions unless they're really necessary. I think the closer we are to other ejb containers (likely application servers themselves) the better so people won't run into any issues during their production deployments. How is it handled by other app servers? GlassFish has a default datasource notion. What about JBAS or JOnAS or WLS? Right, as you point out the spec says "the format of these names and the ability to specify the names are product specific" which makes it unavoidably container specific. As far as I can see everyone has taken their own approach (Geronimo uses the AbstractName of the db pool gbean, JBoss uses the Jboss-specific jndi name of the datasource, etc. etc). Not sure what we can do about that other than do our best to support the situations people bring to us. -David
Re: Database configuration on web application startup
On Fri, May 22, 2009 at 11:09 PM, David Blevins wrote: > Then you could simply leave the > blank and configure a datasource for each application in your openejb.xml > file. Interesting. I thought that leaving these elements blank would violate the spec (I thought they're required) but I've just checked in the spec and it turned out I was mistaken: 6.2.1.5 jta-data-source, non-jta-data-source In Java EE environments, the jta-data-source and non-jta-data-source elements are used to specify the global JNDI name of the JTA and/or non-JTA data source to be used by the persistence provider. If neither is specified, the deployer must specify a JTA data source at deployment or a JTA data source must be provided by the container, and a JTA EntityManagerFactory will be created to correspond to it. These elements name the data source in the local environment; the format of these names and the ability to specify the names are product specific. Really interesting. I'd rather avoid introducing any container-specific solutions unless they're really necessary. I think the closer we are to other ejb containers (likely application servers themselves) the better so people won't run into any issues during their production deployments. How is it handled by other app servers? GlassFish has a default datasource notion. What about JBAS or JOnAS or WLS? Jacek -- Jacek Laskowski Notatnik Projektanta Java EE - http://www.JacekLaskowski.pl
Re: Database configuration on web application startup
On May 22, 2009, at 11:13 AM, Luis Fernando Planella Gonzalez wrote: * Several instances of the same application may be deployed in the same server. So, even that the user could create a data source in tomcat/conf/openejb.xml, he would have to change each application instance's META-INF/persistence.xml, which is packed inside a jar, inside another war. So, this is the showstopper. If weren't for this, it wouldn't be that bad to make the user set the data source in the tomcat file. Still reading the email, but just wanted to post some initial thoughts on this point. We already don't require you to explicitly set the data source names in the persistence.xml and will fill them in automatically in some situations. Our current "guessing" algorithm wouldn't help you, but we might be able to beef it up to allow for more kinds of matching. Recently Karsten had a very similar situation involving multiple persistence units and datasources to match each: http://www.nabble.com/Using-Multiple-PersistenceUnits-tp23520311p23534955.html I suggest there that we might be able to improve the datasource matching we do for persistence.xml files to look for data sources that use the persistence unit name when looking for them by the name listed fails. That won't work for you as you have the same application deployed several times and would need different datasources for each. So as another fallback strategy we could maybe match my application name. The algorithm for resolving the datasources for a persistence unit would then look like this: Look for a datasource whose name matches: 1. the name set in or 2. the name of the persistence-unit 3. the name of the module name (i.e. war, ejb-jar, etc.) 4. the name of the app name (i.e. ear) Then you could simply leave the source> blank and configure a datasource for each application in your openejb.xml file. Would something like that work for you? Seems like it would be a good first step towards what you ultimately want and also a good solution for Karsten. -David
Database configuration on web application startup
Hi. First of all, sorry for the long post. Some time has past since my last thread about programmatic database deployment on the web application startup. First of all, the application is Cyclos (http://project.cyclos.org), which have the following requirements: * The application is being rewritten in GWT / EJB3 (previously was Struts / Hibernate). * It's an open source web application which may be downloaded and installed. * Users are used to having a single .properties to customize the database access. If possible, I'd like to keep the connection in a .properties inside the application. * Several instances of the same application may be deployed in the same server. So, even that the user could create a data source in tomcat/conf/openejb.xml, he would have to change each application instance's META-INF/persistence.xml, which is packed inside a jar, inside another war. So, this is the showstopper. If weren't for this, it wouldn't be that bad to make the user set the data source in the tomcat file. My goal: having each deployed application instance to have an automatically assigned data source, so that the user don't have to unpack the war, jar, modify the META-INF/persistence.xml and then repack. Ideally, if it were possible use a variable in persistence.xml (something like ${webApplicationContext}...), it would be perfect. Perhaps, it wouldn't be hard to implement this in OpenEJB (probably in TomcatWebAppBuilder). So, to make things work, I started to research, and here is the solution I found (and really not satisfied with it, since it's an ugly hack, and not comfortable to put it in production): * I created a custom class for the Tomcat Context handle, setting META-INF/context.xml with * I had to create a custom org.apache.openejb.config.DynamicDeployer which would wrap the existing deployer and do something else. However, since TomcatWebAppBuilder uses a ConfigurationFactory (but don't have a public getter), and ConfigurationFactory doesn't allow a custom deployer, I had to set a few private attributes through reflection: WebAppBuilder webAppBuilder = systemInstance.getComponent(WebAppBuilder.class); try { Field configurationFactoryField = webAppBuilder.getClass().getDeclaredField("configurationFactory"); configurationFactoryField.setAccessible(true); ConfigurationFactory configurationFactory = (ConfigurationFactory) configurationFactoryField.get(webAppBuilder); Field deployerField = configurationFactory.getClass().getDeclaredField("deployer"); deployerField.setAccessible(true); DynamicDeployer currentDeployer = (DynamicDeployer) deployerField.get(configurationFactory); // HERE: Setting the deployer through reflection, as there's no api for setting it. CyclosDeployer deployer = new CyclosDeployer(currentDeployer); deployerField.set(configurationFactory, deployer); } catch (Exception e) { throw new IllegalStateException(e); } * Ok, I had my custom deployer in, but in order to set a custom value for the data source, I had a problem: The standard deployer is a org.apache.openejb.config.ConfigurationFactory.Chain, with several other deployers. The first one is ReadDescriptors and the others would actually deploy the beans. However, to change the data source, my deployer would have to run after ReadDescriptors (otherwise there would be no knowledge about any persistence units), but before the other deployers, or the wrong data source would be already deployed when my deployer would be invoked. So, another hack: by reflection again, retrieve the Chain's deployers and remove the ReadDescriptors from there. Then, my deploy method: public AppModule deploy(AppModule appModule) throws OpenEJBException { //The ReadDescriptors must run in order to have persistence modules new ReadDescriptors().deploy(appModule); for (PersistenceModule pm : appModule.getPersistenceModules()) { for (PersistenceUnit unit : pm.getPersistence().getPersistenceUnit()) { if ("cyclos".equals(unit.getName())) { String path = "/" + appModule.getWebModules().get(0).getContextRoot(); String dataSource = dataSources.get(path); if (dataSource == null) { throw new IllegalStateException("Could not find the datasource for Cyclos instance at " + path); } //Set the data source name unit.setJtaDataSource(dataSource); unit.setNonJtaDataSource(dataSource + "_nonJta"); } } } return delegate.deploy(appModule); } * And, since I was this deep, I've used the ConfigurationFactory / Assembler to deploy the DataSource as David suggested, but I could live with a predefined data source. So, here's my de