I am using Jetty web server, and Jersey for REST handling.
I defined:
#POST
#Path("/sendMessage")
#Consumes ({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
public Response sendMessage(#Context final UriInfo uriInfo)
{
logger.debug("sendMessage:");
System.out.println("Received POST!");
return Response.status(Response.Status.OK).build();
}
However, when I send a http request, http://localhost:8080/hqsim/sendMessage, the server returns a 415 code.
It's like the call is not allowed. How can I fix this error?
415 means that the media type is unsupported.
The most likely case is that you are either missing the Content-Type header in your request, or it's incorrect. In your case it must be application/xml or text/xml.
If you're using axios, and making;
a) A post request, you should define the request as below
await axios.post("the url you're speaking to",
{the data to post},
{
headers: {"Content-Type": "application/json"}
})
b) A get request;
await axios.get("the url you're speaking to",
{
data: {},
headers: {"Content-Type": "application/json"},
params: {'varX': '34'}
})
where varX is the name of the variable you're sending together with the request
params can as well be empty if you're not sending a query string along.
the url would therefore appear as;
https://myurl.com/?varX=34
Related
I have issue in my application. I have various REST enpoints which are working fine. But now I want to send POST request with body. I already have 2 endpoints for POST method, but data are send using PathParam.
I created new endpoint, but when I send request I am getting CORS error. When I use the same endpoint without body in request everything is okay but of course at backend side I do not get any data from frontend (I have breakpoint inside method).
this is how I send request from my angular application:
post(requestUrl: string, body?: any): Observable<any> {
return this.httpClient.post<any>(this.API_URL + requestUrl, {password: 'test'});
}
After sending request I got:
Access to XMLHttpRequest at 'http://localhost:8080/...' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If I send request like this (without body) this endpoint works fine:
post(requestUrl: string, body?: any): Observable<any> {
return this.httpClient.post<any>(this.API_URL + requestUrl);
}
At backend side I have added settings for CORS:
return Response.ok(object).header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.allow("OPTIONS").build();
When I am sending request from Insomnia everything is ok - I can send body and I am getting sent data on backend.
Should I somehow set request headers at frontend side?
Here is my AdminApiController class:
#Path("/admin")
#RequestScoped
public class AdminApiController extends BaseApiController {
#Inject
private AdminAssembler adminAssembler;
#POST
#Path("/login")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response login(LoginRequest request) {
return Response.ok(adminAssembler.login(request))
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.header("Access-Control-Allow-Headers", "Content-Type")
.allow("OPTIONS").build();
}
}
When your angular application sends a JSON payload in a POST request, it probably adds the header Content-Type: application/json. This header classifies the POST request as a "non-simple" request (that is, a request that cannot result out of an HTML <form> element without additional Javascript). Such "non-simple" requests cause to browser to make a preceding preflight request, that is an OPTIONS request with headers
Origin: http://localhost:4200
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
to which the server must respond with an Access-Control-Allow-Origin header and Access-Control-Allow-Headers: Content-Type. If it does not, the browser will not make the POST request and show an error like you observed.
Your Java code covers only #POST, not #OPTIONS, that's why the server does not respond to the preflight request with the necessary headers. How best to handle the OPTIONS requests for all endpoints on your server is a question for Java experts (which I am not).
You need to define your httpOptions.
Try this.
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
post(requestUrl: string, body?: any): Observable<any> {
this.httpClient.post<any>(this.API_URL + requestUrl, {password: 'test'}, this.httpOptions)
}
Let me know if it worked for you.
I have a simple java web service deployed(say /diagnosis). When i hit the URL(/diagnosis) i am getting the JSON output. When i try to hit the rest service(/diagnosis) through Angular JS i am getting:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4201' is therefore not allowed access. The response had HTTP status code 500.
My Java code is:
#GET
#Path("/DiagnosisSortProviderCost")
#Produces(MediaType.APPLICATION_JSON)
public Response DiagnosisSortProviderCost() throws Exception {
// String path_name = "C:\\Users\\526761\\Desktop\\PioDel\\";
JSONArray jsonArr = jsonread.json_extract_provider(path_name);
System.out.println("--");
System.out.println(jsonArr);
Response response = Response.status(200).entity(jsonread.pro_DiagProvCost(jsonArr))
.header("Access-Control-Allow-Origin", "*").build();
return response;
}
I added the code to resolve CORS Filter issue, i even replaced the * with IP and port. Yet i couldn't get the issue resolved.
Please help me!!!
#GET
#Path("/DiagnosisSortProviderCost")
#Produces(MediaType.APPLICATION_JSON)
Because your mapping will never work. It only support GET method, in case of different http method like OPTIONS (for CORS), it will not serve.
All browser will send OPTIONS firstly to detect which method is allowed before sending actually request. If OPTIONS is not support or http method is not supported, browser will prevent it.
Change it to #RequestMaping with method option: The HTTP request methods to map to, narrowing the primary mapping: GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
Is it possible to send two different Content-Type for POST method using post-man? Like, if the service is used for downloading excel file so in that case, #Consumes(MediaType.APPLICATION_JSON) is used for sending some user detail which is json structure and #Produces(MediaType.APPLICATION_OCTET_STREAM) is used for sending back the response as file.
NOTE: I don't want to use form-data, that is a constraint for this service.
On the client request, the Content-Type header is only for the type of data that is in the entity body. The Accept header is what you send for the type of data you want back.
On the server side, it is perfectly fine to do the following.
#POST
#Path("something")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response post(Model model) throws Exception {
final InputStream in = new FileInputStream("path-to-file");
StreamingOutput entity = new StreamingOutput() {
#Override
public void write(OutputStream out) {
IOUtils.copy(in, out);
out.flush();
}
};
return Response.ok(entity)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=somefile.xls")
.build();
}
The request to this endpoint should look like
POST /api/something HTTP 1.1
Content-Type: application/json;charset=utf-8
Accept: application/octet-stream
{"the":"json", "entity":"body"}
See also:
This post about purpose of #Produces and #Consumes and the role they play in content negotiation.
Aside
As an aside, consider using application/vnd.ms-excel as the Content-Type instead of application/octet-stream. This is already the standard MIME type for Microsoft Excel files1. When using StreamingOutput as the response entity type, you can make the #Produces anything you want, as there is no real conversion needed.
In Postman, when you use the "Send and download" feature, you will notice that when the Content-Type is application/octet-stream, it will suggest the file extension of .bin when saving the file. But if you have the Content-Type as application/vnd.ms-excel, then the suggested extension is .xls, which is what it should be.
1. Incomplete list of MIME types
Here is my code :
#RequestMapping(value = "/report/download", method = RequestMethod.GET,produces="application/vnd.ms-excel")
public Response getReportFile(#QueryParam("reportid") Long reportId)
{
System.out.println("Param"+reportId);
Long n=(long) 10;
String json=reportService.getReportFile(n);
File file = new File("D:\\Agent Information.xls");
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition","attachment; filename=Sample.xls");
return response.build();
}
i am getting the below Error in java console: Handler execution resulted in exception: Could not find acceptable representation
Your webservice is saying that the response type it is returning is not provided in the Accept HTTP header in your Client request.
So while making HTTP Request you have to add 'Accept Headers' . If it's JSON request then you will add 'Accept : application/json'. Similarly for your current example it will be
'Accept: text/plain'
'Accept-Charset: utf-8'
Find all accept headers here. And follow this steps to resolve
1) Find out the response (content type) returned by web service.
2) Provide this (content type) in your request Accept header.
Here is my java.net client code
URL server = new URL(serverUrl);
URLConnection connection = server.openConnection();
/* DoOutput flag is set to true to inform URL connection that we are
* sending data out. The default behavior is false. This will change
* the request from GET to a POST.
*/
connection.setDoOutput (true);
/* Setting the UseCaches to false allows the application "tunnel
* through" and ignore the caches.
*/
connection.setUseCaches (false);
connection.setRequestProperty ( "Content-Type", "application/octet-stream" );
ObjectOutputStream sendData = new ObjectOutputStream(connection.getOutputStream());
sendData.writeObject(packet);
sendData.flush();
sendData.close();
ObjectInputStream recieveData = new ObjectInputStream(connection.getInputStream());
response = (Serializable) recieveData.readObject();
System.out.println(response);
recieveData.close();
And this is my server code with spring to receive the request and send back response
#ResponseBody
#RequestMapping(value="/upload", method=RequestMethod.POST)
public Serializable fileUploadHandler(#RequestBody FilePacket packet, HttpServletRequest request, HttpSession session, HttpServletResponse response){
// handle request
return "response";
}
While running the code with above configuration, upon sending the request to server, I get Http error 415
java.io.IOException: Server returned HTTP response code: 415 for URL:
I removed #RequestBody and replaced it with
FilePacket packet = (FilePacket) new ObjectInputStream(request.getInputStream()).readObject();
and the request part was good. But then after a request I got the 406
java.io.IOException: Server returned HTTP response code: 415 for URL:
and so I replaced #ResponseBody with
new ObjectOutputStream(response.getOutputStream()).writeObject("response");
and then everything was good.
I've used these annotations with ajax and they work like charm but with java.net , I'm getting unsupported media type (415) and not acceptable (406). Is spring not able to read the request and send proper response or I'm missing something here? Is there a way to make it work?
Note: The class FilePacket is Serializable, one of whose fields is of type byte[] which holds the file data.
Spring uses a collection of HttpMessageConverter instances to deserialize request bodies into arguments it will pass to your handler method.
Spring does not have a such a HttpMessageConverter which converts application/octet-stream to your custom FilePacket class. You could instead use byte[] and do the conversion yourself (or provide your own HttpMessageConverter to do it).
Spring uses the same tactic for #ResponseBody, using these same HttpMessageConverter instances for serializing an object returned to the response body. It has nothing built-in which uses Java Serialization. Note that for most, if not all, of these response types, your client needs to provide an explicit Accept: header to specify what it accepts.