Thanks for taking the time to think about and respond to this. My reply
follows in-line; I hope that's OK.
On 07/27/2012 07:06 AM, Bill Shannon wrote:
>
> 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.
Accessing them has improved, but defining them hasn't. It's still a PITA
that requires an EAR wrapper or, if you're lucky, container-specific
admin command line incantations - even a web console in some containers.
I can't produce an application with "download, edit a few details in a
config file, deploy/run" complexity if the user has to repackage it into
an EAR to use it, or if I have to provide per-app-server listings of
command line incantations, web UI nav paths, server-specific
descriptors, etc to explain how to set some environment entries up.
I guess it all just seems like a lot of hoops to jump through to
configure an application - instead of just deploying a configuration
file directly.
> You can now do things like
>
> @Resource(name = "myTimeout")
> int timeout = 10;
>
> From a usability perspective, injected environment entries are not too
> bad.
... in sites where injection is available, like EJBs, CDI managed beans,
etc, yes. That's many, but far from all, places. A JNDI access wrapper
isn't exactly hard to write where injection isn't available, though it
does require the user to understand JNDI - something that's obvious to
you and is now obvious to my, but I assure you is /not/ obvious when
learning.
The main issue with this from a usability PoV is that if injection isn't
supported for a given site, it's just silently left null. I know there's
probably no better answer in an extensible, flexible system where all
sorts of different code takes responsibility for injection in different
places, but it's pretty confusing for users.
> They're settable separately from the application code and exposed in a
> way that tools can manage them (although not in a portable way).
I'd argue that their settability is poor and app-server-specific at
best, but they are settable.
>
> 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).
Actually, injection can still work for non-primitives. That's an
interesting idea. Something like CDI's Instance<T> could easily be used
for injection of mutable properties, with a suitable set(..) method.
Essentially an injected wrapper for the entry.
The main issue is that if it's app-settable it'd have to be injected
that way everywhere or changes wouldn't be updated at all injection
sites. Proxies would help with this, but they don't work on primitives
and - since injection sites can't be final (sadly) applications can
easily accidentally replace the proxy by assignment.
This could work if env entries were only app-settable if explicitly
marked as such, and such entries could *only* be injected via an
Instance<T>-like wrapper to prevent accidents like the above.
The main trouble is that it'd be a pain to work with structured
resources like lists and maps, especially when it comes to modifying
them from outside the application via admin tools, configuration
dumps/loads, etc.
>
> 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.
Handily, the preferences API is pretty backend-agnostic. That's part of
why I thought it might be an attractive option. App servers can easily
store prefs in an app-server-provided embedded DB or an external
database shared across a cluster. It's a pity the "system" and "user"
levels are designed into the API, because being able to designate
"global", "cluster", and "application" levels without having to extend
the API would be handy.
> 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.
They are simple, but unlike preferences they don't cater for much in the
way of structure. Not that the preferences API is exactly /nice/ for
storing maps, lists and sets, but it works better than property name
hacks in a properties file.
A tree of properties files, with appropriate injection, could work - but
surely the prefs API folks went down that path and rejected it for good
reasons.
> 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'd be a real pain for containers that want to offer web UI or command
line management of the JNDI env. When the props file is updated, what's
the container to do?
It doesn't answer application updates either.
> 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.
Absolutely, and I'm one of them.
> Managing the lifecycle of application configuration data independently
> of applications is another problem to address.
+1 on that
> 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.
Agreed, that's certainly an interesting target area but one with no
obvious answers. JMX and MBeans don't seem like the answer. Containers
that support remote management are mostly doing it via REST, so this
would seem the logical approach, but it's hard to know where to go
without having an underlying API to expose.
I don't think this can be answered without knowing what the underlying
mechanism for storing and setting preferences will be.
> I'm hoping we can find the resources to do this "soon", although it
> will almost certainly have to come after Java EE 7.
That's ... disheartening. This problem is old, and as Java EE works on a
nearly geological time scale it's going to be really hard to maintain
enthusiasm for it over the several years required. It'd be three or four
years before the solution could actually start hitting real world
deployments.
I wonder if there a reasonable subset of functionality that can be
considered, one container vendors can extend for other needs?
--
Craig Ringer