Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@PostConstruct of abstract ancestors are not invoked

I'm writing a JAX-RS library (not an application).

I have:

abstract class A {

    @PostConstruct
    private void constructed_a() {} // not invoked

    @Inject
    private Some some;
}


public abstract class B extends A {

    @PostConstruct
    private void constructed_b() {} // not invoked
}

And test class:

@Path("c")
public class C extends B {

    @PostConstrct
    private void constructed_c() {} // invoked
}

I'm testing with jersey test framework v2.17

I found that only constructed_c() is invoked and those method defined in ancestors are not invoked. Note that the field(some) declared with @Inject in class A is properly injected.

Is this normal? What should I do?


Conclusion

I tested with embedded-glassfish and found that, as Antonin Stefanutti pointed, those callback methods invoked in order as expected.

constructed_a()
constructed_b()
constructed_c()
like image 851
Jin Kwon Avatar asked Jan 08 '23 12:01

Jin Kwon


1 Answers

According to section Invocation Order of Interceptors Declared on the Target Class of the JSR 318 - Interceptors 1.2 specification:

Interceptor methods declared on the target class or its superclasses are invoked in the following order:

  • If a target class has superclasses, any interceptor methods defined on those superclasses are invoked, most general superclass first.
  • The interceptor method, if any, on the target class itself is invoked.

If an interceptor method is overridden by another method (regardless of whether that method is itself an interceptor method), it will not be invoked.

That means that when writing a library / framework, it is possible to achieve extensibility while using the @PostConstruct lifecyle callback both in the parent class and the child class.

That mechanism is used in the Camel CDI extension that declares a default Camel context with a @PostConstruct lifecycle callback in https://github.com/astefanutti/camel-cdi/blob/b6f52d91b247e36eefb6f3ecde61016d681d3535/impl/src/main/java/org/apache/camel/cdi/CdiCamelContext.java#L37

And that can be extended by users like in https://github.com/astefanutti/camel-cdi/blob/b6f52d91b247e36eefb6f3ecde61016d681d3535/envs/se/src/main/java/org/apache/camel/cdi/se/bean/CustomLifecycleCamelContext.java#L37 that declares its own @PostConstruct lifecycle callback.

Both being called by the container following the specified order.

That means that your approach is correct from the design standpoint. However, as Jersey dependency injection is based on HK2 and not CDI and relies on bridges like jersey-gf-cdi there might be an issue at that level.

like image 136
Antonin Stefanutti Avatar answered Jan 14 '23 17:01

Antonin Stefanutti