alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (ProvisionListenerTest.java)

This example Java source code file (ProvisionListenerTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abort, abstractmodule, atomicboolean, chainasserter, counter, error, fail, foo, injector, override, provider, provisionlistener, retry, runtimeexception, util

The ProvisionListenerTest.java Java example source code

/**
 * Copyright (C) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject;

import static com.google.common.collect.ImmutableList.of;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.name.Names.named;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.spi.DependencyAndSource;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.ProvisionListener;
import com.google.inject.util.Providers;

import junit.framework.TestCase;

import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Tests for {@link Binder#bindListener(Matcher, ProvisionListener...)}
 * 
 * @author sameb@google.com (Sam Berlin)
 */
// TODO(sameb): Add some tests for private modules & child injectors.
public class ProvisionListenerTest extends TestCase {

  public void testExceptionInListenerBeforeProvisioning() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new FailBeforeProvision());
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInListenerAfterProvisioning() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new FailAfterProvision());
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInProvisionExplicitlyCalled() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new JustProvision());
      }
    });
    try {
      injector.getInstance(FooBomb.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName());
      assertEquals("Retry, Abort, Fail", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInProvisionAutomaticallyCalled() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new NoProvision());
      }
    });
    try {
      injector.getInstance(FooBomb.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName());
      assertEquals("Retry, Abort, Fail", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInFieldProvision() throws Exception {
    final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bindListener(new AbstractMatcher<Binding() {
          @Override public boolean matches(Binding<?> binding) {
            return binding.getKey().getRawType().equals(DependsOnFooBombInField.class);
          }
        }, listener);
      }
    });
    assertEquals(0, listener.beforeProvision);
    String expectedMsg = null;
    try {
      injector.getInstance(DependsOnFooBombInField.class);
      fail();
    } catch (ProvisionException expected) {
      assertEquals(1, expected.getErrorMessages().size());
      expectedMsg = expected.getMessage();
      assertContains(listener.capture.get().getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName(),
          " while locating " + DependsOnFooBombInField.class.getName());
    }
    assertEquals(1, listener.beforeProvision);
    assertEquals(expectedMsg, listener.capture.get().getMessage());
    assertEquals(0, listener.afterProvision);
  }
  
  public void testExceptionInCxtorProvision() throws Exception {
    final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bindListener(new AbstractMatcher<Binding() {
          @Override public boolean matches(Binding<?> binding) {
            return binding.getKey().getRawType().equals(DependsOnFooBombInCxtor.class);
          }
        }, listener);
      }
    });
    assertEquals(0, listener.beforeProvision);
    String expectedMsg = null;
    try {
      injector.getInstance(DependsOnFooBombInCxtor.class);
      fail();
    } catch (ProvisionException expected) {
      assertEquals(1, expected.getErrorMessages().size());
      expectedMsg = expected.getMessage();
      assertContains(listener.capture.get().getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName(),
          " while locating " + DependsOnFooBombInCxtor.class.getName());
    }
    assertEquals(1, listener.beforeProvision);
    assertEquals(expectedMsg, listener.capture.get().getMessage());
    assertEquals(0, listener.afterProvision);
  }

  public void testListenerCallsProvisionTwice() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new ProvisionTwice());
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + ProvisionTwice.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.IllegalStateException: Already provisioned in this listener.",
          "while locating " + Foo.class.getName());
      assertEquals("Already provisioned in this listener.", pe.getCause().getMessage());  
    }
  }
  
  public void testCachedInScopePreventsProvisionNotify() {
    final Counter count1 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1);
        bind(Foo.class).in(Scopes.SINGLETON);
      }
    });
    Foo foo = injector.getInstance(Foo.class);
    assertNotNull(foo);
    assertEquals(1, count1.count);
    
    // not notified the second time because nothing is provisioned
    // (it's cached in the scope)
    count1.count = 0;
    assertSame(foo, injector.getInstance(Foo.class));
    assertEquals(0, count1.count);
  }
  
  public void testCombineAllBindListenerCalls() {
    final Counter count1 = new Counter();
    final Counter count2 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1);
        bindListener(Matchers.any(), count2);
      }
    });
    assertNotNull(injector.getInstance(Foo.class));
    assertEquals(1, count1.count);
    assertEquals(1, count2.count);
  }
  
  public void testNotifyEarlyListenersIfFailBeforeProvision() {
    final Counter count1 = new Counter();
    final Counter count2 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1, new FailBeforeProvision(), count2);
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
      
      assertEquals(1, count1.count);
      assertEquals(0, count2.count);
    }
  }
  
  public void testNotifyLaterListenersIfFailAfterProvision() {
    final Counter count1 = new Counter();
    final Counter count2 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1, new FailAfterProvision(), count2);
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
      
      assertEquals(1, count1.count);
      assertEquals(1, count2.count);
    }
  }
  
  public void testNotifiedKeysOfAllBindTypes() {
    final Capturer capturer = new Capturer();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), capturer);
        bind(Foo.class).annotatedWith(named("pk")).toProvider(FooP.class);
        try {
          bind(Foo.class).annotatedWith(named("cxtr")).toConstructor(Foo.class.getDeclaredConstructor());
        } catch (Exception ex) {
          throw new RuntimeException(ex);
        }
        bind(LinkedFoo.class).to(Foo.class);
        bind(Interface.class).toInstance(new Implementation());
        bindConstant().annotatedWith(named("constant")).to("MyConstant");
      }
      
      @Provides @Named("pi") Foo provideFooBar() {
        return new Foo();
      }
    });
    
    // toInstance & constant bindings are notified in random order, at the very beginning.
    assertEquals(
        ImmutableSet.of(Key.get(Interface.class), Key.get(String.class, named("constant"))),
        capturer.getAsSetAndClear());
    
    // simple binding
    assertNotNull(injector.getInstance(Foo.class));
    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
    
    // provider key binding -- notifies about provider & the object, always
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk"))));
    assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear());
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk"))));
    assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear());
    
    // JIT provider key binding -- notifies about provider & the object, always
    assertNotNull(injector.getInstance(JitFoo2.class));
    assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear());
    assertNotNull(injector.getInstance(JitFoo2.class));
    assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear());
    
    // provider instance binding -- just the object (not the provider)
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pi"))));
    assertEquals(of(Key.get(Foo.class, named("pi"))), capturer.getAndClear());
    
    // toConstructor binding
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("cxtr"))));
    assertEquals(of(Key.get(Foo.class, named("cxtr"))), capturer.getAndClear());
    
    // linked binding -- notifies about the target (that's what's provisioned), not the link
    assertNotNull(injector.getInstance(LinkedFoo.class));
    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());

    // JIT linked binding -- notifies about the target (that's what's provisioned), not the link
    assertNotNull(injector.getInstance(JitFoo.class));
    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
  }
  
  public void testSingletonMatcher() {
    final Counter counter = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(new AbstractMatcher<Binding() {
          @Override
          public boolean matches(Binding<?> t) {
            return Scopes.isSingleton(t);
          }
        }, counter);
      }
    });
    assertEquals(0, counter.count);
    // no increment for getting Many.
    injector.getInstance(Many.class);
    assertEquals(0, counter.count);
    // but an increment for getting Sole, since it's a singleton.
    injector.getInstance(Sole.class);
    assertEquals(1, counter.count);
  }
  
  public void testCallingBindingDotGetProviderDotGet() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new ProvisionListener() {
          @Override
          public <T> void onProvision(ProvisionInvocation provision) {
            provision.getBinding().getProvider().get(); // AGH!
          }
        });
      }
    });
    
    try {
      injector.getInstance(Sole.class);
      fail();
    } catch(ProvisionException expected) {
      // We don't really care what kind of error you get, we only care you get an error.
    }
    
    try {
      injector.getInstance(Many.class);
      fail();
    } catch(ProvisionException expected) {
      // We don't really care what kind of error you get, we only care you get an error.
    }
  }
  
  interface Interface {}
  class Implementation implements Interface {}
  
  @Singleton static class Sole {}
  static class Many {}
  
  @ImplementedBy(Foo.class) static interface JitFoo {}  
  @ProvidedBy(JitFoo2P.class) static class JitFoo2 {}  
  static interface LinkedFoo {}
  static class Foo implements JitFoo, LinkedFoo {}
  static class FooP implements Provider<Foo> {
    public Foo get() {
      return new Foo();
    }
  }
  static class JitFoo2P implements Provider<JitFoo2> {
    public JitFoo2 get() {
      return new JitFoo2();
    }
  }
  
  static class FooBomb {
    FooBomb() {
      throw new RuntimeException("Retry, Abort, Fail");
    }
  }
  
  static class DependsOnFooBombInField {
    @Inject FooBomb fooBomb;
  }
  
  static class DependsOnFooBombInCxtor {
    @Inject DependsOnFooBombInCxtor(FooBomb fooBomb) {}
  }
  
  private static class Counter implements ProvisionListener {
    int count = 0;
    public <T> void onProvision(ProvisionInvocation provision) {
      count++;
    }
  }
  
  private static class CountAndCaptureExceptionListener implements ProvisionListener {
    int beforeProvision = 0;
    int afterProvision = 0;
    AtomicReference<RuntimeException> capture = new AtomicReference();
    public <T> void onProvision(ProvisionInvocation provision) {
      beforeProvision++;
      try {
        provision.provision();
      } catch (RuntimeException re) {
        capture.set(re);
        throw re;
      }
      afterProvision++;
    }
  }
  
  private static class Capturer implements ProvisionListener {
    List<Key> keys = Lists.newArrayList(); 
    public <T> void onProvision(ProvisionInvocation provision) {
      keys.add(provision.getBinding().getKey());
      T provisioned = provision.provision();
      // InstanceBindings are the only kind of binding where the key can
      // be an instanceof the provisioned, because it isn't linked to any
      // direct implementation.  I guess maybe it'd also be possible
      // with a toConstructor binding... but we don't use that in our tests.
      if (provision.getBinding() instanceof InstanceBinding) {
        Class<? super T> expected = provision.getBinding().getKey().getRawType();
        assertTrue("expected instanceof: " + expected + ", but was: " + provisioned,
            expected.isInstance(provisioned));
      } else {
        assertEquals(provision.getBinding().getKey().getRawType(), provisioned.getClass());
      }
    }
    
    Set<Key> getAsSetAndClear() {
      Set<Key> copy = ImmutableSet.copyOf(keys);
      keys.clear();
      return copy;
    }
    
    List<Key> getAndClear() {
      List<Key> copy = ImmutableList.copyOf(keys);
      keys.clear();
      return copy;
    }
  }

  private static class FailBeforeProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation provision) {
      throw new RuntimeException("boo");
    }
  }  
  private static class FailAfterProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation provision) {
      provision.provision();
      throw new RuntimeException("boo");
    }
  }  
  private static class JustProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation provision) {
      provision.provision();
    }
  }  
  private static class NoProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation provision) {
    }
  }
  private static class ProvisionTwice implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation provision) {
      provision.provision();
      provision.provision();
    }
  }
  
  private static class ChainAsserter implements ProvisionListener {
    private final List<Class provisionList;
    private final List<Class expected;
    
    public ChainAsserter(List<Class provisionList, Iterable> expected) {
      this.provisionList = provisionList;
      this.expected = ImmutableList.copyOf(expected);
    }
    
    public <T> void onProvision(ProvisionInvocation provision) {
      List<Class actual = Lists.newArrayList();
      for (DependencyAndSource dep : provision.getDependencyChain()) {
        actual.add(dep.getDependency().getKey().getRawType());
      }
      assertEquals(expected, actual);
      provisionList.add(provision.getBinding().getKey().getRawType());
    }
  }
  
  private static Matcher<Binding keyMatcher(final Class clazz) {
    return new AbstractMatcher<Binding() {
      @Override
      public boolean matches(Binding<?> t) {
        return t.getKey().equals(Key.get(clazz));
      }
    };
  }
  
  @SuppressWarnings("unchecked")
  public void testDependencyChain() {
    final List<Class pList = Lists.newArrayList();
    final List<Class totalList = Lists.newArrayList();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Instance.class).toInstance(new Instance());
        bind(B.class).to(BImpl.class);
        bind(D.class).toProvider(DP.class);
        
        bindListener(Matchers.any(), new ProvisionListener() {
          public <T> void onProvision(ProvisionInvocation provision) {
            totalList.add(provision.getBinding().getKey().getRawType());
          }
        });
        
        // Build up a list of asserters for our dependency chains.
        ImmutableList.Builder<Class chain = ImmutableList.builder();
        chain.add(Instance.class);
        bindListener(keyMatcher(Instance.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(A.class);
        bindListener(keyMatcher(A.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(B.class).add(BImpl.class);
        bindListener(keyMatcher(BImpl.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(C.class);
        bindListener(keyMatcher(C.class), new ChainAsserter(pList, chain.build()));
        
        // the chain has D before DP even though DP is provisioned & notified first
        // because we do DP because of D, and need DP to provision D.
        chain.add(D.class).add(DP.class);
        bindListener(keyMatcher(D.class), new ChainAsserter(pList, chain.build()));
        bindListener(keyMatcher(DP.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(E.class);
        bindListener(keyMatcher(E.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(F.class);
        bindListener(keyMatcher(F.class), new ChainAsserter(pList, chain.build()));
      }
      @Provides C c(D d) {
        return new C() {};
      }
    });
    Instance instance = injector.getInstance(Instance.class);
    // make sure we're checking all of the chain asserters..
    assertEquals(
        of(Instance.class, A.class, BImpl.class, C.class, DP.class, D.class, E.class, F.class),
        pList);
    // and make sure that nothing else was notified that we didn't expect.
    assertEquals(totalList, pList);
  }
  
  public void testModuleRequestInjection() {
    final AtomicBoolean notified = new AtomicBoolean();    
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        requestInjection(new Object() {
          @Inject Foo foo;
        });
        bindListener(Matchers.any(),
            new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified));
      }
    });
    assertTrue(notified.get());
  }
  
  public void testToProviderInstance() {
    final AtomicBoolean notified = new AtomicBoolean();    
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Object.class).toProvider(new Provider<Object>() {
          @Inject Foo foo;
          public Object get() {
            return null;
          }
        });
        bindListener(Matchers.any(),
            new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified));
      }
    });
    assertTrue(notified.get());
  }
  
  public void testInjectorInjectMembers() {
    final Object object = new Object() {
      @Inject Foo foo;
    };
    final AtomicBoolean notified = new AtomicBoolean();    
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(),
            new SpecialChecker(Foo.class, object.getClass().getName(), notified));
      }
    }).injectMembers(object);
    assertTrue(notified.get());
  }
  
  private static class SpecialChecker implements ProvisionListener {
    private final Class<?> notifyType;
    private final String firstSource;
    private final AtomicBoolean notified;
    
    public SpecialChecker(Class<?> notifyType, String firstSource, AtomicBoolean notified) {
      this.notifyType = notifyType;
      this.firstSource = firstSource;
      this.notified = notified;
    }
    
    public <T> void onProvision(ProvisionInvocation provision) {
      notified.set(true);
      assertEquals(notifyType, provision.getBinding().getKey().getRawType());            
      assertEquals(2, provision.getDependencyChain().size());
      
      assertNull(provision.getDependencyChain().get(0).getDependency());
      assertContains(provision.getDependencyChain().get(0).getBindingSource(), firstSource);
      
      assertEquals(notifyType,
          provision.getDependencyChain().get(1).getDependency().getKey().getRawType());
      assertContains(provision.getDependencyChain().get(1).getBindingSource(),
          notifyType.getName() + ".class(");
    }
  }
  
  private static class Instance {
    @Inject A a;
  }
  private static class A {
    @Inject A(B b) {}
  }
  private interface B {}
  private static class BImpl implements B {
    @Inject void inject(C c) {}
  }
  private interface C {}
  private interface D {}
  private static class DP implements Provider<D> {
    @Inject Provider<E> ep;
    public D get() {
      ep.get();
      return new D() {};
    }
  }
  private static class E {
    @SuppressWarnings("unused")
    @Inject F f;
  }
  private static class F {
  }

  public void testBindToInjectorWithListeningGivesSaneException() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bindListener(Matchers.any(), new Counter());
          bind(Injector.class).toProvider(Providers.<Injector>of(null));
        }
      });
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(), "Binding to core guice framework type is not allowed: Injector.");
    }
  }

  public void testProvisionIsNotifiedAfterContextsClear() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new ProvisionListener() {
          @Override
          public <T> void onProvision(ProvisionInvocation provision) {
            Object provisioned = provision.provision();
            if (provisioned instanceof X) {
              ((X)provisioned).init();
            } else if (provisioned instanceof Y) {
              X.createY = false;
              ((Y)provisioned).init();
            }
          }
        });
      }
    });

    X.createY = true;
    X x = injector.getInstance(X.class);
    assertNotSame(x, x.y.x);
    assertFalse("x.ID: " + x.ID + ", x.y.x.iD: " + x.y.x.ID, x.ID == x.y.x.ID);
  }

  private static class X {
    final static AtomicInteger COUNTER = new AtomicInteger();
    static boolean createY;

    final int ID = COUNTER.getAndIncrement();
    final Provider<Y> yProvider;
    Y y;

    @Inject X(Provider<Y> yProvider) {
      this.yProvider = yProvider;
    }

    void init() {
      if (createY) {
        this.y = yProvider.get();
      }
    }
  }

  private static class Y {
    final Provider<X> xProvider;
    X x;

    @Inject Y(Provider<X> xProvider) {
      this.xProvider = xProvider;
    }

    void init() {
      this.x = xProvider.get();
    }
  }
  
  public void testDeDuplicateProvisionListeners() {
    final Counter counter = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), counter);
        bindListener(Matchers.any(), counter);
      }
    });
    injector.getInstance(Many.class);
    assertEquals("ProvisionListener not de-duplicated", 1, counter.count);
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java ProvisionListenerTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.