verify connection in jersey - java

I want to be able to verify that the connection is still alive (client not dead) when sending a response from a Jersey (jax-rs) resource. The reason is that if I just return the response object and the client is dead, the response is lost without knowing that the client did not receive it.

httpContext.getResponse().setResponse(myResponse)
try {
httpContext.getResponse().getOutputStream().write(new byte[]{})
} catch (Exception e) {
// writing of headers failed.
}

Related

Java - HTTPS Basic authentification with Apache httpclient

I am trying to get some data (json data -> restful server) from a HTTPS server with basic authentification using the Apache httpclient. The SSL certificate is selfsigned.
The server is responding very well to a browser call and also when using curl.
However using the java Apache httpclient, that's another story.
Client side :
The basic authentification is working : the server sends me 401 errors if forget the authorization header or if I set the wrong base64 encoded login:password.
The https/SSL part is working : I am successfully getting data from online restful json server but sadly no way to find an online restful json server with basic authentification for testing purpose...
try {
CloseableHttpClient httpClient = null;
try {
httpClient = HttpClients.custom()
.setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.build()
)
)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
HttpGet getRequest = new HttpGet("https://localhost:5050/getdata");
getRequest.addHeader("Accept", "*/*");
getRequest.addHeader("Authorization", "Basic UBJ0aHVyOmFo0XElYHU=");
HttpResponse response = httpClient.execute(getRequest);
Debugging is telling me :
Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
True! It's not a valid HTTP response that I would like to get, it's a valid HTTPS response!
I guess that I am missing something...
Solved!
The error was from the server side : my response did not include any headers....
httpclient seems to like well made responses from a server. That's not true for a browser or for curl : garbage they can receive , display they will !

Send an error to appengine endpoint client

In my GAE endpoint, in my user register API method, I check whether a user already exists with the given username. If a user already exists, I need to send an error to the endpoint client.
Currently I throw an exception like below from endpoint.
User user = ofy().load().key(Key.create(User.class, username)).now();
if (user != null) {
throw new BadRequestException("Username already exists");
}
Then in endpoint client, I catch the exception like below.
try {
gaeEndpoint.registerUser(mEmail, mPassword).execute();
} catch (HttpResponseException e) {
mErrorMessage = e.getContent();
} catch (IOException e) {
mErrorMessage = "Failed to communicate with server. Please check your internet connection.";
}
When endpoint throws a BadRequestException, client gets HttpResponseException e and e.getContent() contains a json string including the error message string sent from endpoint. I need to parse json to get the actual error message sent from server.
Even though this works, I feel that there should be a better way to send an error message to the client from the endpoint. So, does anyone know a better (or a recommended) way of doing this?
I think you're doing everything right.
HTTP is designed to send a response with 4xx code and meaningful content to a user. It can be HTML for a browser, JSON for an api client or anything that can provide some context to the client.
If you're worried about using exceptions, that's fine too. Of course, you can prepare a response with a manually set status code, but that doesn't change anything, it's just more code. It's also less likely that you'll create a bug when you're using exceptions in this case.

Java "Broken Pipe" Error (using Unirest http wrapper)

I'm using the unirest http wrapper (http://unirest.io/java.html) in a Java application to send http post requests. Unfortunately I keep getting a "broken pipe" error:
com.mashape.unirest.http.exceptions.UnirestException: java.net.SocketException: Broken pipe
com.mashape.unirest.http.exceptions.UnirestException: java.net.SocketException: Broken pipe
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:145)
at com.mashape.unirest.request.BaseRequest.asString(BaseRequest.java:56)
The code I'm using to call it is as follows:
public static int doHTTPPostWithAdditionalHeaders(String data, String url, HashMap<String, String> additionalHeaders) {
try {
Unirest.setTimeouts(10000, 10000);
HttpResponse<String> jsonResponse = Unirest.post(url)
.headers(additionalHeaders)
.body(data)
.asString();
return jsonResponse.getStatus();
} catch (Exception e) {
System.out.println("doHTTPPostWithAdditionalHeaders failed: "+e.toString());
}
return 0;
}
It works most of the time but seems to fail when I'm hammering it with lots of requests. Have any of you got any ideas how I might solve this, or perhaps could you recommend a more robust solution? This post operation is mission critical to my application.
Looks like it was a simple case of the data I was posting being too large for the allocated timeouts.
Old
Unirest.setTimeouts(10000, 10000);
New
Unirest.setTimeouts(10000, 30000);

Throwing WebapplicationException from one webapp and getting UniformInterfaceException on other

I see a weird issue. I have two webapps. One for the rest webservice that we exposed using Jersey. Another has the JSF Front End implementation which calls above webservice to fetch the details. We are using Tomcat as a container.
The issue that i am facing is when i call a rest webservice, i throw WebApplicationException like this
catch (CustomExceptions e) {
ResponseBuilder response = new ResponseBuilderImpl();
response.status(500);
response.entity(e.getStackTrace());
throw new WebApplicationException(e, response.build());
}
And on the other hand on FE webapps, i do the following:
try {
r.get(MyClass.class);
return "SUCCESS";
} catch (WebApplicationException wae) {
return "FAILURE";
} catch (UniformInterfaceException wae) {
return "FAILURE";
}
Here in the catch block i was expecting the WebApplicationException but its throwing UniformInterfaceException which is weird. Also if it throws UniformInterfaceException, It does not maintain the stacktrace. Even the response that i passed in from rest call is lost. Can somebody help me how can i get the original stacktrace from the rest call?
Thanks in advance.
As specified in both the user guide and the api documentation, a UniformInterfaceException is the expected result when you attempt to retrieve a specific entity by type but receive a non-200-series response. The WebApplicationException is a convenience exception for your use on the server side to embed custom responses in an exception.
Nothing is "lost". Keep in mind you're making an HTTP request here. If you want to inspect the status code and response yourself, use
ClientResponse response = r.get(ClientResponse.class);
if (response.getStatus() == <expected status code>) [
response.getEntity(MyClass.class);
// do happy path stuff
} else {
// bad stuff here
}
Alternately, assume everything will go well, and only check the response on exceptions:
try {
r.get(MyClass.class);
} catch (UniformInterfaceException e) {
ClientResponse response = e.getResponse();
// do whatever with the raw response
}
I had same issue before. I think it's because Jersey WebResource.get method throws only UniformInterfaceException which is not in the inheritance hierarchy of WebApplicationExcpetion. What I did is to abandon Jersey client side api but use plain ApacheHttpClient. Will be able to get the right stacktrace in the httpResponse contents.
Hope this helps.
Thanks, Ryan. I tried your solution. Very nice.

Why does HttpClient throw a SocketTimeOutException when executing POST

I have code similar to the following:
try {
HttpPost post = new HttpPost(httpsUrl);
setHeaders(post);
HttpEntity entity = new StringEntity(request, "UTF-8");
post.setEntity(entity);
HttpResponse response = httpclient.execute(post);
String result = EntityReader.readContent(response.getEntity());
checkAnswer(result);
return result;
} catch (Exception e) {
throw new ZapException("Error executing the http post request: "+e.getMessage(), e);
}
It sends the content of request to a server via POST using a httpclient instance that might have already been used before (it has persistent connections turned on, since we're sending quite some requests to the same server...).
This sometimes fails with a SocketTimeoutException with "Read timed out" as the message.
It's not clear to us, why it only fails at some times, when most times it doesn't. What gives?
In the following, I assume you are using Apache Commons HttpClient (org.apache.commons.httpclient.HttpClient).
Maybe you get thrown a SocketTimeoutException simply because, occasionally, the host your HttpClient instance is communicating with takes too long to respond, triggering HttpClient's cancellation routine.
You can increase the connection timeout and the socket timeout with the following
HttpConnectionParams params = httpclient.getHttpConnectionManager().getParams();
params.setConnectionTimeout(20000);
params.setSoTimeout(15000);
Aditionally, if you still face timeouts despite increasing the timeout limits, it is a good practice to handle the SocketTimeoutException gracefully - for example by retrying the connection a second and third time.

Categories