简体   繁体   中英

JAX-RS, When POST fails, how to get raw JSON

my code uses an external API. When I call it with a correct parameter, I get the expected answer.

When I call it with a wrong parameter (wrong in the sense of incorrect job's data, technical is OK), my code throws an Exception. I was expecting a String containing the data's validation error "sex='3' is wrong".

The API uses JSON and return JSON. I call it with javax.ws.rs

Here is my method where I call the API

    public final String API_URL= "http://sv-t-vtl-pgih-vidal:9900/solfeges/api/v0";

    private void test(String json)
    {
        // The proxy for calling the API.
        SolfegesServices proxy = ProxyFactory.create(SolfegesServices.class, API_URL);

        // 
        try
        {
            // Call the API
            String retourBrut = proxy.callfactureapi(json);

            System.out.println(retourBrut);
        }
        catch (RuntimeException e)
        {
            e.printStackTrace();
        }
    }

Here an other class I use to declare the API

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import fr.pgih.ope.act.dim.gestionfides.utils.RetourSolfegesException;

@Produces("application/json")
@Consumes("application/json")
public interface SolfegesServices
{
    @POST
    @Path("/factures")
    public String callfactureapi(String json) throws RetourSolfegesException;
}

Those both classes are enought to call the API.

When the API is called with incorrect data, the API returns a JSON with a 422 status. When it happens, the code throws a runtimeException that does not contains API's info about the error.

How can I get the JSON returned by the API in case of error?

NB. In case of success, the JSON looks like

{
statut:200,
message:"succes",
b2:"some content"
}

In case of failure, I'm expecting something like

{
statut:422, (or 400)
message:"fail to...",
reason:"sexe='3' is incorrect"
}

I've already dig the whole stackoverflow website and some other without finding a solution to my problems, despite of the amount of similar cases.

Everything looks fine if I try to call the API with Postman (external tool to execute web requests).

You can return the ResponseEntity from your controller. The response entity can be based on the validation failure you mention and this json message should be part of the body.

ResponseEntity response = ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(jsonMessage).build();

Finally, I integrated API's tool to call it (using Swagger). And it ... works ... almost perfectly.

Finally (the comeback). I've surcharged the exception filter to catch them (http statut 400 or 422).

ClientResponseFilter.filter(ClientRequestContext reqCtx, ClientResponseContext resCtx)

public class ClientResponsesExceptionFilter implements ClientResponseFilter
{

    @Override
    public void filter(ClientRequestContext reqCtx, ClientResponseContext resCtx)
            throws ApiSolfegesException, IOException
    {
        if (resCtx.getStatus() == Response.Status.BAD_REQUEST.getStatusCode() || resCtx.getStatus() == 422)
        {
            ...
        }
    }
}

I use it here

@Override
    public ModelApiResponse facturesPost(DossiersPmsi body)
    {

        CustomResteasyJackson2Provider resteasyJacksonProvider = new CustomResteasyJackson2Provider();

        // Ajout d'un Mapper pour gérer la sérialisation et désrialisation json des dates proprement
        ObjectMapper mapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
        javaTimeModule.addSerializer(new LocalDateSerializer());
        mapper.registerModule(javaTimeModule);
        resteasyJacksonProvider.setMapper(mapper);

        // ajout d'un filtre pour les exception
        ClientResponsesExceptionFilter filter = new ClientResponsesExceptionFilter();

        // appel de l'api solfeges
        ResteasyClient client = new ResteasyClientBuilder().register(resteasyJacksonProvider)
                .register(filter).build();
        ResteasyWebTarget target = client.target(UriBuilder.fromPath(URL_SOLFEGE));
        FacturesApi proxy = target.proxy(FacturesApi.class);
        return proxy.facturesPost(body);
    }

I also use these to get the JSON from : https://www.codota.com/code/java/methods/javax.ws.rs.client.ClientResponseContext/getEntityStream

private String getResponseBody(ClientResponseContext context) throws IOException
    {
        // La variable qui contient la description de l'erreur dans un fichier JSON.
        String jsonEchec = null;

        // Essayer de récupérer le JSON
        try (InputStream entityStream = context.getEntityStream())
        {
            if (entityStream != null)
            {
                byte[] bytes = IOUtils.toByteArray(entityStream);
                context.setEntityStream(new ByteArrayInputStream(bytes));
                jsonEchec = new String(bytes);
            }
        }

        // Retour du JSON descriptif de l'erreur
        return jsonEchec;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM