//enterprise java /
We are using the Configurable annotation to override the configuration key. If a
field is denoted with Configurable, we are
using the value() as a lookup key instead
of using the fully qualified field name
(see Listing 11).
The configuration consumer only has
to provide the desired lookup key by
denoting the field with the @Configurable
annotation and providing the value():
can also provide stage-dependent configuration via injection of primitive types:
LISTING 7 LISTING 8 LISTING 9 LISTING 10 LISTING 11 LISTING 12
org. jboss.weld.exceptions.DeploymentException: org.jboss.weld.exceptions.
DeploymentException: WELD-001408 Unsatisfied dependencies for type [String]
with qualifiers [@Default] at injection point [[field] @Inject private com.abien.
configuration.business.primitives.consumer.Messenger.message] […]
COMMUNITY
@Stateless
public class Greeter {
@Inject @StageDependent
private String stagedMessage;
}
The consumer only has to mark the
injected field as @StageDependent to get
environment-dependent values.
JAVA IN ACTION
@Stateless
public class Greeter {
@Inject @Configurable
("greetings")
private String message;
//..
}
Download all listings in this issue as text
Stage-Dependent Configuration
The injection of primitives and the staging mechanism can be combined easily.
The already introduced @StageDependent
qualifier can be used to produce stage-dependent configuration entries. Also,
the exposed Stage is injected to the
getString method and
used to build a stage-dependent key, as
shown in Listing 12.
With the prepended
stage name, the field
name or the value
of the @Configurable
annotation is used to
fetch the configuration
value. Now we are not
only able to inject different implementations
of an interface, but we
In addition to
overriding the
defaults with
plug-ins, you
can even
manage the
configuration
at runtime.
Conventional Configuration Store
The centralization of code dealing with
configuration is the main benefit of
the approach discussed here. All configuration requests are served from
a single place: the Configurator class.
We could apply the “Convention over
Configuration” spirit to the Configurator
also and provide the default values for
all obvious configuration entries out of
the box (see Listing 13).
In the fetchConfiguration method of
the @Singleton Configurator, a java.util
.HashMap is populated with default
values. In our sample, a single Map is
used for all stages, but it could be split
easily into dedicated Map instances
for each stage. Centralizing suitable
defaults in a central Map simplifies
maintenance. To change the values,
however, you will have to recompile the
Configurator class, which might not be
desired for volatile entries.
interface, we introduce a flexible extension mechanism:
public interface
ConfigurationProvider {
}
The ConfigurationProvider interface is injected to the Configurator
wrapped with the
javax.enterprise.inject
.Instance<ConfigurationProvider> interface. With javax.enterprise.inject.Instance
<ConfigurationProvider>, the injection of
the ConfigurationProvider interface is lazy
and will work even if no valid implementation of the interface is deployed (see
Listing 14).
Map<String,String> instance, and merge
it with the default values hardcoded
in the @PostConstruct method. It is the
simplest possible implementation of a
plug-in mechanism in Java EE: you can
easily extend existing functionality with
external implementation on demand.
Because we already relied on
JSF to provide the staging information, we could also use JSF as
a configuration provider. We only
have to expose the Servlet’s
context-params as a Map<String,String> in the
FacesContextExposer (see Listing 15).
In the next step, we implement the
ConfigurationProvider interface and inject
it with the FacesContextExposer provided
by the Map instance (see Listing 16).
Now the hardcoded default values
can be overridden easily in web.xml by
context-param entries (see Listing 17).
You are not limited to web.xml.
Other implementations of the
ConfigurationProvider interface could
fetch the implementation from XML,
property files, or databases with the Java
ABOUT US
blog
Plug-ins (or the Sky Is the Limit)
By encapsulating the configuration
population with the ConfigurationProvider
61
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////////// MAY/JUNE 2012