Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 8 lambda definitions can break Guice's internal exception handling #757

Closed
gissuebot opened this issue Jul 7, 2014 · 52 comments
Closed
Labels

Comments

@gissuebot
Copy link

From abwallis on July 26, 2013 09:10:49

If a @Provides method contains a lambda definition, and an uncaught exception is thrown by the @Provides method, Guice's internal exception handling (UncaughtExceptionHandler) fails with com.google.inject.internal.util.$ComputationException, hiding the underlying cause of the failure and preventing the display of Guice's informative stack trace.
Note that the lambda does not even have to be executed, a user exception can be thrown before the definition of the lambda and will still trigger the failure. Steps to reproduce: 1. Compile and run the attached file.

Guice version: 3.0
JDK version: 1.8.0-ea-b98

Attachment: gist
   Java8LambdaIssue.java

Original issue: http://code.google.com/p/google-guice/issues/detail?id=757

@gissuebot
Copy link
Author

From mcculls on July 26, 2013 07:11:30

Note that UncaughtExceptionHandler is actually the JVM's default handler for exceptions not caught in the application, adding a try...catch block around the main method code and printing out the exception reveals:

Exception in thread "main" com.google.inject.internal.util.$ComputationException: java.lang.ArrayIndexOutOfBoundsException: 17665
        at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553)
        at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:419)
        at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041)
        at com.google.inject.internal.util.$StackTraceElements.forMember(StackTraceElements.java:53)
        at com.google.inject.internal.Errors.formatSource(Errors.java:690)
        at com.google.inject.internal.Errors.format(Errors.java:555)
        at com.google.inject.ProvisionException.getMessage(ProvisionException.java:59)
        at java.lang.Throwable.getLocalizedMessage(Throwable.java:391)
        at java.lang.Throwable.toString(Throwable.java:480)
        at java.lang.String.valueOf(String.java:2985)
        at java.io.PrintStream.println(PrintStream.java:821)
        at java.lang.Throwable$WrappedPrintStream.println(Throwable.java:748)
        at java.lang.Throwable.printStackTrace(Throwable.java:655)
        at java.lang.Throwable.printStackTrace(Throwable.java:643)
        at java.lang.Throwable.printStackTrace(Throwable.java:634)
        at Java8LambdaIssue.main(Java8LambdaIssue.java:16)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 17665
        at com.google.inject.internal.asm.$ClassReader.readClass(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.accept(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.accept(Unknown Source)
        at com.google.inject.internal.util.$LineNumbers.<init>(LineNumbers.java:62)
        at com.google.inject.internal.util.$StackTraceElements$1.apply(StackTraceElements.java:36)
        at com.google.inject.internal.util.$StackTraceElements$1.apply(StackTraceElements.java:33)
        at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:549)
        ... 15 more

Can you try with the "no-aop" flavour of Guice 3?  This should avoid the problem as it doesn't use ASM

@gissuebot
Copy link
Author

From sberlin on July 26, 2013 07:13:41

Could you give it a shot with the latest version from HEAD?  I'm pretty sure I updated ASM & CGLIB in there, and some of the changes might have fixed this.

@gissuebot
Copy link
Author

From mcculls on July 26, 2013 07:19:55

Guice HEAD fails with a slightly different ASM error:

Exception in thread "main" com.google.inject.internal.guava.collect.$ComputationException: java.lang.IllegalArgumentException
        at com.google.inject.internal.guava.collect.$ComputingConcurrentHashMap$ComputingMapAdapter.get(ComputingConcurrentHashMap.java:397)
        at com.google.inject.internal.util.StackTraceElements.forMember(StackTraceElements.java:56)
        at com.google.inject.internal.Errors.formatSource(Errors.java:703)
        at com.google.inject.internal.Errors.format(Errors.java:568)
        at com.google.inject.ProvisionException.getMessage(ProvisionException.java:61)
        at java.lang.Throwable.getLocalizedMessage(Throwable.java:391)
        at java.lang.Throwable.toString(Throwable.java:480)
        at java.lang.String.valueOf(String.java:2985)
        at java.io.PrintStream.println(PrintStream.java:821)
        at java.lang.Throwable$WrappedPrintStream.println(Throwable.java:748)
        at java.lang.Throwable.printStackTrace(Throwable.java:655)
        at java.lang.Throwable.printStackTrace(Throwable.java:643)
        at java.lang.Throwable.printStackTrace(Throwable.java:634)
        at Java8LambdaIssue.main(Java8LambdaIssue.java:16)
Caused by: java.lang.IllegalArgumentException
        at com.google.inject.internal.asm.$ClassReader.<init>(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.<init>(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.<init>(Unknown Source)
        at com.google.inject.internal.util.LineNumbers.<init>(LineNumbers.java:65)
        at com.google.inject.internal.util.StackTraceElements$1.apply(StackTraceElements.java:39)
        at com.google.inject.internal.util.StackTraceElements$1.apply(StackTraceElements.java:36)
        at com.google.inject.internal.guava.collect.$ComputingConcurrentHashMap$ComputingValueReference.compute(ComputingConcurrentHashMap.java:355)
        at com.google.inject.internal.guava.collect.$ComputingConcurrentHashMap$ComputingSegment.compute(ComputingConcurrentHashMap.java:184)
        at com.google.inject.internal.guava.collect.$ComputingConcurrentHashMap$ComputingSegment.getOrCompute(ComputingConcurrentHashMap.java:153)
        at com.google.inject.internal.guava.collect.$ComputingConcurrentHashMap.getOrCompute(ComputingConcurrentHashMap.java:69)
        at com.google.inject.internal.guava.collect.$ComputingConcurrentHashMap$ComputingMapAdapter.get(ComputingConcurrentHashMap.java:393)
        ... 13 more

Which might be because Java8 is still a moving target... I haven't tried pulling in the ASM 5 alpha build.

@gissuebot
Copy link
Author

From mcculls on July 26, 2013 07:20:59

PS. testing with the "no-aop" flavour of Guice works as expected (ie. the application error is reported properly)

@gissuebot
Copy link
Author

From sberlin on July 26, 2013 07:24:05

Yeah, until Java8 stabilizes, I doubt there's much we can do about this.  The error is inside ASM itself, trying to read the class from the bytes of the classfile.  We could potentially put a try/catch around that for IAE, but I'm not a big fan of defensively programming against something that isn't released nor defined.

@gissuebot
Copy link
Author

From mcculls on July 26, 2013 07:30:27

The latest ASM 5 code seems to fix the issue.

@gissuebot
Copy link
Author

From sameb@google.com on July 26, 2013 07:31:57

Happen to know the timeline for when they expect to ship it?

@gissuebot
Copy link
Author

From mcculls on July 26, 2013 07:43:45

Sorry, don't know - http://mail.ow2.org/wws/arc/asm/2013-02/msg00000.html has some related discussion and afaict they're planning to wait for the Java8 spec to finalize before releasing ASM5. There is an early alpha build: http://mail.ow2.org/wws/arc/asm/2013-03/msg00000.html

@gissuebot
Copy link
Author

From mcculls on October 22, 2013 16:44:51

FYI using ASM 5.0_BETA with a patched version of cglib (see Issue 759 ) produces the expected stack trace:

Exception in thread "main" com.google.inject.ProvisionException: Guice provision errors:

  1. Error in custom provider, java.lang.IllegalStateException: Something went wrong
      at Java8LambdaIssue$LambdaIssueModule.createExecutor(Java8LambdaIssue.java:23)
      while locating java.util.concurrent.Executor

1 error
        at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1009)
        at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1035)
        at Java8LambdaIssue.main(Java8LambdaIssue.java:14)
Caused by: java.lang.IllegalStateException: Something went wrong
        at Java8LambdaIssue$LambdaIssueModule.createExecutor(Java8LambdaIssue.java:24)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:491)
        at com.google.inject.internal.ProviderMethod.get(ProviderMethod.java:105)
        at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:86)
        at com.google.inject.internal.InternalFactoryToInitializableAdapter.provision(InternalFactoryToInitializableAdapter.java:55)
        at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:66)
        at com.google.inject.internal.InternalFactoryToInitializableAdapter.get(InternalFactoryToInitializableAdapter.java:47)
        at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1000)
        at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1050)
        at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:996)
        ... 2 more

If you want to experiment with this solution, it's available on central as sisu-guice 3.1.8: https://github.com/sonatype/sisu-guice # README explains differences wrt. google-guice http://search.maven.org/#artifactdetails%7Corg.sonatype.sisu%7Csisu-guice%7C3.1.8%7Cjar

@gissuebot
Copy link
Author

From tebulin on December 04, 2013 06:17:18

Coming from related issue: https://code.google.com/p/google-guice/issues/detail?id=782 > The error is inside ASM itself, trying to read the class from the bytes of the
> classfile.  We could potentially put a try/catch around that for IAE, but I'm
> not a big fan of defensively programming

In my cases ASM only fails for reverse lookups of original source code locations. So on any Guice error I only receive an completely unrelated $ComputedExceptions hiding another unrelated IllegalArgumentException instead of any helpful pointer to the original issue, just because ASM/Guice was unable to resolve the assumed root code line for the exception I do not get any clue about. ;-)

I'd vote for better defense in here, because it's located in the crucial error handling.

Please find attached a small patch against 4.0-beta which makes this part more robust in these error cases and simply omits the line number then.

Attachment: gist
   0001-Do-not-hide-root-exceptions-on-ASM-Java8-errors.patch

@gissuebot
Copy link
Author

From sameb@google.com on December 04, 2013 06:23:16

You missed the key part of that quote. :-) ...  "not a big fan of defensively programming against something that isn't released nor defined.". -- Is the java8 spec finalized?

@gissuebot
Copy link
Author

From sberlin on December 04, 2013 06:51:46

Issue 782 has been merged into this issue.

@gissuebot
Copy link
Author

From tebulin on December 04, 2013 08:02:21

I explicitly left that part out, because in my reasoning I tried to express, that my patch is not about the state of integrated ASM and the Java 8 spec, but Guice robustness on providing meaningful error messages.

In my opinion Guice should not fail on trying to be more precise about an error than needed. Instead it should always fail-safe back to what it is knows about the error instead of hiding it with a totally unrelated subsequent error.

Please have a look at the patch. It's really trivial and I think it's worth to be integrated, because everything else already seems to work for me under Java 8 and I assume the ASM reverse lookup for Errors might be always a candidate for unexpected and flaky failures.

@gissuebot
Copy link
Author

From sberlin on December 04, 2013 08:08:49

I respectfully disagree.  Arbitrarily adding try/catch around places just leads to brittle code that can magically succeed or fail without knowing what's going on. Guice (and the libraries it embeds right now) do not expect things to fail in this kind of way, and it is good to blow up when it encounters something that will cause it to fail.   Stuart's suggested changes from earlier are the best approach IMO (either exposing the problem more transparently, or solving it entirely).

@gissuebot
Copy link
Author

From mingfai.ma on December 27, 2013 21:37:42

tried a number of combination and finally get Guice to show error message for Java 8 Lambda properly :

  1. Build a custom Guice snapshot with Java 8
    1.1 update core/pom.xml
          update to the latest cglib and asm
     <properties>
        <cglib.version>3.1</cglib.version>
        <asm.version>5.0_BETA</asm.version>
      </properties>
          comment maven-javadoc-plugin and animal-sniffer-maven-plugin for building with Java 8

1.2 update extensions/pom.xml
      comment maven-javadoc-plugin and animal-sniffer-maven-plugin for building with Java 8

1.2 build Guice
    mvn clean compile package source:jar install -pl .,core,extensions,extensions/assistedinject,extensions/multibindings  -DskipTests
notice that

  • the above command build two of the extensions
  • assistedinject actually got test failure so something may be broken.
  1. Configure the pom.xml in your project to include javax.inject, incl. Guice with no_aop classifier
     <dependency>
                <groupId>javax.inject</groupId>
                <artifactId>javax.inject</artifactId>
                <version>1</version>
            </dependency>
            <dependency>
                <groupId>com.google.inject</groupId>
                <artifactId>guice</artifactId>
                <version>${guice.version}</version>
                <classifier>no_aop</classifier>
            </dependency>

Some of the steps/configuration may not be needed. At least, it is one of the ways that make it work.

@gissuebot
Copy link
Author

From steven@trumpet.io on April 01, 2014 10:02:40

This problem, or a very similar one, exists still in 4.0beta4 which claims Java 8 compatibility:

Exception in thread "main" com.google.common.util.concurrent.UncheckedExecutionException: java.lang.RuntimeException
        at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2201)
        at com.google.common.cache.LocalCache.get(LocalCache.java:3934)
        at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938)
        at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821)
        at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4827)
        at com.google.inject.internal.util.StackTraceElements.forMember(StackTraceElements.java:66)
        at com.google.inject.internal.Errors.formatInjectionPoint(Errors.java:790)
        at com.google.inject.internal.Errors.formatSource(Errors.java:752)
        at com.google.inject.internal.Errors.formatSource(Errors.java:743)
        at com.google.inject.internal.Errors.format(Errors.java:569)
        at com.google.inject.CreationException.getMessage(CreationException.java:50)
        at java.lang.Throwable.getLocalizedMessage(Throwable.java:391)
        at java.lang.Throwable.toString(Throwable.java:480)
        at java.lang.String.valueOf(String.java:2979)
        at java.io.PrintStream.println(PrintStream.java:821)
        at java.lang.Throwable$WrappedPrintStream.println(Throwable.java:748)
        at java.lang.Throwable.printStackTrace(Throwable.java:655)
        at java.lang.Throwable.printStackTrace(Throwable.java:643)
        at java.lang.Throwable.printStackTrace(Throwable.java:634)
        at com.opentable.service.discovery.server.DiscoveryServerMain.main(DiscoveryServerMain.java:61)
Caused by: java.lang.RuntimeException
        at com.google.inject.internal.asm.$MethodVisitor.visitParameter(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.b(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.accept(Unknown Source)
        at com.google.inject.internal.asm.$ClassReader.accept(Unknown Source)
        at com.google.inject.internal.util.LineNumbers.<init>(LineNumbers.java:65)
        at com.google.inject.internal.util.StackTraceElements$1.load(StackTraceElements.java:46)
        at com.google.inject.internal.util.StackTraceElements$1.load(StackTraceElements.java:43)
        at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524)
        at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317)
        at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280)
        at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195)
        ... 19 more

@gissuebot
Copy link
Author

From sberlin on April 01, 2014 10:08:57

Can you whittle this down to a small reproducible test-case, so we can see what's causing it?

@gissuebot
Copy link
Author

From steven@trumpet.io on April 04, 2014 12:56:15

Here's a test case, requires Java 8 obviously: https://gist.github.com/stevenschlansker/9981948

@gissuebot
Copy link
Author

From steven@trumpet.io on April 04, 2014 16:06:11

Note that changing the ASM level from Opcodes.ASM4 -> ASM5 seems to fix the problem.

@gissuebot
Copy link
Author

From sberlin on April 04, 2014 16:42:05

Well, that's frustrating.

@gissuebot
Copy link
Author

From steven@trumpet.io on April 04, 2014 17:08:26

Tell me about it!  :P
Would love for this to get fixed for 4.0 release.  It is very frustrating to develop with Java 8 when the stack traces get eaten all the time.

@gissuebot
Copy link
Author

From mcculls on April 15, 2014 03:04:12

Issue 804 has been merged into this issue.

@gissuebot
Copy link
Author

From christianedwardgruber on April 15, 2014 11:34:34

Ok - so apparently ASM-5.0.2 (or whatever HEAD is at) fixes yet another little niggling java8-issue with line-numbers, so as soon as that is released, we can try to roll something that is as up-to-date as possible, and see if that addresses the last remaining Java8 weirdnesses that come from ASM.

@gissuebot
Copy link
Author

From srautureau on May 20, 2014 09:57:26

ASM-5.0.2 is released. When do you plan to release new version ?

@gissuebot
Copy link
Author

From ian.clarke on May 26, 2014 13:44:32

I recently decided to use Guice with Java 8 on an experimental project.  This issue is killing me, I keep getting these "Exception in thread "main" com.google.inject.internal.util.$ComputationException: java.lang.ArrayIndexOutOfBoundsException: 52264" errors - which provide no indication as to what the actual problem is.

Due to this problem, it seems clear to me that Guice is not ready for production use with Java 8 :-/

@gissuebot
Copy link
Author

From sberlin on June 01, 2014 12:55:28

Issue 804 has been merged into this issue.

@gissuebot
Copy link
Author

From ian.clarke on June 02, 2014 10:22:01

Just a note that upgrading to 4.0-beta4 seems to have solved the problem.

@gissuebot
Copy link
Author

From JWellington.Moreno on June 02, 2014 12:18:02

For me, using the no-aop version worked for me. Make sure to exclude aopalliance from any maven dependencies you may have. After that Guice reported dependency issues correctly.

@lewisd32
Copy link

I'm seeing the exception reported in https://code.google.com/p/google-guice/issues/detail?id=804 with 4.0-beta4 still. It seems so far like it's only happening when there's an error binding @nAmed values or something. I have everything working now, but when I change the name inside the @nAmed on the constructor of one class, I get the "INVOKESPECIAL/STATIC on interfaces require ASM 5" exception.

@sameb
Copy link
Member

sameb commented Jul 15, 2014

Is it possible to create a small testcase that reproduces the failure you're seeing and attach it here? You might also want to give the latest HEAD a try -- we've fixed a few more things since the last beta was cut.

@sameb
Copy link
Member

sameb commented Aug 11, 2014

Understandable. FWIW, internally at Google we rely essentially on head (in
fact, what's pushed out here is on a delay), so you can feel safe that with
Guice, at least, things are working. The majority of Java services at
Google would be broken otherwise.

On Mon, Aug 11, 2014 at 5:48 PM, Derek Lewis notifications@github.com
wrote:

I'd still really love to be able to get 4.0-beta5 from maven central,
seeing as this issue seems to be resolved. I'm not really comfortable
releasing something that depends on snapshot versions. It looks like beta4
was released in March. It'd would be great to get something newer to try.


Reply to this email directly or view it on GitHub
#757 (comment).

@joshng
Copy link

joshng commented Aug 11, 2014

+1 for pushing a java-8-compatible release to maven central. My project has been working from HEAD for months, requiring an additional submodule (85M code download and significant additional build complexity) for every developer...

@sameb
Copy link
Member

sameb commented Aug 11, 2014

@cgruber -- I won't have time to do this before vacation (and I doubt these
folks want to wait till mid Sept), but if you'd like to it, please feel
free.

On Mon, Aug 11, 2014 at 6:14 PM, josh gruenberg notifications@github.com
wrote:

+1 for pushing a java-8-compatible release to maven central. My project
has been working from HEAD for months, requiring an additional submodule
(85M code download and significant additional build complexity) for every
developer...


Reply to this email directly or view it on GitHub
#757 (comment).

@lewisd32
Copy link

Yeah, and I definitely feel safe using the latest, it's always proven to be good. However, the issue for me is repeatability. If we depend on -SNAPSHOT, then we run the risk of introducing unexpected changes, when maven picks up a newer snapshot than it used last time. I'd have to check on the posibility of depending on a specifically timestamped snapshot build, but that still feels dangerous to me.

@sameb
Copy link
Member

sameb commented Aug 11, 2014

@joshng -- we just started pushing snapshots automatically, so that may ease your complexity, all you'd need to do is add a normal maven snapshot build, no need to get the whole source & build it.

@brianm
Copy link

brianm commented Aug 16, 2014

Please please push a java8 compat version of 3.x to maven central!

@lewisd32
Copy link

Another month has passed, with only a few merges/commits. It looks like the rate of change has slowed down. Would now be a good time do a 4.0-beta5 release, so those of us using 4.0-beta4 and suffering from this issue can have a release to upgrade to?

@jschneider
Copy link

I'd love to see a 3.0 with that bugfix release... Or maybe a 4.0 release very, very soon?

@stevenschlansker
Copy link

+1 to at least a 4.0-beta5...

@sameb
Copy link
Member

sameb commented Sep 25, 2014

4.0-beta5 is now released, I'm going to mark this bug as closed since I don't think there's anything left to do (except promote it to a non-beta release ultimately).

@sameb sameb closed this as completed Sep 25, 2014
@lewisd32
Copy link

Way to make my morning, thanks @sameb!

dboitnot added a commit to dboitnot/spindlebox that referenced this issue Nov 18, 2014
@hartmut27
Copy link

altough 4.0-beta5 solved the issue in one case,
in another java 8 lambda case, where I had a "plain" cycle between two classes with constructor injects vice versa, the error message re-appeared, even with guice:4.0-beta5.
in the log the original error (cycle dependency) was not mentioned at all.

java.util.logging.ErrorManager: 5
com.google.inject.internal.util.$ComputationException: java.lang.ArrayIndexOutOfBoundsException: 51311
    at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553)

@tokuhirom
Copy link

Java 8 users are waiting Guava 4.0 release. When will you release it?

@deanhillertwitter
Copy link

May of 2016 and I ran into this again. I wish they would have put that other hacky patch in to at least give some visibility instead of chasing this problem down to see what in the world caused it :(.

@sameb
Copy link
Member

sameb commented May 17, 2016

Guice 4 was released over a year ago and resolved the problem, hence the issue was closed. If you're still seeing an issue, I recommend opening a new bug that explains exactly what you're doing and the problem you're seeing.

asfgit pushed a commit to apache/aurora that referenced this issue Dec 7, 2017
Upgrading guice was the original goal with this patch, which pulled along
several other dependencies.  Guice 3
[suffers from obscure errors](google/guice#757)
when creating binding error messages with java 8 and lambdas.  This has been a
frequent source of frustration since we first upgraded to java 8 mid-2015.

I've gone spelunking down this path numerous times, and frequently hit a wall
with jersey.  We needed to upgrade jersey-guice, to upgrade jersey, to upgrade
guice.  jersey introduced their own dependency injection (HK2) in jersey 2.0,
which complicated matters.  There have been some promising developments since
(hk2-guice [bridge](https://javaee.github.io/hk2/guice-bridge.html#bi-directional-hk2-guice-bridge),
2.26 [abstracted HK2](https://jersey.github.io/release-notes/2.26.html), and
several [projects](https://github.com/Squarespace/jersey2-guice) have emerged
to solve the issue).  Unfortunately, each avenue failed with some combination
of not working well with our application design, or i just plain couldn't get
it working.  I began to look beyond jersey.

This left restlet and resteasy as the most common alternatives.  I balked early
at restlet due to their guice integration being
[apparently](https://github.com/restlet/restlet-framework-java/commits/master/modules/org.restlet.ext.guice)
[dormant](https://stackoverflow.com/questions/8227583/what-is-the-status-of-org-restlet-ext-guice).

Fortunately i achieved some early wins with resteasy!  Migrating was
straightforward with a small patch based on some examples.

However, i hit a hurdle with shiro-guice.  It
[needed to be updated](https://issues.apache.org/jira/browse/SHIRO-493) to work
with guice 4, and there were some necessary API changes.  No big deal, just the
`filterConfig()` nesting you see in this patch.  This revealed a deeper issue
with binding custom `Filter`s with `ShiroWebModule`.  Previously,
`ShiroWebModule` would effectively only `bind()` keys
[they define](https://github.com/apache/shiro/blob/f326fd3814f672464deb11c3dadadb27af618eec/support/guice/src/main/java/org/apache/shiro/guice/web/ShiroWebModule.java#L65-L86), allowing the API user to `bind()` custom keys.  The [patch](apache/shiro@f2dfa7f#diff-359a7b20d3b7fdcc0ffce11ad57d6e1c) to support guice 4 changed that, and `bind()` will be [called](apache/shiro@f2dfa7f#diff-359a7b20d3b7fdcc0ffce11ad57d6e1cR183)
on these custom keys.  In our case, this caused a duplicate binding.

The simplest workaround to this was to avoid `bind()`ing the custom
`afterAuthFilter` key, and use the custom type as the key type (e.g.
`Key.get(CountingFilter.class)` rather than `Key.get(Filter.class)`).

Lastly, `GuiceResteasyBootstrapServletContextListener` does not integrate with
`GuiceServletContextListener` in the way `GuiceFilter`
[demands](https://github.com/google/guice/blob/e7bef34ef6379735e2a58df1b23f351bb7e30e44/extensions/servlet/src/com/google/inject/servlet/ServletModule.java#L322-L323),
which necessitated the passing of `ServletContext` you see in this patch.

I can't say i'm happy with the outcome here, but i am overall happier given
that guice is upgraded.

Reviewed at https://reviews.apache.org/r/64362/
@gupdurga
Copy link

gupdurga commented Dec 8, 2017

HI Team,
I am getting similar issue and i am using Guice 4, how do fix this issue?

Exception in thread "main" com.google.inject.internal.util.$ComputationException: java.lang.ArrayIndexOutOfBoundsException: 52264
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553)
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:419)
at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041)
at com.google.inject.internal.util.$StackTraceElements.forMember(StackTraceElements.java:53)
at com.google.inject.internal.Errors.formatInjectionPoint(Errors.java:716)
at com.google.inject.internal.Errors.formatSource(Errors.java:678)
at com.google.inject.internal.Errors.format(Errors.java:555)
at com.google.inject.CreationException.getMessage(CreationException.java:48)
at java.lang.Throwable.getLocalizedMessage(Throwable.java:391)
at java.lang.Throwable.toString(Throwable.java:480)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at java.lang.Throwable$WrappedPrintStream.println(Throwable.java:748)
at java.lang.Throwable.printStackTrace(Throwable.java:655)
at java.lang.Throwable.printStackTrace(Throwable.java:643)
at java.lang.Throwable.printStackTrace(Throwable.java:634)
at com.amazon.toucanemr.job.EMRClusterSparkJob.main(EMRClusterSparkJob.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:755)
at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:180)
at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:205)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:119)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 52264
at com.google.inject.internal.asm.$ClassReader.readClass(Unknown Source)
at com.google.inject.internal.asm.$ClassReader.accept(Unknown Source)
at com.google.inject.internal.asm.$ClassReader.accept(Unknown Source)
at com.google.inject.internal.util.$LineNumbers.(LineNumbers.java:62)
at com.google.inject.internal.util.$StackTraceElements$1.apply(StackTraceElements.java:36)
at com.google.inject.internal.util.$StackTraceElements$1.apply(StackTraceElements.java:33)
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:549)
... 25 more
Command exiting with ret '1'

@mcculls
Copy link
Contributor

mcculls commented Dec 8, 2017

@gupdurga I see you've opened #1140 so will continue the discussion there to avoid confusion, but at first glance looking at the line numbers in the stack trace it appears you are still running Guice 3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests