it-swarm.com.de

Wie verwende ich die Jersey JSON POJO-Unterstützung?

Ich habe ein Objekt, das ich in JSON als RESTful-Ressource verwenden möchte. Ich habe die JSON POJO-Unterstützung von Jersey so aktiviert (in web.xml):

<servlet>  
    <servlet-name>Jersey Web Application</servlet-name>  
    <servlet-class>com.Sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.Sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>  
</servlet>  

Beim Versuch, auf die Ressource zuzugreifen, erhalte ich diese Ausnahme:

SEVERE: A message body writer for Java type, class com.example.MyDto, and MIME media type, application/json, was not found
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException
...

Die Klasse, die ich versuche zu dienen, ist nicht kompliziert, es gibt nur einige öffentliche Finalfelder und einen Konstruktor, der alle definiert. Die Felder sind alle Strings, Primitive, Klassen, die dieser ähneln, oder Listen davon (Ich habe versucht, einfache Listen anstelle von generischen List <T> s zu verwenden, ohne Erfolg). Weiß jemand was gibt? Vielen Dank!

Java EE 6

Jersey 1.1.5

GlassFish 3.0.1

39
Nick

Jersey-Json hat eine JAXB-Implementierung. Der Grund für diese Ausnahme ist, dass Sie keine Provider oder genauer MessageBodyWriter registriert haben. Sie müssen einen richtigen Kontext in Ihrem Provider registrieren:

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final static String ENTITY_PACKAGE = "package.goes.here";
    private final static JAXBContext context;
    static {
        try {
            context = new JAXBContextAdapter(new JSONJAXBContext(JSONConfiguration.mapped().rootUnwrapping(false).build(), ENTITY_PACKAGE));
        } catch (final JAXBException ex) {
            throw new IllegalStateException("Could not resolve JAXBContext.", ex);
        }
    }

    public JAXBContext getContext(final Class<?> type) {
        try {
            if (type.getPackage().getName().contains(ENTITY_PACKAGE)) {
                return context;
            }
        } catch (final Exception ex) {
            // trap, just return null
        }
        return null;
    }

    public static final class JAXBContextAdapter extends JAXBContext {
        private final JAXBContext context;

        public JAXBContextAdapter(final JAXBContext context) {
            this.context = context;
        }

        @Override
        public Marshaller createMarshaller() {
            Marshaller marshaller = null;
            try {
                marshaller = context.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            } catch (final PropertyException pe) {
                return marshaller;
            } catch (final JAXBException jbe) {
                return null;
            }
            return marshaller;
        }

        @Override
        public Unmarshaller createUnmarshaller() throws JAXBException {
            final Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            return unmarshaller;
        }

        @Override
        public Validator createValidator() throws JAXBException {
            return context.createValidator();
        }
    }
}

Dies sucht nach einem @XmlRegistry innerhalb des angegebenen Paketnamens. Dies ist ein Paket, das @XmlRootElement annotierte POJOs enthält.

@XmlRootElement
public class Person {

    private String firstName;

    //getters and setters, etc.
}

erstellen Sie dann eine ObjectFactory im selben Paket:

@XmlRegistry
public class ObjectFactory {
   public Person createNewPerson() {
      return new Person();
   }
}

Mit dem registrierten @Provider sollte Jersey das Marshalling in Ihrer Ressource erleichtern:

@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response doWork(Person person) {
   // do work
   return Response.ok().build();
}
12
hisdrewness

Sie können @XmlRootElement verwenden, wenn Sie JAXB-Anmerkungen verwenden möchten (siehe andere Antworten).

Wenn Sie jedoch eine reine POJO-Zuordnung bevorzugen, müssen Sie Folgendes tun (leider nicht in docs geschrieben):

  1. Fügen Sie Ihrem Klassenpfad Jackson * .jar hinzu (wie von @Vitali Bichov angegeben).
  2. Wenn Sie in web.xml den com.Sun.jersey.config.property.packages init-Parameter verwenden, fügen Sie der Liste org.codehaus.jackson.jaxrs hinzu. Dies schließt JSON-Provider in die Scan-Liste von Jersey ein.
15
gamliela

Das hat es für mich getan - Jersey 2.3.1

In der Datei web.xml:

<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value><my webapp packages>;org.codehaus.jackson.jaxrs</param-value>
</init-param>
</servlet>

In der Datei pom.xml:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>
11
yann-h

Ich folgte den Anweisungen here , die zeigen, wie man Jersey- und Jackson-POJOs verwendet (im Gegensatz zu JAXB). Es hat auch mit Jersey 1.12 funktioniert. 

10
bytesmith

Sie haben dies wahrscheinlich bereits herausgefunden, aber Sie müssen nur diese Jackson-Gläser zu Ihrem Klassenpfad hinzufügen: Jackson-Core, Jackson-Jaxrs, Jackson-Mapper und Jackson-Xc

Es scheint, dass es einen anderen Weg gibt, wie andere bemerkt haben. Fügen Sie dies Ihrem Parameter "com.Sun.jersey.config.property.packages" hinzu (wenn Sie Tomcat und web.xml verwenden): "org.codehaus.jackson.jaxrs",

<init-param>
  <param-name>com.Sun.jersey.config.property.packages</param-name>
  <param-value>org.codehaus.jackson.jaxrs</param- value>
</init-param>

Dies erfordert auch die gleichen Jackson-Gläser in Ihrem Klassenpfad

3
ChrisO

Warum benutzt du letzte Felder? Ich benutze Trikot und ich habe ein paar JAXB-Objekte/Pojos. Alles was ich tun musste, war einfach meine Ressourcenmethode mit @Produces ("application/json") zu kommentieren die Kiste. Ich musste mich nicht mit der web.xml herumschlagen. Stellen Sie einfach sicher, dass Ihre Pojos korrekt kommentiert werden.

Hier ist ein einfacher Pojo

package test;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class SampleJaxbObject {

    private String field1;

    private Integer field2;

    private String field3;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public Integer getField2() {
        return field2;
    }

    public void setField2(Integer field2) {
        this.field2 = field2;
    }

    public String getField3() {
        return field3;
    }

    public void setField3(String field3) {
        this.field3 = field3;
    }


}
3
Ricardo Riveros

Jersey 2.0 bietet Unterstützung für JSON mit MOXy und Jackson.

Die MOXy-Unterstützung ist standardmäßig aktiviert, wenn die JAR-Klasse im Klassenpfad vorhanden ist und die Jackson-Unterstützung mithilfe einer Funktion aktiviert werden kann. Dies wird ausführlich im Jersey 2.0 User Guide-Kapitel zum JSON-Binding erläutert:

https://jersey.Java.net/documentation/latest/media.html#json

Um die MOXy-Unterstützung hinzuzufügen, ohne dass eine Konfiguration erforderlich ist, fügen Sie die folgende Abhängigkeit hinzu: pom.xml

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>
3
Arun Gupta

Ich bin neu in diesem Bereich, aber ich konnte POJOs verwenden, nachdem ich den Klassenpfad mit jackson-all-1.9.0.jar hinzugefügt hatte.

2
Vitali Bichov

Folgendes hat für mich gearbeitet. Ich benutze Jersey 2.7 mit Jackson mit Apache Felix (OSGi) auf Tomcat6.

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        super(JacksonFeature.class);
        // point to packages containing your resources
        packages(getClass().getPackage().getName());
    }
}

Und dann würden Sie in Ihrem web.xml (oder in meinem Fall nur eine Hashtable) Ihren javax.ws.rs.Application so angeben

<init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value><MyApplication.class.getName()></param-value>
</init-param>

Keine Angabe von com.Sun.jersey.config.property.pacakges oder com.Sun.jersey.api.json.POJOMappingFeature

Stellen Sie einfach sicher, dass Sie die Abhängigkeit von angeben 

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>
1
shreyas

Das Verschieben der jersey-json-Abhängigkeit auf die oberste Ebene von pom.xml hat dieses Problem für mich gelöst.

<dependencies>
  <dependency>
    <groupId>com.Sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.18.1</version>
  </dependency>

  <!-- other dependencies -->

</dependencies>
1
supercobra