Are you using "tenant" to mean "an application instance running on one server in
a cluster"? Otherwise, I don't understand the connection between clusters and
multi-tenant apps.
What are some examples of parameters that need to be configured differently on
instances in a cluster?
Enrico Olivelli wrote on 07/26/2012 10:38 PM:
> I have another kind of problems, related to this issue(s), that is configuring
> apps deployed in clusters.
> Most of config parameters are shared between all instances in the cluster, but
> some other config parameters have to be configured slightly in a different way
> for each instance.
>
> Therefore in a multi-tenant environment I would like that configuration could
> be overriden for each tenant
>
> -
> Enrico Olivelli
>
> Il 27/07/2012 01:06, Bill Shannon ha scritto:
>> Hi Craig. Thanks for your comments.
>>
>> In this message, let's talk about application configuration.
>>
>> I believe you've seen the discussion in this expert group on the topic of
>> application configuration some time ago. There seems to be general agreement
>> that we need something here, but I'm still trying to decide whether we're all
>> describing the same elephant or whether there are actually multiple animals
>> involved. :-)
>>
>> One of the big questions here is how do we make this configuration
>> information available to applications. We've had a way to do that for quite
>> some time - JNDI environment variables. I understand that people generally
>> haven't used them because, among other reasons, they've been kind of hard to
>> use. That's improved in recent versions. You can now do things like
>>
>> @Resource(name = "myTimeout")
>> int timeout = 10;
>>
>> To access your "myTimeout" configuration parameter. That's comparable to
>>
>> int timeout = prefs.getInt("myTimeout", 10);
>>
>> From a usability perspective, injected environment entries are not too bad.
>> They're settable separately from the application code and exposed in a way
>> that tools can manage them (although not in a portable way). But...
>>
>> Environment entries are read-only to the application. If we want to allow
>> the application to update its configuration parameters, we need something
>> different, or we need to remove that restriction on environment entries (in
>> which case injection isn't going to work).
>>
>> Preferences is a reasonable alternative API to consider, although many others
>> have been proposed, each with its own advantages and disadvantages.
>>
>> As you mention, once the data can be updated by the application, we need to
>> define the semantics of such updates in a cluster. The only existing APIs
>> that do that are the database-based APIs, which is why using JPA entities to
>> model application configuration data is attractive.
>>
>> Yet another issue is the desire to be able to provide configuration data
>> separately from the application. Properties files are simple and well
>> understood and suitable for most such uses, which is why it's worth
>> considering using Properties as the API. Or we could just define a way to
>> initialize JNDI environment entries using a properties file. That would be a
>> really cheap solution for a part of the problem, but can it go far enough or
>> is it a dead end?
>>
>> It's easy to preserve application configuration data across a redeploy of the
>> application, but some people want the ability to specify the application's
>> configuration before the application is ever deployed. Managing the
>> lifecycle of application configuration data independently of applications is
>> another problem to address.
>>
>> Some people also want a portable way to read and update the application
>> configuration data for some application running in a remote app server, e.g.,
>> to enable writing separate management tools for an application. None of the
>> existing APIs is really designed for this. Do we need to define a new web
>> service or ReST interface for this? Should we use JMX? It would be nice if
>> we had a standard management technology for Java EE app servers that we could
>> build on, but we don't.
>>
>> By the time you're done considering all the issues in this space, this is no
>> longer a simple problem. A simple solution *is* possible, but it means
>> rejecting some of the use cases people have proposed. Can we find an 80%
>> solution here? I believe so, but I believe it's going to take more effort
>> than "just do it". Scoping the problem and agreeing on the important uses
>> cases is likely to be far more work than implementing the solution.
>>
>> And unfortunately, that's why it hasn't been done yet.
>>
>> I'm hoping we can find the resources to do this "soon", although it will
>> almost certainly have to come after Java EE 7.
>>
>>
>> Craig Ringer wrote on 07/16/2012 09:16 PM:
>>> Hi all
>>>
>>> I'd like to raise two related areas of difficulty I've encountered with Java
>>> EE 6 projects:
>>>
>>> * The lack of a simple, user-friendly and reliable mechanism for
>>> application configuration; and
>>> * The difficulty of overriding or overlaying deployment descriptors like
>>> beans.xml on a per-deployment basis.
>>>
>>>
>>> I've written a detailed post about the topic here:
>>>
>>> http://blog.ringerc.id.au/2012/07/java-ee-7-needs-improvements-in-app.html
>>>
>>> which I reproduce below. I'd appreciate your thoughts, especially on the
>>> suggestions for improvements at the end of the piece. This seems like a
>>> HTML-friendly mailing list so I've retained the original formatting rather
>>> than reformatting in plain text. Hope that's OK.
>>>
>>>
>>>
>>> Most applications need configuration options or preferences, a way for the
>>> user to edit them, and a way for the application to read and edit them. Java
>>> EE applications are no exception. Right now Java EE applications have
>>> numerous options for such settings - but no single choice that's simple,
>>> admin- and app-author friendly, and easy for both admin and app to modify.
>>>
>>> Java EE is supposed to provide much of the groundwork for apps as part of
>>> the container, so the app author can get on with solving their problem.
>>> Right now it doesn't help much with application settings, and this needs
>>> improvement so that apps:
>>>
>>> * Don't need to each provide a custom UI in order to edit even the
>>> simplest settings
>>> * Can easily modify their own settings
>>> * Can guarantee the persistence of their settings across redeploys and
>>> across cluster nodes
>>> * Don't require a full database and data access layer / JPA / etc just to
>>> store simple configuration options.
>>>
>>> I'd like to highlight this as an issue for Java EE 7 or 8.
>>>
>>>
>>> Approaches
>>>
>>> A Java SE app can:
>>>
>>> * Use a .properties file stored in a well-known location like the user's
>>> homedir. The user can edit this file and/or the app can load and rewrite
>>> it easily.
>>> * Use the Preferences API. This doesn't provide easy direct editing by the
>>> user, but gives the app a very simple way to store its settings.
>>> * Have the user set system properties
>>>
>>> All these options are available to Java EE apps, but with caveats that
>>> render them unappealing as noted below. Java EE apps also have some
>>> additional options:
>>>
>>> * Servlet context parameters
>>> * JNDI environment resources
>>> * Storing settings in a container-defined SQL datasource
>>> * For JBoss AS 7: Deploy a companion archive
>>>
>>> Again, none of them are particularly nice, though keeping the configuration
>>> in the database is usually the most reasonable choice.
>>>
>>>
>>> Direct file system access
>>>
>>> Direct file system access for storing configuration isn't trivial, because
>>> there's no clear and obvious place for configuration files to live. Should
>>> they be stored in the homedir of the user who's running the app server? In
>>> the app server's directory? In some arbitrary platform-specific location?
>>>
>>> More importantly, will the app actually have rights to read or write the
>>> file wherever it lands up, given that a SecurityManager may be in effect?
>>>
>>>
>>> Preferences API
>>>
>>> The Preferences API would seem like the ideal solution despite the lack of
>>> direct .properties editing by users. Unfortunately, at least some
>>> application servers seem to like to overwrite preferences when an
>>> application is re-deployed. Replication of preferences in a clustered app
>>> server is undefined and app-server specific. It's a mess.
>>>
>>> The app must also provide an editing UI for settings in the preferences API;
>>> there's no way for the user to edit it directly.
>>>
>>>
>>> System properties
>>>
>>> System properties work well, but they're set via different methods in each
>>> application server. They're globally visible across all applications, which
>>> could be a security concern for some properties. Most importantly, they're
>>> difficult or impossible for the application to update - they're effectively
>>> read-only.
>>>
>>>
>>> Servlet context parameters
>>>
>>> Servlet context parameters can be difficult to access globally across the
>>> application without hacks like adding a servlet filter to capture them.
>>> Methods for setting them without source changes are application-server
>>> specific and not at all friendly.
>>>
>>>
>>> JNDI environment resources
>>>
>>> JNDI environment resources are even less fun to define for the admin, and
>>> can be clumsy to use within the application. They have a legacy Java EE
>>> 5-or-older feel and appear little-used.
>>>
>>>
>>> JBoss AS 7 deployment companion JARs
>>>
>>> JBoss AS 7's ability to deploy companion JARs with a deployment archive is
>>> extremely useful. These JARs are private to the deployment and on the
>>> classpath. They provide an easy mechanism for customising some application
>>> descriptors and configuration. Unfortunately you can't deploy a companion
>>> jar as a jar overlay to override descriptors in the original jar, but
>>> you /can/ use it to provide app-server-specific injectable beans and
>>> services, and to provide deployment-specific configuration. However, this
>>> feature (a) isn't available on Glassfish and (b) requires the user to build
>>> a .jar and deploy it with your app using |jboss-cli|. Again, the app cannot
>>> easily modify the configuration bundled in the archive.
>>>
>>>
>>> Best choice: Configuration in the database
>>>
>>> A very common solution for Java EE applications is to store their
>>> configuration in a database. Many (most) EE apps are database driven anyway,
>>> so keeping the configuration in the DB makes sense. The DB is generally
>>> accessible to all instances of a distributed/clustered app.
>>>
>>> This is all fine so long as you're using a container-provided JDBC / JTA
>>> datasource. However it isn't suitable for apps that want to
>>> use |_at_DataSourceDefinition| or a bundled datasource like a |-ds.xml| file to
>>> make deployment easier for users.
>>>
>>> It's also useless for the purpose of /specifying the name of the data source
>>> you want the application to connect to/ if you need to avoid hard-coding
>>> that. You can use a system property for that purpose and get the rest of the
>>> configuration from the database, though.
>>>
>>> Even for apps that require a container data source anyway, one annoyance
>>> with this approach is that it's hard for users to go in and edit it. You are
>>> likely to need to write configuration pages for everything; you can't just
>>> direct them to a config file. That's OK for highly dynamic configuration,
>>> but it's a real pain for largely static stuff that gets set at the start of
>>> the deployment and forgotten.
>>>
>>>
>>> Alternative choice: System properties pointing to properties files
>>>
>>> If your app isn't database driven you probably don't want to make the user
>>> set up a datasource in the container for your app to store its settings. You
>>> just want them to be able to deploy the app. This isn't really practical at
>>> the moment.
>>>
>>> A system property pointing to a properties file location can be a somewhat
>>> ugly but reasonable compromise in this case. It avoids the user needing to
>>> deal with per-app-server quirks re how to configure a new persistent H2 /
>>> Derby datasource. Setting system properties is at least usually easier.
>>>
>>>
>>> So what do I think should be available?
>>>
>>>
>>> Preferences API constrained for Java EE applications
>>>
>>>
>>> My ideal would be for the Java EE 7 spec to constrain the Preferences API
>>> support on Java EE 7 compliant app servers with the following additional
>>> requirements:
>>>
>>> * Implementations /must/ preserve the preferences API settings across
>>> re-deploys of an application. They /may/ offer a deployment option to
>>> clear and reset preferences.
>>> * Implementations /must/ provide an interface to edit, back up, clear, and
>>> restore/load stored preferences for a deployment. Command line, web,
>>> whatever; just provide an interface for it. This interface /must/ accept
>>> and produce compliant preferences XML
>>> <http://docs.oracle.com/javase/6/docs/api/java/util/prefs/Preferences.html#importPreferences%28java.io.InputStream%29>;
>>> it /may/ accept and produce other formats.
>>> * On EE7 implementations that provide clustering
>>> features, |java.util.prefs.Preferences
>>> <http://docs.oracle.com/javase/6/docs/api/java/util/prefs/Preferences.html>| /must/ implement
>>> the new java.util.prefs.SharedPreferences interface, which provides
>>> methods (yet to be defined) to allow applications to control
>>> synchronization of preferences across the
>>> cluster. |SharedPreferences| /must/ be injectable via CDI.
>>> * On non-clusterable EE7
>>> implementations, |java.util.prefs.SharedPreferences| must be
>>> CDI-injectable as a stub that throws UnsupportedOperationException on
>>> implemented methods.
>>>
>>>
>>> This would make j.u.p.Preferences useful in EE apps. I'm sure the details
>>> would need work - for example, maybe java.util.prefs.SharedPreferences
>>> shouldn't be injectable unless supported, so you'd use an Instance to inject it.
>>>
>>>
>>> Standardize a deployment overlay mechanism
>>>
>>>
>>> Right now it's areal pain to change things like bean alternatives
>>> in |beans.xml| or the settings in|persistence.xml| on a per-deployment or
>>> per-app-server basis.
>>>
>>> How can we make it easy to override or merge/overlay deployment arbitrary
>>> deployment descriptors on a per-deployment basis? Things like:
>>>
>>> * persistence.xml
>>> * beans.xml
>>> * JBoss's -ds.xml files
>>> * glassfish-resource.xml
>>> * ... and you name it, lots more
>>>
>>> Right now, changing most of these involves modifying unpacking the jar,
>>> editing the contents, and repacking it, or requires altering the source tree
>>> and rebuilding. That isn't good for users or app developers/deployers:
>>>
>>> * It makes it hard for "end users" to just deploy an app in a fuss-free
>>> manner;
>>> * It dramatically reduces the utility of CDI's |beans.xml| configuration file
>>> * It forces the creation of per-app-server flavours of many app builds
>>> * It's slow, fiddly, and annoying
>>>
>>> What's needed is a standard way to deploy additional descriptors alongside a
>>> deployment archive, with control over whether these
>>> descriptors /override/ the bundled descriptor, or are /merged with/ the
>>> bundled descriptor. The latter case would probably only be supported for
>>> selected descriptors like |beans.xml| where merging could be made relatively
>>> well-defined.
>>>
>>>
>>> --
>>> Craig Ringer
>>>
>>
>