it-swarm.com.ru

Java 8 Лямбда-выражение в REST Сервис не работает

Если я помещаю лямбда-выражение Java 8 в службу REST, оно вылетает. Если я уберу лямбда-выражение, оно будет работать. Не имеет значения, использую ли я лямбда-выражение или нет. Просто существование лямбды достаточно, чтобы разбиться. Все остальное, что связано с 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);
    }

}

Как видно из приведенного выше кода, просто наличие лямбда-выражения приведет к сбою. Как только я убираю лямбду, все работает нормально. Другие вещи Java 8 хороши (например, входной параметр «Предикат»).

Я получаю сообщение об ошибке: Java.lang.ArrayIndexOutOfBoundsException: 25980

Я попробовал это на Tomcat 7 и 8, используя Java 8 ... Я использую стандартную штуку jax-rs из JavaEE 6 .... другими словами, мой файл 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 в org.objectweb.asm.ClassReader.readClass (ClassReader.Java:2015) в org.objectweb.asm.ClassReader.accept (ClassReader.Java:469) в org.objectweb.asm.ClassReader.accept (ClassReader.Java:425) в org.glassfish.hk2.classmodel.reflect.Parser $ 5.on (Parser.Java:362) в 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) на Java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.Java:1142) в Java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.Java:617) на Java.lang.Thread.run (Thread.Java:744)

24
David Jensen

Я нашел решение! Я использовал Джерси 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? Только того факта, что я включил Jersey 1.x, было достаточно, чтобы аварийно завершить работу при использовании лямбда-выражений (независимо от того, был ли задействован фактический REST сервис). Но, во всяком случае, я рад, что проект снова работает; Я все равно хотел обновить систему до последней версии jax-rs & Jersey, так что это заставило меня сделать это (это стоило мне нескольких часов работы и мне нужно объяснить «мастеру SCRUM», почему моя оценка не соответствует (не начните с этой темы.) Теперь, если я смогу только выяснить, почему Jersey 2 возвращает XML, когда я сказал ему вернуть JSON, я вернусь в нужное русло.

Спасибо всем за вашу помощь!

26
David Jensen

Джерси 1.19 совместим с JDK 1.8.0. См. Краткое описание выпуска Jersey 1.19Поддержка JDK8 в Jersey 1.19Переупаковка библиотеки ASM в Jersey 1.19

Пожалуйста, удалите asm-3.1.jar, поскольку jersey-server-1.19.jar перепакован в asm 5.0.

12
Tom Shen

Трассировка стека показывает, что класс org.objectweb.asm.ClassReader.readClass дает исключение. Я полагаю, что это парсер, который Glassfish использует внутри.

Одна из причин его сбоя заключается в том, что он не настроен для правильной обработки заданного ввода. В этом случае данный ввод является лямбда-выражением, и он не знает, как с ним обращаться.

Вам нужно будет найти поддержку Java 8 байт-кода (лямбда) для Glassfish и Tomcat. Если это не проблема, то это может быть ошибка в анализаторе, который используется внутри.

3
skiwi

Мне пришлось обновить spring до 4.3.6.RELEASE и junit до 4.12, прежде чем я избавился от этой конкретной ошибки при попытке запустить тест junit с Java 1.8 после того, как я ввел lamdas.

1
David B

В дополнение ко всем другим ответам,

В моей системе эта проблема возникает на Glassfish 4.0(build 89) 

Решение;

Я обновил Glassfish to 4.1(build 13), и это решило эту проблему.

0
Yusuf K.