what is default http method in rest web services - java

Is there any default method for java restful web services.
If I dont annotate my root resource class method with any html method annotation then will it match the upcoming get request to that method
#Path("xyz")
class abc
{
String methodName(String name)
{
//processing
}
}
In this case if I have an get request , then will this method be treated as resource .
I read that when our resource methods are annotated with #Path and not with #AnyHttpMehtod then its a sub resource locator. I want to know when we dont have any http method annotation then will there be some default behavior.

From the documentation:
By default, the JAX-RS runtime will automatically support the methods HEAD and OPTIONS if not explicitly implemented. For HEAD, the runtime will invoke the implemented GET method, if present, and ignore the response entity, if set. For OPTIONS, the Allow response header will be set to the set of HTTP methods supported by the resource. In addition, the JAX-RS runtime will return a Web Application Definition Language (WADL) document describing the resource; see https://wadl.dev.java.net/ for more information.
source

Related

Why does Apache CXF - Jax RS allows 'GET' requests to take up 'HEAD' requests?

I am using Apache CXF Jax-RS to implement RESTfull services. I have implemented a GET call as shown below:
#GET
#Path("getSomething")
#Produces("application/xml")
public String getSomething() {
return null;
}
This is working fine for me but a bug is raised on this after the tester was able to use this service operation with a HEAD request (POST and other calls fail). I did a little research and found that HEAD request is similar to GET, with the only difference being that it doesn't return a body. So i have a few questions regarding this.
1) Why does JAX RS allow operations annotated with #GET to receive HEAD requests while it does have a separate #HEAD annotation available ?
2) Could this cause any kind of problem in my application
3) If i have to disallow #GET operations to take #HEAD operations, i could i do that ?
1) It is defined in JAX-RS 1.0:
HEAD and OPTIONS requests receive additional automated support. On receipt of a HEAD request an implementation MUST either:
Call a method annotated with a request method designator for HEAD or, if none present,
Call a method annotated with a request method designator for GET and discard any returned entity.
Note that option 2 may result in reduced performance where entity creation is significant.
2) No, because your method has to be safe, see Wikipedia:
The GET method is a safe method (or nullipotent), meaning that calling it produces no side-effects. In other words, retrieving or accessing a record does not change it.
3) You could annotate another method with HEAD, see Jersey 2.22 User Guide:
By default the JAX-RS runtime will automatically support the methods HEAD and OPTIONS, if not explicitly implemented.

SOAP annotation for path

I need to manage different versions that come in the URL of the Webservice. I'm using a common method in the Webservice for SOAP and REST, and when I tried to get the path in the endPoint class I got the correct path for REST, but not for SOAP(I got a null in this case), does anybody how to get the path in soap?
The url looks like: http://localhost:8083/webService/v1/test and the code is:
#Stateless
#WebService(endpointInterface = "ItestgEndpoint", serviceName="testService")
#Component("testEndpoint")
#Path("/webService")
#Consumes({MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_XML})
public class TestEndpoint implements ItestgEndpoint{
#PUT
#Path("/{version}/test")
#Consumes({MediaType.APPLICATION_XML })
#Produces({MediaType.APPLICATION_XML })
#WebResult(name="testResponse")
public testResponse testEvent(#WebParam(targetNamespace="http://test/web", name="message")
#RequestParam MessageClass message,
#WebParam(name="version") #PathParam("version") String version
) throws TimeoutException, EMSException, ValidationException, AuthenticationException {
logger.info(version);
}
I saw this post SOAP and REST Webservice with one implementation in Java EE, but it didn't solve my problem.
Thanks
SOAP has no "path" like REST has. Depending on the service toolkit you use (CXF, axis, ...) you may need to collect the information in the request that you can extract from the transport mechanism of the soap message. This may or may not be available to you.
Usually, you wire the SOAP service to a path in a configuration. For example in axis, you set the soap servlet dispatcher in the web.xml, same is for cxf. The actual service is then wired in the beans.xml or services.wsdd.
The SOAP handler finds the service by the name of the endpoint and will then send the call to that endpoint which will dispatch it to the right method. The method is in the transmitted SOAP header, not in the URI.
In REST, the identification of the target service/method is in the URI, not in the XML.
So, in my opinion, for SOAP, this is by declaration and the wiring is static, while in REST, you can have the version as a path parameter.
UPDATE: Since everything is possible if you just try hard enough :-) you could rewrite the dispatcher code to allow an extra path parameter on SOAP, maybe the available packages allow some kind of interceptor class, that allows you to rewrite the SOAP header to point to another endpoint, depending on a header attribute that you invent.

How exactly works the #ResponseStatus Spring annotation for RESTful application?

I am studying for the Spring Core certification and I have some doubts about how Spring handles REST requests.
I know that with REST the resources are exposed as name and that the actions on these resources are the HTTP methods, such as GET, PUT, POST, and DELETE.
And I know that requests are handled by the use of #RequestMapping annotations over the method that handles the operation on the resource.
From what I have understood, both standard web applications and RESTful applications use some codes to communicate with their clients (the RESTful application have an expanded set of codes) that I think represent the status of the request (for example 200 is the request is a successful GET returning content, etc.).
Now the documentation shows the use of the #ResponseStatus annotation as in this example:
#RequestMapping(value="/orders", method=RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED) // 201
public void createOrder(HttpServletRequest request, HttpServletResponse response) {
Order order = createOrder(request);
// determine full URI for newly created Order based on request
response.addHeader("Location",
getLocationForChildResource(request, order.getId()));
}
So looking at the previous method I know that it handles HttpRequest POST requests towards the resource named /orders (using REST the resource is seen as an URL, is that correct?).
But what exactly does the annotation below do:
#ResponseStatus(HttpStatus.CREATED) // 201
I know that the 201 status code means that a new resource was created on POST.
And looking at the official documentation I can read:
Marks a method or exception class with the status code and reason that
should be returned. The status code is applied to the HTTP response
when the handler method is invoked, or whenever said exception is
thrown.
So what exactly it means? I think that as is done in the previous example it sets the 201 status that says that the resource is correctly created by the POST request. If this is correct I have 2 questions:
The resource is the /orders URI. So what is created? a file named orders (I think that this assertion is false) or what?
Where the 201 status is put?
201 is an HTTP status code. It indicates that the
request has been fulfilled and resulted in a new resource being created.
So if your server is returning such a status code, then the client understands that some (conceptual) resource was created. What that resource is is your responsibility, you're the server.
A status code is part of the HTTP response status line.
Actually, the JavaDocs for the ResponseStatus annotation warn us not to use this annotation for REST APIs. This annotation will cause Spring to call the HttpServletResponse.sendError() method, which will result in an HTML Error page. You don't want that in a RESTful service. Here's what it says:
Warning: when using this annotation on an exception class, or when setting the reason attribute of this annotation, the HttpServletResponse.sendError method will be used.
With HttpServletResponse.sendError, the response is considered complete and should not be written to any further. Furthermore, the Servlet container will typically write an HTML error page therefore making the use of a reason unsuitable for REST APIs. For such cases it is preferable to use a ResponseEntity as a return type and avoid the use of #ResponseStatus altogether.

Authenticating with an API key in JAX-RS

We'd like to secure our rest api using an api key. Here are the requirements:
Public-facing services require an api key.
"Private" services can only accept a call from within the cluster,
not the outside world.
Each api identifies a user, and the User object must be available to
the rest service.
Is there some standard way to do this in a JAX-RS app? (We're using Resteasy.)
I've read all about filters, interceptors and basic auth, but it isn't clear to me what's the best approach.
In an earlier version of the app we had a roll-your-own solution in which public services ran on a public port and private ones on a private port. There was a custom api key lookup that set the User object as a variable into the rest service object.
I can't figure out how to do either of these things using standard JAX-RS.
Using a filter to intercept the request
This kind of authentication could be achieved with a ContainerRequestFilter, intercepting the requests to your resource methods.
The filter will be used to extract the API key from the request and validate it. If the API key is not valid, the request will be refused. Otherwise, the request will proceed to the resource methods.
Have a look at the following piece of code. The ContainerRequestContext API can be used to extract information from the HTTP request:
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Extract and validate the API key from the request
String apiKey = requestContext.getHeaderString("API-Key");
...
}
}
Also have a look at this answer I wrote a while ago about authentication with tokens in JAX-RS. There you will find plenty of details that can be useful to address the situation you described in your question.
Identifying the user
During the authentication process, you must be able to identify the user who is performing the request. To propagate this information to your resource classes/methods you could:
Override the SecurityContext and inject it into your resource classes/methods.
Use a CDI Event and a producer method to create an object that contains the user identifier that can be injected in your resource classes/methods.
For more details on the these approaches, refer to the answer I mentioned above.
Binding the filter to some resource classes/methods
By default, the filters are global (it means they are executed for all the resource methods of your application). To bind the filter to a subset of resource methods or classes, you could use name binding annotations.
Not giving a detailed answer, but just a suggestion. Check for CustomInvokers and register the invoker for the services. Validate the api-key and throw an error if it's not valid. If there is an error then your client gets an error. The Service code won't be called.
For the actual security framework, please check netflix zuul.

Using MessageBodyReader for multiple parameters in RESTful services

The following method does not allow my servlet container to start:
#PUT
public String upload(final Customer customer, final Control control) {
// ...
}
I get, not surprisingly:
SEVERE: Missing dependency for method ... at index 0
SEVERE: Missing dependency for method ... index 1
SEVERE: Method, ..., is not recognized as valid resource method.
I have implemented MessageBodyReaders for each type. Removing any of the parameters enables the servlet container to start gracefully, so I suspect there must be a restriction on the number of parameters that will be resolved via Entity-Providers.
The problem is that I NEED these two parameters, since I am providing both SOAP and REST support, and of course, I am not in the liberty of changing method signatures, and I also do not want to create one specific Jersey method and one specific JAX-WS method as entry points.
I'm using Jersey 1.7.
JAX-RS allows only one entity parameter. The reson is very simple: each request may have at most one body (multiparts are not supported by spec)
So you must create two methods.
Btw, I don't think it's a good practice to mix JAXRS and JAXWS in the same class.

Categories