I was recently asked how to Inject a Java Enum into a bean constructor using CDI. This turns out to be a fairly interesting situation, because enums are not usually available for Injection.
The first attempt
As much as we would hope for this to work, it does not. Enums are not beans because they have no default constructor (hence CDI does not know how to construct them,) and there is no standard way to resolve which enumerated value should be injected by default (Unless there is only one value, but this is still not supported due to the lack of default constructor.)
public class InjectedObject {
private MyEnum e;
@Inject
public InjectedObject(MyEnum e) {
this.e = e;
}
public MyEnum getValue() {
return e;
}
/**
* Our enum
*/
public enum MyEnum {
ONE
}
}
This will result in a deployment failure
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [MyEnum] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject public org.example.InjectedObject(MyEnum)] at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:365) at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:297) at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:157) at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:184) at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:470) at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:74) at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:72) at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:60) at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:53) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) ... 1 more |
The solution
We must turn to producer methods in order to make this possible. It takes just a little bit of code, but it is possible, and very easy! The reason this works is because any
value may be injected if it resolves to a unique set of qualifiers and types. You could even inject a java.lang.String
using this technique.
/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public class InjectedObject
{
private MyEnum e;
@Inject
public InjectedObject(MyEnum e)
{
this.e = e;
}
public MyEnum getValue()
{
return e;
}
/**
* A producer is required in order to {@link Inject} an Enum
*/
@Produces
public static MyEnum getEnum()
{
return MyEnum.THREE;
}
/**
* Our enum
*/
public enum MyEnum
{
ONE, TWO, THREE
}
}
And there you have it! A perfectly functional method of injecting enum values in CDI. You will, however, need to make sure you know which type of enum you want to inject, and if you need multiple types, then you’ll need to create qualifiers for each value.
You could also use the built-in @Named qualifier
The @Named
qualifier is a built in qualifying type that allows unique qualifiers to be created using String values.
/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public class InjectedObject
{
private MyEnum e1;
private MyEnum e2;
@Inject
public InjectedObject(@Named("ONE") MyEnum e1, @Named("TWO") MyEnum e2)
{
this.e1 = e1;
this.e2 = e2;
}
public MyEnum getValue1()
{
return e1;
}
public MyEnum getValue2()
{
return e2;
}
/**
* A producer is required in order to {@link Inject} an Enum
*/
@Produces
@Named("ONE")
public static MyEnum getEnumOne()
{
return MyEnum.ONE;
}
@Produces
@Named("TWO")
public static MyEnum getEnumTwo()
{
return MyEnum.TWO;
}
/**
* Our enum
*/
public enum MyEnum
{
ONE, TWO, THREE
}
}
We would not, however, be able to @Inject @Named("THREE") MyEnum e
because we have not declared a producer with such a qualifier!