Do SOAP Web services support only "POST" http method - java

I faced this question on one of interviews, so could you please tell whether SOAP Web services support only "POST" http method or there is some way to accept other methods on the server side?

I always used POST but according to the W3C standard, SOAP supports both POST and GET methods.
Edit: After some research, it seems that it's not completely true, as you can see here. It is theoretically possible to use GET because POST and GET are methods of HTTP transport protocol and SOAP can be used over HTTP.
But as you know, GET includes the request in the query string. SOAP requests (XML messages) are usually too complex and verbose to be included in the query string, so almost every implementation (for example JAX-WS) supports only POST.

Thread is three years old but I think that there will be still a lot of people who will give this same question to themselves and will find wrong answer in the web. The answer to the question is no, GET method can be used too.
According to SOAP specification, which can found here: https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#transport
both GET and POST methods can be used to exchange SOAP messages over http.
The use of the HTTP POST method for conveying SOAP messages in the bodies of HTTP request uses a pattern called SOAP request-response message exchange pattern. In the case of HTTP GET a pattern is used called SOAP response message exchange pattern. The main difference of this two patterns is:
The first type of interaction allows for the use of data within the body of a HTTP POST to create or modify the state of a resource identified by the URI to which the HTTP request is destined. The second type of interaction pattern offers the ability to use a HTTP GET request to obtain a representation of a resource without altering its state in any way. In the first case, the SOAP-specific aspect of concern is that the body of the HTTP POST request is a SOAP message which has to be processed (per the SOAP processing model) as a part of the application-specific processing required to conform to the POST semantics. In the second case, the typical usage that is forseen is the case where the representation of the resource that is being requested is returned not as a HTML, or indeed a generic XML document, but as a SOAP message. That is, the HTTP content type header of the response message identifies it as being of media type "application/soap+xml"
So both GET and POST methods can be used. The other thing is that in practice mostly POST method is used.
The bad thing is that when comparing RESTful services with SOAP services, as an advantage of REST people are bringing caching, which is not available in SOAP, because SOAP uses only POST. This is totally wrong.

This is an implementation of GET in SOAP:
#WebServiceProvider(targetNamespace="http://attachment.service.soap.com/download")
#ServiceMode(value = javax.xml.ws.Service.Mode.MESSAGE)
#BindingType(value = HTTPBinding.HTTP_BINDING)
public final class ImageDownloadServiceProvider implements Provider<DataSource> {
#Resource
private WebServiceContext wsContext;
#Override
public DataSource invoke(DataSource request) {
if (wsContext == null)
throw new RuntimeException("dependency injection failed on wsContext");
MessageContext msgContext = wsContext.getMessageContext();
HttpExchange exchange = (HttpExchange) msgContext.get("com.sun.xml.internal.ws.http.exchange");
String filename = exchange.getRequestURI().getQuery().replace("file=", "");
switch ((String) msgContext.get(MessageContext.HTTP_REQUEST_METHOD)) {
case "GET":
return doGet(filename);
default:
throw new HTTPException(405);
}
}
private DataSource doGet(String filename) {
FileDataSource fds = new FileDataSource(filename);
MimetypesFileTypeMap mtftm = new MimetypesFileTypeMap();
mtftm.addMimeTypes("image/jpeg jpg");
fds.setFileTypeMap(mtftm);
return fds;
}

Related

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.

Best practices for method types in JAX-RS

What are the best practices regarding the method types in JAX-RS ?
I am interested in the following methods: GET, POST, PUT and DELETE.
My possible approaches:
GET - always return a response.
#GET
#Path("/path/{something}")
public T getT() {
...
return t; // t - instance of T
}
POST
#POST
#Path("/path")
public T/void createOrUpdate() {
...
return t; // t - instance of T
}
Q: Is it better to return the entire created resource or just an "ACK response" or to have a void method? What about a POST that is used as GET (when we want to avoid the URL length limitation)?
PUT
#PUT
#Path("/path")
public T/void createOrUpdate() {
...
return t; // t - instance of T
}
Q: Is it better to have a void method or a response for the created/updated resource or different responses for creation / update or just an ACK response ?
DELETE
#DELETE
#Path("/path/{something}")
public T/void deleteT() {
...
return t; // t - instance of T
}
Q: Is is better to have a void method or to return the deleted resource or to return an ACK response ?
Is it ok to always have T = javax.ws.rs.core.Response (when T is used)?
I saw that:
Lars Vogel uses GET - T, POST - void, PUT - T, DELETE - void
Oracle uses GET - T, POST - T/void, DELETE - void
JAX-RS is a specification for developing RESTful Web Services with Java. There is a reference implementation that is included in Java EE but since it is a specification, other frameworks can be written to implement the spec, and that includes Jersey, Resteasy, and others.
JAX-RS as such does not lay down any guidelines on the return types and response codes for the REST API's. However, there are a few guidelines (these are not hard and fast rules) in the REST standard which you might want to follow:
Method GET
Successful Response RETURN the resource with 200 OK
Failure Response RETURN appropriate response code
Method POST
Successful Response RETURN the link to the newly created resource in Location response header with 201 status code
Failure Response RETURN appropriate response code
Method PUT
Successful Response RETURN the updated resource representation with 200 OK or return nothing with 204 status code
Failure Response RETURN appropriate response code
Method DELETE
Successful Response RETURN nothing with 200 or 204 status code
Failure Response RETURN appropriate response code
In practice, POST works well for creating resources. The URL of the newly created resource should be returned in the Location response header. PUT should be used for updating a resource completely. Please understand that these are the best practices when designing a RESTful API. HTTP specification as such does not restrict using PUT/POST with a few restrictions for creating/updating resources. Take a look at Twitter REST API best practices that summarizes the best practices for RESTful API's.
This answer is not correct/up to date. Please check #ROMANIA_engineer answer instead.
You should never return void. The best practice is to always return a javax.ws.rs.core.Response. But note that even if you define the webresource with void, your server will return a HTTP response.
On POST and PUT, it may be better to return the modified resource, including its id. Some front-end framework and/or middleware will use it to synchronise the resource with your server (as instance, see Backbone Model).
On DELETE, it depends of the action you try to achieve.. But usually an ACK is enough.
NB : Anyway, whatever you return, don't forget to respect your security policies !
Response #Atul : When you send HTTP Request from client or HTTP Response from your server, some data may be protected. As instances :
On user update (username, password, or anything else) do not return the user password in the HTTP Response.
When user log in, you better use a HTTPS protocol and never send the password in plaintext
.. etc
I give it a shot and state a "no there is no best practice". This because the underlying protocol (HTTP) actually has return values (such as 200-OK, 500-Internal Error...) in any case unless a broken connection which should be followed by your service as well.
Since you are not implementing the HTTP-Protocol but a own-designed service following its own rules, no there is no best practice, you will have to define "your protocol" in a way it matches your day to day business the best.
For example when it comes to your delete operation a caller could either not be interested in a response at all or as well expect you to work like a stack and return him the "deleted/removed" element on call. It is up to you to know what fits your needs best.

Jersey web service proxy

I am trying to implement a web service that proxies another service that I want to hide from external users of the API. Basically I want to play the middle man to have ability to add functionality to the hidden api which is solr.
I have to following code:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection,
#Context Request request) {
//extract URL params
//update URL to target internal web service
//put body from incoming request to outgoing request
//send request and relay response back to original requestor
}
I know that I need to rewrite the URL to point to the internally available service adding the parameters coming from either the URL or the body.
This is where I am confused how can I access the original request body and pass it to the internal web service without having to unmarshall the content? Request object does not seem to give me the methods to performs those actions.
I am looking for Objects I should be using with potential methods that would help me. I would also like to get some documentation if someone knows any I have not really found anything targeting similar or portable behaviour.
Per section 4.2.4 of the JSR-311 spec, all JAX-RS implementations must provide access to the request body as byte[], String, or InputStream.
You can use UriInfo to get information on the query parameters. It would look something like this:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection, #Context UriInfo info, InputStream inputStream)
{
String fullPath = info.getAbsolutePath().toASCIIString();
System.out.println("full request path: " + fullPath);
// query params are also available from a map. query params can be repeated,
// so the Map values are actually Lists. getFirst is a convenience method
// to get the value of the first occurrence of a given query param
String foo = info.getQueryParameters().getFirst("bar");
// do the rewrite...
String newURL = SomeOtherClass.rewrite(fullPath);
// the InputStream will have the body of the request. use your favorite
// HTTP client to make the request to Solr.
String solrResponse = SomeHttpLibrary.post(newURL, inputStream);
// send the response back to the client
return Response.ok(solrResponse).build();
One other thought. It looks like you're simply rewriting the requests and passing through to Solr. There are a few others ways that you could do this.
If you happen to have a web server in front of your Java app server or Servlet container, you could potentially accomplish your task without writing any Java code. Unless the rewrite conditions were extremely complex, my personal preference would be to try doing this with Apache mod_proxy and mod_rewrite.
There are also libraries for Java available that will rewrite URLs after they hit the app server but before they reach your code. For instance, https://code.google.com/p/urlrewritefilter/. With something like that, you'd only need to write a very simple method that invoked Solr because the URL would be rewritten before it hits your REST resource. For the record, I haven't actually tried using that particular library with Jersey.
1/ for the question of the gateway taht will hide the database or index, I would rather use and endpoint that is configured with #Path({regex}) (instead of rebuilding a regexp analyser in your endpoint) .
Use this regex directly in the #path, this is a good practice.
Please take a look at another post that is close to this : #Path and regular expression (Jersey/REST)
for exemple you can have regexp like this one :
#Path("/user/{name : [a-zA-Z][a-zA-Z_0-9]}")
2/ Second point in order to process all the request from one endpoint, you will need to have a dynamic parameter. I would use a MultivaluedMap that gives you the possibility to add params to the request without modifying your endpoint :
#POST
#Path("/search")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({"application/json"})
public Response search( MultivaluedMap<String, String> params ) {
// perform search operations
return search( params);
}
3/ My 3rd advice is Reuse : make economy and economy make fewer bugs.
it's such a pitty to rewrite a rest api in order to perform solr search. You can hide the params and the endpoint, but could be great to keep the solr uri Rest formatting of the params in order to reuse all the search logic of solr directly in your api. This will make you perform a great economy in code even if you hide your solr instance behind you REST GATEWAY SERVER.
in this case you can imagine :
1. receive a query in search gateway endpoint
2. Transform the query to add your params, controls...
3. execute the REST query on solr (behind your gateway).

GWT RPC security, http header, authentication and requestbuilder

I am presuming that GWT RPC actually uses RequestBuilder.
Is there a way to extract the RequestBuilder instance used by my RPC service async requestor?
Actually, my question is, how do you extract the RequestBuilder instance to insert the authentication token as a http header? Is there a way to insert http headers into an RPC service request?
Even if I could insert a http header into the request, how then would the remote servlet be told to expect that auth token? Therefore, in fact, does GWT RPC provide a framework for secure authentication at all?
I am thinking the answer is NO, or at least not in a convenient way. Am I right?
I am coming from having used RestEasy in combination with RestyGWT over SSL, where we can insert headers anytime we wish. BTW, RestyGWT constructs its request to use RequestBuilder.
My actual motivation is comparing the security effectiveness between GWT RPC and GWT JAX-RS (RestyGWT + RestEasy). So if you, as the answerer, have an alternative detailed discourse comparing the security effectiveness of RPC with direct use of RequestBuilder or REST (rather than answering this question directly) please feel free to elaborate.
Am I right to presume that GWT RPC is not security friendly/effective and I should avoid using GWT RPC for secure authenticated requests?
You can have your async method return a Request or a RequestBuilder instead of void. Request allows you to abort() a pending request, whereas RequestBuilder allows you to modify the request before its sent (if you declare the return-type as RequestBuilder, you're responsible for calling send() to actually make the request).
Alternately, you can use an RpcRequestBuilder to customize the RequestBuilder for each and every call made with a specific async service proxy.
As far as I know there is no built in security solution for gwt rpc.
But If I need such authentication I would make the following steps:
1) To be able to set http headers you can make your custom request builder, as I do myself:
MyServiceAsync myService = GWT.create(MyService.class);
MyRequestBuilder myRequestBuilder = new MyRequestBuilder();
myRequestBuilder.addHeader("header", "value");
((ServiceDefTarget) serviceInstance).setRpcRequestBuilder(myRequestBuilder);
MyRequestBuilder extends RpcRequestBuilder. And inside MyRequestBuilder I override method doFinish(RequestBuilder rb) where I put my headers.
Maybe it is not a super solution, but I haven't yet found anything better.
2) For the server side I would implement the AuthenticationFilter for checking the headers and perform server side auth functions prior calling the Servlet.

How to distinguish what format a client requests back to my REST webservice?

I have a Java WebService setup which consumes an xml file and want to be able to produce either xml or json based on what the client requests. I know that this is possible through reading up on Jersey REST methods but it does not show how to extract this information. I have also looked on google all over but can't seem to find any examples of this.
http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features is the site that I was initially referencing which shows that it is possible, I was just wondering if anyone would be able to help me find out how to actually distinguish the client's request. Is it in the html header? body? And if so what is the proper way to extract it?
This is what my method currently looks like, I do not have any issues with connection, just finding out what the client requests as a return type.
#POST
#Path("getStatisticData")
#Produces ({"application/xml","application/json"})
#Consumes ("application/xml")
public String getStatisticData(#FormParam("xmlCoords") String xmlFile) throws Exception{
Thanks in advance.
You can extract it using the #HeaderParam annotation:
...
public String getStatisticData(#HeaderParam("Accept") String accept,
#FormParam("xmlCoords") String xmlFile) throws Exception {
...
}
The Accept header in the request is used for the client to indicate to the server what methods it supports.
If the client can set HTTP headers, the proper way to do it is to use the Accept header:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
IF this is not possible, the type requested could be passed in as an argument.
Alternatively, expose two different web services: one that returns XML, one that returns JSON. Each web service would call the same code but with a parameter specifying which format to use.

Categories