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)
Lambda Expressions were added in Java 8.
Introduction. Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection .
Each lambda expression is mapped to a functional interface internally. The compiler decides which functional interface it should be mapped to from the context at the time of compiling the source code. Contrary to other functions in Java, you can define lambda functions that exist outside of the scope of any object.
In Java lambda expression, if there is only one statement, you may or may not use return keyword. You must use return keyword when lambda expression contains multiple statements. // Lambda expression without return keyword. Addable ad1=(a,b)->(a+b);
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With