Getting 404 Not Found, while calling JAX-RS Rest API method - java

I am trying to call REST API method (method been declared without #Path annotation).
Resource path for this API has been loaded in server start up itself using BaseRestServer.rootPath.
I expect that this API will get called by default, as there are no other apis available to process the request.
But when i call this api, I am getting '404 Not Found' as response.
code is something like, as given below,
**#Path("")**
public class JobResource{
#POST
#Consumes("application/job")
#Produces("application/job")
public Response postJob(
#Context HttpServletRequest hRequest, Job job){
}
}
resource path has been defined in the server file itself, as given below
BaseRestServer.rootPath = "/shared/job/"+companyName.
Reason on why i have not used resource path in the class is, that it allows only constant value inside #Path annotation.
But in my case, companyName value changes dynamically
When I pass this dynamic value inside #Path("/shared/job/"+companyName), i am getting compilation error as 'The Value for annotation attribute Path.value must be a constant expression'

Related

Jersey resource that matches any path

I am using Jersey v1.x and a Guice Servlet.
What I'm trying to do is bind a Jersey Resource that matches any #Path, such that I can use Jersey to respond with a 404.
I'm looking to do this, since my servlet consists of different components (e.g. a rest API that lives under /api, and a web UI that lives under /.
In Guice terms, that means I have several ServletModules that each set up one part of the servlet:
In my ApiServletModule: serve("/api").with(GuiceContainer.class, conf)
In my WebUiServletModule: serve("/").with(GuiceContainer.class, conf)
In this setup, I want to define what the 404 response body looks like for each part of the webapp (/api or /) from the codebase of each subproject responsible, without having to reimplement Jersey
So far I have tried to bind a resource that match #Path("/"), #Path("*") and #Path("/*"), but none of these seem to be picked up when I request /some/path/that/doesnt/exist
You need to use the regex format of the path expression, i.e.
#Path("{any: .*}")
You could inject List<PathSegment> to look at all the segments if you need them.
public Response getSomething(#PathParam("any") List<PathSegment> segments)
#peeskillet's answer is indeed correct, in the sense that it describes how you can create a Jersey resource that matches any path.
However, my goal of creating a resource that delivers 404 responses for whenever any other unmatched path is requested is not quite met by this answer:
At least in combination with Guice, will such a "match all"-resource intercept all requests, regardless of whether any more specific resources are available. Additionally, you cannot modify the HTTP response status code from within a resource.
For this purpose, Jersey has ExceptionMappers that can be implemented and loaded by adding the #Provider annotation. One particular type would be a ExceptionMapper<NotFoundException>, which is invoked when a Resource throws a NotFoundException. The ExceptionMapper can then decide what response to generate, including the status code.

Spring URL when both controller and method do not have #RequestMapping values

I'm being asked to take over a piece of code. Being that I am not an seasoned Spring developer, I have a question on what is the URI when both the controller and method does not specify a value for #RequestMapping.
For example, the code looks like this:
#Controller
public class FooController {
#RequestMapping
public String getThis(String input) {
return "This";
}
}
So what is the URL that I need to access the getThis method?
Sometime back i also had the same doubt. Am thinking that Controller without #RequestMapping will throw an exception (am not sure).
For method case:
If you don't have any values in #RequestMapping, method will listen on Controller path and you dint specify any method so it will listen ALL HTTP Methods.
Your method will not be reachable and you can see this via a warning message from Spring like :
21:57:50.608 [main] DEBUG o.s.w.s.h.BeanNameUrlHandlerMapping -
Rejected bean name
'org.springframework.context.annotation.internalConfigurationAnnotationProcessor':
no URL paths identified
If you need to have this method in the root URL, you need to use the value "/" instead of nothing.

Interfere in Jersey REST life cycle

I have variant resources that all extend BaseResource<T>
#Component
#Path("/businesses")
public class BusinessResource extends BaseResource<Business>{
#GET
#Path({businessId}/)
public Business getBusiness(#PathParam("businessId") Integer businessId){..}
}
#Component
#Path("/clients")
public class ClientResource extends BaseResource<Client>{
#GET
#Path({clientId}/)
public Client getClient(#PathParam("clientId") Integer clientId){..}
}
I would like, that when there is a call to
/businesses/3, it will first go through a method that I will write which validates the T object and if everything is ok I will tell jersey to continue handling the resource.
Same goes for Client.
I can't use a regular servlet/filter - since it's being called BEFORE jersey servlet and I wouldn't know which resource is being called.
What is the best way to do it in Jersey?
Is there a place to interfere between knowing the method that jersey will invoke and the invokation?
There are 4 basic http methods in REST, namly GET, PUT, POST, DELETE.
Your annotation tells Jersey what method to call when a http request occurs. Jersey looks up the target URI in the request and matches it against your model. If the request is a http get it will execute the method annotiated with #Get from the class with the correct #Path annotiaton.
Usually you dont want to grant access to your resources in this annotated method directly. A common (may not perfect) way is to implement a DAO class that handles access to your resources, and of course does the validation before it returns the resource back to the #Get annotated method, which will itself only pass the resource to the client. So you will get another layer in your application between persisting (SQL, etc) and the client interface (Jersey).
You can use jersey 2.x ContainerRequestFilters with NameBinding. After having matched the resource, the bound filter will be executed prior to executing the method itself.
You can see the Jersey user guide, which states that it is possible:
Chapter 9.2.1.1 explains about PreMatching and PostMatching filters and chapter 9.4 chapter shows the execution order of jersey filters.
See my post for the implementation where I had the problem to make the filters with jersey 2 work.

Jersey, return response to browser before hitting the resource

I am using Jersey framework for my RESTful services.
Each of my resource class inherits a base class, I have few URL parameter validations in place inside my base class, so if I find that a mandatory field is missing in the URL, I want to stop the flow in my base class (i.e. Don't want to go and hit my resource method and return a response to browser from my base class).
Currently I am not able to do that and even if I try like for e.g do something like following to go back to browser with missing param message, it won't and still goes and hit the resource class web service method being called:
return Response.status(Response.Status.BAD_REQUEST)
.entity("Parameter value missing for "+ StringHelper.ArrayToString(requiredParametersValueMissing))
.build();
Any ideas or similar situation being faced by you guys. Input appreciated.
You can throw a WebApplicationException like so:
throw new javax.ws.rs.WebApplicationException(javax.ws.rs.core.Response
.status(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.entity("Parameter value missing for ").type("text/html").build());
I handled what you're trying to do by extending com.sun.jersey.spi.container.servlet.ServletContainer and parsing out the params myself from HttpServletRequest. If I find an error I call
return super.service(baseUri, requestUri, request, response);
Is this what you're doing in your base class?

Passing the URI Path to the JAX-RS Providers

I recently implemented a Jersey JAX-RS Rest service. I created a JIBX provider that allows one to unmarshal and marshall between XML and Java types. I would like to also version my service by specifying the version in the URL path. Versioning would include the version of message binding used to marshal and unmarshall the Java types.
Therefore, it is necessary that the version is passed to the custom JIBX provider, and therefore the URL path that contains the version. However, the Provider interfaces (MessageBodyWriter and MessageBodyReader) do not provide the URI path in their interface methods.
The following is the method signature of the writeTo() method of the MessageBodyWriter interface:
writeTo(Object, Type, Annotation[], MediaType, MultivaluedMap, OutputStream)
This method parameters does not contain the path uri, therefore, the custom jibx provider cannot know which message binding version it should use to marshall the Java type. Is there a way around this?
If you want something a bit more JAX-RS specific than HttpServletRequest, you can inject a javax.ws.rs.core.UriInfo.
public class MyProvider implements MessageBodyWriter {
#javax.ws.rs.core.Context
javax.ws.rs.core.UriInfo uriInfo;
}
I'm assuming that you're using a #javax.ws.rs.PathParam to capture the path parameter. You can then potentially use UriInfo.getPathParameters(). You can also fall back to UriInfo.getPathSegments() to get the information you're looking for. This saves you the trouble of parsing the request URI yourself. Any JAX-RS implementation should be able to do this.
You can access the URI path from the Provider by defining the #Context annotation on a field on the Provider.
For example,
public class CustomProvider implements MessageBodyWriter
{
#Context HttpServletRequest request;
....
}
This field will automatically be set for each request. Even though the request is set as a field, the value is thread-safe as the actual request is using a proxy and most likely thread local to determine the request that belongs to thread.

Categories

Resources