How to inject String constants easily with Weld? - java

We have a situation where we provide an external configuration in form of a Map to our running programs. I have found that JSR-330 Dependency Injection gives a much cleaner way to use that configuration map in the code instead of passing the map around or to use JNDI to get it.
#Inject #Named("server.username") String username;
lets the JSR-330 implementation fill in this field automatically.
With Guice I can set the value with
bindConstant().annotatedWith(Names.named(key)).to(value);
I would like to be able to do the same in Weld (bind "server.username" to e.g. "foobar") and I understand that the mechanism most likely is beans.xml, but I would prefer a simple "feed this map to Weld, please" code alternative. What would be a good way to do this?
EDIT 2013-10-16: After looking into Dagger which works at compile time and not runtime, I found that with us usually having 10-20 per program we could live with having a #Provider method for each configuration string which then looks up in the configuration map. This allows for method specific behavior (including default values), ability to provide javadoc, and ability to put all these methods in the same class. Also it works well with Weld out of the box. I am considering writing a fuller explanation in a blog entry.

I'd like that bounty now please. Figuring this out taught me quite a bit about the innards of WELD, and here's the most interesting lesson: #Named is a qualifier, and must be treated as such if you are going to be able to match against it.
I do have a warning for you: If you are missing any values in your app, it will fail at deploy or load time. This may be desirable for you, but it does specifically mean that "default" values are not possible.
The injection point is specified exactly as you have above, and here's the extension code needed to make it work:
#ApplicationScoped
public class PerformSetup implements Extension {
Map<String, String> configMap;
public PerformSetup() {
configMap = new HashMap<String, String>();
// This is a dummy initialization, do something constructive here
configMap.put("string.value", "This is a test value");
}
// Add the ConfigMap values to the global bean scope
void afterBeanDiscovery(#Observes AfterBeanDiscovery abd, BeanManager bm) {
// Loop through each entry registering the strings.
for (Entry<String, String> configEntry : configMap.entrySet()) {
final String configKey = configEntry.getKey();
final String configValue = configEntry.getValue();
AnnotatedType<String> at = bm.createAnnotatedType(String.class);
final InjectionTarget<String> it = bm.createInjectionTarget(at);
/**
* All of this is necessary so WELD knows where to find the string,
* what it's named, and what scope (singleton) it is.
*/
Bean<String> si = new Bean<String>() {
public Set<Type> getTypes() {
Set<Type> types = new HashSet<Type>();
types.add(String.class);
types.add(Object.class);
return types;
}
public Set<Annotation> getQualifiers() {
Set<Annotation> qualifiers = new HashSet<Annotation>();
qualifiers.add(new NamedAnnotationImpl(configKey));
return qualifiers;
}
public Class<? extends Annotation> getScope() {
return Singleton.class;
}
public String getName() {
return configKey;
}
public Set<Class<? extends Annotation>> getStereotypes() {
return Collections.EMPTY_SET;
}
public Class<?> getBeanClass() {
return String.class;
}
public boolean isAlternative() {
return false;
}
public boolean isNullable() {
return false;
}
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
#Override
public String create(CreationalContext<String> ctx) {
return configValue;
}
#Override
public void destroy(String instance,
CreationalContext<String> ctx) {
// Strings can't be destroyed, so don't do anything
}
};
abd.addBean(si);
}
}
/**
* This is just so we can create a #Named annotation at runtime.
*/
class NamedAnnotationImpl extends AnnotationLiteral<Named> implements Named {
final String nameValue;
NamedAnnotationImpl(String nameValue) {
this.nameValue = nameValue;
}
public String value() {
return nameValue;
}
}
}
I tested that this worked by making a WELD-SE app:
#ApplicationScoped
public class App {
#Inject
#Parameters
List<String> parameters;
#Inject
#Named("string.value")
String stringValue;
public void printHello(#Observes ContainerInitialized event) {
System.out.println("String Value is " + stringValue);
}
}
Lastly, don't forget /META-INF/services/javax.enterprise.inject.spi.Extension, replacing weldtest with the classpath you use:
weldtest.PerformSetup
That should make all of this work. Let me know if you run into any difficulties and I'll send you my test project.

Not all that interested in the bounty, but I'll take it if it's still on the table. This is VERY similar to some code I'm using at $DAYJOB, and so this isn't theory, it's what I use in production code, but modified to protect the guilty. I haven't tried compiling the modified code, so be warned that I may have made some errors in changing names and such, but the principles involved here have all been tested and work.
First, you need a Value Holder Qualifier. Use #Nonbinding to keep WELD from matching ONLY to qualifiers with identical values, since we want all values of this particular qualifier to match a single injection point. By keeping the qualifier and value in the same annotation, you can't just "forget" one of them by accident. (KISS principle)
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface ConfigValue {
// Excludes this value from being considered for injection point matching
#Nonbinding
// Avoid specifying a default value, since it can encourage programmer error.
// We WANT a value every time.
String value();
}
Next, you need a producer method which knows how to get the Map. You should probably have a Named bean which holds the producer method, so you can either explicitly initialize the value by using getters/setters, or else have the bean initialize it for you.
We must specify a blank value for the qualifier on the producer method to avoid compile time errors, but it's never used in practice.
#Named
public class ConfigProducer {
//#Inject // Initialize this parameter somehow
Map<String,String> configurationMap;
#PostConstructor
public void doInit() {
// TODO: Get the configuration map here if it needs explicit initialization
}
// In general, I would discourage using this method, since it can be difficult to control exactly the order in which beans initialize at runtime.
public void setConfigurationMap(Map<String,String> configurationMap) {
this.configurationMap = configurationMap;
}
#Produces
#ConfigValue("")
#Dependent
public String configValueProducer(InjectionPoint ip) {
// We know this annotation WILL be present as WELD won't call us otherwise, so no null checking is required.
ConfigValue configValue = ip.getAnnotated().getAnnotation(ConfigValue.class);
// This could potentially return a null, so the function is annotated #Dependent to avoid a WELD error.
return configurationMap.get(configValue.value());
}
}
Usage is simple:
#Inject
#ConfigValue("some.map.key.here")
String someConfigValue;

It may be possible to implement this as an #Dependent Producer method that itself injects an #InjectionPoint which would allow you to reflect upon the field you're being injected into -- this would let you peek into a custom annotation (not a qualifier) member on the field to figure out the val you want to return
#Inject #ConfigMapQualifier #Val("user.name") String user;
...
#Produces #ConfigMapQualifier configProducr(...) {
...
#Inject InjectionPoint ip;
// use e.g. ip/getJavaMember() then reflection to figure out the #Val value membr.

Would implementing a custom Weld InjectionServices not be an option here ?

what about
#Resource(name = "server.username", type = java.lang.String.class)
private String injectTo;
Javadoc: http://download.oracle.com/javase/6/docs/api/javax/annotation/Resource.html

Related

How to simply handle a factory of multiple parameter-diverging classes with Guice?

I have the following very simple interface:
public interface IDataSource<T> {
Observable<T> observable();
}
Now I'll be having multiple implementations of it. Each of those implementation may rely on varying parameters (different storage objects: JDBC, Cassandra, Redis...). So for instance I'll have:
public class CassandraDataSource implements IDataSource<MyCassandraObject> {
#Inject
public CassandraDataSource(Keyspace ks) {
// ...
}
}
public class OtherCassandraDataSource implements IDataSource<MyOtherCassandraObject> {
#Inject
public OtherCassandraDataSource(Keyspace ks) {
// ...
}
}
public class JDBCDataSource implements IDataSource<MyJdbcObject> {
#Inject
public JDBCDataSource(Database db) {
// ...
}
}
And so on.
What I would like is to reference each of those with a string so that i can call a factory which would return the appropriate IDataSource. Something that would behave like that:
public class DataSourceFactory {
public static final Map<String, Supplier<IDataSource<?>>> map = new HashMap<>();
#SuppressWarnings("unchecked")
public <T> IDataSource<T> get(String ref) {
return (IDataSource<T>) map.get(ref).get();
}
}
I could be giving N Providersas parameters (or direct field injection) to my factory (N being the number of IDataSource I use) and map strings to those in the constructor or use a switch in the get method but this would become quite a mess once I reach 10 to 20 IDataSource (or more!)
Is there some simpler solution I've been overlooking ?
Thanks
If you have to have a factory, then no—as in this question a manual factory is probably the best you can get.
However, if you bind all of your IDataSource implementations to IDataSource with different binding annotations, then you might be able to skip the factory and simply inject #Source("foo") IDataSource and get back the instance you want. The configuration between String and implementation still has to live somewhere, but you can have it live in a Guice module if you'd like. And, by injecting the Injector and supplying a compatible annotation implementation, you can even write a factory like DataSourceFactory that defers to Guice.
As a side note, beware of your DataSourceFactory; get will have no safe way to supply a value for its type parameter T.

Is there a handy way to get the name of a Spring Bean/Service?

I could do SomeSpringService.class.getSimpleName() and lowercase the first letter to get the default bean name, but I'm wondering if there is a simple Spring function that could find this for me? Simple meaning I'm not getting the application context, or building a factory, or such.
Thank you
Update: current hack
#Service
public class ServiceSelector
{
#Autowired
Map<String, IThing> implementations;
public SomethingInterface getDecisionStrategy(AnEnum type)
{
SomethingInterface something;
switch (type)
{
case ONE:
implementation = findInstance(Impl1.class);
break;
case TWO:
implementation = findInstance(Impl2.class);
break;
default:
implementation = findInstance(Impl2.class);
}
return implementation;
}
private SomethingInterface findInstance(Class clazz)
{
String className = clazz.getSimpleName();
String defaultBeanName = Character.toLowerCase(className.charAt(0)) + className.substring(1);
return implementations.get(defaultBeanName);
}
}
your bean can implement BeanNameAware, so you must add setBeanName(String beanName), in your class. Spring IoC will return your bean name.
For example:
public class Control implements BeanNameAware{
private String beanName;
#Override
public void setBeanName(String s) {
this.beanName = beanName;
}
}
No; you're basically asking to invert a map. Beans can be registered with arbitrary and even multiple names, and the name can come from a variety of places at runtime--the class name, a component annotation, an #Configuration method, XML, and more. The only way to find the name(s) given a specific object would be to enumerate all the beans and find which entries match.
Update: Based on your code sample, it looks like you're trying to go a very long way around two simpler patterns. The more direct implementation of your current approach is to just use the class to ask for the bean directly:
#Autowired ApplicationContext ctx;
...
implementation = ctx.getBean(Impl2.class);
However, this seems like a case for Replace Conditional with Polymorphism: While you've phrased your question in general terms, it's usually the case that it's appropriate either for the enum to know the class (so the switch is replaced by strategy.getImplementingClass()) or for the services to know information directly (see, for example, how Converter instances identify the objects they can operate on to their users) and for you to get a Set<IThing> and iterate over them to query for a suitable match.
org.springframework.beans.factory.ListableBeanFactory#getBeanNamesForType(java.lang.Class<?>)
org.springframework.beans.factory.BeanFactoryUtils#beanNamesForTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class<?>)

Configuring a Provider that returns a generic type in Guice

I'm trying to set up a Provider for DAOs created using JDBI. JDBI uses a Handle object (which is a wrapper around a JDBC Connection) and you can get hold of a DAO by using handle.attach(MyDaoType.class). Rather than having to write a separate Provider implementation for every DAO class I thought it would make sense to do this:
public class DaoProvider<T> implements Provider<T> {
private final Class<T> daoType;
private final Handle handle;
#Injected
public DaoProvider(Class<T> daoType, Handle handle) {
this.daoType = daoType;
this.handle = handle;
}
#Override
public T get() {
return handle.attach(daoType);
}
}
But it seems tremendously difficult to wire this up with Guice. I have tried using the #Assisted annotation on the 1st constructor argument as suggested in this answer. I defined a factory like this:
public interface DAOProviderFactory {
<T> DAOProvider<T> create(Class<T> daoType);
}
But it's not clear how I should invoke the FactoryModuleBuilder.implemented method as the whole point is that I don't want to have to extend my provider class.
It also seems a bit crazy that I'd have a factory that returns a provider that returns the thing I actually want!
It strikes me that this would be really easy to do with the Spring DI container so I want to believe it's possible with Guice. Can anyone point me in the right direction?
Thanks to #condit for pointing me at something that enabled me to solve the issue. It's actually very simple. I changed the Provider implementation to use field injection for the Handler like this:
public class DAOProvider<T> implements Provider<T> {
private #Inject Handle handle;
private final Class<T> daoType;
public DAOProvider(Class<T> daoType) {
this.daoType = daoType;
}
#Override public T get() {
return handle.attach(daoType);
}
}
Then in any module or application where I have specific DAO classes I want to bind I can just do something like this:
bind(UserStore.class).toProvider(new DAOProvider<>(UserStore.class));
bind(MessageStore.class).toProvider(new DAOProvider<>(MessageStore.class));
Guice then injects the Handle into the DAOProvider instances automatically.
I think you're making this far too complicated. When you call the get() method, you are storing the result in a reference, which means you know the type of the particular DAO, which means you can write your code knowing the DAO class. I mean, think about how Guice itself works, you call Injector.getInstance(Class<?> type)... in other words, methods like this can't infer the type without you passing the Class anyway, so pass the Class when you use it!
I can understand why you might not want to inject Handle directly though, so why not just make a wrapper, e.g.
public interface DaoProvider {
<T> T provideDao(Class<T> daoType);
}
And then:
public class JdbiDaoProvider implements DaoProvider {
private final Handle handle;
#Inject
JdbiDaoProvider(Handle handle) {
this.handle = handle;
}
public <T> T provideDao(Class<T> daoType) {
return handle.attach(daoType);
}
}

Java CDI: Dynamically selecting an implementation based on qualifier?

I'm trying to make an application extensible by using CDI, but it seems like I'm missing a piece of the puzzle.
What I want:
Have a global configuration that will define which implementation of an interface to use. The implementations would have annotations like #ImplDescriptor(type="type1").
What I tried:
#Produces
public UEInterface createUserExit(#Any Instance<UEInterface> instance, InjectionPoint ip) {
Annotated annotated = ip.getAnnotated();
UESelect ueSelect = annotated.getAnnotation(UESelect.class);
if (ueSelect != null) {
System.out.println("type = " + ueSelect.type());
}
System.out.println("Inject is ambiguous? " + instance.isAmbiguous());
if (instance.isUnsatisfied()) {
System.out.println("Inject is unsatified!");
return null;
}
// this would be ok, but causes an exception
return instance.select(ueSelect).get();
// or rather this:
for (Iterator<UEInterface> it = instance.iterator(); it.hasNext();) {
// problem: calling next() will trigger instantiation which will call this method again :(
UEInterface candidate = it.next();
System.out.println(candidate.getClass().getName());
}
}
This code is close to an example I've seen: The #Produces method will be used to select and create instances and a list of candidates is injected as Instance<E>. If the method simply creates and returns an implementation, it works fine. I just don't know how to examine and select a candidate from the Instance<E>. The only way of looking the the "contents" seems to be an Iterator<E>. But as soon as I call next(), it will try to create the implementation... and unfortunately, calls my #Produces method for that, thereby creating an infinite recursion. What am I missing? How can I inspect the candidates and select one? Of course I want to instantiate only one of them...
Thanks in advance for any help and hints!
I think the issue is you are trying to select the annotation's class rather than using the annotation as a selector qualifier. Using the class directly searches for an implementation that implements that class. You need to create an AnnotationLiteral using the #ImplDescriptor class to perform a select using it as a qualifier. Create a class extending AnnotationLiteral like so.
public class ImplDescriptorLiteral extends AnnotationLiteral<ImplDescriptor> implements ImplDescriptor {
private String type;
public ImplDescriptorLiteral(String type) {
this.type = type;
}
#Override
public String type() {
return type;
}
}
then you can pass an instance of this class to the select method using the type you want.
instance.select(new ImplDescriptorLiteral("type1")).get();
Refer to the Obtaining a contextual instance by programmatic lookup documentation for more information.
Finch, what you have here should work. it assumes though that you have an instance of UEInterface that is annotated #UESelect, e.g.
#UESelect("one")
public class UEOne implements UEInterface {
..
}
Is this how you're expecting it to work?

configurable dependencies with easy to mock out default implementations

I'm working on a kind of parameter values parser library. I'd like to have an Parser defined as follows:
public class Parser {
private ValuesConfiguration configuration;
private ValuesProvider valuesProvider;
private ValuesMapper valuesMapper;
public Parser(ValuesConfiguration configuration) {
this.configuration = configuration;
}
public Result parse(String parameterName) {
List<Values> values = valuesProvider.getValues(parameterName);
// do other stuff on values
// ...
return valuesMapper.transformValues(values, configuration);
}
}
I'd like this library clients to be unaware of ValuesProvider and ValuesMapper default implementations and use it like
Result result = new Parser(myConfig).parse("sampleParam");
Although there must be possibility to set their own implementations when needed. I wonder how and where should I init those default implementations and still let clients to set their own if they want. I don't want to stick to
new DefaultValuesProvider()
etc. in constructor, because default implementation would e.g. access filesystem, so that it would be hard to test (mock them out). I know I can use setters (like in DI) but what about defaults?
EDIT:
After your all answer, I guess it is best here to have setters to allow clients to provider their own implementations of ValuesProvider and ValuesMapper. But how to create default implementations? I'd like to decouple instantiation from logic, so I don't want to use new DefaultValueProvider() here. Is the factory pattern applicable here? If so how and where should I use it?
How about:
public void setValuesProvider(ValuesProvider valuesProvider) {
this.valuesProvider = valuesProvider;
}
public Result parse(String parameterName) {
if (valuesProvider == null) {
valuesProvider = new DefaultValuesProvider();
}
List<Values> values = valuesProvider.getValues(parameterName);
// do other stuff on values
// ...
return valuesMapper.transformValues(values, configuration);
}
As Mark points out, constructor injection might be the better way to go. That would look as follows:
public Parser(ValuesConfiguration configuration) {
this(configuation, new DefaultValuesProvider());
}
public Parser(ValuesConfiguration configuration, ValuesProvider valuesProvider) {
this.configuration = configuration;
this.valuesProvider = valuesProvider;
}
public Result parse(String parameterName) {
List<Values> values = valuesProvider.getValues(parameterName);
// do other stuff on values
// ...
return valuesMapper.transformValues(values, configuration);
}
I also agree with his summary of advantages:
This would enable you to make the dependency final/readonly. Property Injection provides quite weak guarantees about invariants - e.g. you could keep changing the dependency on the same instance, and that's probably not what you want.
However, there are also disadvantages:
The number of constructors is exponential in the number of optional parameters, causing a lot of delegation and duplicated JavaDoc for the parameters. Therefore, I'd only use constructor injection if there are few optional dependencies. You have 2, which about my pain threshold for this kind of thing.
Constructor injection ist not very subclassing friendly, as the subclass constructors will have to redeclare the super class dependencies. In your case, a subclass that wishes to expose all configuration options will need 4 constructors ... and if it adds an optional parameter it better shouldn't to this with constructor injection, as this would require another 4 constructors.
My recommendation therefore is to use setter injection, and if it is necessary to prevent the reassignment of dependences, do:
public void setValuesProvider(ValuesProvider valuesProvider) {
if (this.valuesProvider != null) {
throw new IllegalStateException("Dependency already set");
}
this.valuesProvider = valuesProvider;
}
Use Google Guice or similiar Dependency Injection framework:
http://code.google.com/p/google-guice/
It's perfect for your needs. You can configure several modules describing what implementations will be instantiated for particular interfaces. You can have a ProductionModule and UnitTestModule for example.

Categories