It's true that Java EE doesn't define anything that helps support heterogeneous
clusters. For that matter, it says very little (too little) about even
homogeneous clusters, the general assumption being that a properly written
application on a properly implemented cluster won't know or care that it's
running in a cluster. I'd really like to see more in the spec about how to
"properly" write such an application.
Standardizing support for heterogeneous clusters seems like a much lower
priority. I'd be very interested in hearing from users that this is more
important than I think it is, and from vendors that they're wiling to implement
such a standard, especially if they already support such features.
Enrico Olivelli wrote on 07/27/12 10:31:
> there is no direct relation between multi-tenancy and clustered deployment
>
> Clustered Deployment
> the application is deployed on a cluster, a group of JVMs running on diferrent
> hosts
> machines can have specific hardware tuned for some specific operation or can
> have different network configuration
> some examples of configuration parameters that can be different for each JVM:
> - enable some operation (for example an MDB) only on some machine (because
> that machine hardware is better for some kind of processing....)
> - enable some scheduled (EJB timer) operation only on some machine
> - enable the execution of an operation that need a particular network setup
> (for example firewall ports....)
> - enable the execution of some interface (for example a webservice endpoint)
> only on machines that can be accessed from the public network
>
> Multi-Tenant Configuration:
> each "tenant" has an instance of the same application that is deployed on a
> container (which can be deployed on a single machine or a cluster)
> resources are "logically" separated between tenants
>
> some examples of configuration parameters that can be different for each tenant:
> - some parameter that enables/disables some feature of the application
> - name of the app (for example a logo in the header of the webapp) ?, help
> desk email addesses/phone numbers
> - resource usage limits ?
> - datasources ?
> - javamail sessions ?
> - jms destinations ?
>
> - Enrico
>
>
> Il 27/07/2012 09:10, Bill Shannon ha scritto:
>> 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
>>>>>
>>>>
>>>
>>
>