4 Replies Latest reply on Mar 18, 2014 4:18 AM by Sueleyman Vurucu

    Inject multible instances of a custom scoped bean

    Sueleyman Vurucu Expert

      Hi guys,

       

      I need a CDI Context behavour like EJB Stateful beans.

      For example

       

      @Inject

      MyScopedBean bean1;

       

      @Inject

      MyScopedBean bean2;

       

       

      So the bean1 and the bean2 should have two diffrent proxies.

       

      The relevant part of my context implementation is:

        @Override
          public <T> T get(final Contextual<T> contextual) {
              return null;
          }
      
          @Override
          public <T> T get(final Contextual<T> contextual, final CreationalContext<T> creationalContext) {
              Bean<T> bean = (Bean) contextual;
              if (creationalContext == null) {
                  return null;
              }
              System.err.println("bean "+bean.hashCode() +" creationalContext "+creationalContext.hashCode());
              MultiSessionScopeContextHolderV2.MultiSessionScopeInstance beanHolder = customScopeContextHolder.getBean(bean, creationalContext);
              if(beanHolder == null){
                  T instance = bean.create(creationalContext);
                  MultiSessionScopeContextHolderV2.MultiSessionScopeInstance<T> customInstance = new MultiSessionScopeContextHolderV2.MultiSessionScopeInstance(bean, creationalContext, instance);
                  customScopeContextHolder.putBean(customInstance);
                  beanHolder = customScopeContextHolder.getBean(bean, creationalContext);
              }
              return (T) beanHolder.getInstance();
          }
      }
      

       

      I thought that Weld gives me a creational context per injectionpoint. Thats not so

       

      After debugging I see that ContextBeanInstance<T> is responsible for that behaviour.

       public T getInstance() {
              Container container = Container.instance(contextId);
              if (bean == null) {
                  bean = container.services().get(ContextualStore.class).<Bean<T>, T>getContextual(id);
              }
              Context context = container.deploymentManager().getContext(bean.getScope());
      
              T existingInstance = context.get(bean);
              if (existingInstance != null) {
                  return existingInstance;
              }
      
              WeldCreationalContext<T> creationalContext;
              WeldCreationalContext<?> previousCreationalContext = currentCreationalContext.get();
              if (previousCreationalContext == null) {
                  creationalContext = new CreationalContextImpl<T>(bean);
              } else {
                  creationalContext = previousCreationalContext.getCreationalContext(bean);
              }
              final CurrentInjectionPoint currentInjectionPoint = container.services().get(CurrentInjectionPoint.class);
              currentCreationalContext.set(creationalContext);
              try {
                  // Ensure that there is no injection point associated
                  currentInjectionPoint.push(EmptyInjectionPoint.INSTANCE);
                  return context.get(bean, creationalContext);
              } finally {
                  currentInjectionPoint.pop();
                  if (previousCreationalContext == null) { // ------>>>> ???? When is the context not null
                      currentCreationalContext.remove();
                  } else {
                      currentCreationalContext.set(previousCreationalContext);
                  }
              }
          }
      

       

       

      See my comment on line 28. The previousCreationalContext is always null and I get every time a new creationalcontext.

       

      So the quetion is, is that possible to tell weld that it have to create one proxy and creationalcontext per injection??

        • 1. Re: Inject multible instances of a custom scoped bean
          Martin Kouba Master

          Hi Sueleyman,

          first, for normal scopes client proxies may be shared between multiple injection points and Weld does reuse client proxies per bean. Keep in mind that there may be no more than one mapped instance per contextual type per thread. With regard to CreationalContext - it's not tied to injection point, but bean instance creation and destruction. The previousCreationalContext from your comment is not null if there's some "recursive creation", e.g. if you inject Foo and it has a dependency Bar which is created and injected during Foo creation.

          • 2. Re: Inject multible instances of a custom scoped bean
            Sueleyman Vurucu Expert

            Hi Martin,

            first, for normal scopes client proxies may be shared between multiple injection points and Weld does reuse client proxies per bean. Keep in mind that there may be no more than one mapped instance per contextual type per thread. With regard to CreationalContext - it's not tied to injection point, but bean instance creation and destruction.

             

            That's maybe very useful for the build in scopes but not so flexible for custom scopes.  For example. I have some EJB @Stateful session beans. But I want to migrate it to CDI beans for use the CDI event bus and maybe for use CDI mocks. That's very useful for my neeeds. But the limitation "one instance per context" breaks my prupose. For that need I can work with CDI procuder or since CDI 1.1 with getNoContexualReference but then I could not use the CDI Event bus for my instantiated objects. CDI will call for every event a new dependant object insance and not my session objects.

             

             

            Also why don't make CDI more flexible for CDI 2.0 . A proxy per injectionpoint shlould enough for this work .  

             

            The previousCreationalContext from your comment is not null if there's some "recursive creation", e.g. if you inject Foo and it has a dependency Bar which is created and injected during Foo creation.

            Ok this is new and important information for me.