Search code examples
javaguiceproviderguice-servlet

Provider extending


I need to create provider for session scopes, like ServletScopes.SESSION, but with one extra action after object construction (like add listener). First idea - to extend ServletScopes.SESSION and override some method, but, unfortunately ServletScopes.SESSION is object, not class. So, how I can get such provider without copy-pasting code from ServletScopes?


Solution

  • First create an annotation:

    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    @Target({TYPE, METHOD})
    @Retention(RUNTIME)
    public @interface AfterInjectionListener
    {
    }
    

    Then, annotate every class that implements a method `afterInjection()' with the annotation and add this binding to one of your Guice modules:

    bindListener(Matchers.any(), new TypeListener()
    {
      @Override
      public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> iTypeEncounter)
      {
        if (typeLiteral.getRawType().isAnnotationPresent(AfterInjectionListener.class))
        {
          logger.debug("adding injection listener {}", typeLiteral);
          iTypeEncounter.register(new InjectionListener<I>()
          {
            @Override
            public void afterInjection(I i)
            {
              try
              {
                logger.debug("after injection {}", i);
                i.getClass().getMethod("afterInjection").invoke(i);
              } catch (NoSuchMethodException e)
              {
                logger.trace("no such method", e);
              } catch (Exception e)
              {
                logger.debug("error after guice injection", e);
              }
            }
          });
        }
      }
    });
    

    Place a breakpoint inside of afterInjection() method, run the app in debugging mode and check if the method is called after injection.