26

If I put a Java 8 Lambda expression in a REST service, it crashes. If I remove the lambda expression, it works. It does not matter if I use the lambda expression or not. Just the existence the lambda is enough to crash. Everything else Java 8 related seems to work.

Below is my code (simplified):

@Path("finance")
public class FinanceRest {

    @GET
    @Produces("text/plain")
    public String speak() {
        return "Hello world.";
    }

    private void lambdaFunction(Predicate<Account> predicate) {
        // Any lambda will cause problems, no matter how simple
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Stream<Integer> onlyOdds = numbers.stream().filter(n -> n%2 != 0);
    }

}

As you can see from the code above, just the existence of a lambda expression will cause failure. As soon as I remove the lambda, it works fine. The other Java 8 stuff is fine (for example, the "Predicate" input parameter).

The error message I'm getting is: java.lang.ArrayIndexOutOfBoundsException: 25980

I've tried this on Tomcat 7 and 8 using Java 8. I'm using the standard jax-rs stuff from JavaEE 6.... in other words my POM file has this:

    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>6.0</version>
        <scope>provided</scope>
    </dependency>

Any help would be appreciated. Thanks.

The exact error message (on Glassfish 4.0... I've tried both Tomcat and Glassfish) is:

java.lang.ArrayIndexOutOfBoundsException: 52264 at org.objectweb.asm.ClassReader.readClass(ClassReader.java:2015) at org.objectweb.asm.ClassReader.accept(ClassReader.java:469) at org.objectweb.asm.ClassReader.accept(ClassReader.java:425) at org.glassfish.hk2.classmodel.reflect.Parser$5.on(Parser.java:362) at com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.handleEntry(ReadableArchiveScannerAdapter.java:165) at com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.onSelectedEntries(ReadableArchiveScannerAdapter.java:127) at org.glassfish.hk2.classmodel.reflect.Parser.doJob(Parser.java:347) at org.glassfish.hk2.classmodel.reflect.Parser.access$300(Parser.java:67) at org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:306) at org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:744)

Yusuf K.
  • 4,022
  • 28
  • 63
David Jensen
  • 565
  • 1
  • 7
  • 10
  • I hate to say that it sounds like a bug, but it does. Just adding a lambda expression shouldn't break JAX-RS implementations. – Eric Stein Apr 07 '14 at 16:11
  • 1
    You will need to use Tomcat 8, not 7. Make sure JAVA_HOME is pointed to the Java8 JRE so tomcat will pick it up. Other than that, I'm not really sure what the issue could be. – jacobhyphenated Apr 07 '14 at 16:15
  • 1
    @jacobhyphenated Java 8 will run on Tomcat 7 as well. I have an instance running Java 8 with no problems. Just make sure the version is 7.52+ (I believe) – Bart Apr 07 '14 at 16:42
  • @Bart Are you using any of the new Java 8 bytecode constructs? (Lambda, etc.) – skiwi Apr 07 '14 at 16:52
  • Can you post the full stacktrace of the error? – skiwi Apr 07 '14 at 17:03
  • I just tried the same code on Glassfish 4.0. I get the same error message (essentially). The exact error message from Glassfish is: – David Jensen Apr 07 '14 at 17:18
  • I also discovered this isn't a REST issue. The existence of a lambda expression anywhere within my web-app will cause the problem (Tomcat or Glassfish). In Netbeans, I created a command-line project (non-web), and everything runs fine. – David Jensen Apr 07 '14 at 17:23
  • @skiwi I've put the exact stacktrace up-above in the main question area. – David Jensen Apr 07 '14 at 17:32

5 Answers5

27

I found the solution! I was using Jersey 1.17.1. When I upgraded to 2.7 it worked. My pom file had the following:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-bundle</artifactId>
    <version>1.17.1</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.17.1</version>
    <scope>compile</scope>
</dependency>

I removed those and added:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.7</version>
</dependency>

And of course I had to modify the web.xml file to have:

<servlet>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>

<servlet-mapping>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <url-pattern>/rs/*</url-pattern>
</servlet-mapping>

Now everything is working well. The question is: Why were lambda expressions still failing when I removed them from the REST class and put them in a non-REST class? Just the fact I was including Jersey 1.x was enough to crash when using lambda expressions (whether or not an actual REST service was involved). But at any rate, I'm pleased the project is working again; I had been wanting to upgrade to the latest version of jax-rs & Jersey anyway so this forced me to do it (costing me several hours of work and need to explain to the "SCRUM master" why my estimate is off (don't get me started on that topic). Now if I can only figure out why Jersey 2 is returning XML when I told it to return JSON I'll be back on track.

Thanks everyone for your help!

David Jensen
  • 565
  • 1
  • 7
  • 10
12

Jersey 1.19 is compatible with JDK 1.8.0. Refer to Jersey 1.19 Release summaryJDK8 support in Jersey 1.19Repackage ASM lib in Jersey 1.19

Please remove asm-3.1.jar since jersey-server-1.19.jar has asm 5.0 repacked in it.

Tom Shen
  • 1,447
  • 1
  • 10
  • 6
4

The stacktrace shows that the class org.objectweb.asm.ClassReader.readClass gives an exception. I suppose this is a parser that Glassfish uses internally.

One of the reasons it would crash, is because it is not configured to handle the given input properly. In this case the given input is a lambda expression and it does not know how to handle it.

You will need to look for Java 8 bytecode (lambda) support for Glassfish and Tomcat. If it is not the issue, then it might be a bug in the parser that is internally used.

skiwi
  • 59,273
  • 29
  • 118
  • 198
1

I had to upgrade spring to 4.3.6.RELEASE and junit to 4.12 before I got rid of this particular error when trying to run a junit test with java 1.8 after I had introduced lamdas.

David B
  • 21
  • 1
0

In addition to all other answers,

On my system this problem is occured on Glassfish 4.0(build 89)

Solution;

I upgraded Glassfish to 4.1(build 13) and it solved that problem.

Yusuf K.
  • 4,022
  • 28
  • 63