REST服务中的Java 8 Lambda表达式无法正常工作

时间:2014-04-07 16:02:59

标签: java lambda glassfish java-8 glassfish-4

如果我将一个Java 8 Lambda表达式放在REST服务中,它就会崩溃。如果我删除lambda表达式,它的工作原理。如果我使用lambda表达式并不重要。只是存在lambda足以崩溃。 Java 8相关的所有其他内容似乎都有效。

以下是我的代码(简化):

@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);
    }

}

从上面的代码中可以看出,只有lambda表达式的存在才会导致失败。一旦我删除lambda,它工作正常。其他Java 8的东西很好(例如,&#34; Predicate&#34;输入参数)。

我得到的错误信息是: java.lang.ArrayIndexOutOfBoundsException:25980

我已经使用Java 8在Tomcat 7和8上尝试过这个。 我使用JavaEE 6中标准的jax-rs ...换句话说我的POM文件有这个:

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

任何帮助将不胜感激。 感谢。

准确的错误消息(在Glassfish 4.0上......我已经尝试过Tomcat和Glassfish):

  

java.lang.ArrayIndexOutOfBoundsException:52264 at   org.objectweb.asm.ClassReader.readClass(ClassReader.java:2015)at 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)     在   com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.onSelectedEntries(ReadableArchiveScannerAdapter.java:127)     在org.glassfish.hk2.classmodel.reflect.Parser.doJob(Parser.java:347)     在   org.glassfish.hk2.classmodel.reflect.Parser.access $ 300(Parser.java:67)     在   org.glassfish.hk2.classmodel.reflect.Parser $ 3.call(Parser.java:306)     在   org.glassfish.hk2.classmodel.reflect.Parser $ 3.call(Parser.java:295)     在java.util.concurrent.FutureTask.run(FutureTask.java:266)at   java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)     在   java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:617)     在java.lang.Thread.run(Thread.java:744)

6 个答案:

答案 0 :(得分:26)

我找到了解决方案! 我在使用Jersey 1.17.1。当我升级到2.7时它起作用了。我的pom文件有以下内容:

<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>

我删除了这些内容并添加了:

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

当然,我必须修改web.xml文件:

<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>

现在一切都运转良好。 问题是:当我从REST类中删除它们并将它们放在非REST类中时,为什么lambda表达式仍然失败?我使用lambda表达式(无论是否涉及实际的REST服务),我在使用Jersey 1.x时就崩溃了。但无论如何,我很高兴这个项目再次运作;我一直想升级到最新版本的jax-rs&amp;泽西无论如何所以这迫使我这样做(花了我几个小时的工作,需要向&#34; SCRUM大师解释&#34;为什么我的估计已经关闭(不要让我开始讨论这个话题)。现在,如果我只能弄清楚为什么Jersey 2返回XML时我告诉它返回JSON我会回到正轨。

感谢大家的帮助!

答案 1 :(得分:12)

Jersey 1.19与JDK 1.8.0兼容。参考 Jersey 1.19 Release summary JDK8 support in Jersey 1.19 Repackage ASM lib in Jersey 1.19

请删除asm-3.1.jar,因为jersey-server-1.19.jar中重新包装了asm 5.0。

答案 2 :(得分:3)

堆栈跟踪显示类org.objectweb.asm.ClassReader.readClass给出异常。我想这是Glassfish内部使用的解析器。

崩溃的原因之一是因为它未配置为正确处理给定输入。在这种情况下,给定的输入是一个lambda表达式,它不知道如何处理它。

您需要为Glassfish和Tomcat寻找Java 8字节码(lambda)支持。如果不是问题,那么它可能是内部使用的解析器中的错误。

答案 3 :(得分:1)

在我介绍lamdas之后尝试使用java 1.8运行junit测试时,我必须将spring升级到4.3.6.RELEASE并将junit升级到4.12才能摆脱这个特殊错误。

答案 4 :(得分:0)

除了所有其他答案外,

在我的系统上,此问题发生在Glassfish 4.0(build 89)

解;

  

我升级了Glassfish to 4.1(build 13)并解决了这个问题。

答案 5 :(得分:-3)