title: Guice Assisted Inject - java.lang.IllegalStateException: zip file closed
body: <p>I'm having problems with using Guice's assisted inject within my spigot plugin, and can't seem to narrow down the problem. This is the error I'm getting:</p>
  
  <pre><code>&gt; [12:00:38 INFO]: [DestinyMC] Enabling DestinyMC v1.0
  &gt; 2019-01-14 12:00:41,492 Log4j2-TF-1-AsyncLogger[AsyncContext@5c647e05]-1 ERROR An exception occurred processing Appender File com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: zip file closed
      at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2217)
      at com.google.common.cache.LocalCache.get(LocalCache.java:4154)
      at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4158)
      at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5147)
      at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5153)
      at com.google.inject.internal.util.StackTraceElements.forMember(StackTraceElements.java:71)
      at com.google.inject.internal.Messages.formatSource(Messages.java:241)
      at com.google.inject.internal.Messages.formatSource(Messages.java:220)
      at com.google.inject.internal.Messages.formatMessages(Messages.java:90)
      at com.google.inject.CreationException.getMessage(CreationException.java:50)
      at org.apache.logging.log4j.core.impl.ThrowableProxy.&lt;init&gt;(ThrowableProxy.java:134)
      at org.apache.logging.log4j.core.impl.ThrowableProxy.&lt;init&gt;(ThrowableProxy.java:122)
      at org.apache.logging.log4j.core.async.RingBufferLogEvent.getThrownProxy(RingBufferLogEvent.java:330)
      at org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter.format(ExtendedThrowablePatternConverter.java:61)
      at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38)
      at org.apache.logging.log4j.core.layout.PatternLayout$PatternSelectorSerializer.toSerializable(PatternLayout.java:455)
      at org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:232)
      at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:217)
      at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:57)
      at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:177)
      at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:170)
      at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:161)
      at org.apache.logging.log4j.core.appender.RollingRandomAccessFileAppender.append(RollingRandomAccessFileAppender.java:218)
      at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
      at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
      at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
      at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
      at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:448)
      at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:433)
      at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
      at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:79)
      at org.apache.logging.log4j.core.async.AsyncLogger.actualAsyncLog(AsyncLogger.java:337)
      at org.apache.logging.log4j.core.async.RingBufferLogEvent.execute(RingBufferLogEvent.java:161)
      at org.apache.logging.log4j.core.async.RingBufferLogEventHandler.onEvent(RingBufferLogEventHandler.java:45)
      at org.apache.logging.log4j.core.async.RingBufferLogEventHandler.onEvent(RingBufferLogEventHandler.java:29)
      at com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:168)
      at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:125)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)
  Caused by: java.lang.IllegalStateException: zip file closed
      at java.util.zip.ZipFile.ensureOpen(Unknown Source)
      at java.util.zip.ZipFile.getEntry(Unknown Source)
      at java.util.jar.JarFile.getEntry(Unknown Source)
      at java.util.jar.JarFile.getJarEntry(Unknown Source)
      at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:120)
      at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:104)
      at java.lang.ClassLoader.loadClass(Unknown Source)
      at java.lang.ClassLoader.loadClass(Unknown Source)
      at com.google.inject.internal.util.StackTraceElements$1.load(StackTraceElements.java:49)
      at com.google.inject.internal.util.StackTraceElements$1.load(StackTraceElements.java:45)
      at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3716)
      at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2424)
      at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2298)
      at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2211)
      ... 39 more
  </code></pre>
  
  <p>This is my Binder Class:</p>
  
  <pre><code>public class MainBinder extends AbstractModule {
  
  @Override
  protected void configure() {
      bind(DestinyMC.class).toInstance(this.plugin);
  
      install(new FactoryModuleBuilder().build(InventoryFromFileFactory.class));
  }
  </code></pre>
  
  <p>The error goes away when I comment out the install line. That line uses this factory class</p>
  
  <pre><code>public interface InventoryFromFileFactory {
      InventoryFromFile create(String targetRootKey, String targetFile);
  }
  </code></pre>
  
  <p>which declare the parameters that need to be manually provided at object creation for this class:</p>
  
  <pre><code>public class InventoryFromFile {
      @Inject
      public InventoryFromFile
      (
          @Assisted String targetRootKey,
          @Assisted String targetFile,
          ConfigAccessorFactory configAccessorFactory
      )
      {
          ConfigurationSection targetCS = configAccessorFactory.create(targetFile).getCustomConfig().getConfigurationSection(targetRootKey);
      ...
      }
  }
  </code></pre>
  
  <p>The <code>ConfigAccessFactory</code> is another factory class for assisted inject</p>
  
  <pre><code>public interface ConfigAccessorFactory {
      ConfigAccessor create(String filename);
  }
  </code></pre>
  
  <p>which is used here:</p>
  
  <pre><code>public class ConfigAccessor {
      private Plugin plugin;
      private final String customFileName;
  
      @Inject
      public ConfigAccessor
      (
          @Assisted String fileName,
          DestinyMC plugin
      )
      {
          this.customFileName = fileName;
          this.plugin = plugin;
      }
      ...
  }
  </code></pre>
  
  <p>Finally, the <code>DestinyMC</code> dependency is the main class for the spigot plugin:</p>
  
  <pre><code>public class DestinyMC extends JavaPlugin {
  //Inject dependencies
  @Inject private ConfigAccessorFactory configAccessorFactory;
  
  //Code only run once when the plugin is enabled
  public void onEnable() {
      MainBinder mainBinder = new MainBinder(this);
      Injector injector = Guice.createInjector(mainBinder);
      injector.injectMembers(this);
  
      //Saves config files to disk if they don't exist
      saveDefaultConfig();
      Arrays.asList(
          "inventory-gui.yml",
          "player-tree-template.yml",
          "player-tree-data.yml"
      ).forEach((file) -&gt; {
          configAccessorFactory.create(file).saveDefaultConfig();
      });
      ...
  }
  </code></pre>
  
  <p>I'm not too sure what I'm doing wrong, but I'm fairly new to Guice so I'm most likely misunderstanding something. Also, if there's simply a better way to do this, let me know. Thanks for the help.</p>