[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