Resteasy - Override Method with generics - java

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?

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!!!!!!!!!!!

Get request body in failed access of method with POST annotation

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();
}
}

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?

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.

RESTlet Authorization Filter

I am developing a RESTlet API (JAVA), and I've created a custom authorization filter that I run all requests through before passing it to my router. In my requests I always pass the session ID as a request attribute, e.g.
http://localhost:8080/myAPI/{sid}/someResource/
Now, in my functions that extends ServerResource, I can do something like this to easily extract that {sid}:
String sid = (getRequestAttributes().containsKey("sid")) ? getRequestAttributes().get("sid").toString() : "";
My problem is, in my authorization function, which extends Filter (the authorization function is not called via a router, but is called in my main createInboundRoot() function), I cannot use the same method to extract the {sid}. I've created a workaround using string manipulation of request.getResourceRef().getSegments(), but there must be a better way?
Any help will be appreciated!
Thanks
You can create a common parent class for any child of ServerResource. like this:
public class CommonParentResource extends ServerResource
{
// class definition
}
And then override the doInit() method of the ServerResource class in it.
public class CommonParentResource extends ServerResource
{
public void doInit()
{
boolean authorized=false;
String sid = getRequestAttributes().containsKey("sid") ? (String)getRequestAttributes().get("sid") : StringUtils.EMPTY;
// Authorization logic here.
if(!authorized)//after authorization process completed.
{
getResponse().setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
getResponse().setEntity(/*Representation carrrying message for unauthorized user*/);
}
}
}
Now any new child class of ServerResource that you want to perform this authorization check, must extend this CommonParentResource class. Like this:
public class FriendsListResource extends CommonParentResource
{
#Get
//......
}
Two points are important here:
doInit() of any child class of ServerResource is called before calling any method annotated with #Get / #Post / ...
(Caution) If you do not use this statement:
getResponse().setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
i.e. if you do not set status of response to an error, then methods annotated with #Get / #Post / #Put / ... will get called ! But if your program sets the status of the response to an error-status, then the #Get / #Post / #Put / ... will not get executed, and the end user will see the error message represented by:
getResponse().setEntity(/*Representation carrrying message for unauthorized user*/);

Categories

Resources