GEDOPLAN
Jakarta EE (Java EE)

Jackson und Java EE 8

Jakarta EE (Java EE)


Jackson ist eine Bibliothek die sich unter anderem darum kümmert das unsere Businessobjekte in JSON umgewandelt werden. Als default Provider für diese Aufgabe war Jackson bisher im Wildfly Application Server vorhanden. Seit Java EE 8 (und Wildfly 13) gibt es nun einen neuen Standard der sich um diese Aufgabe kümmert: JSON-B. Dieser ist leider in Sachen Funktionsumfang bei weitem noch nicht auf den Stand den Jackson erreicht hat. Um Jackson weiterhin zu nutzen sind (leider) einige Schritte von nöten

Laut Spezifikation von JAX-RS reicht es aus eine @Provider-Klasse an zu bieten welche für einen bestimmten Media Type die Konvertierung unserer Businessobjekte übernimmt. Diesen liefert Jackson mit einer entsprechenden Maven Dependency praktischerweise gleich mit (com.fasterxml.jackson.jaxrs, jackson-jaxrs-json-provider ). Schade nur das es bei dieser Theorie bleibt. Zumindest der Wildfly 13 (im EE8 Profil) und der Glassfish 5 weigern sich dieses einfache Vorgehen mit Erfolg zu krönen.

Wildfly 13

Ein Bug in RestEasy (RESTEASY-1911 ) verhindert hier das Jackson korrekt eingebunden wird. Ab der Version 3.6 soll dieser Umstand behoben sein, bis dahin hilft der Ausschluss des Resteasy Json Providers:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
    <jdeployment>
        <jexclusions>
            <jmodule name="org.jboss.resteasy.resteasy-json-binding-provider"><j/module>
        <j/exclusions>
    <j/deployment>
<j/jboss-deployment-structure>

src/main/webapp/WEB-INF/jboss-deployment-structure.xml

Glassfish 5

Die Referenzimplementierung für Java EE 8 ist hartnäckig was das Ersetzen von JSON-B als JSON Provider angeht. Hier ist ein zusätzlicher Konfigurationsparamter notwenig:

@ApplicationPath("resources")
public class ApplicationConfig extends Application {

    @Override
    public Map getProperties() {
        Map proprties = new HashMap();
        proprties.put("jersey.config.server.disableMoxyJson", true); //Glassfish = 5

        return proprties;
    }

}

Optional: globaler ObjectMapper

Jacksons ObjectMapper bietet eine ganze Reihe von globalen Einstellungen um das Verhalten beim Parsen von JSON-Strukturen zu beeinflussen (Format, Umgang mit null-Werten und unbekannter Attribute…). Um in der gesamten Anwendung eine einheitliche Konfiguration zu verwenden bietet sich ein entsprechner CDI Producer an:

@ApplicationScoped
public class GlobalCDIProducer {

    private ObjectMapper mapper;
    
    @Produces
    public ObjectMapper getMapper(){
        if(this.mapper==null){
            this.mapper=new ObjectMapper();
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            this.mapper.setDateFormat(df);
        }
        return this.mapper;
    }
}

Diesen können wir natürlich selber in unseren Resouce-Klassen injizieren und Verwenden, aber auch JAX-RS zur Verfügung stellen:

@Provider
public class JacksonProvider implements ContextResolver<ObjectMapper> {

    @Inject
    private ObjectMapper mapper;
    
    @Override
    public ObjectMapper getContext(Class<?> type) {
        return getMapper();
    }
}

2 Kommentare. Hinterlasse eine Antwort

  • Danke, das ist sicher für viele hilfreich, die nicht einfach umstellen können. Allerdings ist JSON-P 1.1 und JSON-Bind 1.0 ein sinnvoller Kompromiss, den man auch nutzen sollte. Wir brauchen solche Standards für Interoperabilität in heterogenen Servicelandschaften. Mich würde interessieren, welche wichtigen Features nicht in der Referenzimplementierung abgedeckt sind?

    Antworten
    • Avatar-Foto
      Dominik Mathmann
      1. März 2019 9:14

      Das ist völlig richtig: die Nutzung eines Standards würde ich hier immer vorziehen. Standard des Standards willen ist für mich aber kaum eine praktikable Lösung, am Ende des Tages geht es für mich auch darum stabile und wartbare Software zu schreiben mit einem angemessenen Aufwand. Wenn ich dafür auf Bibliotheken zurückgreifen muss die nicht dem Standard unterworfen sind nehme ich das gerne in Kauf.

      Im Fall von JSON-B ist man sicherlich auf dem richtigen Weg und ich hoffe das hier noch ein paar Handschläge getan werden. Die grundlegenden Funktionen sind ja auch bereits alle zu finden, in den Feinheiten merkt man meiner Meinung allerdings das Bibliotheken wie „Jackson“ schon wesentlich länger gereift sind: um nur mal zwei Features zu nennen die in Jackson zur Verfügung stehen und in JSON-B fehlen oder sich wesentlich unflexbiler einsetzen lassen: JsonViews (fehlt leider in dieser einfachen Form im neuen Standard). Zweites Resolver (https://javaeeblog.wordpress.com/2018/06/29/jpa-rest-jackson-resolver/ ) , so etwas lässt sich leider derzeit aus meiner Sicht ebenfalls nicht mit einem einzigen generischen Resolver in JsonB lösen ( weil die Möglichkeit der Scope- / Ziel-Klassen nicht unterstützt wird, was dazu führt das wir für jede Entity eine eigene konkrete Resolver Klassen benötigen )

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Kurse

weitere Blogbeiträge

IT-Training - GEDOPLAN
DevOps

Docker Orchestrierung mit Kubernetes

Docker bietet uns eine leichtgewichtige, containerbasierte Form der Virtualisierung, welche sich gut dafür eignet, Anwendungen zu paketieren und auszuliefern. Dabei…

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!