Http Response Header in java - java

Hi I am sending Http Request using HttpClient . I am able to call the Servlet but returning 405 status code.doPost method not allowed . tried get also same status code.
And also i am not able to get The Header in response. Do i need to forward or include the request back to Request.
//Code to Send Http Request
public void perform(Date now, long remainingRepetitions)
{
log.info("Starting the Job " + now);
System.out.println("Before try 2");
try {
HttpResponse response;
while(true){
HttpClient client = new DefaultHttpClient();
System.out.println("Http Client instantiated");
HttpPost request = new HttpPost("http://localhost:8080/Servlet");
System.out.println("Post Request created");
response = client.execute(request);
System.out.println("Http Status Code = " + response.getStatusLine().getStatusCode() );
Header headers[] = response.getAllHeaders();
for(Header h:headers){
System.out.println("New" +h.getName() + ": " + h.getValue());
}
if(response.getStatusLine().getStatusCode()==200 || response.getStatusLine().getStatusCode()== 405){
if(response.getLastHeader("JobStatus").equals("Success"))
{
break;
}
}
client.getConnectionManager().shutdown();
Thread.sleep(10000);
}
} catch (ClientProtocolException e) {
log.info(e);
} catch (IOException e) {
log.info(e);
} catch (Exception e) {
// TODO Auto-generated catch block
log.info("Exception Occured");
e.printStackTrace();
}finally{
System.out.println("finally");
}
// Servlet
private void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("Inside ProcessReqest");
try{
//some method call
resp.addHeader("JobStatus", "Success");
}catch(Exception e){
resp.addHeader("JobStatus", "Failure");
}
}

It sounds like your server doesn't support the POST method. Try using a HttpGet request instead.
POST is used to send data to a server, whereas GET is used to request information. Your code is not attempting to send any data, so I think HttpGet is what you want.
http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/methods/HttpGet.html

If this is code both from your client and servlet, the doPost method is private, hence you're servlet will not respond to POST requests. Make your doPost method public.

I think you should change the access modifier in your post method from private. This is why it is not visible. Change the modifier to either protected or public
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("Inside ProcessReqest");
try{
//some method call
resp.addHeader("JobStatus", "Success");
}catch(Exception e){
resp.addHeader("JobStatus", "Failure");
}
}

I think the Servlet implements only doGet(). When you are calling POST method, either doPost() or service() method should be implemented by the servlet.
By default, when the servlet's service method is called, it calls the corresponding doXXX() method. If that method is not implemented by the subclass of HttpServlet, the doXXX() method in HttpServlet returns 405 Method Not Supported status code.
The snippet of doPost() method in HttpServlet is below:
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_put_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
I think in your case, you have declared doPost() method as private. It's access is hidden. Modify it as protected and try.
It is not correct to have weaker access in subclass. Usually, the compiler should have given error when you compiled that servlet.

the problem is that the headers added with
HttpServletResponse.setHeader(...)
or
HttpServletResponse.addtHeader(...)
are "servlet response headers", not "HTTP headers".
So among them you find also the http headers, but what you set is not received by the client together with them.
I suggest you to use URL parameters instead of headers.

Related

Does a HttpServlet have to respond to a request?

I have several servlets that do things server side. On a few I just encode some unnecessary data and send it back, which seems pointless. Do you have to respond ? What happens when you just say return ? I've done that before and nothing seems to go wrong but I am relatively new to servlets. Are there consequences for simply returning that go above my head ? And what exactly happens when you return;
if(request.getParameter("name").equals("saveusedcards")) {
String sessId = request.getSession().getId();
//encode request with confirmation that cards were successfully updated
if(usersUpdatedCards.get(sessId).isEmpty()){
//no cards were seen
}
boolean success = DataDAO.updateCards(usersUpdatedCards.get(sessId));
if(success){
System.out.println("Data base update successfull!");
String responseMessage = new Gson().toJson("card successfully udpated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
} else {
System.out.println("Data base update failed...");
String responseMessage = new Gson().toJson("card was not successfully updated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
}
}
The servlet must produce an HTTP response for the client, however it is perfectly acceptable to return no content in the response body. When doing so your servlet should make this clear to the client by sending a response code of 204 (no content). Reference: https://httpstatuses.com/204
Here is an example of how you would set the response code from the doGet method. You could do the same from doPost or service methods.
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// Do whatever work you need to do here...
res.setStatus(HttpServletResponse. SC_NO_CONTENT); // This returns a 204
}

AsyncInvoker not releasing the Thread

I am using AsyncInvoker using Jersey 2.0. This works fine for me. However, thread is not ending after completion of the return. Please note that I don't expect any response for the services I call.
public Future<Response> fire(WebTarget webTarget) {
Future<Response> response = null;
try {
response = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
.accept(MediaType.APPLICATION_JSON_TYPE)
.headers(headers)
.async().get();
}
catch (Exception e) {
e.printStackTrace();
}
return response;
}
As long as you don't do anything with the actual javax.ws.rs.core.Response that is provided to you once the future value resolves, the request response stream is kept open (and the thread associated with it the raw HTTP request as wel I guess). You should either:
Do something with the javax.ws.rs.core.Response object and close it (or it's stream).
Use .get(MyPojo.class) to have the response steam converted into an actual object. This will close the stream for you and resolve a MyPojo instance in the future instead.
You need to close your client object that you created in the calling method. In the calling method you would have something like below -
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target(SERVER_URL).path(API_PATH).path(String.valueOf(id));
fire(webTarget);
So you need to close your client after calling this method -
client.close()
However, the recommended way of closing client is after receiving response. Something like below -
public void fire(WebTarget webTarget) {
try {
webTarget.request(MediaType.APPLICATION_JSON_TYPE)
.accept(MediaType.APPLICATION_JSON_TYPE)
.headers(headers)
.async().get(new InvocationCallback<Response>() {
#Override
public void completed(Response response) {
// Do whatever your wish with response
client.close();
}
#Override
public void failed(Throwable throwable) {
throwable.printStackTrace();
client.close();
}
});
}
catch (Exception e) {
e.printStackTrace();
}
}

What is the behaviour of getParameter for post and get actions?

I have a java servlet with a URL Query string with instructions like this
http://hostname/servet?param1=value1&param2=value2
I also structure the doPost/doGet like this
public void doPost(HttpServletRequest req, HttpServletResponse res) {
try {
doGet(req, res);
} catch (Exception e) {
e.printStackTrace();
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res) {
try {
String sParam1 = req.getParameter("param1")
} catch (Exception e) {
e.printStackTrace();
}
}
I can access each queryString parameters via getParameter() for GET actions. But when I attempt to access the same queryString via getParameter() for POST actions, the returned value is NULL.
So, I would like to confirm this behaviour of getParameter for POST and GET actions. That is getParameter does NOT return queryString parameters for POST actions ? And do I need to manually dissect a query string to process them in cases of a POST action ?
For GET method, parameters are sent as part of the URL (the query string), for POST method parameters are sent as part of the body, that's why in the POST case you don't get the parameters, as they are searched in the body not in the URL.
do I need to manually dissect a query string to process them in cases of a POST action ?
Yes, if you are in the case where you are sending a query string but using method POST, you'll have to parse the query string by yourself, unless you honor the standards and send parameters inside the body rather than in the URL.

GWT HTTP request response code 0 with CORS working

I am using GWT 2.4 to build an application that runs entirely client-side and uses a web service that I control but is hosted on a different server. On this Java Servlet web service, I have implemented doOptions like so:
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET");
}
And client-side in GWT I submit a request the standard way, e.g.
public static void makeHttpGetRequest(String query, RequestCallback callback) {
String url = "http://example.webservice.com/endpoint" + "?q=" + query;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url));
try {
builder.sendRequest(query, callback);
} catch (RequestException e) {
Window.alert("Server encountered an error: \n" + e.getMessage());
e.printStackTrace();
}
}
And then my callback implements onResponseReceived like this:
#Override
public void onResponseReceived(Request request, Response response) {
if (response.getStatusCode() == 200) {
System.out.println("HTTP request successful, received "
+ response.getText());
processResponse(response.getText());
} else {
System.out.println("HTTP error code " +
response.getStatusCode() + ":" +
response.getStatusText());
}
}
Whenever I run the application in late versions of Chrome or Firefox and send a request, onResponseReceived is called but the response code is 0 and there is no error message. Research indicates that most other instances of this problem arise from SOP restrictions. However, when looking at the HTTP traffic in Fiddler I see that when this is executed, the browser is indeed sending the expected HTTP request, and the web service is indeed returning the expected response, with a 200 response code. Somehow, the browser just isn't handling it properly.
Update: when I look at the traffic in Fiddler, it indicates that the request is sent and a response is received, but when I look at the same request in Chrome's developer console it shows that the request is 'canceled'. If the request is actually happening, what does that mean in this context?
Has anyone run across this problem? Any suggestions on what may be going on?
Error code 0 means that the CORS has been aborted, check that your servlet implementation is all right, I think you have to send Allow instead of Access-Control-Allow-Methods, and also you have to add the Access-Control-Allow-Headers since GWT adds extra headers to ajax requests.
Try this implementation from the gwt-query example which works fine:
private static final String ALLOWED_DOMAINS_REGEXP = ".*";
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String origin = req.getHeader("Origin");
if (origin != null && origin.matches(ALLOWED_DOMAINS_REGEXP)) {
resp.addHeader("Access-Control-Allow-Origin", origin);
resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
if (origin != null) {
String headers = req.getHeader("Access-Control-Request-Headers");
String method = req.getHeader("Access-Control-Request-Method");
resp.addHeader("Access-Control-Allow-Methods", method);
resp.addHeader("Access-Control-Allow-Headers", headers);
resp.setContentType("text/plain");
}
}
I would rather a filter instead a servlet, like in the link above is explained, though.

Sending bytes via a servlet, getting " HTTP method GET is not supported by this URL"

I have the following code...
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
final int idValue = Integer.parseInt(req.getParameter("id"));
final ProjectRunEntity projectRunEntity = projectDataService.findProjectRunEntity(idValue);
try {
final byte[] documentAsBytes = wordFileGenerationService.getDocumentAsBytes(projectRunEntity);
resp.setContentType("application/msword");
resp.setHeader("Content-Disposition", "inline; filename=example.doc;");
final ServletOutputStream out = resp.getOutputStream();
out.write(documentAsBytes);
out.flush();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Which gets some bytes which happen to be a word document and write them to the servlet response. For some reason I get the following message in my browser when I hit the url...
"HTTP Status 405 - HTTP method GET is
not supported by this URL"
I am on Tomcat 6. Any ideas? I know that nothing is breaking in my debugger, the bytes are being written to the outputstream of the response.
I guess the error is thrown by the default doGet implementation (when you call super.doGet(req, resp)).
That status is set in super.doGet(...). Please remove that call.
the do{Http-Method} methods are meant to be overridden. And their default implementation is "not supported". No need to call the super.do{http-Method}
I just had to remove this line...
super.doGet(req, resp);

Categories

Resources