Question

I'm trying to set up a very simple implementation of weld in java SE.

I have the extension class:

public class MyExtension implements Extension {

    void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) {
        System.out.println("Starting scan...");
    }      
    <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> annotatedType, BeanManager beanManager) {
        System.out.println("Scanning type: " + annotatedType.getAnnotatedType().getJavaClass().getName());
    } 
    void afterBeanDiscovery(@Observes AfterBeanDiscovery abd) {
        System.out.println("Finished the scanning process");
    }

    public void main(@Observes ContainerInitialized event) {
        System.out.println("Starting application");
        new Test();
    }
}

I then have a simple class that I want to inject:

public class SimpleClass {
    public void doSomething() {
        System.out.println("Consider it done");
    }
}

And lastly the class I want to inject it in:

public class Test {

    @Inject
    private SimpleClass simple;

    @PostConstruct
    public void initialize() {
        simple.doSomething();
    }

    @PreDestroy
    public void stop() {
        System.out.println("Stopping");
    }
}

The resulting output is:

80 [main] INFO org.jboss.weld.Version - WELD-000900 1.1.10 (Final)
272 [main] INFO org.jboss.weld.Bootstrap - WELD-000101 Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Starting scan...
Scanning type: test.Test
Scanning type: test.SimpleClass
Scanning type: test.MyExtension
640 [main] WARN org.jboss.weld.interceptor.util.InterceptionTypeRegistry - Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled
640 [main] WARN org.jboss.weld.interceptor.util.InterceptionTypeRegistry - Class 'javax.ejb.PrePassivate' not found, interception based on it is not enabled
Finished the scanning process
Starting application

I would expect the simple class to be injected when Test() is constructed and the postconstruct method to be called which should output the expected text.

What exactly am I doing wrong?

Was it helpful?

Solution

There's two issues with your code:

Problem 1:

CDI does not manage beans created with new. For the most part you need to @Inject a bean in order for its life cycle to be managed by the container

Problem 2:

For the most part, you cannot inject bean instances into observers of container events. That's because the events are firing as the container is being initialized, aka before it can actually begin managing object life cycles.

You could hook the container initializer observer directly into your Test class. Something like this:

public class SimpleClass {
    public void doSomething() {
        System.out.println("Consider it done");
    }

   @PostConstruct
    public void initialize() {
        System.out.println("Starting");
    }

    @PreDestroy
    public void stop() {
        System.out.println("Stopping");
    }
}

public class Test {

    @Inject
    private SimpleClass simple;

    public void main(@Observes ContainerInitialized event) {
        System.out.println("Starting application");
        simple.doSomething();
    }       
}

OTHER TIPS

What you're doing wrong is calling new Test(). This constructs a new instance of Test, but in the back of CDI. For CDI to inject your Test instance, CDI has to create it itself.

See the documentation for how to boostrap Weld in a Java SE environment.

Create a utils class with @ApplicationScoped. This class can produce objects of every type. In your case this is just like this:

@Produces
static SimpleClass generateSimpleClass(){
return new SimpleClass();
}

Otherwise, if simpleclass for you is going to be a unique class in the application, set its class as @ApplicationScoped. Problem is that weld does not know that the class belongs to the container if there is neither annotation nor producer

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