Uploaded image for project: 'Weld'
  1. Weld
  2. WELD-1766

In some situations, client proxies cache custom scoped bean instances

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 3.0.0.Alpha2, 2.2.7.Final
    • 2.1.2.Final, 3.0.0.Alpha17
    • Proxies
    • None
    • Hide

      The problem can be reproduced with a small Arquillian test, that I added to the Weld-core sources (see pull request, based on Weld 3.0.0). The test class injects a request scoped instance and a custom scoped instance of the same type:

          @Inject
          @Qualifier1
          private TestComponent requestScopedComponent;
      
          @Inject
          @Qualifier2
          private TestComponent customScopedComponent;
      

      The instances are created by two producer methods:

          @Produces
          @Qualifier1
          @RequestScoped
          public TestComponent produceRequestScopedComponent() {
              return new TestComponent();
          }
      
          @Produces
          @Qualifier2
          @CustomScoped
          public TestComponent produceCustomScopedComponent() {
              return new TestComponent();
          }
      

      Injection of the request scoped instance triggers the creation of a proxy class that supports caching. The proxy class contains generated code which caches the bean instance in a ThreadLocal (RequestScopedBeanCache). As soon as the second injection is encountered, Weld observes that the client proxy class is already there, so it will just use the class that has been created for the request scoped bean. This leads to caching of the bean instance, while the scope does not support caching (if it supports caching, it needs to call beginRequest/endRequest on RequestScopedBeanCache when a scope is activated/deactivated).

      Show
      The problem can be reproduced with a small Arquillian test, that I added to the Weld-core sources (see pull request, based on Weld 3.0.0). The test class injects a request scoped instance and a custom scoped instance of the same type: @Inject @Qualifier1 private TestComponent requestScopedComponent; @Inject @Qualifier2 private TestComponent customScopedComponent; The instances are created by two producer methods: @Produces @Qualifier1 @RequestScoped public TestComponent produceRequestScopedComponent() { return new TestComponent(); } @Produces @Qualifier2 @CustomScoped public TestComponent produceCustomScopedComponent() { return new TestComponent(); } Injection of the request scoped instance triggers the creation of a proxy class that supports caching. The proxy class contains generated code which caches the bean instance in a ThreadLocal (RequestScopedBeanCache). As soon as the second injection is encountered, Weld observes that the client proxy class is already there, so it will just use the class that has been created for the request scoped bean. This leads to caching of the bean instance, while the scope does not support caching (if it supports caching, it needs to call beginRequest/endRequest on RequestScopedBeanCache when a scope is activated/deactivated).

      In WildFly 8.1.0.Final, I observed that sometimes an injected instance of a custom scoped component was an old instance, belonging to a scope that had already been removed. After a long investigation, I found the root cause of this problem. It has to do with the bean instance caching that happens in client proxies for built in scoped beans (see Weld's class ClientProxyFactory). All beans with the same bean type make use of the same client proxy class, and this proxy class determines whether instances are cached or not. If, for a certain bean type, the first proxy that needs to be constructed is for a built in scoped bean, a caching proxy class is created, and that class will also be used for all future proxies, even if they refer to a bean that is custom scoped.

      See "steps to reproduce" for further details.

      The problem can be fixed by including a caching indicator in the name of the generated client proxy class (see pull request).

              Unassigned Unassigned
              marcelkolsteren_jira Marcel Kolsteren (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: