Get request body in failed access of method with POST annotation - java

I have a RESTful web service with an #POST annotated method that throws an exception when the request content type cannot be consumed. I would like to see what exactly went wrong. For this I would like to access all the details of the failed POST call, such as the body content. For this I created an #Provider catching NotSupportedException. I still have problems finding a way to get the desired details though. How would I do that?
The #POST annotated method:
#Path("/language")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class LanguageResource {
#POST
public Response postLanguages(Session session) {
return Response.status(Response.Status.OK)
.entity(Mock.getLanguages())
.build();
}
}
The #Provider:
#Provider
public class NotSupportedMapper implements ExceptionMapper<NotSupportedException> {
#Override
public Response toResponse(NotSupportedException exception) {
System.out.println(exception.toString());
return Response.status(Response.Status.NOT_IMPLEMENTED)
.build();
}
}

Related

Overriding specific resource in REST API

I have a particular scenario where I have a rest resource having some methods with their path.
My requirement is to create a new resource which will extend the above resource and I want to override only a specific method and want to call rest methods from the parent API only.
For example -
#Path("/data")
public class AResource {
#GET
#Path("/login")
public Response login()
{
//login code
}
#GET
#Path("/logout")
public Response logout()
{
//logout code
}
}
#Path("/data")
public class BResource extends AResource {
#GET
#Path("/login")
#Override
public Response login()
{
//login code modified as per requirement
}
}
I tried this, But its still calling parent class methods only for both the methods.
Is there any alternative to this, please suggest.
Thanks in advance!!!!!!!!!!!

Quarkus Microprofile Rest Client ResponseExceptionMapper doesn't catch errors

I have a Rest Client in a Quarkus (1.8.1) service defined like this:
#RegisterRestClient
#Path("/")
#Produces("application/json")
#Consumes("application/json")
public interface MyClient {
#POST
#Path("/{entity}")
Response postEntity(#HeaderParam(value = "Authorization") String auth,
#PathParam("entity") String entity, Object payload) throws MyException;
}
And I have implemented ResponseExceptionMapper in the same package like this:
public class MyExceptionMapper implements ResponseExceptionMapper<MyException> {
#Override
public MyException toThrowable(Response r) {
return new DynamicsException(r.getStatus() + " - " + r.readEntity(String.class));
}
}
When I call the service it is currently returning a 404 error, and I expected the code in the MyExceptionMapper class to be called. However it doesn't and instead a javax.ws.rs.WebApplicationException is thrown. The stack trace includes a call to the DefaultResponseExceptionMapper. It's seems that my mapper has not been registered.
How can I register my handler for invalid responses from calls to the service?
You need to register MyExceptionMapper as provider to the rest client with #RegisterProvider(MyExceptionMapper.class).
#RegisterRestClient
#RegisterProvider(MyExceptionMapper.class)
#Path("/")
#Produces("application/json")
#Consumes("application/json")
public interface MyClient {
Each implementation provides a default ResponseExceptionMapper implementation that will map and invoke a response to javax.ws.rs.WebApplicationException when the response status code is >= 400. It has a priority of Integer.MAX_VALUE, and is meant to be
used as a fallback whenever an error is encountered. This mapper will be registered bydefault to all client interfaces, but this can be disabled by setting an MP Config property,
microprofile.rest.client.disable.default.mapper, to true.
RestClientBuilder.newBuilder().property("microprofile.rest.client.disable.default.mapper",true)

Two #POST on a single resource

Using Jetty with Jersey embedded.
I was wondering if it is possible for one of my resources to have 2 method with #POST annotation on the same path but use the parameters to distinguish which method to call.
For example, lets say I have /api/v1/MyResource. And the MyResource class look like this:
// The /api is set in my context.
#Path("/v1/MyResource")
public class MyResource {
private final MyService service;
public MyResource(MyService service){
this.service = service;
}
#POST
#PermitAll
#Consumes(MediaType.APPLICATION_JSON)
public Response doPost(MyParam param){
this.service.doStuffWith(param);
}
#POST
#PermitAll
#Consumes(MediaType.APPLICATION_JSON)
public Response doPost(MyParamOfADiffType param){
this.service.doStuffWith(param);
}
}
Since my service has two implementation of the doStuffWith() function, I expected Jersey to try to serialize the request body into a MyParam object and if its not working try into a MyParamOfADiffType object. Then if its not working I expected a 500 Internal error.
But I get a ModelValidationException instead. Anyone know if what I am trying is possible?

Resteasy - Override Method with generics

Right now i am working with resteasy. I have build a little Rest Application with the following struktur:
Controller Class:
#PATH("/rest")
public abstract class Controller<T>
{
#POST
public Response post(T ressource){[..]}
#PUT
public Response put(T ressource){[..]}
#DELETE
#Path("/{id}")
public Response delete(#PathParam(value = "id") int id)
#GET
public Response get(){[..]}
}
ConrollerA Class (This is only an Example):
PATH("/rest/A")
public class ControllerA extends Controller<RessourceA>
{
#Override
public Response post(RessourceA ressource){[..]}
[..]
#Override
public Response get(){[..]}
}
I start the server with jetty right now and everytime i make a POST Request to "/rest/A", the Server tells me, that there is no such a method but if i make a GET Requst to the Path it all works.
Is there a Problem with Jetty or Java if i override a Method with generic typs?
If i write the "#POST" annotation above the method it works, but i do not want this kind of solution. Do i have to make some settings in the web.xml or is the problem with java?

JAX-RS custom SecurityContext leads to wrong error code in Jersey

I followed the Jersey tutorials to implement a completely custom SecurityContext for my application. I created a custom ContainerRequestFilter to set the SecurityContext as follows:
package com.my.security;
#Provider
#Priority(Priorities.AUTHORIZATION)
public class SecurityRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) {
requestContext.setSecurityContext(new MySecurityContext(requestContext));
}
public static final class MySecurityContext implements SecurityContext {
private String token;
public MySecurityContext(ContainerRequestContext requestContext) {
token = requestContext.getHeaderString("token");
}
#Override
public boolean isUserInRole(String role) {
return role.equals("admin") && token.equals("token-for-admin");
}
// other methods omitted
}
}
The logic in the isUserInRole method is irrelevant, it's just a mock to make the point.
My endpoint looks something like:
package com.my.rest;
#PermitAll
#Path("/people")
public class PeopleRestService {
#RolesAllowed({"admin"})
#Path("/{email}")
#DELETE
public Response deletePerson(#PathParam("email") final String email) {
peopleService.removePerson(email);
return Response.ok().build();
}
}
Now I created a test (using JerseyTest) configured with the packages where the two classes are:
#Override
protected Application configure() {
return new ResourceConfig().packages("com.my.rest", "com.my.security");
}
If I execute the following in my test:
Response response = target("people/my#email.com")
.request().header("token", "token-for-admin").delete();
Assert.assertEquals(200, response.getStatus());
everything works fine.
However, if I execute the following:
Response response = target("people/my#email.com").request().delete();
Assert.assertEquals(403, response.getStatus());
I would expect a 403 error code because I didn't set the authentication token. However, I get a 500 error code and a Grizzly (the container used for the test) HTML response with the string "Request failed.".
If I comment out the #Provider annotation on the SecurityRequestFilter class or remove the package com.my.security from the test configuration, Jersey uses the container provided SecurityContext and correctly returns a 403 instead.
Why is this happening? Shouldn't Jersey return a 403 with a custom SecurityContext too? What am I missing?
I apologize for my dumbness. the logic in the isUserInRole method is completely relevant! I had a NPE in there that I didn't see and was causing the 500.

Categories

Resources