More Thoughts on Configuration

This is a distillation of the thoughts I had in my previous piece on configuration.

The key insight for me was that application configuration takes place within a configuration value space with one or more dimensions or axes.

Next, these dimensions or axes are not hierarchical (after all, how could a dimension or axis be hierarchical?) and have nothing to do with the name of the configuration setting (other than that it can be considered to be one of the dimensions or axes).

Following on from all of that, an application asks for configuration values suitable for where it sits in multidimensional configuration space.  (I know this sounds like I’m five miles above the earth, but I really think this is important.)  I like to call this location its configuration coordinates.  There are always more coordinates than you think (something like locale often slips through the cracks!) but the total number is still probably under 20 or 10 for almost any application.  Many simple applications probably have somewhere around only two or three.

Next, a (flexible, well-written) application is typically unaware of most (if not all) of its own configuration coordinates.  (An application, in other words, from the standpoint of its running code, doesn’t “know” whether it’s in the test environment or not.)  But these coordinates are always, whether you know it or not, implicit in a semantic configuration request.

Next, configuration systems or sources are capable of supplying configuration values that are more or less specific along one or more of the configuration space axes.  A configuration system might supply a value that is maximally specific along the name axis (db.url), and minimally specific along (but suitable for) all possible other axes (environment, phase, region, etc.).  The holy grail is a value that is exactly suited for all of and exactly those configuration coordinates expressed by the application. Non-holy grails are configuration values that are still suitable by virtue of applying to a wide range of configuration coordinates.  This is the only place where hierarchies come into play: for any given configuration axis, a more-specific configuration value always trumps (I hate that word) a less-specific configuration value, but if a more-specific value does not exist, then the less-specific value is suitable.

This lets us start theorizing clumsily about a procedure where an application can ask for configuration values suitable for its configuration coordinates:

  • The application asks the configuration system for a value for the db.url configuration key and expects a String back.
  • The configuration system figures out what the application’s coordinates are, and re-expresses the request in terms of those coordinates.  db.url becomes a value for the—I don’t know—configurationKey axis.
  • The configuration system grabs all of its sources or subsystems or providers or whatever they should be called.
    • For each one, it asks it for a configuration value suitable for the supplied coordinates—and expects back, in return, not just the value, but also the coordinates for which it is explicitly suited.  Also of note: if the subsystem returns a value with no coordinates, then this value matched, but minimally specifically.  It’s suitable, but as a last resort.
    • Each subsystem responds appropriately.
  • The configuration system loops through the results.  Any result is presumed or enforced to be a match for at least the (hypothetical) configurationKey axis!  (That is, if I ask for foo, and I get a value for bar back, regardless of other coordinates, something went wrong.)
    • If there are no results, then there are no matches, and either null is returned or an error is thrown.
    • If there is exactly one result, then the value is returned.
    • If there is exactly one exact match, then the value is returned.
    • If there is more than one exact match, then an error is thrown.
    • If there are no exact matches:
      • The configuration system sorts the results in terms of specificity.  There are some details to work out here, but loosely and hazily and sketchily speaking if a set of configuration coordinates is expressed as a Map, then a Map with a bigger size (assuming the same universe of possible keys) is more specific, let’s say, than a Map with a smaller size. For example, {a=b, c=d} is a more specific set of coordinates (let’s say) than {a=b}.  The mere presence of a value indicates some kind of match, so it is possible for a configuration subsystem to return a value with, say, empty configuration coordinates.  This would indicate that the match is least specific.  So the specificity of a configuration value can be said, I think, to be equal to the number of configuration coordinates it reports as having matched on.  Tersely, the greater the specificity, the greater the Map‘s size.
      • If there is exactly one value with a given specificity, then it is returned—it is a suitable match.
      • If there is more than one value with the same specificity of coordinates, then this represents a misconfiguration and an error is thrown. For example, one subsystem might report that it has a value for {b=c, d=e} and another might report that it has a value for {d=e, f=g} when asked for a value suitable for {b=c, d=e, f=g}. Since configuration axes are not (by definition) hierarchical, this represents a misconfiguration.

OK, I think I’ll leave it there for now and chew on this over the weekend.

CDI Qualifiers are Values, Part 2

In a previous post I wrote that CDI qualifiers are values.

After some more thinking, there are two classes of CDI qualifiers: those that are values for implicit aspects (arbitrary examples: @Synchronous (a value for synchronicity), @Yellow (a value for color)), and rarer ones—those that are both aspects and values for those aspects (as an example, @Named is the aspect; the value of its value element is the qualification value).  There aren’t a lot of the latter, but they do exist.

If you want to write a producer method that works with the latter class of qualifiers, then you must look at the element of the qualifier that represents its value and see if it is meta-annotated with @Nonbinding or not.

If it is, then you are all set: you can just put the qualifier on your producer method, and now your producer method will be able to produce all possible values for that qualifier.

If it is not, then in order to write producer methods you must know in advance of all the members of the domain over which the qualifier’s value element can range.

Consider @Named as an example.  It is a qualifier that does not represent a value.  It represents an aspect.  Its value element holds the value that does the actual qualifying.  But its value element is not meta-annotated with @Nonbinding, so that means there’s no way to write one producer method that can produce items for injection points qualified with the @Named qualifier with arbitrary values.  That is, if your producer method is annotated with @Named(""), then the only injection point it will satisfy is one that is also  qualified with @Named("").  If it is annotated with @Named("fred"), then it will produce objects suitable only for injection points that are also annotated with @Named("fred").

So if you knew all the possible names your application could ever use, you could write a producer method for each of them, annotated appropriately (one annotated with @Named("fred"), one annotated with @Named("alice"), and so on).  Of course, if you knew that, you could just define your own “regular” qualifier annotations: @Fred, @Alice and so on, with an implicit aspect of name.

Whoa, you think; this is cumbersome and in some cases impossible!

Let’s invent a qualifier of the second class called @Labeled, with a single value element. It’s basically kind of like @Named, but with one important difference: on this qualifier we’ll add @Nonbinding to its value element.

Now all you have to do is mark your producer method with @Labeled, and you’ve effectively said, “I’ll take care of anything annotated with @Labeled, no matter what the requested value is.”  You’d better do that, because otherwise the container won’t start up.

This is of course very convenient and the way that a lot of configuration frameworks proceed.  Imagine a configuration framework backed by such a producer method: if someone asks for a String value to be injected at an injection point annotated with @Labeled("fred"), then it is easy for the producer method to go hunting for that value (however it does it) and return it.

There is a faint sense, though, in which this sort of thing doesn’t quite fit the CDI mindset. CDI “wants” you to know all your values in advance whenever possible: that’s why qualifiers are usually values themselves. Then the wiring is utterly explicit: the producer method annotated with @Yellow satisfies injection points also annotated with @Yellow. There is a way in which a producer method annotated with just @Labeled and an injection point annotated with @Labeled("fred") don’t quite plug into that way of thinking.  I have a hazy (possibly misguided) sense that there’s a better way of doing this sort of thing, but I don’t know what it is yet.

Anyway, all of this can serve as a helpful litmus test for clarifying your thinking and identifying which of your qualifiers need @Nonbinding on their elements and which do not.

CDI Qualifiers are Values

I had this realization today that I’m frankly not sure quite what to do with.

The realization, briefly put, is that CDI qualifiers are values for various unnamed aspects.  They are not those aspects themselves.

For example, the often-seen-in-CDI-examples qualifier @Synchronous is really a possible value for a hypothetical aspect called—I don’t know—synchronicity.  @Yellow is really a value for a hypothetical aspect called, presumably, color.  And yet we’re always left to infer what the aspect is from the qualifier itself (representing a possible value for that unnamed aspect).

We do this in English too: if you say “get me my yellow coat,” I don’t have to ask you about what aspect for which yellow serves as a value.  But that’s what’s going on.

This also led me to realize that, seen through a certain lens, there are other implicit qualifiers that are present everywhere, in an abstract sense (not actually in code).  For example, if I run my CDI application in a test environment, then there is this abstract sense in which all of my injection points (and their corresponding beans or producer methods) are semantically qualified with something like @Test, where @Test is a possible value for a hypothetical environment aspect.

What other aspects are there?  Well, there’s environment, I guess, and project stage, maybe, and data center ID, I guess, and region, and phase of the moon…and all of the other things that go into describing my application’s effective coordinates, all of which affect, potentially, what sorts of things are injected.

For non-configuration injection points, when you inject a Frobnicator, there’s only one choice (perhaps disambiguated from a set of alternatives via a META-INF/beans.xml file). So a lot of this just stays in thought experiment land: the Frobnicator you get is, well, the one you get. It’s not like there are dozens of them lying around.

But with configuration, you’re usually talking about plain types (String), indexed under names, suitable for certain worlds and not for others (“don’t use the production database url!”).

Standard procedure among the 34,472 CDI configuration “frameworks” out there is to make a “qualifier” called, say, @Config, with all @Nonbinding-annotated elements, thus rendering it not much of a qualifier at all (primarily so that a single producer method can use it), and then a producer method or a CDI extension or something that is actually in charge of figuring out what the name of the configuration item is whose value should be retrieved (thus turning the “qualifier” into a name, really). Note how using @Config here confuses the fact that a qualifier is a value, not an aspect.

(CDI itself (well, JSR-330 actually) gets confused in a similar way with its own annotations!  The javax.inject.Named “qualifier” is, note, not a value, but an aspect.  The value of the aspect is given by the annotation’s value() element.)

So what to do with all this?  I am not sure as of this writing, but I have this nagging sense that there’s the germ of a more powerful, more properly-aligned-with-the-spirit-of-CDI configuration extension brewing in here.

Changing Annotations at Startup in CDI 2.0

Today’s CDI 2.0 topic is actually about features that have been in there for a long while, but that I don’t see much evidence of out in the wild.

A lot of people are used to injection as provided by Jersey.  This is implemented under the covers by the excellent little underappreciated HK2 project, not by CDI.

HK2 can do really neat things with annotations.  In today’s blog, I want to show you how I took an annotation that was being used by an HK2-based system to provide configuration injection and, using the sledgehammer of the CDI portable extension API, made it usable in a CDI project.

The annotation looks like this, more or less:


public class Config {
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@interface Key {
String value();
}
}

view raw

Config.Key.java

hosted with ❤ by GitHub

As you can see, it is a simple Qualifier annotation that can be applied to fields and parameters only.  It has a value element, which ends up being the name of a particular piece of configuration you want.

So you could see it being used like this:

@Inject
@Config.Key("frobnicationInterval")
private int frobnicationInterval;

Or like this:

@Inject
public Frobnicator(@Config.Key("frobnicationInterval") final int frobnicationInterval) {
  super();
  this.frobnicationInterval = frobnicationInterval;
}

HK2 has a concept somewhat analogous to CDI’s producer.  While a CDI producer can be a method or a field, it can’t be a class.  HK2, on the other hand, defines only one kind of thing-that-can-make-other-things, and calls it a Factory.  Factory‘s provide method returns the thing it can make, and you annotate the provide method in much the same way as you do a CDI producer method.

Unless, of course, you’re working with this particular annotation, as its Target meta-annotation does not allow it to be placed on methods of any kind.

In the HK2 project I was looking at, then, the Factory in question behind this Config.Key annotation simply declared that it provides Object.  No qualifiers.  Hmm.

Now, to get a Factory to be treated as a Factory by HK2, you have to mark it as such, or otherwise instruct HK2 to treat it as a Factory.  Otherwise it’s just another object that happens to implement the Factory interface.  None of those markings or instructions were immediately apparent.

The other thing you can do, though, is define something called an InjectionResolver.  If you do that, then inside that class you can do whatever you like to resolve the given injection point.  As I looked at this project, I found one for Config.Key.  It delegated its work off to the Factory I found, and other various internal configuration engines and whatnot, and the end result is that any class inside this project could do something like the examples I showed above.

I thought I’d cobble together some CDI constructs to do the same thing.

I knew that I couldn’t make any use of managed beans, because of course int and String are not managed beans.  Short of really convoluted potential other solutions, obviously I’d need a producer method.  I would just need to make a producer method that returned Object and that is qualified by Confi

Oops.  The annotation doesn’t have ElementType.METHOD as one of the places listed where it can be used. So my producer method code won’t compile, because I can’t put the Config.Key annotation on it.

Off to the portable extension toolbox.

First, I wrote a private annotation (I named it Property) that looks like this:


@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
private @interface Property {
@Nonbinding
String value() default "";
}

view raw

Property.java

hosted with ❤ by GitHub

This private annotation (an inner annotation) is solely for my bean-housing-the-producer-method’s use, and the use of the extension that installs it.

You’ll note it looks almost the same as Config.Key, but this time it has ElementType.METHOD in its Target annotation.  It also features the Nonbinding annotation applied to its value element, and the value element now has a default value of "".  We’ll talk about those things in a bit.

Then, for reasons to be clear in a bit, I wrote an AnnotationLiteral implementation for it:


private static final class PropertyLiteral extends AnnotationLiteral<Property> implements Property {
private static final long serialVersionUID = 1L;
private final String value;
private PropertyLiteral() {
this("");
}
private PropertyLiteral(final String value) {
super();
Objects.requireNonNull(value);
this.value = value;
}
@Nonbinding
@Override
public final String value() {
return this.value;
}
public static final PropertyLiteral of(final String value) {
return new PropertyLiteral(value);
}
}

The new Property annotation will let me write a producer method like this:


@Produces
@Dependent // not really needed; I like to be explicit
@Property
private final Object produceProperty(final InjectionPoint ip, final BigCoConfigurationEngine config) {
// Get the right configuration value identified by the injection point
// using the BigCoConfigurationEngine
throw new UnsupportedOperationException("Not done yet");
}

…now that I can use @Property on methods and not just on parameters and fields.

But who cares? No user code can use my new, private inner Property annotation!  So who the heck is ever going to cause this method to be invoked?

Enter portable extensions.  Now we need a portable extension that will search for injection points that feature @Config.Key and make them behave as though they were written with @Property instead.  Once we do that, then we have a linkage: the user’s code says that it wants a particular kind of Object to be injected—namely a @Config.Key-ish one—but we know that for our purposes this should be translated into a desire for a @Property-ish one, and that will be satisfied by the CDI typesafe resolution algorithm and this producer method will be invoked.

There is a container event for just this sort of thing.  It’s called ProcessInjectionPoint, and you can do things with it like this:


private final void processInjectionPoint(@Observes final ProcessInjectionPoint<?, ?> event) {
if (event != null) {
final InjectionPoint ip = event.getInjectionPoint();
assert ip != null;
final Set<Annotation> existingQualifiers = ip.getQualifiers();
if (existingQualifiers != null && !existingQualifiers.isEmpty()) {
final Set<Annotation> newQualifiers = new HashSet<>();
existingQualifiers.stream().forEach((qualifier) -> {
assert qualifier != null;
if (qualifier instanceof Key) {
newQualifiers.add(new PropertyLiteral(((Key)qualifier).value()));
} else {
newQualifiers.add(qualifier);
}
});
event.configureInjectionPoint().qualifiers(newQualifiers);
}
}
}

This (private!) method will be called on every injection point found by the container (or created by other portable extensions!).  You can restrict the types of points you’re interested in by using something other than wildcards, but this will do for our purposes.

Here, you can see that we ask the InjectionPoint directly for its qualifiers, and we effectively remove the Config.Key qualifier and replace it with an equivalent Property qualifier.

So under the covers it now looks like all client code is using Property, not Config.Key in its injection points.  Cool!

Let’s circle back to the producer method, now that we know it will be invoked.

In CDI, a producer method can take parameters.  If it does, then the parameters are supplied to it by the container as if the method had been marked with @Inject.  So our producer method is handed an InjectionPoint object and a BigCoConfigurationEngine object.  (Let’s pretend for the sake of this article that an instance of BigCoConfigurationEngine has already been found by the container.  We’ll just assume it’s there so will be successfully injected here.)

The InjectionPoint unsurprisingly represents the site of the injection that the producer method will be called upon to implement as needed (as determined by the scope, in our case Dependent).  You can get lots of useful things from it: the parameter or field being injected “into”, the class housing the injection point, and so on.

So we should be able to get the actual Property instance that caused our producer method to fire, and, using the value of its value element, ask the BigCoConfigurationEngine to get us the right configuration value.

There is one very important thing to note here.

There are a couple of “paths” to the information we would like.  Only one of them is valid.

The first path looks like an easy one: we could just call injectionPoint.getAnnotated(), and then call getAnnotation(Class) on it and pass it our Property class.

But we’ll get back no such annotation!  How can that be?  Didn’t our portable extension munge things at startup so that all Config.Key qualifiers got effectively replaced by Property qualifiers?

Yes, but on the injection point itself, not on the objects reachable from the injection point.

That gives us path #2, which is the right one, though it is more cumbersome.  We need to call injectionPoint.getQualifiers(), and then find the Property annotation in there.  That is, our portable extension affected the contents of the return value of the InjectionPoint::getQualifiers method, not the contents of the return value of injectionPoint.getAnnotated().getAnnotations().  Sit and think about that for a moment.  I’ll wait.

So our producer method ends up looking like this:


@Produces
@Dependent
@Property
private static final Object produceProperty(final InjectionPoint injectionPoint, final BigCoConfigurationEngine config) {
Objects.requireNonNull(config);
Object returnValue = null;
if (injectionPoint == null) {
// This is a case that really shouldn't happen.
return null; // ok to do with Dependent scope
} else {
final Set<Annotation> qualifiers = injectionPoint.getQualifiers();
assert qualifiers != null;
assert !qualifiers.isEmpty();
final Optional<Annotation> propertyAnnotation = qualifiers.stream().filter((annotation) -> {
return annotation instanceof Property;
}).findFirst();
assert propertyAnnotation.isPresent();
final Property property = Property.class.cast(propertyAnnotation.get());
assert property != null;
final String name = property.value();
assert name != null;
returnValue = config.get(name);
}
return returnValue;
}

The takeaway for me here was: in your producer method, if you want to be maximally flexible and a good citizen of the CDI multiverse, make sure you investigate the InjectionPoint metadata itself as much as possible for information, not the Annotated instances reachable from it.

Starting CDI beans eagerly and portably

There are several web resources out there that describe how to get a CDI bean (usually ApplicationScoped) to be instantiated when the CDI container comes up.  Here’s an arbitrarily selected one from Dan Allen:


@ApplicationScoped
@Startup
public class StartupBean
{
@PostConstruct
public void onStartup()
{
System.out.println("Application starting up.");
}
}


public class StartupBeanExtension implements Extension
{
private final Set<Bean<?>> startupBeans = new LinkedHashSet<Bean<?>>();
<X> void processBean(@Observes ProcessBean<X> event)
{
if (event.getAnnotated().isAnnotationPresent(Startup.class) &&
event.getAnnotated().isAnnotationPresent(ApplicationScoped.class))
{
startupBeans.add(event.getBean());
}
}
void afterDeploymentValidation(@Observes AfterDeploymentValidation event, BeanManager manager)
{
for (Bean<?> bean : startupBeans)
{
// the call to toString() is a cheat to force the bean to be initialized
manager.getReference(bean, bean.getBeanClass(), manager.createCreationalContext(bean)).toString();
}
}
}

Let’s look at the extension immediately above.

The AfterDeploymentValidation event is the only event a portable extension can observe in a portable manner that indicates that the container is open for business. It is guaranteed to fire last in the dance that the container performs as it starts up.

In the extension above, then, you can see that it has saved off the beans it has discovered that have been annotated with a Startup annotation (which isn’t defined in the gist, so it could be javax.ejb.Startup or a Startup annotation that Dan has defined himself). Then, for these beans, it uses the BeanManager‘s getReference() method to get an actual Java object representing those beans.

So what’s the toString() call for?

The short answer is: this is the only method that could conceivably cause the container-managed client proxy that is the object reference here to call the actual constructor of the actual underlying object that the user and everyone else is actually interested in.

For more detail, let’s look at the specification, section 6.5.3, which concerns contextual references—the return value of the getReference() method above—and which reads in part:

If the bean has a normal scope [e.g. not Dependent or Singleton], then the contextual reference for the bean is a client proxy, as defined in Client proxies, created by the container, that implements the given bean type and all bean types of the bean which are Java interfaces.

OK, so whatever the getReference() method returns is a client proxy. That means it’s going to forward any method invocation it receives to the object that it’s proxying (known as the bean’s contextual instance. CDI containers try to be efficient, so that object may not have been created yet—the proxy, in other words, might be lazy. So here, the contextual reference returned is a contextual reference (a client proxy) of type Object, and the toString() invocation causes the contextual reference (client proxy) to realize that oh, hey, the underlying contextual instance of whatever bean this is doesn’t yet exist, and to therefore invoke the “real” constructor, so that the “real” object (the contextual instance) can return something from its toString() method.

As a happy side effect, the container is of course the one causing the instantiation of the “real” object, so it is going to perform dependency injection, invoke initializer methods, invoke any PostConstruct-annotated methods, and so on.  Presto: you have a portable way for your bean to be instantiated when the container comes up.

(Side note: toString() in particular is used because there is a little nugget at the bottom of the Client Proxies section of the specification that says, innocuously (emphasis mine):

The behavior of all methods declared by java.lang.Object, except for toString(), is undefined for a client proxy. Portable applications should not invoke any method declared by java.lang.Object, except for toString(), on a client proxy.

File that one away: among other things that might mean don’t put your CDI-managed objects in Maps or Collections, since doing so will use client proxy equals(Object) and hashCode() methods!)

So.  If you’re feeling like this whole thing is a bit of a steaming hack—you call toString(), and a whole lot of very sophisticated magic happens (!)—I can’t disagree.

Fortunately, there’s a better way.

Instead of the toString() hack above, you can do the same thing in the extension in a more sanctioned, more explicit manner.

The first thing to understand is: who is doing the actual creation?  If we can understand that, then we can understand how to do it eagerly and idiomatically.

The ultimate answer is: the bean itself, via the create() method it implements from the Contextual interface. So if you ever get a Bean in your hand (or any other Contextual), you can call create() on it all day long and get new instances (this should sound scary, because it is).  For example, suppose you have an ApplicationScoped-annotated bean in your hand in the form of a Bean object.  If you call create() on it three times, you will create three instances of this object, hopefully surprising and gently horrifying you. Those instances may be wrapped in proxies (for interception and such), but they won’t be wrapped in client proxies.  Don’t do this!

Still, scary or not, we’ve found the method that some part of the container somewhere at some point will invoke when a contextual instance is needed (to further wrap in a contextual reference). But obviously when you inject an ApplicationScoped-annotated bean into, say, three different locations in your code somewhere, everything behaves as though there’s only one instance, not three. So clearly the container is not running around rampantly calling create() every time it needs an object.  It’s acquiring them from somewhere, and having them created if necessary.

The container is actually calling a particular get() method on the bean’s associated Context, the machinery that implements its scope. This method’s contract basically says that the Context implementation should decide whether to return an existing contextual instance, or a new one. So you can see that the Context underlying application scope will (hopefully!) return the One True Instance™ of the bean in question, whereas the Context implementation underlying some other scope may create new instances each time.

OK, so what do we know?  Let’s step back.

So to eagerly instantiate beans at startup while respecting their scopes, we should follow this approach in the extension as well—we’ll do basically what a lazy contextual reference (client proxy) does, in other words, when a toString() method is invoked on it.  We’ll need to effectively ask the right Context for a contextual instance of the bean in question, creating it if necessary.  This also would allow for custom-scoped beans to be instantiated eagerly, provided of course that the Context backing the custom scope is actually active.

If you have a BeanManager handy, and a Bean object of a particular type (say Bean<Object>), then you can get the relevant Context quite easily:

final Context context = beanManager.getContext(bean.getScope());

Then you need a CreationalContext, the somewhat opaque object that assists the Context with creation, should the Context decide that creation is necessary:

final CreationalContext<Object> cc = beanManager.createCreationalContext(bean);

Finally, we can ask the Context for a contextual instance directly:

final Object contextualInstanceNotContextualReference = context.get(bean, cc);

Note, as the variable name makes clear, this is a contextual instance, not a contextual reference!  This is not a client proxy!  So you really don’t want to use it after this point.

So if you replace Dan’s line 19 above with these code snippets, you will eagerly instantiate beans at startup without relying on magic side effects.

CDI 2.0: Fun With Composition, Part 3

(Disclaimer: I work for Oracle doing Java EE architecture and other things, but none of my writings here or anywhere else on this site have anything to do with my day job there.  In short, as always, these are just the writings of a Java EE hacker using publicly available stuff.)

In the last post, we saw how you could write a portable extension that starts up a JAX-RS runtime after the CDI container is open for business.  (I recommend reading all the posts in this series, starting with the first one.)

Here’s the extension again:


/*
* Copyright © 2016–2017 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package com.serverco;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.event.Observes;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.enterprise.inject.spi.Extension;
import org.glassfish.grizzly.http.server.HttpServer;
public class HttpServerStartingExtension implements Extension {
private volatile HttpServer server;
private void startHttpServer(@Observes final AfterDeploymentValidation event, final BeanManager beanManager) {
if (beanManager != null && this.server == null) {
final HttpServer server = get(beanManager, HttpServer.class);
if (server != null) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public final void run() {
shutdown(server);
}
});
if (!server.isStarted()) {
try {
server.start();
} catch (final IOException ioException) {
event.addDeploymentProblem(ioException);
}
}
this.server = server;
}
}
}
private void shutdownHttpServer(@Observes final BeforeShutdown event, final BeanManager beanManager) {
if (this.server != null) {
try {
// You should really run this thing on another thread;
// join()ing here just for expediency
Thread.currentThread().join();
} catch (final InterruptedException interruptedException) {
Thread.currentThread().interrupt();
}
shutdown(server);
}
}
private static final <T> T get(final BeanManager beanManager, final Type c, final Annotationqualifiers) {
T returnValue = null;
if (beanManager != null && c != null) {
final Set<Bean<?>> beans = beanManager.getBeans(c, qualifiers);
if (beans != null && !beans.isEmpty()) {
final Bean<?> bean = beanManager.resolve(beans);
assert bean != null;
final CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean);
assert creationalContext != null;
@SuppressWarnings("unchecked")
final T reference = (T)beanManager.getReference(bean, c, creationalContext);
returnValue = reference;
}
}
return returnValue;
}
private static final void shutdown(final HttpServer server) {
if (server != null && server.isStarted()) {
try {
server.shutdown().get();
} catch (final ExecutionException ignore) {
} catch (final InterruptedException interruptedException) {
Thread.currentThread().interrupt();
}
}
}
}

For this extension to work, though, line 34 has to return a non-null HttpServer.  As you can see, there’s nothing in this extension that makes such a thing.  The extension is, fortunately, relatively fault-tolerant (or at least that’s the idea 😀), so if no such HttpServer is around, then the extension should just silently do nothing.

In CDI in general, you write things so that the supplying of an object you need is SEP (someone else’s problem).  That is, quite apart from the mechanics of injection and so on, the important part of dependency injection is that if you need something, you just presume that it will be handed to you.  So here we presume that somehow, some way, an HttpServer will be available in the CDI container.  If it turns out that no such object exists, well, OK, we just do no harm.

So how could an HttpServer get in to the container so that it would be picked up by this extension?  Well, it could be a bean itself.  Maybe we’ll get lucky?  But probably not, as the Javadoc shows.  Sure enough, although HttpServer has a zero argument constructor, and hence could be a CDI bean, there are no further injection points on it, and furthermore the Grizzly module of which it is a part does not feature a META-INF/beans.xml descriptor, suggesting, though not proving, that we’re not going to get lucky.  So HttpServer is technically speaking a valid CDI bean, but a pretty limited one if discovered or added programmatically to a CDI container as-is.

How else could it get in there?  Well, there could be a producer method.  This seems like a good way to go.  A producer method makes bean instances out of raw materials available in the CDI container.  That sounds like exactly what we want.  So let’s say that ServerCo, writes one to make an HttpServer using the features of the GrizzlyHttpServerFactory class present in Jersey.  Let’s say it looks like this, and, just for kicks, lives in a different jar file than the one that houses the portable extension:


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package serverco;
import java.net.URI;
import java.net.URISyntaxException;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.CreationException;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.ws.rs.core.Application;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ContainerFactory;
@ApplicationScoped
class Producers {
private Producers() {
super();
}
@Produces
@Dependent
private static final GrizzlyHttpContainer produceGrizzlyHttpContainer(final Instance<Application> applicationInstance) {
final GrizzlyHttpContainer returnValue;
if (applicationInstance == null || applicationInstance.isUnsatisfied()) {
returnValue = null;
} else {
returnValue = ContainerFactory.createContainer(GrizzlyHttpContainer.class, applicationInstance.get());
}
return returnValue;
}
@Produces
@Dependent
private static final HttpServer produceHttpServer(final Instance<GrizzlyHttpContainer> handlerInstance) {
final HttpServer returnValue;
if (handlerInstance == null || handlerInstance.isUnsatisfied()) {
returnValue = null;
} else {
URI uri = null;
try {
uri = new URI("ignored", null /* no userInfo */, "localhost", 80, null, null /* no query */, null /* no fragment */);
} catch (final URISyntaxException uriSyntaxException) {
throw new CreationException(uriSyntaxException);
}
returnValue = GrizzlyHttpServerFactory.createHttpServer(uri, handlerInstance.get(), false, null, false);
}
return returnValue;
}
}

Let’s look at line 46 above.  This is a producer method that creates an HttpServer if one is needed.  To do so, it requires a GrizzlyHttpContainer, but such a thing might not exist.  To express this kind of optional behavior, it requests that an Instance<GrizzlyHttpContainer> be supplied to it.  The CDI container will make such a thing available whether its underlying “payload” exists or not, so we can test things about it here.  See line 48: if the Instance is unsatisfied—that is, if there isn’t a GrizzlyHttpContainer in the CDI container anywhere, nor a means for one to be synthesized or manufactured—then we can return null here, and the portable extension we saw earlier will effectively quietly become one big no-op.

On the other hand, starting at line 51, if there is a GrizzlyHttpContainer we can work with, well, then, it’s a pretty simple matter to use it to construct a new HttpServer (line 57).

Very cool.  OK, so where does the GrizzlyHttpContainer come from?

That’s the purpose of the first producer method, that you can see at line 34.  That method says how a GrizzlyHttpContainer can be created, provided that someone supplies a javax.ws.rs.core.Application object.  Obviously, if no such object is available in the CDI container then the method should effectively quietly do nothing, so you can see at lines 36 and 37 that’s what happens.

OK, so clearly the first producer method makes something that the second producer method needs.  And the first producer method works if there’s an Application.  And the portable extension consumes the output of the second producer method and uses it to start a server when the container comes up.

So where does the Application come from?

Let us turn back to our poor developer, who, you recall from my last post, was done.  She had written a JAX-RS application and a root resource class and—right at that point—wanted to be finished.  She simply wanted some magic to happen that would let her application start.  She didn’t want to write a main method.  She didn’t want to go start an application server and run some complicated deployment recipe.

Recall also that if you’re keeping track we have several notional jar files (or directory locations—classpath roots, really) that we’ve stuck in fictional corners.  We have:

  • A CDI 2.0 EDR2 implementation (like weld-se-core version 3.0.0.Alpha17 or later)
  • the developer’s classpath root, containing nothing but her Application subclass and her root resource class
  • ServerCo’s portable extension jar file described in Part 2
  • A classpath root that contains the boilerplate main class that brings a CDI container up and shuts it down, described in my first post
  • ServerCo’s jar file containing the producer methods noted above

What’s really neat is if you run this:

java -classpath /path/to/weld-se-core-3.0.0.Alpha17.jar:/path/to/weld-se-core/dependencies:/path/to/developer/code:/path/to/serverco/portable-extension-1.0.jar:/path/to/boilerplate/code:/path/to/serverco/producers-1.0.jar:/path/to/serverco/dependencies com.foobar.Main

…then I hope to have shown that you will get an HTTP endpoint up and running on localhost port 80 that runs our developer’s JAX-RS application.

 

CDI 2.0: Fun With Composition, Part 2

In my last post I laid the groundwork for a compositional approach to deploying applications in CDI 2.0.  The main method doesn’t need to do anything.  Portable extensions don’t need to know anything about the main method.  User code doesn’t need to know anything about portable extensions.

Recall that our developer has written the following standards-compliant JAX-RS application:


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package developer;
import java.util.Collections;
import java.util.Set;
import javax.ws.rs.core.Application;
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class HelloWorldApplication extends Application {
public HelloWorldApplication() {
super();
}
@Override
public Set<Class<?>> getClasses() {
return Collections.singleton(HelloWorldResource.class);
}
}


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package developer;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.core.Application;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("hello")
@RequestScoped
public class HelloWorldResource {
@GET
@Produces("text/plain")
public String hello() {
return "Hello, world!";
}
}

…and just wants to run it.  But she also wants to be done here, and doesn’t want to write a main method or depend in code on vendor-specific classes.  Also, because we are living in The Future™, she wants to avoid deploying to some application server by hand.

Enter portable extensions and composition.

First, recall our generic main method, parked over in a corner in a jar of its own:


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package com.foobar;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
public class Main {
public static final void main(final String[] args) throws Exception {
final SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
assert containerInitializer != null;
try (final SeContainer container = containerInitializer.initialize()) {
assert container != null;
}
}
}

Now let’s say ServerCo authors this nice little extension:


/*
* Copyright © 2016–2017 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package com.serverco;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.event.Observes;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.enterprise.inject.spi.Extension;
import org.glassfish.grizzly.http.server.HttpServer;
public class HttpServerStartingExtension implements Extension {
private volatile HttpServer server;
private void startHttpServer(@Observes final AfterDeploymentValidation event, final BeanManager beanManager) {
if (beanManager != null && this.server == null) {
final HttpServer server = get(beanManager, HttpServer.class);
if (server != null) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public final void run() {
shutdown(server);
}
});
if (!server.isStarted()) {
try {
server.start();
} catch (final IOException ioException) {
event.addDeploymentProblem(ioException);
}
}
this.server = server;
}
}
}
private void shutdownHttpServer(@Observes final BeforeShutdown event, final BeanManager beanManager) {
if (this.server != null) {
try {
// You should really run this thing on another thread;
// join()ing here just for expediency
Thread.currentThread().join();
} catch (final InterruptedException interruptedException) {
Thread.currentThread().interrupt();
}
shutdown(server);
}
}
private static final <T> T get(final BeanManager beanManager, final Type c, final Annotationqualifiers) {
T returnValue = null;
if (beanManager != null && c != null) {
final Set<Bean<?>> beans = beanManager.getBeans(c, qualifiers);
if (beans != null && !beans.isEmpty()) {
final Bean<?> bean = beanManager.resolve(beans);
assert bean != null;
final CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean);
assert creationalContext != null;
@SuppressWarnings("unchecked")
final T reference = (T)beanManager.getReference(bean, c, creationalContext);
returnValue = reference;
}
}
return returnValue;
}
private static final void shutdown(final HttpServer server) {
if (server != null && server.isStarted()) {
try {
server.shutdown().get();
} catch (final ExecutionException ignore) {
} catch (final InterruptedException interruptedException) {
Thread.currentThread().interrupt();
}
}
}
}

Ignoring the utility methods for a moment, at line 32 the extension is notified that the CDI container it’s a part of is now open for business.

At line 34, using the get() utility method (see line 65), it asks the container for an HttpServer instance, if there is one.

If indeed there is one, then it starts the server.

Control flows back to the main method.  Specifically, the main method now has an SeContainer in its hands.  It promptly, of course, does nothing, and so the container starts to shut down.

At line 54 above, the portable extension is notified that unless something else happens, the container is going to shut down.  It arranges for the server to stay up with the join() call on line 57, and until the server is interrupted or killed or otherwise stopped we will block here.

Look, a JAX-RS server that comes up as a side effect of a CDI container starting up!

But wait…at line 35…will that HttpServer ever be non-null?  Who put an HttpServer into the CDI container?  Did anyone?

No.  Not yet.

We’ll address that in the next post!

CDI 2.0: Fun With Composition, Part 1

(Disclaimer: I work for Oracle doing Java EE architecture and other things, but none of my writings here or anywhere else on this site have anything to do with my day job there.  In short, as always, these are just the writings of a Java EE hacker using publicly available stuff.)

So in my last post I was musing on the fact that a CDI SE application that appears to do nothing may do a great deal indeed.

Recall that you start a CDI container from Java SE like this:


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package com.foobar;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
public class Main {
public static final void main(final String[] args) throws Exception {
final SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
assert containerInitializer != null;
try (final SeContainer container = containerInitializer.initialize()) {
assert container != null;
}
}
}

Now let’s write a portable extension that is notified after the container is open for business:


package com.serverco;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
public class SimplePortableExtension implements Extension {
public SimplePortableExtension() {
super();
// Called by java.util.ServiceLoader
}
public void containerIsOpenForBusiness(@Observes final AfterDeploymentValidation event, final BeanManager beanManager) {
System.out.println("*** container is open for business!");
}
}

This extension is not a CDI bean exactly.  It doesn’t have a scope (that’s a bit of a white lie, but substantially true).  It is created by the java.util.ServiceLoader mechanism once as part of container initialization.  That means it needs a no-argument constructor (see line 11) and an entry in its containing archive’s META-INF/services/javax.enterprise.inject.spi.Extension file that, in this case, looks like this:

com.serverco.SimplePortableExtension

So let’s mentally park com.serverco’s extension over in the corner in its own jar file, and the main method we outlined above over in the other corner in another jar file.

If we were to run that main method with a classpath consisting of both jar files, we would see:

*** container is open for business!

…on the console, even though neither the main method nor the extension inherently knew about each other.

That’s pretty neat.

Now, just for fun, let’s say our developer creates a simple, standard JAX-RS application (no Jersey, no RestEasy, just standards):


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package developer;
import java.util.Collections;
import java.util.Set;
import javax.ws.rs.core.Application;
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class HelloWorldApplication extends Application {
public HelloWorldApplication() {
super();
}
@Override
public Set<Class<?>> getClasses() {
return Collections.singleton(HelloWorldResource.class);
}
}


/*
* Copyright 2016 Laird Nelson. Released under the terms of the MIT license: https://opensource.org/licenses/MIT
*/
package developer;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.core.Application;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("hello")
@RequestScoped
public class HelloWorldResource {
@GET
@Produces("text/plain")
public String hello() {
return "Hello, world!";
}
}

Let’s say now our developer wants to be done, right here, and in the abstract in some sense wants to just run this application right here, right now.

Well, she’s going to need some kind of container to do so.  She could package this thing up in a .war file and deploy it somewhere, but that is not The Future™, so instead she just wants to run this application.

Jersey, of course, is one implementation of the JAX-RS standard.  Our developer could embed Jersey’s recipe for starting an embedded Grizzly server in a main() method she writes, and…but she wanted to be done!  She doesn’t want to write a main method with this recipe in it:


java.net.URI baseUri = javax.ws.rs.core.UriBuilder.fromUri("http://localhost/&quot;).port(9998).build();
org.glassfish.jersey.server.ResourceConfig config = new org.glassfish.jersey.server.ResourceConfig(developer.HelloWorldResource.class);
org.glassfish.grizzly.http.server.HttpServer server = org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer(baseUri, config);
// and so on and so on

Well, OK, someone else could write this main method, and accept her application as a command line argument…which is sort of like deploying, and that’s not The Future™ either.

It would be kind of cool if our developer’s application, when placed on a classpath with potentially other jar files, one of which contains a main method, another of which contains a server implementation, etc., just ran.

It would also be kind of cool if our developer could easily try switching from using Jersey to using RestEasy without really doing much.

CDI 2.0 as you’ve probably guessed makes this pretty simple.  Stay tuned for the next post.

CDI 2.0

(Disclaimer: I work for Oracle doing Java EE architecture and other things, but none of my writings here or anywhere else on this site have anything to do with my day job there.  In short, as always, these are just the writings of a Java EE hacker using publicly available stuff.)

Have you taken a look at CDI 2.0 (Early Draft 2) yet?

You really should.

If you weren’t paying attention, CDI added a few interesting things that are on their way to being part of the official standard.

Perhaps the most notable is that CDI is no longer a parasite.

A parasite is a being that lives inside a host.  Just so, CDI in versions prior to 2.0 could be instantiated only in non-standardized manners.  That is, you would have to invoke Weld classes, or OpenWebBeans classes, to get a CDI environment up and running that your code could play in.

But no longer.  Now you can discover and instantiate a CDI container from Java SE in a vendor independent fashion.  Here’s what it looks like, and 80% of the following snippet is license text and documentation:


/*
* Copyright 2016 Laird Nelson.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.foobar;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
/**
* A class whose {@linkplain #main(String[]) <code>main</code> method}
* {@linkplain SeContainerInitializer#initialize() initializes} a new
* {@link SeContainer}.
*
* @author <a href="http://about.me/lairdnelson&quot; target="_parent">Laird Nelson</a>
*
* @see SeContainerInitializer#initialize()
*/
public class Main {
/**
* Creates a new {@link Main}.
*/
public Main() {
super();
}
/**
* {@linkplain SeContainerInitializer#initialize() Initializes} a
* new {@link SeContainer} and then {@linkplain SeContainer#close()
* closes} it.
*
* @param args command-line arguments; may be {@code null}
*
* @exception Exception if an error occurs
*
* @see SeContainerInitializer#newInstance()
*
* @see SeContainerInitializer#initialize()
*
* @see SeContainer#close()
*/
public static final void main(final String[] args) throws Exception {
final SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
assert containerInitializer != null;
try (final SeContainer container = containerInitializer.initialize()) {
assert container != null;
}
}
}

view raw

Main.java

hosted with ❤ by GitHub

See line 61 above?  That gets an SeContainerInitializer.  From there, you call initialize(), and that gets you an SeContainer.  From there, you can get its BeanManager, and from there you can do anything you like.

But what’s really interesting is what is not going on on line 65 above.

On line 65 above, nothing is happening!  That means the container comes up (line 63), and when it has come up, it goes down again (the implicit close() called by the try-with-resources block, also at line 63).  Hmm; I guess this application doesn’t do anything.

Actually, you don’t know that.

In between coming up and going down, the container has found and created all the portable extensions on the classpath, if there were any, run through its startup lifecycle (which portable extensions can be involved in and affect), discovered all the bean archives on the classpath whether by itself or with the assistance of portable extensions and alerted (potentially) every bean that its ApplicationScoped scope has initialized.  Then depending on what injection any observing bean might perform, it may notify other beans about the availability of other scopes.

Lastly, it notifies the beans about the scopes going away, and then it notifies extensions that the container is about to go down.

In the meantime all the beans and portable extensions involved can fire events of any kind on the local event bus to notify each other of interesting things.

That’s an awful lot of valuable stuff for an application that doesn’t do anything.

It also means that you could have an executable that doesn’t presume anything about the work to be done, but still frees the developer from having to supply a main method, and provides an integration backplane for a whole host of technologies.

For example, the act of placing a JAX-RS application in a jar file could—depending on the portable extensions in play in any given CDI container environment—result in that JAX-RS application being deployed on an embedded server.

I’ll leave you with that before my next post.