Выражение Lambda Java 8 в службе REST не работает
Если я поставлю выражение Java 8 Lambda в службе 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 at org.objectweb.asm.ClassReader.readClass(ClassReader.java:2015) в 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) в com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.handleEntry(ReadableArchiveScannerAdapter.java:165) в com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.onSelectedEntries(ReadableArchiveScannerAdapter.java:127) at 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)
Ответы
Ответ 1
Я нашел решение!
Я использовал Джерси 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 и помещал их в класс non-REST? Просто факт, что я включил Джерси 1.x, был достаточным для краха при использовании лямбда-выражений (независимо от того, была ли задействована реальная служба REST). Но, во всяком случае, я рад, что проект снова работает; Я так и хотел обновиться до последней версии jax-rs и Jersey, так что это заставило меня это сделать (стоило мне несколько часов работы и мне нужно было объяснить "мастеру SCRUM", почему моя оценка отключена (не запустите меня по этой теме). Теперь, если я смогу только выяснить, почему Джерси 2 возвращает XML, когда я сказал ему вернуть JSON, я вернусь в нужное русло.
Спасибо всем за вашу помощь!
Ответ 2
Джерси 1.19 совместим с JDK 1.8.0. Ссылаться на
Джерси 1.19 Выпуск с комментариями Поддержка JDK8 в Джерси 1.19 Repackage ASM lib в Джерси 1.19
Пожалуйста, удалите asm-3.1.jar, поскольку jersey-server-1.19.jar имеет asm 5.0, упакованную в него.
Ответ 3
Столбец показывает, что класс org.objectweb.asm.ClassReader.readClass
дает исключение. Я полагаю, что это парсер, который Glassfish использует внутри.
Одна из причин, по которой он произошел сбой, заключается в том, что он не настроен правильно обрабатывать данный вход. В этом случае данный ввод является лямбда-выражением, и он не знает, как его обрабатывать.
Вам нужно будет найти поддержку байт-кода Java (lambda) для Glassfish и Tomcat. Если это не проблема, то это может быть ошибка в парсер, который используется внутри.
Ответ 4
Мне пришлось обновить spring до 4.3.6.RELEASE и junit до 4.12, прежде чем я избавился от этой конкретной ошибки при попытке запустить junit-тест с java 1.8 после того, как я представил lamdas.
Ответ 5
В дополнение ко всем другим ответам,
В моей системе эта проблема возникает на Glassfish 4.0(build 89)
Решение
Я обновил Glassfish to 4.1(build 13)
и решил эту проблему.
Ответ 6
Обновление до asm5 для jdk8
скачать: http://asm.ow2.org/eclipse/index.html
https://bugs.eclipse.org/bugs/show_bug.cgi?id=429992
или
eclipse luna