DciContextWithAutoThreadBindingAspect.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *********************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  12.  * the License. You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  23.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.role.spring.spi;

  28. import javax.annotation.Nonnull;
  29. import org.aspectj.lang.ProceedingJoinPoint;
  30. import org.aspectj.lang.annotation.Around;
  31. import org.aspectj.lang.annotation.Aspect;
  32. import it.tidalwave.util.Task;
  33. import it.tidalwave.role.ContextManager;
  34. import it.tidalwave.dci.annotation.DciContext;
  35. import lombok.extern.slf4j.Slf4j;
  36. import static it.tidalwave.role.spi.impl.LogUtil.shortId;

  37. /***********************************************************************************************************************
  38.  *
  39.  * An aspect which implements {@link DciContext} with {@code autoThreadBinding=true}. This class must not be used
  40.  * directly. Instead, add the library which contains it as a dependency of your project and make it visible to the
  41.  * AspectJ compiler.
  42.  *
  43.  * @author  Fabrizio Giudici
  44.  * @since   3.0
  45.  *
  46.  **********************************************************************************************************************/
  47. @Aspect @Slf4j
  48. public class DciContextWithAutoThreadBindingAspect
  49.   {
  50.     @Around("within(@it.tidalwave.dci.annotation.DciContext *) && execution(* *(..))")
  51.     public Object advice (@Nonnull final ProceedingJoinPoint pjp)
  52.       throws Throwable
  53.       {
  54.         final var context = pjp.getTarget();

  55.         if (!context.getClass().getAnnotation(DciContext.class).autoThreadBinding())
  56.           {
  57.             return pjp.proceed();
  58.           }
  59.         else
  60.           {
  61.             if (log.isTraceEnabled())
  62.               {
  63.                 log.trace("executing {}.{}() with context thread binding", shortId(context), pjp.getSignature().getName());
  64.               }

  65.             // It looks like the @Inject approach creates bogus multiple instance of ContextManager
  66.             final var contextManager = ContextManager.Locator.find();
  67.             return contextManager.runWithContext(context, new Task<Object, Throwable>()
  68.               {
  69.                 @Override
  70.                 public Object run()
  71.                   throws Throwable
  72.                   {
  73.                     return pjp.proceed();
  74.                   }
  75.               });
  76.           }
  77.       }
  78.   }