developer tip

JAX-RS 서비스에 JSON 오브젝트를 POST하는 방법

copycodes 2020. 11. 18. 09:17
반응형

JAX-RS 서비스에 JSON 오브젝트를 POST하는 방법


JAX-RS의 Jersey 구현을 사용하고 있습니다. 이 서비스에 JSON 개체를 게시하고 싶지만 오류 코드 415 Unsupported Media Type이 표시됩니다. 내가 무엇을 놓치고 있습니까?

내 코드는 다음과 같습니다.

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

Order 개체는 다음과 같습니다.

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

이와 같은 GET 요청은 완벽하게 작동하며 JSON 형식으로 주문을 반환합니다.

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

그러나 이와 같은 POST 요청은 415를 반환합니다.

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

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

대답은 놀랍도록 간단했습니다. 요청에 값이 있는 Content-Type헤더 를 추가해야했습니다 . 이 헤더가 없으면 Jersey는 주석 에도 불구하고 요청 본문으로 무엇을해야할지 몰랐습니다 !POSTapplication/json@Consumes(MediaType.APPLICATION_JSON)


Jersey는 프로세스를 매우 쉽게 만들어 내 서비스 클래스가 JSON과 잘 작동합니다. 내가해야 할 일은 pom.xml에 종속성을 추가하는 것뿐입니다.

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

그리고 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>

I faced the same 415 http error when sending objects, serialized into JSON, via PUT/PUSH requests to my JAX-rs services, in other words my server was not able to de-serialize the objects from JSON. In my case, the server was able to serialize successfully the same objects in JSON when sending them into its responses.

As mentioned in the other responses I have correctly set the Accept and Content-Type headers to application/json, but it doesn't suffice.

Solution

I simply forgot a default constructor with no parameters for my DTO objects. Yes this is the same reasoning behind @Entity objects, you need a constructor with no parameters for the ORM to instantiate objects and populate the fields later.

Adding the constructor with no parameters to my DTO objects solved my issue. Here follows an example that resembles my code:

Wrong

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

Right

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

I lost hours, I hope this'll save yours ;-)

참고URL : https://stackoverflow.com/questions/7693669/how-to-post-a-json-object-to-a-jax-rs-service

반응형