title: Using RoboGuice context injection with an AbstractThreadedSyncAdapter
body: <p>I am using RoboGuice 2.0b4 to wire up my Android application, which makes use of a SyncAdapter (derived from AbstractThreadedSyncAdapter) hosted in a regular service:</p>
  
  <pre><code>@ContextSingleton
  public class SyncAdapter extends AbstractThreadedSyncAdapter {
      @Inject
      private AccountManager accountManager;
  
      @Inject
      public SyncAdapter(Context context) {
          super(context, true, false);
  
          Injector injector = RoboGuice.getInjector(context);
          ContextScope scope = injector.getInstance(ContextScope.class);
          synchronized(ContextScope.class) {
              scope.enter(context);
              try {
                  injector.injectMembers(this);
              } finally {
                  scope.exit(context);
              }
          }
      }
      [...]
  }
  
  
  @ContextSingleton
  public class SynchronizationService extends RoboService {
      @Inject
      private SyncAdapter syncAdapter;
  
      @Override
      public IBinder onBind(Intent intent) {
          if (equal("android.content.SyncAdapter", intent.getAction())) {
              return syncAdapter.getSyncAdapterBinder();
          } else [...]
          }
          return null;
      }
  }
  </code></pre>
  
  <p>Unfortunately, RoboGuice bails out during the dependency injection when it becomes recursive while calling <code>scope.enter</code> from the <code>SyncAdapter</code>'s constructor:</p>
  
  <pre><code>java.lang.IllegalArgumentException: Scope for com.example.SynchronizationService@412c65b0 must be closed before scope for com.example.SynchronizationService@412c65b0 may be opened
  </code></pre>
  
  <p>when it sees the context attached to the current thread by the <code>onCreate</code> call of <code>SynchronizationService</code>. Stack trace:</p>
  
  <pre><code>  at roboguice.inject.ContextScope.enter(ContextScope.java:67)
    at roboguice.inject.ContextScopedRoboInjector.getInstance(ContextScopedRoboInjector.java:141)
    at com.example.SyncAdapter.&lt;init&gt;(SyncAdapter.java:65)
    at java.lang.reflect.Constructor.constructNative(Constructor.java:-1)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
    at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:85)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    at roboguice.inject.ContextScope$1.get(ContextScope.java:126)
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
    at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
    at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
    at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:75)
    at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:73)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1024)
    at com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:73)
    at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:60)
    at com.google.inject.internal.InjectorImpl.injectMembers(InjectorImpl.java:944)
    at roboguice.inject.ContextScopedRoboInjector.injectMembersWithoutViews(ContextScopedRoboInjector.java:243)
    at roboguice.inject.ContextScopedRoboInjector.injectMembers(ContextScopedRoboInjector.java:236)
    at roboguice.service.RoboService.onCreate(RoboService.java:57)
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:2253)
    [...]
    at dalvik.system.NativeStart.main(NativeStart.java:-1)
  </code></pre>
  
  <p>So, apparently, RoboGuice's dependency injection is not reentrant.</p>
  
  <p>Unfortunately, a SyncAdapter needs constructor-based injection as <code>AbstractThreadedSyncAdapter</code> expects a context to be supplied to its constructor.</p>
  
  <p>Any ideas? I might hack RoboGuice to allow for reentrance, but that's probably not a light undertaking, so I'd prefer a less invasive workaround. ;-)</p>