CXF's readEntity() got "Entity is not available" - cxf

I am working on a piece of code that uses CXF (3.1.2)
I am seeing this error intermittently:
java.lang.IllegalStateException: Entity is not available
at org.apache.cxf.jaxrs.impl.ResponseImpl.checkEntityIsClosed(ResponseImpl.java:481)
at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:333)
at org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:320)
at org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:310)
To improve performance, the Response objects are held through a Google Guava LoadingCache (com.google.common.cache.LoadingCache). It seems like I would get this error after an object has been in the cache for a few minutes. Could the Response object because invalid
after a few minutes?
private static LoadingCache<String, Response> cachedLdapRespMap
= CacheBuilder.newBuilder()
.maximumSize(Constants.LDAP_RESP_CACHE_SIZE)
.expireAfterWrite(Constants.LDAP_RESP_CACHE_KEEP_ALIVE_MINUTE
, TimeUnit.MINUTES)
.build(
new CacheLoader<String, Response>() {
#Override
public Response load(String uid)
throws Exception {
Response res = makeLdapRequest(uid);
return res;
}
}
);

(I am answer the question myself)
The problem was that I have concurrent processes that attempted to readEntity(), the first process consumed the input stream (or may have even closed the stream), and the second process would either get thrown an IllegalStateException or got an empty message. Here is what the JavaDoc of javax.ws.rs.core.Response (which org.apache.cxf.jaxrs.impl.ResponseImpl extends) says:
Throws:
IllegalStateException - if the entity is not backed by an
input stream, the response has been closed already, or if the entity
input stream has been fully consumed already and has not been buffered
prior consuming.
So to fix the problem, I changed my design to cache not the Response object but rather the string message that is the result of the readEntity() call. The call would be done exactly once when the response comes back:
Response resp ...
String respStr = resp.readEntity(String.class);
and the problem is solved.

Related

GAE/Java LocalChannelFailureException at development server

I'm using Channel API (Java) with Google App Engine for my web application. I have implemented a Token-reusing-mechanism for not exceeding the Channel API Quotas that fast.
This means, that my implementation reuses an existing channel for a user that refreshes the page as long as the expiration time of the token received by the ChannelService.createChannel() call, is not over.
When refreshing my page I get the following exception (with x starting at 0 and increasing for every refresh). However, my page continues to work as intended. Is there a way to avoid the exception being thrown? Or can I just ignore the exception?
com.google.appengine.api.channel.dev.LocalChannelFailureException: Client connection with ID connection-x not found.
at com.google.appengine.api.channel.dev.Channel.getClientMessageQueue(Channel.java:79)
at com.google.appengine.api.channel.dev.ChannelManager.getNextClientMessage(ChannelManager.java:300)
at com.google.appengine.api.channel.dev.LocalChannelServlet.doGet(LocalChannelServlet.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
...
Im reusing tokens with the following classes:
When calling ChannelService.createChannel() I save the expiration date and the generated token in an Entity called "Channel"
public class Channel {
private String id;
private String token;
private Date expiration;
}
Then I have a ChannelService class that returns a valid Channel with its get() method. The channelDAO is a class that just uses a Map for storing Channels. So there is no database persistence, which would keep a token alive over a server restart.
public Channel get(String clientId) {
Calendar calendar = Calendar.getInstance();
Channel channel = channelDAO.get(clientId);
if (channel == null || calendar.getTime().after(channel.getExpiration())) {
com.google.appengine.api.channel.ChannelService channelService = ChannelServiceFactory
.getChannelService();
calendar.add(Calendar.MINUTE, CHANNEL_UPTIME);
String token = channelService.createChannel(player.toString(), CHANNEL_UPTIME);
channel = new Channel(clientId, token, calendar.getTime());
channelDAO.persist(channel);
}
return channel;
}
I fixed the problem by further investigations on the source of the exception. The Channel API works with polling requests that are executed every 500ms. I used Firefox's console to track these. Here is an example poll:
[20:40:15.978] GET http://localhost:8080/_ah/channel/dev?command=poll&channel=920a60f9b27ece1a1ba43d251fdacf2e-channel-eqt3xi-1385927324758-{clientId}&client=connection-2 [HTTP/1.1 200 OK 0ms]
In my question I stated, that the exception occurs on page reload, so the problem with this was: When the page is reloaded, something (I don't know what exactly, but i assume it has something to do with sockets getting closed and reopened on page refresh) happens which causes the client (last parameter of the GET request) to no longer be available. However, a new client is available: the client "connection-{i+1}". So when you enter the page initially, the client is "connection-0". After page refresh it is "connection-1". But as the old page used a delayed execution for the poll, a false request (still connection-0) is sent to the server, that, as a result, throws the Exception.
I fixed the problem by manually cancelling the delayed execution, when leaving the page with jQuery.
var channel = new goog.appengine.Channel('${channel.token}');
var socket = channel.open(handler);
$(window).on('beforeunload', function() {
clearTimeout(socket.pollingTimer_);
});
Your token re-use scheme should be carefully checked for bugs as that exception shouldn't occur each page reload.
There is a known issue after local server restarts but as stated it should only be only if the development server restarted.
I had the same issue using GWT and gwt-gae-channel. The solution would be something like:
Socket socket = channel.open(new SocketListener() {...});
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
socket.close();
}
});

Download File (using Thread class)

Ok, I understand that maybe very stupid question, but i never did it before, so i ask this question. How can i download file (let's say, from the internet) using Thread class?
What do you mean with "using Thread class"? I guess you want to download a file threaded so it does not block your UI or some other part of your program.
Ill assume that your using C++ and WINAPI.
First create a thread. This tutorial provides good information about WIN32 threads.
This thread will be responsible for downloading the file. To do this you simply connect to the webserver on port 80 and send a HTTP GET request for the file you want. It could look similar to this (note the newline characters):
GET /path/to/your/file.jpg HTTP/1.1\r\n
Host: www.host.com\r\n
Connection: close\r\n
\r\n
\r\n
The server will then answer with a HTTP response containing the file with a preceding header. Parse this header and read the contents.
More information on HTTP can be found here.
If would suggest that you do not use threads for downloading files. It's better to use asynchronous constructs that are more targeted towards I/O, since they will incur a lower overhead than threads. I don't know what version of the .NET Framework you are working with, but in 4.5, something like this should work:
private static Task DownloadFileAsync(string uri, string localPath)
{
// Get the http request
HttpWebRequest webRequest = WebRequest.CreateHttp(uri);
// Get the http response asynchronously
return webRequest.GetResponseAsync()
.ContinueWith(task =>
{
// When the GetResponseAsync task is finished, we will come
// into this contiuation (which is an anonymous method).
// Check if the GetResponseAsync task failed.
if (task.IsFaulted)
{
Console.WriteLine(task.Exception);
return null;
}
// Get the web response.
WebResponse response = task.Result;
// Open a file stream for the local file.
FileStream localStream = File.OpenWrite(localPath);
// Copy the contents from the response stream to the
// local file stream asynchronously.
return response.GetResponseStream().CopyToAsync(localStream)
.ContinueWith(streamTask =>
{
// When the CopyToAsync task is finished, we come
// to this continuation (which is also an anonymous
// method).
// Flush and dispose the local file stream. There
// is a FlushAsync method that will flush
// asychronously, returning yet another task, but
// for the sake of brevity I use the synchronous
// method here.
localStream.Flush();
localStream.Dispose();
// Don't forget to check if the previous task
// failed or not.
// All Task exceptions must be observed.
if (streamTask.IsFaulted)
{
Console.WriteLine(streamTask.Exception);
}
});
// since we end up with a task returning a task we should
// call Unwrap to return a single task representing the
// entire operation
}).Unwrap();
}
You would want to elaborate a bit on the error handling. What this code does is in short:
See the code comments for more detailed explanations of how it works.

java.sql.SQLRecoverableException: Connection is already in use

In my java code, I am processing huge amount of data. So I moved the code as servlet to Cron Job of App Engine. Some days it works fine. After the amount of the data increases, the cron job is not working and shows the following error message.
2012-09-26 04:18:40.627
'ServletName' 'MethodName': Inside SQLExceptionjava.sql.SQLRecoverableException:
Connection is already in use.
I 2012-09-26 04:18:40.741
This request caused a new process to be started for your application, and thus caused
your application code to be loaded for the first time. This request may thus take
longer and use more CPU than a typical request for your application.
W 2012-09-26 04:18:40.741
A problem was encountered with the process that handled this request, causing it to
exit. This is likely to cause a new process to be used for the next request to your
application. If you see this message frequently, you may be throwing exceptions during
the initialization of your application. (Error code 104)
How to handle this problem?
This exception is typical when a single connection is shared between multiple threads. This will in turn happen when your code does not follow the standard JDBC idiom of acquiring and closing the DB resources in the shortest possible scope in the very same try-finally block like so:
public Entity find(Long id) throws SQLException {
Connection connection = null;
// ...
try {
connection = dataSource.getConnection();
// ...
} finally {
// ...
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
return entity;
}
Your comment on the question,
#TejasArjun i used connection pooling with servlet Init() method.
doesn't give me the impression that you're doing it the right way. This suggests that you're obtaining a DB connection in servlet's init() method and reusing the same one across all HTTP requests in all HTTP sessions. This is absolutely not right. A servlet instance is created/initialized only once during webapp's startup and reused throughout the entire remaining of the application's lifetime. This at least confirms the exception you're facing.
Just rewrite your JDBC code according the standard try-finally idiom as demonstrated above and you should be all set.
See also:
Is it safe to use a static java.sql.Connection instance in a multithreaded system?

HttpWebRequest.BeginGetResponse results in System.NotSupportedException on Windows Phone

I realise that similar questions have been asked before however none of the solutions provided worked.
Examining the token returned from the BeginGetResponse method I see that the following exception is thrown there:
'token.AsyncWaitHandle' threw an exception of type 'System.NotSupportedException'
This page tells me that this exception means the Callback parameter is Nothing, however I'm passing the callback - and the debugger breaks into the callback method when I insert a breakpoint. However the request object in the callback is always null. I can view the same exception detail in the result object in the callback method.
I've tried using new AsyncCallback(ProcessResponse) when calling BeginGetResponse
I've tried adding request.AllowReadStreamBuffering = true;
I've tried this in-emulator and on-device, with no luck on either.
public static void GetQuakes(int numDays)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://magma.geonet.org.nz/services/quake/geojson/quake?numberDays=" + numDays);
// Examining this token reveals the exception.
var token = request.BeginGetResponse(ProcessResponse, request);
}
static void ProcessResponse(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
if (request != null)
{
// do stuff...
}
}
So I'm at a bit of a loss as to where to look next.
'token.AsyncWaitHandle' threw an exception of type
'System.NotSupportedException'
This page tells me that this exception means the Callback parameter is
Nothing
The documentation you are looking at http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse%28v=vs.95%29.aspx is for BeginGetResponse. Silverlight does not use the AsyncWaitHandle, and correctly throws a NotSupportedException. You are seeing the exception System.NotSupportedException is for call to IAsyncResult.AsyncWaitHandle you are making when you inspect token.
The documentation on IAsyncResult.AsyncWaitHandle says explicitly that it is up to the implementation of IAsyncResult whether they create a wait handle http://msdn.microsoft.com/en-us/library/system.iasyncresult.asyncwaithandle(v=vs.95).aspx. Worrying about this is sending you down th wrong path.
I think you need to descibe the actual problem you are seeing. It is great to know what you have investigated, but in this case it does help resolve the problem.
The code should work and in ProcessResponse request should not be null when you test it in the if statement. I just copied the code you have provided into a windows phone application and ran it with no problems.

Random System.NotSupportedException on WP7

Sporadically, I receive an error in my WP7 Silverlight application. The error is a random "System.NotSupportedException". This error is thrown occassionally when the following code is executed:
// 1. Build the url
string serviceURL = "http://www.mydomain.com/service.svc/param1/param2";
// 2. Asynchronously execute the query using HttpWebRequest instead of WebClient. There is a UI performance issue with the WebClient currently
WebRequest request = HttpWebRequest.Create(serviceUrl);
request.BeginGetResponse(new AsyncCallback(MyService_Completed), request);
...
private void MyService_Completed(IAsyncResult result)
{
// Do stuff
}
I have verified that the URL I am sending is correct. Please note, that this request is part of my view model, which may have other network requests fired off at the same time. I have no idea why this happens ocassionally. Can anybody point out any potential reasons?
Thank you!
When this happens, make sure you look at the View Detail part of the exception report. It might be that your service is refusing connection or the data passed is invalid. NotSupported is a very general exception that covers many possible situations.
A similar question has been asked previously. If you look at the comments the original poster added to the answer, he claims to have solved the problem by replacing
request.BeginGetResponse(new AsyncCallback(MyService_Completed), request);
with
request.BeginGetResponse( MyService_Completed, request);

Resources