JAX-RS - Bagaimana cara mengembalikan kode status JSON dan HTTP?

248

Saya sedang menulis aplikasi web REST (NetBeans 6.9, JAX-RS, TopLink Essentials) dan mencoba mengembalikan kode status JSON dan HTTP. Saya memiliki kode yang siap dan berfungsi yang mengembalikan JSON ketika metode HTTP GET dipanggil dari klien. Pada dasarnya:

@Path("get/id")
@GET
@Produces("application/json")
public M_機械 getMachineToUpdate(@PathParam("id") String id) {

    // some code to return JSON ...

    return myJson;
}

Tetapi saya juga ingin mengembalikan kode status HTTP (500, 200, 204, dll.) Bersama dengan data JSON.

Saya mencoba menggunakan HttpServletResponse:

response.sendError("error message", 500);

Tapi ini membuat browser berpikir itu "nyata" 500 sehingga halaman web output adalah halaman kesalahan HTTP 500 biasa.

Saya ingin mengembalikan kode status HTTP sehingga JavaScript sisi klien saya dapat menangani beberapa logika tergantung padanya (untuk misalnya menampilkan kode kesalahan dan pesan pada halaman HTML). Apakah ini mungkin atau haruskah kode status HTTP tidak digunakan untuk hal seperti itu?

meong
sumber
2
Apa perbedaan antara 500 yang Anda inginkan (tidak nyata? :)) dan 500 nyata?
Pisau cukur
@razor Here real 500 berarti halaman kesalahan HTML alih-alih respons JSON
Nupur
browser web tidak dirancang untuk bekerja dengan JSON, tetapi dengan halaman HTML, jadi jika Anda merespons dengan 500 (dan bahkan beberapa badan pesan), browser dapat menunjukkan kepada Anda hanya pesan kesalahan (sangat tergantung pada implementasi browser), hanya karena itu berguna untuk pengguna biasa.
Pisau cukur

Jawaban:

347

Ini sebuah contoh:

@GET
@Path("retrieve/{uuid}")
public Response retrieveSomething(@PathParam("uuid") String uuid) {
    if(uuid == null || uuid.trim().length() == 0) {
        return Response.serverError().entity("UUID cannot be blank").build();
    }
    Entity entity = service.getById(uuid);
    if(entity == null) {
        return Response.status(Response.Status.NOT_FOUND).entity("Entity not found for UUID: " + uuid).build();
    }
    String json = //convert entity to json
    return Response.ok(json, MediaType.APPLICATION_JSON).build();
}

Lihatlah kelas Respon .

Perhatikan bahwa Anda harus selalu menentukan jenis konten, terutama jika Anda melewati beberapa jenis konten, tetapi jika setiap pesan akan direpresentasikan sebagai JSON, Anda bisa membuat anotasi metode dengan @Produces("application/json")

kesedihannya
sumber
12
Ini berfungsi, tetapi apa yang saya tidak suka tentang nilai pengembalian respons adalah bahwa menurut pendapat saya itu mencemari kode Anda, khususnya yang berkaitan dengan klien yang mencoba menggunakannya. Jika Anda menyediakan antarmuka yang mengembalikan Respons ke pihak ketiga, dia tidak tahu jenis apa yang benar-benar Anda kembalikan. Spring membuatnya lebih jelas dengan anotasi, sangat berguna jika Anda selalu mengembalikan kode status (yaitu HTTP 204)
Guido
19
Membuat class generic (Response <T>) akan menjadi peningkatan yang menarik untuk jax-rs, untuk memiliki keunggulan dari kedua alternatif.
Guido
41
Tidak perlu mengubah entitas menjadi json entah bagaimana. Anda dapat melakukan return Response.status(Response.Status.Forbidden).entity(myPOJO).build();Pekerjaan seolah-olah Anda mau return myPOJO;, tetapi dengan pengaturan tambahan kode Status-HTTP.
kratenko
1
Saya pikir memisahkan logika bisnis menjadi kelas layanan terpisah berfungsi dengan baik. Titik akhir menggunakan Respons sebagai jenis kembali dan metode itu sebagian besar hanya panggilan ke metode layanan plus path dan anotasi param. Ini memisahkan logika dari url / tipe konten pemetaan (di mana karet menyentuh jalan sehingga untuk berbicara).
Stijn de Witt
sebenarnya, kita bisa mengembalikan objek yang tidak terbungkus ke Response.
ses
191

Ada beberapa kasus penggunaan untuk mengatur kode status HTTP di layanan web REST, dan setidaknya satu tidak cukup didokumentasikan dalam jawaban yang ada (yaitu ketika Anda menggunakan JSON / XML serialisasi otomatis menggunakan JAXB, dan Anda ingin mengembalikan objek menjadi serial, tetapi juga kode status berbeda dari standar 200).

Jadi izinkan saya mencoba dan menyebutkan berbagai kasus penggunaan dan solusi untuk masing-masingnya:

1. Kode kesalahan (500, 404, ...)

Kasus penggunaan paling umum ketika Anda ingin mengembalikan kode status berbeda dari pada 200 OKsaat kesalahan terjadi.

Sebagai contoh:

  • suatu entitas diminta tetapi tidak ada (404)
  • permintaan itu secara semantik salah (400)
  • pengguna tidak diotorisasi (401)
  • ada masalah dengan koneksi database (500)
  • dll ..

a) Melempar pengecualian

Dalam hal itu, saya berpikir bahwa cara terbersih untuk menangani masalah adalah dengan melemparkan pengecualian. Pengecualian ini akan ditangani oleh ExceptionMapper, yang akan menerjemahkan pengecualian menjadi respons dengan kode kesalahan yang sesuai.

Anda dapat menggunakan default ExceptionMapperyang datang dengan pra-konfigurasi dengan Jersey (dan saya kira itu sama dengan implementasi lainnya) dan membuang salah satu dari sub-kelas yang ada javax.ws.rs.WebApplicationException. Ini adalah tipe pengecualian yang ditentukan sebelumnya yang dipetakan ke kode kesalahan yang berbeda, misalnya:

  • BadRequestException (400)
  • InternalServerErrorException (500)
  • NotFoundException (404)

Dll. Anda dapat menemukan daftar di sini: API

Atau, Anda dapat menentukan pengecualian dan ExceptionMapperkelas khusus Anda sendiri , dan menambahkan pemetaan ini ke Jersey dengan cara @Provideranotasi ( sumber contoh ini ):

public class MyApplicationException extends Exception implements Serializable
{
    private static final long serialVersionUID = 1L;
    public MyApplicationException() {
        super();
    }
    public MyApplicationException(String msg)   {
        super(msg);
    }
    public MyApplicationException(String msg, Exception e)  {
        super(msg, e);
    }
}

Pemberi :

    @Provider
    public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException> 
    {
        @Override
        public Response toResponse(MyApplicationException exception) 
        {
            return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();  
        }
    }

Catatan: Anda juga bisa menulis ExceptionMappers untuk jenis pengecualian yang ada yang Anda gunakan.

b) Gunakan pembuat Respons

Cara lain untuk menetapkan kode status adalah menggunakan Responsepembangun untuk membangun respons dengan kode yang dimaksud.

Dalam hal itu, jenis pengembalian metode Anda harus javax.ws.rs.core.Response. Ini dijelaskan dalam berbagai tanggapan lain seperti jawaban diterima hisdrewness dan terlihat seperti ini:

@GET
@Path("myresource({id}")
public Response retrieveSomething(@PathParam("id") String id) {
    ...
    Entity entity = service.getById(uuid);
    if(entity == null) {
        return Response.status(Response.Status.NOT_FOUND).entity("Resource not found for ID: " + uuid).build();
    }
    ...
}

2. Sukses, tetapi tidak 200

Kasus lain ketika Anda ingin mengatur status pengembalian adalah ketika operasi berhasil, tetapi Anda ingin mengembalikan kode sukses yang berbeda dari 200, bersama dengan konten yang Anda kembalikan di badan.

Kasus penggunaan yang sering terjadi adalah ketika Anda membuat entitas baru ( POSTpermintaan) dan ingin mengembalikan info tentang entitas baru ini atau mungkin entitas itu sendiri, bersama dengan 201 Createdkode status.

Salah satu pendekatan adalah dengan menggunakan objek respons seperti dijelaskan di atas dan mengatur tubuh permintaan sendiri. Namun, dengan melakukan ini, Anda kehilangan kemampuan untuk menggunakan serialisasi otomatis ke XML atau JSON yang disediakan oleh JAXB.

Ini adalah metode asli yang mengembalikan objek entitas yang akan diserialisasi ke JSON oleh JAXB:

@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user){
    User newuser = ... do something like DB insert ...
    return newuser;
}

Ini akan mengembalikan representasi JSON dari pengguna yang baru dibuat, tetapi status pengembalian akan 200, bukan 201.

Sekarang masalahnya adalah jika saya ingin menggunakan Responsepembangun untuk mengatur kode kembali, saya harus mengembalikan Responseobjek dalam metode saya. Bagaimana saya masih mengembalikan Userobjek yang akan diserialisasi?

a) Tetapkan kode pada respons servlet

Salah satu pendekatan untuk mengatasi ini adalah dengan mendapatkan objek permintaan servlet dan mengatur sendiri kode respons secara manual, seperti yang ditunjukkan dalam jawaban Garett Wilson:

@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public User addUser(User user, @Context final HttpServletResponse response){

    User newUser = ...

    //set HTTP code to "201 Created"
    response.setStatus(HttpServletResponse.SC_CREATED);
    try {
        response.flushBuffer();
    }catch(Exception e){}

    return newUser;
}

Metode ini masih mengembalikan objek entitas dan kode statusnya adalah 201.

Perhatikan bahwa untuk membuatnya berfungsi, saya harus memadamkan respons. Ini adalah kebangkitan kode API Servlet tingkat rendah yang tidak menyenangkan di sumber daya JAX_RS kami yang bagus, dan jauh lebih buruk, hal itu menyebabkan tajuk tidak dapat dimodifikasi setelah ini karena mereka sudah dikirim melalui telepon.

b) Gunakan objek respons dengan entitas

Solusi terbaik, dalam hal ini, adalah dengan menggunakan objek Respons dan mengatur entitas untuk diserialisasi pada objek respons ini. Akan menyenangkan untuk membuat objek Respons generik untuk menunjukkan jenis entitas payload dalam kasus itu, tetapi saat ini tidak demikian.

@Path("/")
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addUser(User user){

    User newUser = ...

    return Response.created(hateoas.buildLinkUri(newUser, "entity")).entity(restResponse).build();
}

Dalam hal itu, kami menggunakan metode yang dibuat dari kelas pembuat respons untuk menetapkan kode status ke 201. Kami meneruskan objek entitas (pengguna) ke respons melalui metode entitas ().

Hasilnya adalah bahwa kode HTTP adalah 401 seperti yang kita inginkan, dan isi dari respons adalah JSON yang sama persis seperti yang kita miliki sebelumnya ketika kita baru saja mengembalikan objek Pengguna. Itu juga menambahkan header lokasi.

Kelas Respons memiliki sejumlah metode pembangun untuk status yang berbeda (stati?) Seperti:

Response.accepted () Response.ok () Response.noContent () Response.notAcceptable ()

NB: objek hateoas adalah kelas pembantu yang saya kembangkan untuk membantu menghasilkan sumber daya URI. Anda harus membuat mekanisme sendiri di sini;)

Itu saja.

Saya harap tanggapan panjang ini membantu seseorang :)

Pierre Henry
sumber
Saya bertanya-tanya apakah ada cara bersih untuk mengembalikan objek data itu sendiri, bukan responsnya. The flushmemang kotor.
AlikElzin-kilaka
1
Hanya kencing kesayangan saya: 401 tidak berarti pengguna tidak diotorisasi. Itu berarti klien tidak diotorisasi, karena server tidak tahu siapa Anda. Jika pengguna yang dicatat / dikenali tidak diizinkan melakukan tindakan tertentu, kode respons yang benar adalah 403 Dilarang.
Demonblack
69

Jawaban oleh hisdrewness akan bekerja, tetapi memodifikasi seluruh pendekatan untuk membiarkan penyedia seperti Jackson + JAXB secara otomatis mengkonversi objek Anda kembali ke beberapa format output seperti JSON. Terinspirasi oleh pos Apache CXF (yang menggunakan kelas khusus-CXF) Saya telah menemukan satu cara untuk mengatur kode respons yang harus bekerja dalam implementasi JAX-RS: menyuntikkan konteks HttpServletResponse dan secara manual mengatur kode respons. Misalnya, berikut adalah cara mengatur kode respons CREATEDbila perlu.

@Path("/foos/{fooId}")
@PUT
@Consumes("application/json")
@Produces("application/json")
public Foo setFoo(@PathParam("fooID") final String fooID, final Foo foo, @Context final HttpServletResponse response)
{
  //TODO store foo in persistent storage
  if(itemDidNotExistBefore) //return 201 only if new object; TODO app-specific logic
  {
    response.setStatus(Response.Status.CREATED.getStatusCode());
  }
  return foo;  //TODO get latest foo from storage if needed
}

Perbaikan: Setelah menemukan jawaban terkait lainnya , saya belajar bahwa seseorang dapat menyuntikkan HttpServletResponsesebagai variabel anggota, bahkan untuk kelas layanan singleton (setidaknya di RESTEasy) !! Ini adalah pendekatan yang jauh lebih baik daripada mencemari API dengan detail implementasi. Akan terlihat seperti ini:

@Context  //injected response proxy supporting multiple threads
private HttpServletResponse response;

@Path("/foos/{fooId}")
@PUT
@Consumes("application/json")
@Produces("application/json")
public Foo setFoo(@PathParam("fooID") final String fooID, final Foo foo)
{
  //TODO store foo in persistent storage
  if(itemDidNotExistBefore) //return 201 only if new object; TODO app-specific logic
  {
    response.setStatus(Response.Status.CREATED.getStatusCode());
  }
  return foo;  //TODO get latest foo from storage if needed
}
Garret Wilson
sumber
Anda benar-benar dapat menggabungkan pendekatan: menjelaskan metode dengan @Produces, dan jangan menentukan jenis media di final Response.ok, dan Anda akan mendapatkan objek kembali dengan benar JAXB-serial ke dalam jenis media yang sesuai untuk mencocokkan permintaan. (Saya baru saja mencoba ini dengan metode tunggal yang dapat mengembalikan XML atau JSON: metode itu sendiri tidak perlu menyebutkan, kecuali dalam @Producesanotasi.)
Royston Shufflebotham
Anda Garret benar. Contoh saya lebih merupakan ilustrasi tentang penekanan penyediaan jenis konten. Pendekatan kami serupa, tetapi gagasan untuk menggunakan MessageBodyWriterdan Providermemungkinkan untuk negosiasi konten implisit, meskipun tampaknya contoh Anda kehilangan beberapa kode. Inilah jawaban lain yang saya berikan yang menggambarkan hal ini: stackoverflow.com/questions/5161466/…
hisdrewness
8
Saya tidak dapat mengganti kode status di response.setStatus(). Satu-satunya cara untuk mengirim misalnya 404 Tidak Ditemukan tanggapan adalah dengan mengatur kode status tanggapan response.setStatus(404)dan kemudian menutup aliran output response.getOutputStream().close()sehingga JAX-RS tidak dapat mengatur ulang status saya.
Rob Juurlink
2
Saya bisa menggunakan pendekatan ini untuk menetapkan kode 201, tetapi harus menambahkan blok try-catch response.flushBuffer()untuk menghindari kerangka kerja yang menimpa kode respons saya. Tidak terlalu bersih.
Pierre Henry
1
@RobJuurlink, jika Anda ingin secara khusus mengembalikan 404 Not Found, mungkin lebih mudah digunakan throw new NotFoundException().
Garret Wilson
34

Jika Anda ingin menjaga lapisan sumber daya Anda bersih dari Responseobjek, maka saya sarankan Anda menggunakan @NameBindingdan mengikat implementasi ContainerResponseFilter.

Inilah daging anotasi:

package my.webservice.annotations.status;

import javax.ws.rs.NameBinding;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Status {
  int CREATED = 201;
  int value();
}

Inilah daging saringannya:

package my.webservice.interceptors.status;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class StatusFilter implements ContainerResponseFilter {

  @Override
  public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
    if (containerResponseContext.getStatus() == 200) {
      for (Annotation annotation : containerResponseContext.getEntityAnnotations()) {
        if(annotation instanceof Status){
          containerResponseContext.setStatus(((Status) annotation).value());
          break;
        }
      }
    }
  }
}

Dan kemudian implementasi sumber daya Anda menjadi:

package my.webservice.resources;

import my.webservice.annotations.status.StatusCreated;
import javax.ws.rs.*;

@Path("/my-resource-path")
public class MyResource{
  @POST
  @Status(Status.CREATED)
  public boolean create(){
    return true;
  }
}
Nthalk
sumber
Menjaga API bersih, jawaban yang bagus. Apakah mungkin untuk membuat parametrize anotasi Anda seperti @Status (kode = 205), dan minta pencegat mengganti kode dengan apa pun yang Anda tentukan? Saya pikir itu pada dasarnya akan memberi Anda anotasi untuk menimpa kode kapan pun Anda perlu.
user2800708
@ user2800708, saya sudah melakukan ini untuk kode lokal saya, memperbarui jawabannya seperti yang Anda sarankan.
Nthalk
Terima kasih banyak. Dengan ini dan beberapa trik lain pada dasarnya saya sekarang dapat membersihkan API REST dalam kode saya, sehingga sesuai dengan antarmuka Java sederhana tanpa menyebutkan REST di dalamnya; itu hanya mekanisme RMI lainnya.
user2800708
6
Alih-alih mengulangi anotasi di StatusFilter, Anda dapat membuat anotasi filter dengan @ Status selain @ Penyedia. Maka filter hanya akan dipanggil pada sumber daya yang dijelaskan dengan @ Status. Ini adalah tujuan dari @ NameBinding
trevorism
1
Callout @trevorism yang bagus. Ada satu efek samping yang tidak terlalu bagus annotating StatusFilterdengan @Status: Anda baik perlu menyediakan default untuk penjelasan ini valuelapangan, atau menyatakan satu ketika annotating kelas (ex: @Status(200)). Ini jelas tidak ideal.
Phil
6

Jika Anda ingin mengubah kode status karena pengecualian, dengan JAX-RS 2.0 Anda dapat mengimplementasikan ExceptionMapper seperti ini. Ini menangani pengecualian semacam ini untuk seluruh aplikasi.

@Provider
public class UnauthorizedExceptionMapper implements ExceptionMapper<EJBAccessException> {

    @Override
    public Response toResponse(EJBAccessException exception) {
        return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
    }

}
ercalamar
sumber
6

Jika WS-RS Anda perlu meningkatkan kesalahan mengapa tidak hanya menggunakan WebApplicationException?

@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("{id}")
public MyEntity getFoo(@PathParam("id") long id,  @QueryParam("lang")long idLanguage) {

if (idLanguage== 0){
    // No URL parameter idLanguage was sent
    ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST);
    builder.entity("Missing idLanguage parameter on request");
    Response response = builder.build();
    throw new WebApplicationException(response);
    }
... //other stuff to return my entity
return myEntity;
}
Ariel
sumber
4
Menurut pendapat saya WebApplicationExceptions tidak cocok untuk kesalahan sisi klien karena mereka membuang jejak tumpukan besar. Kesalahan klien seharusnya tidak membuang jejak tumpukan sisi server dan mencemari logging dengan itu.
Rob Juurlink
5

JAX-RS memiliki dukungan untuk kode HTTP standar / khusus. Lihat ResponseBuilder dan ResponseStatus, misalnya:

http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/Response.ResponseBuilder.html#status%28javax.ws.rs.core.Response.Status%29

Perlu diingat bahwa informasi JSON lebih tentang data yang terkait dengan sumber daya / aplikasi. Kode HTTP lebih lanjut tentang status operasi CRUD yang diminta. (setidaknya begitulah seharusnya dalam sistem REST-ful)

kvista
sumber
tautannya rusak
Umpa
5

Saya merasa sangat berguna untuk membangun juga pesan json dengan kode berulang, seperti ini:

@POST
@Consumes("application/json")
@Produces("application/json")
public Response authUser(JsonObject authData) {
    String email = authData.getString("email");
    String password = authData.getString("password");
    JSONObject json = new JSONObject();
    if (email.equalsIgnoreCase(user.getEmail()) && password.equalsIgnoreCase(user.getPassword())) {
        json.put("status", "success");
        json.put("code", Response.Status.OK.getStatusCode());
        json.put("message", "User " + authData.getString("email") + " authenticated.");
        return Response.ok(json.toString()).build();
    } else {
        json.put("status", "error");
        json.put("code", Response.Status.NOT_FOUND.getStatusCode());
        json.put("message", "User " + authData.getString("email") + " not found.");
        return Response.status(Response.Status.NOT_FOUND).entity(json.toString()).build();
    }
}
Himpunan
sumber
4

Silakan lihat contoh di sini, yang terbaik menggambarkan masalah dan bagaimana menyelesaikannya di Jersey versi terbaru (2.3.1).

https://jersey.java.net/documentation/latest/representations.html#d0e3586

Ini pada dasarnya melibatkan mendefinisikan Pengecualian khusus dan menjaga jenis pengembalian sebagai entitas. Ketika ada kesalahan, pengecualian dilemparkan, jika tidak, Anda mengembalikan POJO.

annouk
sumber
Saya ingin menambahkan bahwa contoh yang menarik adalah di mana mereka mendefinisikan kelas pengecualian mereka sendiri dan membangunnya Response. Cari saja CustomNotFoundExceptionkelasnya dan mungkin salin ke posting Anda.
JBert
Saya menggunakan pendekatan ini untuk kesalahan dan saya menyukainya. Tapi itu tidak berlaku untuk kode sukses (berbeda dengan 200) seperti '201 dibuat'.
Pierre Henry
3

Saya tidak menggunakan JAX-RS, tapi saya punya skenario serupa di mana saya menggunakan:

response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
Topi
sumber
Itu tidak untuk saya menggunakan Spring MVC tetapi ada cara mudah untuk mengetahuinya!
Tutup
1

Juga, perhatikan bahwa Jersey default akan menimpa badan respons jika kode http 400 atau lebih.

Untuk mendapatkan entitas yang Anda tentukan sebagai badan respons, cobalah untuk menambahkan init-param berikut ke Jersey Anda di file konfigurasi web.xml Anda:

    <init-param>
        <!-- used to overwrite default 4xx state pages -->
        <param-name>jersey.config.server.response.setStatusOverSendError</param-name>
        <param-value>true</param-value>
    </init-param>
Maxime T
sumber
0

Kode berikut ini berfungsi untuk saya. Menyuntikkan messageContext melalui setter beranotasi dan mengatur kode status dalam metode "add" saya.

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.ext.MessageContext;

public class FlightReservationService {

    MessageContext messageContext;

    private final Map<Long, FlightReservation> flightReservations = new HashMap<>();

    @Context
    public void setMessageContext(MessageContext messageContext) {
        this.messageContext = messageContext;
    }

    @Override
    public Collection<FlightReservation> list() {
        return flightReservations.values();
    }

    @Path("/{id}")
    @Produces("application/json")
    @GET
    public FlightReservation get(Long id) {
        return flightReservations.get(id);
    }

    @Path("/")
    @Consumes("application/json")
    @Produces("application/json")
    @POST
    public void add(FlightReservation booking) {
        messageContext.getHttpServletResponse().setStatus(Response.Status.CREATED.getStatusCode());
        flightReservations.put(booking.getId(), booking);
    }

    @Path("/")
    @Consumes("application/json")
    @PUT
    public void update(FlightReservation booking) {
        flightReservations.remove(booking.getId());
        flightReservations.put(booking.getId(), booking);
    }

    @Path("/{id}")
    @DELETE
    public void remove(Long id) {
        flightReservations.remove(id);
    }
}
JBernhardt
sumber
0

Memperluas pada jawaban dari Nthalk dengan Microprofile OpenAPI Anda dapat menyelaraskan kode kembali dengan dokumentasi Anda menggunakan @APIResponse penjelasan.

Ini memungkinkan menandai metode JAX-RS seperti

@GET
@APIResponse(responseCode = "204")
public Resource getResource(ResourceRequest request) 

Anda dapat menguraikan anotasi standar ini dengan ContainerResponseFilter

@Provider
public class StatusFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        if (responseContext.getStatus() == 200) {
            for (final var annotation : responseContext.getEntityAnnotations()) {
                if (annotation instanceof APIResponse response) {
                    final var rawCode = response.responseCode();
                    final var statusCode = Integer.parseInt(rawCode);

                    responseContext.setStatus(statusCode);
                }
            }
        }
    }

}

Peringatan terjadi ketika Anda menaruh beberapa anotasi pada metode Anda

@APIResponse(responseCode = "201", description = "first use case")
@APIResponse(responseCode = "204", description = "because you can")
public Resource getResource(ResourceRequest request) 
itu
sumber
-1

Saya menggunakan jersey 2.0 dengan pembaca dan penulis isi pesan. Saya memiliki tipe metode pengembalian sebagai entitas spesifik yang juga digunakan dalam implementasi penulis badan pesan dan saya mengembalikan pojo yang sama, SkuListDTO. @Dapatkan @Konsumen ({"application / xml", "application / json"}) @Produces ({"application / xml", "application / json"}) @Path ("/ skuResync")

public SkuResultListDTO getSkuData()
    ....
return SkuResultListDTO;

yang saya ubah adalah ini, saya meninggalkan implementasi penulis sendiri dan itu masih berfungsi.

public Response getSkuData()
...
return Response.status(Response.Status.FORBIDDEN).entity(dfCoreResultListDTO).build();
b. phillips
sumber