[cdi-dev] [JBoss JIRA] (CDI-666) simplify context implementation

John Ament (JIRA) issues at jboss.org
Tue Dec 13 08:53:02 EST 2016


    [ https://issues.jboss.org/browse/CDI-666?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13337817#comment-13337817 ] 

John Ament commented on CDI-666:
--------------------------------

+1 to doing something like this.  This is effectively every context implementation I've seen.

> simplify context implementation
> -------------------------------
>
>                 Key: CDI-666
>                 URL: https://issues.jboss.org/browse/CDI-666
>             Project: CDI Specification Issues
>          Issue Type: Feature Request
>            Reporter: Romain Manni-Bucau
>
> Today implementing a context leads to implementing Context or AlterableContext interface.
> Then for Thread Local related scopes it leads to handle activation, deactivation (thread local set/remove) and delegation of the context to a sub context (implementing or not Context interface). Finally it requires a destroyEnd() method destroying all instances.
> It also requires the instance tracking and instantiation correctly (with lock or not depending the usage).
> Here is a schematic implementation (easier than previous paragraph to read ;)):
> {code}
> public class CommandContext implements AlterableContext {
>     private final ThreadLocal<Delegate> delegate = new ThreadLocal<>();
>     @Override
>     public Class<? extends Annotation> getScope() {
>         return CommandScoped.class;
>     }
>     @Override
>     public <T> T get(final Contextual<T> component, final CreationalContext<T> creationalContext) {
>         return delegate.get().get(component, creationalContext);
>     }
>     @Override
>     public <T> T get(final Contextual<T> component) {
>         return delegate.get().get(component);
>     }
>     @Override
>     public boolean isActive() {
>         final Delegate instance = delegate.get();
>         if (instance == null) {
>             delegate.remove();
>             return false;
>         }
>         return instance.isActive();
>     }
>     @Override
>     public void destroy(final Contextual<?> contextual) {
>         delegate.get().destroy(contextual);
>     }
>     public Delegate newInstance() {
>         return new Delegate();
>     }
>     public void withContext(final Delegate value, final Runnable task) {
>         delegate.set(value);
>         try {
>             task.run();
>         } finally {
>             delegate.remove();
>         }
>     }
>     public void destroy(final Delegate delegate) {
>         new ArrayList<>(delegate.componentInstanceMap.keySet()).forEach(delegate::destroy);
>     }
>     public class Delegate implements AlterableContext {
>         private final Map<Contextual<?>, BeanInstanceBag<?>> componentInstanceMap = new HashMap<>();
>         private Delegate() {
>             // no-op
>         }
>         @Override
>         public Class<? extends Annotation> getScope() {
>             return CommandScoped.class;
>         }
>         @Override
>         public <T> T get(final Contextual<T> component, final CreationalContext<T> creationalContext) {
>             final BeanInstanceBag value = new BeanInstanceBag<>(creationalContext);
>             return (T) ofNullable(componentInstanceMap.putIfAbsent(component, value)).orElse(value).create(component);
>         }
>         @Override
>         public <T> T get(final Contextual<T> component) {
>             return (T) ofNullable(componentInstanceMap.get(component)).map(b -> b.beanInstance).orElse(null);
>         }
>         @Override
>         public void destroy(final Contextual<?> contextual) {
>             ofNullable(componentInstanceMap.remove(contextual)).filter(b -> b.beanInstance != null).ifPresent(b -> {
>                 final Contextual c = contextual;
>                 c.destroy(b.beanInstance, b.beanCreationalContext);
>                 b.beanCreationalContext.release();
>             });
>         }
>         @Override
>         public boolean isActive() {
>             return true;
>         }
>     }
>     @RequiredArgsConstructor
>     private static class BeanInstanceBag<T> {
>         private final CreationalContext<T> beanCreationalContext;
>         private T beanInstance;
>         public T create(final Contextual<T> contextual) {
>             if (beanInstance == null) {
>                 beanInstance = contextual.create(beanCreationalContext);
>             }
>             return beanInstance;
>         }
>     }
> }
> {code}
> This is a lot for finally just define (what the user wants) when a context is active.
> Therefore it would be awesome is the spec would provide a context builder. Raw api proposal could be:
> {code}
> void addContext(@Observes final AfterBeanDiscovery abd) {
>     context = abd.contextBuilder().concurrent().scope(TheScoped.class).create();
>     abd.addContext(context);
> }
> {code}



--
This message was sent by Atlassian JIRA
(v7.2.3#72005)


More information about the cdi-dev mailing list