Best practice for use constants in scala annotations - java

I use tapestry 5 as my choice of web framework. Tapestry allows me to define symbols in the configure class and inject symbols into other components.
for example,
public interface SymbolConstants {
static String DEFAULT_TIMEOUT_KEY = "default.timeout";
}
public class AppModule {
void contributeApplicationDefault(Configuration conf) {
conf.add(SymbolConstants.DEFAULT_TIMEOUT_KEY, "10");
}
}
public class MyComponent {
#Symbol(SymbolConstants.DEFAULT_VALUE_KEY)
private long timeout;
}
The ability to define static constants and use them as annotation values gives me compile time check.
I am wondering how to define constants and use them as values of scala annotations. If not, what is the best practice to define/limit the value that we can assign to annotations in scala.

The 'final' keyword is required to make the compiler emit it as you would do it in Java. E.g.,
object Foo
{
final val MY_SYMBOLIC_CONSTANT="whatever"
}
It seems that, otherwise, you only get an accessor method under the hood which is not statically calculable.

It doesn't seem possible w/ scala versions 2.8.1.final, 2.8.2.final, or 2.9.1.final (the result was the same with all):
object Constant { val UNCHECKED = "unchecked" }
class Test {
#SuppressWarnings(Array(Constant.UNCHECKED))
def test: Unit = println("testing.. 1, 2... 3")
}
.
<console>:7: error: annotation argument needs to be a constant; found: Constant.UNCHECKED
#SuppressWarnings(Array(Constant.UNCHECKED))

Related

jqwik strategies for combining arbitraries

(Context: my background in property-based testing is mostly from scala's scalacheck library, the use of some of the types and annotations in jqwik feels a bit different and there are a couple paradigms I can't quite get the hang of yet.)
I'm not sure how best to combine existing Arbitrary definitions for primitive types to produce a re-usable (needed for more than a single #Property or test class) Arbitrary that is built atop other Aribtrary definitions I've defined.
Given this is probably much clearer with an illustration:
// assume this has a builder pattern or all-args constructor.
// consider this is some sort of core domain object that I need in various
// test suites
public class MyComplexClass {
private final String id; // positive-integer shaped
private final String recordId; // uuid-shaped
private final String creatorId; // positive-integer shaped
private final String editorId; // positive-integer shaped
private final String nonce; // uuid-shaped
private final String payload; // random string
}
My instinct is to define Aribrary<String> that produces UUID-like strings and another that produces positive integer strings, something like:
public class MyArbitraries {
public Arbitrary<String> arbUuidString() {
return Combinators.combine(
Arbitraries.longs(), Arbitraries.longs(), Arbitraries.of(Set.of('8', '9', 'a', 'b')))
.as((l1, l2, y) -> {
StringBuilder b = new StringBuilder(new UUID(l1, l2).toString());
b.setCharAt(14, '4');
b.setCharAt(19, y);
return UUID.fromString(b.toString());
});
}
public Arbitrary<String> arbNumericIdString() {
return Arbitraries.shorts().map(Math::abs).map(i -> "" + i);
}
}
But then I'm not sure the best way to utilize these to produce an Arbitrary< MyComplexClass>. I'd want something like:
public class MyDomain extends DomainContextBase {
#Provider
public Arbitrary<MyComplexClass> arbMyComplexClass() {
return Builders.withBuilder(MyComplexClass::newBuilder)
// best way to reference these?!
.use(arbNumericIdString()).in(MyComplexClass.Builder::setId)
.use(arbUuidString()).in(MyComplexClass.Builder::setCreatorId)
// etc.
.build(MyComplexClass.Builder::build);
}
}
My understanding here is:
I cannot use #ForAll to 'inject' or provide these Arbitraries as ForAll is only supported in #Property-annotated methods
I cannot use #Domain here for similar reasons
I can't really use ArbitrarySupplier or similar as there is no obvious 'type' here, it's mostly just a bunch of strings
Is the best option to just create static Arbitrary<String> functions and call them directly?
One initial comment: #ForAll also works in methods annotated with #Provide and in domains. Here's a simple example:
class MyDomain extends DomainContextBase {
#Provide
public Arbitrary<String> strings(#ForAll("lengths") int length) {
return Arbitraries.strings().alpha().ofLength(length);
}
#Provide
public Arbitrary<Integer> lengths() {
return Arbitraries.integers().between(3, 10);
}
// Will not be used by strings() method
#Provide
public Arbitrary<Integer> negatives() {
return Arbitraries.integers().between(-100, -10);
}
}
class MyProperties {
#Property(tries = 101)
#Domain(MyDomain.class)
public void printOutAlphaStringsWithLength3to10(#ForAll String stringsFromDomain) {
System.out.println(stringsFromDomain);
}
}
Maybe the confusing thing is that the string reference in #ForAll("myString") is only evaluated locally (the class itself, superclasses and containing classes).
This is by purpose, in order to prevent string-based reference magic;
having to fall back to strings in the first place - since method refs cannot be used in Java annotations - is already bad enough.
As for your concrete question:
Is the best option to just create static Arbitrary functions and call them directly?
I consider that a "good enough" approach for sharing generators within a single domain or when you have several related domains that inherit from a common superclass.
When you want to share generators across unrelated domains, you'll have to either:
Use type-based resolution: Introduce value types for things like RecordId, UUIDString etc. Then you can use domains (or registered ArbitraryProviders to generate based on type.
Introduce annotations to mark different variants of the same type.
You can then check the annotation in your provider method or arbitrary provider. Here's an example:
class MyNumbers extends DomainContextBase {
#Provide
Arbitrary<Integer> numbers() {
return Arbitraries.integers().between(0, 255);
}
}
#Domain(MyNumbers.class)
class MyDomain extends DomainContextBase {
#Target({ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
#interface Name {}
#Target({ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
#interface HexNumber {}
#Provide
public Arbitrary<String> names(TypeUsage targetType) {
if (targetType.isAnnotated(Name.class)) {
return Arbitraries.strings().alpha().ofLength(5);
}
return null;
}
#Provide
public Arbitrary<String> numbers(TypeUsage targetType) {
if (targetType.isAnnotated(HexNumber.class)) {
return Arbitraries.defaultFor(Integer.class).map(Integer::toHexString);
}
return null;
}
}
#Property(tries = 101)
#Domain(MyDomain.class)
public void generateNamesAndHexNumbers(
#ForAll #MyDomain.Name String aName,
#ForAll #MyDomain.HexNumber String aHexNumber
) {
System.out.println(aName);
System.out.println(aHexNumber);
}
This examples also shows how one domain (MyNumbers) can be used
in another domain (MyDomain) through annotating the domain implementation class and either having a parameter being injected or use
Arbitraries.defaultFor(TypeProvidedInOtherDomain.class).
But maybe there's a useful feature for sharing arbitraries missing in jqwik.
The jqwik team's happy about any suggestion.

Dynamic access of method based on external field in Spring boot

We have multiple external variables in application.yml in spring boot application and i want to access this variable from my java code and based on the field value I want to redirect the call to various functions.
Example:
String externalVariable1 abc;
String externalVariable2 xyz;
method: if(string == abc) {
call function1; }
else {
call function2; }
Now problem here is there might be further addition to external variable in furture, I want to write robust method which should be adaptable to future addition to external variable without changing my core code. i might add the functionality as part of helper methods.
All I can think of reflection way, Can you guys help me with better approach given i am using spring boot application.
Don't do reflection for this. Instead, wrap function1/function2 into some kind of strategy object:
interface Strategy {
void doStuff();
}
class Function1 implements Strategy {
void doStuff() {
function1();
}
}
class Function2 implements Strategy {
void doStuff() {
function2();
}
}
Then, register all of these with some factory-style class:
class StrategyFactory {
private Strategy defaultStrategy = new Function2();
Map<String, Strategy> strategies = ....
strategies.put("abc", new Function1());
...
Strategy getStrategy(String key) {
return strategies.getOrDefault(key, defaultStrategy);
}
}
Finally, use it:
factory.getStrategy(valueFromYaml).doStuff();
Make key a more complex object than just String if you need to accommodate for more complicated scenarios, or use a more sophisticated way of selecting a strategy than a map lookup.
If you don't know the available strategies before runtime (e.g. if the configuration for these comes from a DB or files) keep only the class name of the Strategy implementation in a map:
Map<String, String> strategyClassNames = ...;
strategy.put(keyFromDB, valueFromDB);
...
and use it by:
Class<? extends Strategy> strategy = Class.forName(strategyClassNames.get(key));
strategy.newInstance().doStuff();

Java - Alternatives to forcing subclass to have a static method

I often find I want to do something like this:
class Foo{
public static abstract String getParam();
}
To force a subclasses of Foo to return a parameter.
I know you can't do it and I know why you can't do it but the common alternative of:
class Foo{
public abstract String getParam();
}
Is unsatisfactory because it requires you to have an instance which is not helpful if you just want to know the value of the parameter and instantiating the class is expensive.
I'd be very interested to know of how people get around this without getting into using the "Constant Interface" anti pattern.
EDIT: I'll add some more detail about my specific problem, but this is just the current time when I've wanted to do something like this there are several others from the past.
My subclasses are all data processors and the superclass defines the common code between them which allows them to get the data, parse it and put it where it needs to go.
The processors each require certain parameters which are held in an SQL database. Each processor should be able to provide a list of parameters that it requires and the default values so the configuration database can be validated or initialised to defaults by checking the required parameters for each processor type.
Having it performed in the constructor of the processor is not acceptable because it only needs to be done once per class not once per object instance and should be done at system startup when an instance of each type of class may not yet be needed.
The best you can do here in a static context is something like one of the following:
a. Have a method you specifically look for, but is not part of any contract (and therefore you can't enforce anyone to implement) and look for that at runtime:
public static String getParam() { ... };
try {
Method m = clazz.getDeclaredMethod("getParam");
String param = (String) m.invoke(null);
}
catch (NoSuchMethodException e) {
// handle this error
}
b. Use an annotation, which suffers from the same issue in that you can't force people to put it on their classes.
#Target({TYPE})
#Retention(RUNTIME)
public #interface Param {
String value() default "";
}
#Param("foo")
public class MyClass { ... }
public static String getParam(Class<?> clazz) {
if (clazz.isAnnotationPresent(Param.class)) {
return clazz.getAnnotation(Param.class).value();
}
else {
// what to do if there is no annotation
}
}
I agree - I feel that this is a limitation of Java. Sure, they have made their case about the advantages of not allowing inherited static methods, so I get it, but the fact is I have run into cases where this would be useful. Consider this case:
I have a parent Condition class, and for each of its sub-classes, I want a getName() method that states the class' name. The name of the sub-class will not be the Java's class name, but will be some lower-case text string used for JSON purposes on a web front end. The getName() method will not change per instance, so it is safe to make it static. However, some of the sub-classes of the Condition class will not be allowed to have no-argument constructors - some of them I will need to require that some parameters are defined at instantiation.
I use the Reflections library to get all classes in a package at runtime. Now, I want a list of all the names of each Condition class that is in this package, so I can return it to a web front end for JavaScript parsing. I would go through the effort of just instantiating each class, but as I said, they do not all have no-argument constructors. I have designed the constructors of the sub-classes to throw an IllegalArgumentException if some of the parameters are not correctly defined, so I cannot merely pass in null arguments. This is why I want the getName() method to be static, but required for all sub-classes.
My current workaround is to do the following: In the Condition class (which is abstract), I have defined a method:
public String getName () {
throw new IllegalArugmentException ("Child class did not declare an overridden getName() method using a static getConditionName() method. This must be done in order for the class to be registerred with Condition.getAllConditions()");
}
So in each sub-class, I simply define:
#Override
public String getName () {
return getConditionName ();
}
And then I define a static getConditionName() method for each. This is not quite "forcing" each sub-class to do so, but I do it in a way where if getName() is ever inadvertently called, the programmer is instructed how to fix the problem.
It seems to me you want to solve the wrong problem with the wrong tool. If all subclasses define (can't really say inherit) your static method, you will still be unable to call it painlessly (To call the static method on a class not known at compile time would be via reflection or byte code manipulation).
And if the idea is to have a set of behaviors, why not just use instances that all implement the same interface? An instance with no specific state is cheap in terms of memory and construction time, and if there is no state you can always share one instance (flyweight pattern) for all callers.
If you just need to couple metadata with classes, you can build/use any metadata facility you like, the most basic (by hand) implementation is to use a Map where the class object is the key. If that suits your problem depends on your problem, which you don't really describe in detail.
EDIT: (Structural) Metadata would associate data with classes (thats only one flavor, but probably the more common one). Annotations can be used as very simple metadata facility (annotate the class with a parameter). There are countless other ways (and goals to achieve) to do it, on the complex side are frameworks that provide basically every bit of information designed into an UML model for access at runtime.
But what you describe (processors and parameters in database) is what I christened "set of behaviors". And the argument "parameters need to be loaded once per class" is moot, it completely ignores the idioms that can be used to solve this without needing anything 'static'. Namely, the flyweight pattern (for having only once instance) and lazy initialization (for doing work only once). Combine with factory as needed.
I'm having the same problem over and over again and it's hard for me to understand why Java 8 preferred to implement lambda instead of that.
Anyway, if your subclasses only implement retrieving a few parameters and doing rather simple tasks, you can use enumerations as they are very powerful in Java: you can basically consider it a fixed set of instances of an interface. They can have members, methods, etc. They just can't be instanciated (as they are "pre-instanciated").
public enum Processor {
PROC_IMAGE {
#Override
public String getParam() {
return "image";
}
},
PROC_TEXT {
#Override
public String getParam() {
return "text";
}
}
;
public abstract String getParam();
public boolean doProcessing() {
System.out.println(getParam());
}
}
The nice thing is that you can get all "instances" by calling Processor.values():
for (Processor p : Processorvalues()) {
System.out.println(String.format("Param %s: %s", p.name(), p.getParam()));
p.doProcessing();
}
If the processing is more complex, you can do it in other classes that are instanciated in the enum methods:
#Override
public String getParam() {
return new LookForParam("text").getParam();
}
You can then enrich the enumeration with any new processor you can think of.
The down side is that you can't use it if other people want to create new processors, as it means modifying the source file.
You can use the factory pattern to allow the system to create 'data' instances first, and create 'functional' instances later. The 'data' instances will contain the 'mandatory' getters that you wanted to have static. The 'functional' instances do complex parameter validation and/or expensive construction. Of course the parameter setter in the factory can also so preliminary validation.
public abstract class Processor { /*...*/ }
public interface ProcessorFactory {
String getName(); // The mandatory getter in this example
void setParameter(String parameter, String value);
/** #throws IllegalStateException when parameter validation fails */
Processor construct();
}
public class ProcessorA implements ProcessorFactory {
#Override
public String getName() { return "processor-a"; }
#Override
public void setParameter(String parameter, String value) {
Objects.requireNonNull(parameter, "parameter");
Objects.requireNonNull(value, "value");
switch (parameter) {
case "source": setSource(value); break;
/*...*/
default: throw new IllegalArgumentException("Unknown parameter: " + parameter);
}
}
private void setSource(String value) { /*...*/ }
#Override
public Processor construct() {
return new ProcessorAImpl();
}
// Doesn't have to be an inner class. It's up to you.
private class ProcessorAImpl extends Processor { /*...*/ }
}

Shared methods between enums

I want to refactor an emun in two new enums, but I don't like to copy/paste the enum methods in all new enums.
enum EmailType {
REMINDER_ADMIN('reminderForAdmin')
REMINDER_PRODUCTION('reminderForProduction')
REMINDER_MANAGEMENT('reminderForManagement')
REMINDER_CUSTOMER('reminderForCustomer')
private final propertiesIdentifier
String getTemplate(type) {
...
}
String getFrom(type) {
...
}
String getTo(type) {
...
}
String getBcc(type) {
...
}
...
}
It's possible to implements only one time the methods and use in several enums?
enum EmailTypeAdministration {
REMINDER_ADMIN('reminderForAdmin')
REMINDER_PRODUCTION('reminderForProduction')
...
}
enum EmailTypeClients {
REMINDER_MANAGEMENT('reminderForManagement')
REMINDER_CUSTOMER('reminderForCustomer')
...
}
As my old friend Clippy would say, "it looks like you're using Groovy". If so, you can use a mixin to add the common methods to both enums.
// This class holds the methods that will be mixed-in to the enums
class EnumUtils {
String getTemplate(type) {
"template" + type
}
String getFrom(type) {
}
String getTo(type) {
}
String getBcc(type) {
}
}
// This annotation adds the common methods to the enum
#Mixin(EnumUtils)
enum EmailTypeAdministration {
REMINDER_ADMIN('reminderForAdmin'),
REMINDER_PRODUCTION('reminderForProduction')
EmailTypeAdministration(str) {}
}
// This annotation adds the common methods to the enum
#Mixin(EnumUtils)
enum EmailTypeClients {
REMINDER_MANAGEMENT('reminderForManagement'),
REMINDER_CUSTOMER('reminderForCustomer')
EmailTypeClients(str) {}
}
// Quick test to prove the methods exist and return the expected values
EmailTypeAdministration emailTypeAdmin = EmailTypeAdministration.REMINDER_ADMIN
assert 'templateParam' == emailTypeAdmin.getTemplate('Param')
You can run the code above in the Groovy console to prove it works as advertised
Enums cannot extend any other class since all enums automatically extend class named Enum. So, your only option is to delegate the methods implementation to separate utility. This may be relevant if the implementation is not trivial (more than one line). Otherwise delegation does not give you serious benefits.
Other possibility is to extend Enum manually but I be ready to write verbose code like valueOf(), values() etc., so I am not sure you really need this.
EDIT:
Take a look on my article about Hierarchical Enums. It can probably help you too.
Finally the Mixin solution don't works because #Mixin annotation only works with classes instead of enums.
I use a similar approach with delegate. Delegate transformation works fine! This code can be improve to use EnumUtils with factory or singleton pattern.
class EnumUtils {
String getTemplate(type) {
"template" + type
}
String getFrom(type) {
}
String getTo(type) {
}
String getBcc(type) {
}
}
enum EmailTypeAdministration {
REMINDER_ADMIN('reminderForAdmin'),
REMINDER_PRODUCTION('reminderForProduction')
#Delegate EnumUtils enumUtils = new EnumUtils()
EmailTypeAdministration(str) {}
}
enum EmailTypeClients {
REMINDER_MANAGEMENT('reminderForManagement'),
REMINDER_CUSTOMER('reminderForCustomer')
#Delegate EnumUtils enumUtils = new EnumUtils()
EmailTypeClients(str) {}
}
EmailTypeAdministration emailTypeAdmin = EmailTypeAdministration.REMINDER_ADMIN
assert 'templateParam' == emailTypeAdmin.getTemplate('Param')
The Enum type can't do that but you can use Groovy Mixins or a factory with an interface:
In the enums, just define the constants. All enums must implement a common marker interface.
Create a factory which accepts the marker interface and contains the getters.
The factory approach allows you to move the configuration (like templates, email addresses) into a config file which the factory reads at startup.
Lesson: Don't put configuration into enums. Enums are constants. Configuration changes.

How to inject String constants easily with Weld?

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

Categories