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
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!!!!!!!!!!!
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();
}
}
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?
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.
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*/);