Post request to Jersey from Laravel - java

I have a simple REST API created with Jersey on Glassfish server.
On the other hand, I have a Laravel application that uses this API. Now, I have several GET routes on Jersey app, and this works with no problem. I used it with curl and everything went well.
At the end, I have one post request that I should send. Form consists of about 50 fields, and I'm not sure how to triger it.
When I put the url to post method into form action attribute, I get this message
HTTP Status 415 - Unsupported Media Type
I have tried with
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
And with
#Consumes(MediaType.APPLICATION_JSON)
And I get the same error with both

I haven't done this but it, but be sure to include the form parameters in the method signature
#POST
#Consumes("application/x-www-form-urlencoded")
public void post(#FormParam("name") String name) {
// Store the message
}
as described here

Related

Feign Client Call(to a http service) is converted from GET request to POST when the call is made in runtime

I was trying to call a http GET service through feign client but I see the request being converted into POST before the call is made.
Without header the Get call works fine(I meant gives a 401 instead 404), the header content is expected by http service I'm trying to call, so cannot remove the header.
#FeignClient(name="commonservice")
#Path("/company/service/module")
public interface getCaseInfo{
#GET
#Path("/endpointURI/{pathparam}")
public ResponseObject getCaseDetails(#PathParam("pathparam") String param, #RequestHeader Map<String,String> header) throws exception
}
/TRIED #HeaderParam Annotation as well/
The feign client call has to be made as GET request with Headers
I was able to resolve the issue by using #headerparam for each of the custom header parameter I had. But it would still keep doing that GET to POST, if i use:
"#Headerparam/#HeaderMap Map headers"
Updated code:
public ResponseObject getCaseDetails(#PathParam("pathparam") String param, #HeaderParam("custom_header1") String custom_header1,#HeaderParam("custom_header2") String custom_header2)
If someone can give me the reason on why a map wouldn't work, that would be great!

ResponseEntity body lost between two webservice calls

I have a webservice which calls another WS and returns the response from the second WS. It looks like so:
// MyController
public ResponseEntity<Foo> requestFooController(#RequestBody #Valid Bar request) {
return this.myService.requestFooService(request);
}
//MyService
ResponseEntity<Foo> requestFooService(Bar request) {
Buzz improvedRequest = ...
return this.secondWS.secondRequestFoo(improvedRequest);
}
When I call the API through Postman, I receive a HTTP OK response with an empty body. Yet, when I'm in debug mode I can see that the service is returning a ResponseEntity with a body. The headers are not lost though.
I changed my code like so and it works fine:
// MyController
public ResponseEntity<Foo> requestFooController(#RequestBody #Valid Bar request) {
ResponseEntity<Foo> tmp = this.myService.requestFooService(request);
return ResponseEntity.status(tmp.getStatusCode()).body(tmp.getBody());
}
Now through Postman I do have the expected body. However, I don't understand the behaviour. I thought that maybe it's due to the fact that the body is some kind of stream that can be read once or something similar. But from reading the source code I don't see anything that could explain this behaviour.
I'm using the Netflix-stack (so HTTP calls between the two WS are made through a Feign client).
Any idea why I'm getting this result?
EDIT:
More details on my stask:
SpringBoot 1.5.3.RELEASE
Feign 2.0.5
There is a bug that causes the named body of an HTTP MultiPart POST to fail. The symptom of this is that you make a POST request with a body, and Spring-Boot can't match it up to an endoint. The exception I see is:
2019-01-23 15:22:45.046 DEBUG 1639 --- [io-8080-exec-10] .w.s.m.m.a.ServletInvocableHandlerMethod : Failed to resolve argument 3 of type 'org.springframework.web.multipart.MultipartFile'
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
Zuul is doing caching of the request in order to re-try multiple times. In this process, it fails to preserve the named field for the binary body. You may find it working if you preface the request with zuul. So instead of http://myserver.com/myservice/endpoint use zuul in the path: http://myserver.com/zuul/myservice/endpoint
That will effectively avoid the saving of the request and the retry mechanism.
More details are available on this issue in Zuul's GitHub Bug List.

Jax-RS consume ANY Content-Type

I have a REST channel with POST method for uploading a binary content. This can be anything.
The method body is as follows:
#POST
#Path("/")
public Response upload(#Context HttpServletRequest httpRequest) {
It has worked when the client has not set Content-Type header, however if he set it, for example, to application/xml, an error occured:
Unsupported Media Type</pre></p><hr>Powered by Jetty:// 9.3.15.v20161220
I've tried adding wildcard:
#Consumes(MediaType.WILDCARD)
however, it still produces the same error.
How can I make jax-rs to accept ANY content type? Or I'm simply using the wrong tool for my job? I've taken Jax-RS because it can consume beans instantiated by IoC frameworks like blueprint...

How to create RESTful web service client by Jersey2.0 or above

There seems to be many examples about creating RESTful clients by Jersey 1.x, but not Jersey 2.0 or above.
I referred to other questions and the Jersey's web site, but I still cannot create a client for REST due to the differences between Jersey 2.0 and the previous one.
So I'd like to ask some advice.
So far, my coding is like this.
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target("http://localhost:8080/CustomerBack2211/webresources/entities.customer");
Invocation.Builder invocationBuilder = target.request(MediaType.TEXT_XML_TYPE);
Response response = invocationBuilder.get();
System.out.println(response.getStatus());
System.out.println(response.readEntity(String.class));
This produces 406 error.
However, when I tried to test RESTful service by Glassfish server, the test works properly, and the server side class has its #GET methods having #Produces({"application/xml", "application/json"}).
So I don't see why the coding above produces 406 error on a Java application.
(i.e. the client side has #GET methods in the following way)
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public Customer find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Override
#Produces({ "application/xml"})
public List<Customer> findAll() {
return super.findAll();
}
Does any of you see what I'm doing wrong, or could you please suggest an example of a RESTful client?
Any advice will be helpful...thanks in advance!
In addition, I'd appreciate if you would offer information about how to invoke methods like GET, PUT and DELETE with appropriate parameters.
I just needed to put an ID number (i.e. integer values) when I was testing the server side class on Glassfish RESTful test. However, it seems that I need to set "Class" and/or "Entity" values as arguments, but I cannot see any information associated with them on the Jersey website.
For the first block of code:
406 means Not Acceptable.
Look at your request() method target.request(MediaType.TEXT_XML_TYPE). From the Javadoc of request() if states
Invocation.Builder request(MediaType... acceptedResponseTypes)
Start building a request to the targeted web resource and define the accepted response media types.
Invoking this method is identical to:
webTarget.request().accept(types);
So basically, in your request, you are saying that you will only Accept: text/plain. Now look at your resource methods. Look at the #Produces. None of them "produce" text/plain. It's all json or xml. That's why you get the exception. Change the accept to application/xml (or MediaType.APPLICATION_XML) on the client side, and you should no longer get this error.
For the second question: I'm assuming you mean why does it work when you test it from the browser.
If you send a request from the browser by simply typing in the url, it will send out the request with many Accept types. If you have firebug (for FireFox) or the developer tools (for Chrome), if you send out a request, you will see a header similar to
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
You can see application/xml in there. Even if application/xml wasn't there, the wild card */* is there, so basically almost all media types are acceptable as a return type when working in the browser.
For your last question:
Look at the API for SyncInvoker, which Invocation.Builder extends from. You will see different overrloaded put and post methods, most of which, as you mentioned accept an Entity.
There are a few different ways to build an Entity, all of which use one of the static methods. Here are some
Entity.entity( body, mediaType )
Entity.json( body )
Entity.xml( body )
And many more (see the Entity link above). But all of these static method return an Entity. So we could do something like
// resource method
#POST
#Consumes(MediaType.APPLICATION_XML)
public Response getResponse(Customer customer) { ... }
// some model class
#XmlRootElement
public class Customer { ... }
// client request
Customer customer = new Customer();
Response response = target.request().post(Entity.xml(customer));
Internally, the Customer will get converted to XML. If you used Entity.json is would get converted to JSON, BUT you need to make sure you have a JSON provider dependency. Jersey will not come with one by default. See more at Support for Common Media Type Representations
Also note, with your method find, when you try and make a request to the method, the request should end with an integer value, as that's the type specified for the {id} path parameter.

HTTP Status 405 - Method Not Allowed Error on Invoking a DELETE method using WebServices

I am trying to delete a "Contact" from the "Contacts" table using the following #DELETE method (using Jersey Framework (JAX-RS implementation)
#DELETE
#Path("/delete/{contact}")
public String deleteContact(#PathParam("contact") String name) throws ClassNotFoundException, SQLException {
String response = DAOaccess.deleteContact(name);
return response;
}
And the following url is used to invoke the webservice from the browser:
/contacts/delete/contactname
But HTTP Status 405 - Method Not Allowed is thrown on doing so.
What might be the reason? How do I overcome this?
URL = /contacts/delete/contactname
405 because
It seems delete is always behave as submit (Post method)
and you are trying to call as like get method from the URL.
This is not possible to call the post method as like get.
if you really want to call this web service from the browser to test, just download a Mozilla plugin (Poster) which will help you to submit the web service in your all method types.
If you are using Firefox use this plugin to test your service. When you directly hit the URL from browser it goes as a #GET request which is not allowed in this case. RestClient is also available as standalone app. If you need more functionalities try SoapUI. I have also posted a response to your question on #DELETE.

Categories