question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How is ContainerEventTest#testProcessInjectionTargetEventFiredForServlet supposed to pass?

See original GitHub issue

The CDK contains test org.jboss.cdi.tck.tests.extensions.lifecycle.processInjectionTarget.ContainerEventTest.testProcessInjectionTargetEventFiredForServlet()

This test that during startup a Servlet is injected.

However, there are no load-on-startup directives set for this Servlet, nor does the test do any request to it.

The Servlet in question contains this:

@Vetoed
@WebServlet("/test")
public class TestServlet extends HttpServlet {

    private static final long serialVersionUID = -7672096092047821010L;
    private static boolean isWrappedInjectionSuccessfull = false;

    Sheep sheep;

    @Inject
    Fence fence;

    @Inject
    public void initialize(Sheep sheep) {
        this.sheep = sheep;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

There is no web.xml setting load-on-startup.

How is this supposed to work?

/cc @scottmarlow @dmatej

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:11 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
arjantijmscommented, Jun 23, 2022

@Pandrex247 Thanks for your sharp analysis there. Comparing to GF 6/CDI 3 to find out what changed was on my list, but I indeed hadn’t come back to it.

It looks like the previous behaviour was in a certain way a side-effect of registering everything as a bean in the first place. As the Servlet is explicitly vetoed, it shouldn’t have worked previously (maybe we need to check ourselves for the @Vetoed annotation).

Following that, and the reason why I didn’t just fire the event to satisfy the CDI TCK, is that when somebody actually does something in the event (replace the inject target), it would not take effect. The “problem” in GlassFish (and as a result Payara) is that the Servlet isn’t actually a CDI bean, but a more manually created “injected Jakarta EE component”.

This is according to the specifications, but it makes all of this a bit more difficult.

If you consider the code I quoted above again:

public <T> CDIInjectionContext<T> createManagedObject(Class<T> managedClass, BundleDescriptor bundle, boolean invokePostConstruct) {
        // First get BeanDeploymentArchive
        BeanDeploymentArchiveImpl beanDeploymentArchive = getBeanDeploymentArchiveFromBundle(bundle);
        WeldManager beanManager = getWeldManagerFromBundle(bundle, beanDeploymentArchive);

        AnnotatedType annotatedType = beanManager.createAnnotatedType(managedClass);
        if (!invokePostConstruct) {
            annotatedType = new NoPostConstructPreDestroyAnnotatedType(annotatedType);
        }

        InjectionTarget injectionTarget = beanDeploymentArchive.getInjectionTarget(annotatedType);
        if (injectionTarget == null) {
            injectionTarget = beanManager.fireProcessInjectionTarget(annotatedType);
        }

        CreationalContext creationalContext = beanManager.createCreationalContext(null);

        Object managedObject = injectionTarget.produce(creationalContext);

        injectionTarget.inject(managedObject, creationalContext);

        if (invokePostConstruct) {
            injectionTarget.postConstruct(managedObject);
        }

        return new CDIInjectionContextImpl(injectionTarget, creationalContext, managedObject);
    }

Then I think the injection target obtained by this line:

injectionTarget = beanManager.fireProcessInjectionTarget(annotatedType);

Should be stored and used when the Servlet is actually created. Otherwise the event would fire twice for each Servlet, and the result of the first event would just be lost.

Probably the best thing would be to standardise the approach taken by WildFly, and make a Servlet an actual bean, and then later on also obtain it as an actual bean (without the manual CDI simulating code that there’s now). I’ve discussed this with the Servlet spec team before, but it didn’t make it in yet (Red Hat was supportive though).

@manovotn What do you think?

1reaction
Pandrex247commented, Jun 23, 2022

@arjantijms just in case you decide to come back to it.

The code is slightly different now between Payara and GlassFish, but I suspect the cause will be the same. In Payara at least this test now fails as a knock-on effect from the change of the bean discovery mode.

At this point on CDI 3 this evaluates to true, on CDI 4 it evaluates to false. The effect of this is that here the if check fails on CDI 4, and so the servlet isn’t registered as a bean. As the application gets loaded, PITs are only fired for bean classes.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found