wake-up-neo.net

Java 8 Lambda-Ausdruck innerhalb REST Service funktioniert nicht

Wenn ich einen Java 8-Lambda-Ausdruck in einen REST -Dienst setze, stürzt er ab. Wenn ich den Lambda-Ausdruck entferne, funktioniert es. Es spielt keine Rolle, ob ich den Lambda-Ausdruck verwende oder nicht. Allein die Existenz des Lambda reicht zum Absturz. Alles andere, was mit Java 8 zu tun hat, scheint zu funktionieren.

Unten ist mein Code (vereinfacht):

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

}

Wie Sie dem obigen Code entnehmen können, führt das Vorhandensein eines Lambda-Ausdrucks zu Fehlern. Sobald ich das Lambda entferne, funktioniert es gut. Das andere Java 8-Zeug ist in Ordnung (zum Beispiel der Eingabeparameter "Predicate").

Die Fehlermeldung, die ich bekomme, ist: Java.lang.ArrayIndexOutOfBoundsException: 25980

Ich habe dies auf Tomcat 7 und 8 mit Java 8 ausprobiert. Ich verwende den Standard-Jax-rs-Kram von JavaEE 6 ... mit anderen Worten, meine POM-Datei hat folgendes:

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

Jede Hilfe wäre dankbar. Danke.

Die genaue Fehlermeldung (auf Glassfish 4.0 ... Ich habe sowohl Tomcat als auch Glassfish ausprobiert):

Java.lang.ArrayIndexOutOfBoundsException: 52264 um Org.objectweb.asm.ClassReader.readClass (ClassReader.Java:2015) um Org.objectweb.asm.ClassReader.accept (ClassReader.Java:469) ) um org.objectweb.asm.ClassReader.accept (ClassReader.Java:425) um org.glassfish.hk2.classmodel.reflect.Parser $ 5.on (Parser.Java:362) um com.Sun.enterprise.v3.server.ReadableArchiveScannerAdapter.handleEntry (ReadableArchiveScannerAdapter.Java:165) um..... .............................. (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) um org.glassfish.hk2.classmodel.reflect.Parser $ 3.call (Parser.Java:306) at org.glassfish.hk2.classmodel.reflect.Parser $ 3.call (Parser.Java:295) bei Java.uti l.concurrent.FutureTask.run (FutureTask.Java:266) um Java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.Java:1142) um Java.util .concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.Java:617) unter Java.lang.Thread.run (Thread.Java:744)

24
David Jensen

Ich habe die Lösung gefunden! Ich habe Jersey 1.17.1 verwendet. Als ich auf 2.7 aufgerüstet habe, hat es funktioniert. Meine Pom-Datei hatte folgendes:

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

Ich entfernte diese und fügte hinzu:

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

Und natürlich musste ich die web.xml-Datei ändern, um Folgendes zu haben:

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

Jetzt funktioniert alles gut. Die Frage ist: Warum fehlten Lambda-Ausdrücke immer noch, als ich sie aus der Klasse REST entfernte und in eine Nicht-REST-Klasse einordnete? Allein die Tatsache, dass ich Jersey 1.x einbezog, reichte aus, um zu stürzen, wenn Lambda-Ausdrücke verwendet wurden (unabhängig davon, ob tatsächlich ein REST -Dienst beteiligt war oder nicht). Ich freue mich jedenfalls, dass das Projekt wieder funktioniert. Ich wollte sowieso auf die neueste Version von jax-rs & Jersey upgraden, deshalb zwang ich mich dazu (dies kostete mich mehrere Stunden Arbeit und musste dem "SCRUM-Master" erklären, warum meine Schätzung nicht stimmt Wenn ich nur wissen kann, warum Jersey 2 XML zurückgibt, als ich ihm gesagt habe, JSON zurückzugeben, bin ich wieder auf dem richtigen Weg.

Danke an alle für Ihre Hilfe!

26
David Jensen

Jersey 1.19 ist mit JDK 1.8.0 kompatibel. Siehe Jersey 1.19 ReleaseübersichtJDK8-Unterstützung in Jersey 1.19Repackage ASM lib in Jersey 1.19

Bitte entfernen Sie asm-3.1.jar, da in jersey-server-1.19.jar asm 5.0 neu verpackt ist.

12
Tom Shen

Der Stacktrace zeigt, dass die Klasse org.objectweb.asm.ClassReader.readClass eine Ausnahme gibt. Ich nehme an, dies ist ein Parser, den Glassfish intern verwendet.

Einer der Gründe, warum das System abstürzen würde, ist, dass es nicht für die korrekte Verarbeitung der angegebenen Eingabe konfiguriert ist. In diesem Fall handelt es sich bei der gegebenen Eingabe um einen Lambda-Ausdruck, der nicht weiß, wie er damit umgehen soll.

Für Glassfish und Tomcat müssen Sie nach Unterstützung für Java 8-Bytecode (Lambda) suchen. Wenn es sich nicht um das Problem handelt, kann es sich um einen Fehler im Parser handeln, der intern verwendet wird.

3
skiwi

Ich musste den Frühling auf 4.3.6.RELEASE und junit auf 4.12 upgraden, bevor ich diesen speziellen Fehler beendete, als ich versuchte, einen Junit-Test mit Java 1.8 auszuführen, nachdem ich Lamdas eingeführt hatte.

1
David B

Neben allen anderen Antworten

Auf meinem System ist dieses Problem bei Glassfish 4.0(build 89) aufgetreten. 

Lösung;

Ich habe Glassfish to 4.1(build 13) aufgerüstet und dieses Problem gelöst.

0
Yusuf K.