Thank you for the hints.

Alas, am still struggling with realization of template method.

I tried different approaches now and am unable to find the "clean" implementation for my problem. Ok thats my problem and not a CDI issue, but just for the sake of completeness I'd like to show the solution I now have and to put the disadvantages to the discussion.

So now I changed AbstractFooProducer to

class BaseFooProducer {
    protected void init(Foo foo) {
        throw new NotImplementedException();
    }

    @Produces
    public Foo produceFoo() {
        //method template goes here e.g. init()
    }
}

and

@Specializes
public class ConcreteFooProducer extends BaseFooProducer {
    @Override
    protected void init(Foo foo) {
        foo.setI(234);
    }
}

This works as expected but is no elegant solution I would get with an abstract base class.

Someone suggested me to use @Alternative but I don't see how that can help me. I don't have different implementations for the same interface but, rather, I want to enforce particular program flow and allow descendants to implement parts of it in a specific way (e.g. load data from xml source or otherwise).

Would be great if someone could suggest me a pattern for this.

br
Reinis

On 27.05.2013 22:50, John D. Ament wrote:
The answer's in the spec (JSR-299)

A producer method must be a non-abstract method of a managed bean class or
session bean class.

Your abstract class is neither a managed bean nor a session bean.

I also confirmed that your project doesn't run with weld.


On Mon, May 27, 2013 at 9:57 AM, Reinis Vicups <[email protected]> wrote:

Hello,

I have three classes

public abstract class AbstractFooProducer {

     protected void init(Foo foo) {}

     @Produces
     public Foo produceFoo() {
         Foo foo = new Foo();
         init(foo);
         return foo;
     }
}

then

public class ConcreteFooProducer extends AbstractFooProducer {
     @Override
     protected void init(Foo foo) {
         foo.setI(234);
     }
}

and

@Typed(Object.class)
public class Foo {
...
}

Foo is annotated with @Typed to avoid CDI directly injecting Foo in
injection points.

This cause following exception:

javax.enterprise.inject.**UnsatisfiedResolutionException**: Api type
[de.orbitx.specializes.Foo] is not found with the qualifiers
Qualifiers: [@javax.enterprise.inject.**Default()]
for injection into Field Injection Point, field name :  foo, Bean Owner :
[FooTest, Name:null, WebBeans Type:ENTERPRISE, API
Types:[java.lang.Object,de.**orbitx.specializes.FooTest,**java.io.Serializable],
Qualifiers:[javax.enterprise.**inject.Default,javax.**
enterprise.inject.Any]]
     at org.apache.webbeans.util.**InjectionExceptionUtil.**
throwUnsatisfiedResolutionExce**ption(InjectionExceptionUtil.**java:77)
     at org.apache.webbeans.container.**InjectionResolver.**
checkInjectionPoints(**InjectionResolver.java:178)
     at org.apache.webbeans.container.**BeanManagerImpl.validate(**
BeanManagerImpl.java:947)
     at org.apache.webbeans.config.**BeansDeployer.validate(**
BeansDeployer.java:440)
     at org.apache.webbeans.config.**BeansDeployer.**
validateInjectionPoints(**BeansDeployer.java:390)
     at org.apache.webbeans.config.**BeansDeployer.deploy(**
BeansDeployer.java:194)
     at org.apache.openejb.cdi.**OpenEJBLifecycle.**startApplication(**
OpenEJBLifecycle.java:182)
     at org.apache.openejb.cdi.**ThreadSingletonServiceImpl.**initialize(**
ThreadSingletonServiceImpl.**java:158)
     at org.apache.openejb.cdi.**CdiBuilder.build(CdiBuilder.**java:43)
     at org.apache.openejb.assembler.**classic.Assembler.**
createApplication(Assembler.**java:798)
     at org.apache.openejb.assembler.**classic.Assembler.**
createApplication(Assembler.**java:612)
     at org.apache.openejb.assembler.**classic.Assembler.**
createApplication(Assembler.**java:608)
     at org.apache.openejb.testing.**ApplicationComposers.before(**
ApplicationComposers.java:580)
     at org.apache.openejb.testing.**ApplicationComposers.evaluate(**
ApplicationComposers.java:664)
     at org.apache.openejb.junit.**ApplicationComposer$**
DeployApplication.evaluate(**ApplicationComposer.java:64)
     at org.junit.runners.**ParentRunner.runLeaf(**ParentRunner.java:263)
     at org.junit.runners.**BlockJUnit4ClassRunner.**runChild(**
BlockJUnit4ClassRunner.java:**68)
     at org.junit.runners.**BlockJUnit4ClassRunner.**runChild(**
BlockJUnit4ClassRunner.java:**47)
     at org.junit.runners.**ParentRunner$3.run(**ParentRunner.java:231)
     at org.junit.runners.**ParentRunner$1.schedule(**ParentRunner.java:60)
     at org.junit.runners.**ParentRunner.runChildren(**
ParentRunner.java:229)
     at org.junit.runners.**ParentRunner.access$000(**ParentRunner.java:50)
     at org.junit.runners.**ParentRunner$2.evaluate(**
ParentRunner.java:222)
     at org.junit.runners.**ParentRunner.run(ParentRunner.**java:300)
     at org.eclipse.jdt.internal.**junit4.runner.**JUnit4TestReference.run(
**JUnit4TestReference.java:50)
     at org.eclipse.jdt.internal.**junit.runner.TestExecution.**
run(TestExecution.java:38)
     at org.eclipse.jdt.internal.**junit.runner.RemoteTestRunner.**
runTests(RemoteTestRunner.**java:467)
     at org.eclipse.jdt.internal.**junit.runner.RemoteTestRunner.**
runTests(RemoteTestRunner.**java:683)
     at org.eclipse.jdt.internal.**junit.runner.RemoteTestRunner.**
run(RemoteTestRunner.java:390)
     at org.eclipse.jdt.internal.**junit.runner.RemoteTestRunner.**
main(RemoteTestRunner.java:**197)

Why is AbstractFooProducer#**produceFoo() not seen by CDI?

I am also attaching a test project

Thank you very much for your hints
Reinis.


Reply via email to