glassfish
  1. glassfish
  2. GLASSFISH-16115

WELD A Class in a Normal (proxiable) scope that extends a class with final methods is NOT caught at deployment time

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1
    • Fix Version/s: 4.0
    • Component/s: cdi
    • Labels:
      None
    • Environment:

      Ubuntu Linux 10.04 x86, Sun JVM 1.6.0_24-b07

      Description

      Using javax.enterprise.inject.Instance, my application is able to inject objects at runtime. The qualifier annotations are defined properly (runtime retention, method/field/parameter/type targets, @Qualifier), with a single member string (value). The string value is binding (i.e. no @NonBinding annotation)

      The annotated, @Dependent class is also properly annotated.

      In Glassfish 3.0.1, this injection model works perfectly.

      In Glassfish 3.1, CDI (WELD) raises an exception that it can't satisfy the dependency.

      Clearly, all jars/WARs have "beans.xml" in the right place (else it wouldn't work with 3.0.1).

      All other (static) injection appears to be working normally.

        Activity

        Hide
        drivera added a comment - - edited

        Here's an example of what the code is doing:

        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
        Annotation declaration:
        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o

        @Qualifier
        @Target(

        { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }

        )
        @Retention(RetentionPolicy.RUNTIME)
        public @interface QualifierAnnotation

        { public String value(); }

        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
        Class declaration:
        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o

        @QualifierAnnotation("qualifierSelector")
        public class InjectableClass implements Injectable

        { ... /* bla bla bla ... content shouldn't matter, should it? */ /* importantly, there is NO @PostConstruct, or even an explicit constructor */ ... }

        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
        Code snippet where injection is looked up programmatically:
        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o

        @Inject
        Instance<Injectable> injectable;

        public Injectable resolveInjectable(final String qualifierValue) {
        QualifierAnnotation a = new QualifierAnnotation() {
        @Override
        public Class<? extends Annotation> annotationType()

        { return QualifierAnnotation.class; }

        @Override
        public String value()

        { return qualifierValue; }

        };
        Instance<Injectable> narrow = injectable.select(a);
        if (narrow.isAmbiguous()) throw new RuntimeException("Ambiguity upon injection");
        if (narrow.isUnsatisfied()) throw new RuntimeException("Injection unsatisfied");
        return narrow.get();
        }

        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
        Invocation of the injection:
        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o

        Injectable i = resolveInjectable("qualifierSelector"};

        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
        End code examples
        -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o

        The result is that the 2nd RuntimeException described above ("Injection unsatisfied") is raised. This exact same code works in Glassfish 3.0.1 (confirmed, in production even!) and JBoss 6 (I think, unconfirmed).

        Show
        drivera added a comment - - edited Here's an example of what the code is doing: -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o Annotation declaration: -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o @Qualifier @Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER } ) @Retention(RetentionPolicy.RUNTIME) public @interface QualifierAnnotation { public String value(); } -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o Class declaration: -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o @QualifierAnnotation("qualifierSelector") public class InjectableClass implements Injectable { ... /* bla bla bla ... content shouldn't matter, should it? */ /* importantly, there is NO @PostConstruct, or even an explicit constructor */ ... } -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o Code snippet where injection is looked up programmatically: -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o @Inject Instance<Injectable> injectable; public Injectable resolveInjectable(final String qualifierValue) { QualifierAnnotation a = new QualifierAnnotation() { @Override public Class<? extends Annotation> annotationType() { return QualifierAnnotation.class; } @Override public String value() { return qualifierValue; } }; Instance<Injectable> narrow = injectable.select(a); if (narrow.isAmbiguous()) throw new RuntimeException("Ambiguity upon injection"); if (narrow.isUnsatisfied()) throw new RuntimeException("Injection unsatisfied"); return narrow.get(); } -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o Invocation of the injection: -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o Injectable i = resolveInjectable("qualifierSelector"}; -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o End code examples -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o The result is that the 2nd RuntimeException described above ("Injection unsatisfied") is raised. This exact same code works in Glassfish 3.0.1 (confirmed, in production even!) and JBoss 6 (I think, unconfirmed).
        Hide
        drivera added a comment -

        Attached are some logs I extracted in FINEST setting, ranging from a button click on the browser to the actual rendering of the error back on the browser.

        The button click triggers the injection to happen, and thus all info regarding the action should be there.

        Show
        drivera added a comment - Attached are some logs I extracted in FINEST setting, ranging from a button click on the browser to the actual rendering of the error back on the browser. The button click triggers the injection to happen, and thus all info regarding the action should be there.
        Hide
        drivera added a comment -

        Bump.... can anyone so much as comment on the (in)validity of this issue?

        Show
        drivera added a comment - Bump.... can anyone so much as comment on the (in)validity of this issue?
        Hide
        drivera added a comment - - edited

        Ok...the issue has been found - this isn't a problem with NOT finding injections. The problem is with WELD not properly reporting injection spec violations.

        I had 2 classes - A and B, of which B was a subclass of A. B was being injected directly, A was not. A contained final methods which were causing the CDI injection to fail.

        I found the problem by creating C as a subclass of B (B and A were generic, so C was a specification of those generics), and injecting C instead of B. At that point Weld did complain rather loudly that A contained final methods and thus, CDI injection could not properly succeed.

        So, in conclusion, the error is that Weld did not report the problem with final methods in the injectable class's superclass. Obviously the code was broken, but the error Weld displayed when I created C should have been displayed from the beginning.

        Feel free to downgrade this, or pass this off to the weld guys. This is no longer a blocker issue.

        Show
        drivera added a comment - - edited Ok...the issue has been found - this isn't a problem with NOT finding injections. The problem is with WELD not properly reporting injection spec violations. I had 2 classes - A and B, of which B was a subclass of A. B was being injected directly, A was not. A contained final methods which were causing the CDI injection to fail. I found the problem by creating C as a subclass of B (B and A were generic, so C was a specification of those generics), and injecting C instead of B. At that point Weld did complain rather loudly that A contained final methods and thus, CDI injection could not properly succeed. So, in conclusion, the error is that Weld did not report the problem with final methods in the injectable class's superclass. Obviously the code was broken, but the error Weld displayed when I created C should have been displayed from the beginning. Feel free to downgrade this, or pass this off to the weld guys. This is no longer a blocker issue.
        Hide
        Sivakumar Thyagarajan added a comment -

        Marked this as 3_1_1-review. Need to ensure Weld properly reports this invalid scenario.

        Show
        Sivakumar Thyagarajan added a comment - Marked this as 3_1_1-review. Need to ensure Weld properly reports this invalid scenario.
        Hide
        Sivakumar Thyagarajan added a comment -

        Requires a fix in Weld and hence marking this as 3_1_1-next

        Show
        Sivakumar Thyagarajan added a comment - Requires a fix in Weld and hence marking this as 3_1_1-next
        Hide
        Sivakumar Thyagarajan added a comment -

        Marking this issue as "3_1_2_exclude", as a fix doesn't seem to be available in the 3.1.2 timeframe.

        Show
        Sivakumar Thyagarajan added a comment - Marking this issue as "3_1_2_exclude", as a fix doesn't seem to be available in the 3.1.2 timeframe.
        Hide
        Sivakumar Thyagarajan added a comment -

        Transferring to JJ Snyder

        Show
        Sivakumar Thyagarajan added a comment - Transferring to JJ Snyder
        Hide
        jwells added a comment -

        Section 5.4.1 of the CDI specification (1.0) states that a bean in a Normal scope must not have final methods, and that such an injection point should be handled as a deployment error. Here is the exact wording:

        If an injection point whose declared type cannot be proxied by the container resolves to a bean with a normal scope, the
        container automatically detects the problem and treats it as a deployment problem.

        If I have a class B that extends a class A, where B is in a Normal scope (@ApplicationScoped) and A has a final method the error is NOT caught (still, with the latest Weld) and is later manifested in a NullPointerException when Weld tries to proxy the class. If I add a final method to B the error IS caught at deployment time and made into a deployment failure.

        This looks to me like an error in Weld, for which I can provide a simple test case.

        Show
        jwells added a comment - Section 5.4.1 of the CDI specification (1.0) states that a bean in a Normal scope must not have final methods, and that such an injection point should be handled as a deployment error. Here is the exact wording: If an injection point whose declared type cannot be proxied by the container resolves to a bean with a normal scope, the container automatically detects the problem and treats it as a deployment problem. If I have a class B that extends a class A, where B is in a Normal scope (@ApplicationScoped) and A has a final method the error is NOT caught (still, with the latest Weld) and is later manifested in a NullPointerException when Weld tries to proxy the class. If I add a final method to B the error IS caught at deployment time and made into a deployment failure. This looks to me like an error in Weld, for which I can provide a simple test case.
        Hide
        jjsnyder83 added a comment -

        I have forward the information to JBoss.

        Show
        jjsnyder83 added a comment - I have forward the information to JBoss.
        Hide
        jwells added a comment -

        I have submitted a test case under appserver/tests/cdi/negative/normalScopeWithFinal. The test is currently disabled (as the JAR erroneously is deployed). We should keep this bug open until the test case succeeds.

        Show
        jwells added a comment - I have submitted a test case under appserver/tests/cdi/negative/normalScopeWithFinal. The test is currently disabled (as the JAR erroneously is deployed). We should keep this bug open until the test case succeeds.
        Show
        jjsnyder83 added a comment - https://issues.jboss.org/browse/WELD-1388
        Hide
        jwells added a comment -

        Weld has fixed this bug, and the test that catches this bug has been re-enabled with change 61362

        Show
        jwells added a comment - Weld has fixed this bug, and the test that catches this bug has been re-enabled with change 61362

          People

          • Assignee:
            jwells
            Reporter:
            drivera
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: