web-dev-qa-db-de.com

Gewusst wie: POST ein JSON-Objekt an einen JAX-RS-Dienst

Ich verwende die Jersey-Implementierung von JAX-RS. Ich möchte POST ein JSON-Objekt an diesen Dienst senden, erhalte jedoch den Fehlercode 415 Nicht unterstützter Medientyp. Was fehlt mir?

Hier ist mein Code:

@Path("/orders")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class OrderResource {

    private static Map<Integer, Order> orders = new HashMap<Integer, Order>();

    @POST
    public void createOrder(Order order) {

        orders.put(order.id, order);
    }

    @GET
    @Path("/{id}")
    public Order getOrder(@PathParam("id") int id) {
        Order order = orders.get(id);
        if (order == null) {
            order = new Order(0, "Buy", "Unknown", 0);
        }
        return order;
    }
}

Hier ist das Bestellobjekt:

public class Order {
    public int id;
    public String side;
    public String symbol;
    public int quantity;
    ...
}

Eine solche GET-Anfrage funktioniert einwandfrei und gibt eine Bestellung im JSON-Format zurück:

GET http://localhost:8080/jaxrs-oms/rest/orders/123 HTTP/1.1

Jedoch gibt eine POST Anfrage wie diese eine 415 zurück:

POST http://localhost:8080/jaxrs-oms/rest/orders HTTP/1.1

{
    "id": "123",
    "symbol": "AAPL",
    "side": "Buy",
    "quantity": "1000"
}
64
Naresh

Die Antwort war überraschend einfach. Ich musste einen Content-Type - Header in die POST -Anforderung mit dem Wert application/json Einfügen. Ohne diesen Header wusste Jersey nicht, was er mit dem Anfragetext tun sollte (trotz der @Consumes(MediaType.APPLICATION_JSON) Annotation)!

76
Naresh

Jersey macht den Prozess sehr einfach, meine Serviceklasse hat gut mit JSON funktioniert, ich musste nur die Abhängigkeiten in die pom.xml einfügen

@Path("/customer")
public class CustomerService {

    private static Map<Integer, Customer> customers = new HashMap<Integer, Customer>();

    @POST
    @Path("save")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public SaveResult save(Customer c) {

        customers.put(c.getId(), c);

        SaveResult sr = new SaveResult();
        sr.sucess = true;
        return sr;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{id}")
    public Customer getCustomer(@PathParam("id") int id) {
        Customer c = customers.get(id);
        if (c == null) {
            c = new Customer();
            c.setId(id * 3);
            c.setName("unknow " + id);
        }
        return c;
    }
}

Und in der pom.xml

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.7</version>
</dependency>
12
glm

Ich stand vor dem gleichen 415 http-Fehler beim Senden von in JSON serialisierten Objekten über PUT/Push-Anforderungen an meine JAX-rs-Dienste. Mit anderen Worten, mein Server konnte die Objekte von JSON nicht de-serialisieren. In meinem Fall konnte der Server dieselben Objekte in JSON erfolgreich serialisieren, als er sie an seine Antworten sendete.

Wie in den anderen Antworten erwähnt, habe ich die Accept und Content-Type Header zu application/json, aber es reicht nicht aus.

Lösung

Ich habe einfach einen Standardkonstruktor ohne Parameter für meine DTO-Objekte vergessen. Ja, dies ist der gleiche Grund für @Entity-Objekte. Sie benötigen einen Konstruktor ohne Parameter, damit der ORM Objekte instanziiert und die Felder später auffüllt.

Das Hinzufügen des Konstruktors ohne Parameter zu meinen DTO-Objekten löste mein Problem. Hier folgt ein Beispiel, das meinem Code ähnelt:

Falsch

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NumberDTO {
    public NumberDTO(Number number) {
        this.number = number;
    }

    private Number number;

    public Number getNumber() {
        return number;
    }

    public void setNumber(Number string) {
        this.number = string;
    }
}

Rechts

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NumberDTO {

    public NumberDTO() {
    }

    public NumberDTO(Number number) {
        this.number = number;
    }

    private Number number;

    public Number getNumber() {
        return number;
    }

    public void setNumber(Number string) {
        this.number = string;
    }
}

Ich habe Stunden verloren, ich hoffe das wird deine retten ;-)

6
Fabiano Tarlao