Question

I am experimenting with Weld. Given the following prerequisites...

public interface Printer {
    void print(Job job) throws IOException;

    interface Job { void feed(PrintStream out); }
}

@Qualifier
@Target({ METHOD, FIELD, PARAMETER, TYPE })
@Retention(RUNTIME)
public @interface StandardOutput { }

@Qualifier
@Target({ METHOD, FIELD, PARAMETER, TYPE })
@Retention(RUNTIME)
public @interface StandardError { }

... I would like to provide two standard instances, one for the standard output stream and one for the standard error stream (JSE environment):

public class PrintStreamPrinter implements Printer {

    private final PrintStream out;

    @Produces static final @StandardOutput PrintStreamPrinter
            stdout = new PrintStreamPrinter(System.out);

    @Produces static final @StandardError PrintStreamPrinter
            stderr = new PrintStreamPrinter(System.err);

    private PrintStreamPrinter() { throw new AssertionError(); }

    public PrintStreamPrinter(final PrintStream out) {
        this.out = Objects.requireNonNull(out);
    }

    public void print(final Job job) throws IOException {
        job.feed(out);
        if (out.checkError()) throw new IOException();
    }
}

Now I can use this like so:

@Inject @StandardOutput Printer printer;

and use it happily ever after.

However, this fails if I remove the useless private constructor without parameters from the PrintStreamPrinter class. It took me a while to figure this and I don't know why. Obviously, the implementation is never called, so why does it have to exist in the first place? Note that I am using the @Dependent scope here, so no client proxy has ever to be created.

This is the exception I am getting from Weld SE 2.0.1.Final after removing the useless private constructor:

Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Printer] with qualifiers [@StandardOutput] at injection point [[BackedAnnotatedField] @Inject @StandardOutput private com.company.mavenproject1.Main.printer]
    at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:404)
    at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:326)
    at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:177)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:208)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:520)
    at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:70)
    at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:68)
    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:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)

What's more interesting: If the private constructor is present, the Weld logs tell me:

WELD-000106 Bean: Producer Field [PrintStreamPrinter] with qualifiers [@StandardOutput @Any] declared as [[BackedAnnotatedField] @Produces @StandardOutput final static com.company.mavenproject1.PrintStreamPrinter.stdout]
WELD-000106 Bean: Producer Field [PrintStreamPrinter] with qualifiers [@StandardError @Any] declared as [[BackedAnnotatedField] @Produces @StandardError final static com.company.mavenproject1.PrintStreamPrinter.stderr]

These lines are missing when the constructor is removed.

Is this a bug or a feature?

Was it helpful?

Solution

In order for CDI to properly proxy your classes you must have either a no args constructor (thought it had to be public, could be implementation though) or a constructor marked with @Inject.

Take a look at the specification source.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top