Volley doesn't cache post request - caching

I fetch data from server with following method:
public void process(final String url){
this.url=url;
GsonRequest<T> request=new GsonRequest<>(url, responseType, requestData, new Response.Listener<T>() {
#Override
public void onResponse(T response) {
//handle response here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//handle error here
}
});
request.setRetryPolicy(new DefaultRetryPolicy(
0,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
request.setShouldCache(true);
queue.add(request);
}
Some of the requests fetch signficant amount of data.I'd like Volley to cache data in some cases.However when I do one of these heavy request and then turn network off and then repeat my request Volley throws
java.net.UnknownHostException: Unable to resolve host "...": No address associated with hostname.
Is there something I can do to make Volley cache responses?

The problem was in server code - it didn't allow caching

Related

Media Type not acceptable exception when using SseEmitter

Following this tutorial, I am trying to set up a Sse Emitter. When I open the html page I get a
Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
On client side (javascript) it sais it cannot connect to the server. I have tried various other tutorials, but I am clueless on why my code isnt working.
I set up a clean test project containing only and exactly the tutorial code.
I Was in the middle of doing something else when I got the same issue.
The code below fixed it.
Simply put Mismatch Media type.
#GetMapping(value = "/api/push/notification",headers = "Accept=*/*", consumes = MediaType.ALL_VALUE, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public String doNotify(#RequestParam("authToken") String token, #RequestParam("clientId") String clientId, HttpServletResponse response) throws InterruptedException, IOException {
response.addHeader("charset","UTF-8");
final SseEmitter emitter = new SseEmitter(30000l);
service.addEmitter(clientId,emitter);
service.sendConnectedNotification(clientId);
emitter.onCompletion(() -> service.removeEmitter(clientId));
emitter.onTimeout(() -> service.removeEmitter(clientId));
return "Connected OK";
}
any my event handler
#Async
public void doNotify(String clientId, Object data) {
SseEmitter emitter= emitters.get(clientId);
if(emitter!=null) {
try {
emitter .send(SseEmitter.event() .reconnectTime(30000)
.data(data,MediaType.APPLICATION_JSON)
.id(UUID.randomUUID().toString())
.name("Notification")
.comment("Client connection notification")
);
} catch (Exception e) {
emitters.remove(clientId);
}
}
}

How to implement receiving a server push in OkHttp?

Following the question Does OkHttp support HTTP/2 server push?, are there any examples available on how receiving pushed content on the client side could be implemented?
How will the interaction of OkHttpClient, Request, Response and Http2Connection be? I understand that the Http2Connection has a PushObserver, but how will it play together with OkHttpClient and Request/Response?
Consider the snippet below. There is a client and a request. How would they come together with the PushObserver?
OkHttpClient client = getOkHttpClient();
Request request = new Request.Builder()
.url("https://nghttp2.org:443") // The Http2Server should be running here.
.build();
try {
Socket socket = client.socketFactory().createSocket();
Http2Connection con = new Http2Connection.Builder(true)
.socket(socket)
.pushObserver(new PushObserver(){
#Override
public boolean onRequest(int streamId, List<Header> requestHeaders) {
// do something here
return true;
}
#Override
public boolean onHeaders(int streamId,
List<Header> responseHeaders, boolean last) {
// do something here
return true;
}
#Override
public boolean onData(int streamId, BufferedSource source,
int byteCount, boolean last) throws IOException {
// do something here
return true;
}
#Override
public void onReset(int streamId, ErrorCode errorCode) {
// do something
}
}).build();
} catch (IOException e) {
LOG.error("IOException", e);
}
OkHttp has no public APIs for server push and it is unlikely to gain them. We’re building mechanisms to persist pushed responses into the cache, but it’s unlikely this will be visible to application code. You just get a faster response sometimes because the server pushed it into the cache.
If you need this kind of behavior please look at web sockets.

jersey at serverside nerver stopped processing a request even though client cancelled the connection

Am using restyGwt to send a request to jersey , I have closed the request using request object at client side(request.cancel) , but i found that the server is processing my request even though i closed at client side , it is never notified to server that the connection is stopped.
I want a way to tell the server as soon as the client cancel a request , to stop proccessing that request
this is my client resty gwt code
#POST
#Produces("application/json")
#Consumes("application/json")
#Path("servicepoint/getAllServicepointAndCount")
public Request findAllServicepointandCount(#QueryParam("startIndex") Integer startIndex,
#QueryParam("maxSize") Integer maxSize,
MethodCallback<ServicepointResponse> methodCallback);
this is the gwt class where am making my request to server
ServicepointRestyService service = GWT
.create(ServicepointRestyService.class);
((RestServiceProxy) service).setResource(resource);
final Request method=service.findAllServicepointandCount( index, length,
new MethodCallback<ServicepointResponse>() {
#Override
public void onFailure(Method method, Throwable exception) {
Window.alert(exception.getMessage());
}
#Override
public void onSuccess(Method method,
ServicepointResponse response) {
Window.alert("response.getMassege");
}
});
Timer t=new Timer() {
#Override
public void run() {
Window.alert("cancelled");
method.cancel();// cancel connection
}
};
t.schedule(2000);
}
jersey impl
#POST
#Produces("application/json")
#Consumes("application/json")
#Path("/getAllServicepointAndCount")
public ServicepointResponse findAllServicepointandCount(
#QueryParam("startIndex") Integer startIndex,
#QueryParam("maxSize") Integer maxSize) {
logger.finer("Entering startIndex" + startIndex + "" + maxSize);
ServicepointResponse data = new ServicepointResponse();
List<ServicepointPojo> spPojos = new ArrayList<>();
try {
while(true){
System.out.println(new Date().getTime());
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
eventhough i stopped my request after 2sec, server still prints the date and time it never stoped , i have written this code to check this functionality

Use google volley to receive streaming data

I am trying to use volley to receive streaming strings. The api works well with curl command or HttpURLConnection:
curl http://streamingurl.com // fake url
string-piece1 string-piece2 string-piece3...
After you make such a request, the server just keep feeding you string pieces about every second.
However when I try it with Volley it doesn't work:
queue = Volley.newRequestQueue(context);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, "http://streamingurl.com",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("Streaming", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Streaming", error.toString());
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
I expect to receive a string snippet every second in the console. However I didn't. I just receive a TimeoutError after several second. Is it possible to use Volley to receive the streaming strings?

Session management in gwt

I am using GWT for my client side application. However, I am not sure how I can handle session management. The GWT application resides on one page, all server calls are done via AJAX. If a session expires on the server. let's assume the user didn't close the browser, and sending some request to server using RPC, how could my server notify the application that the session has expired and that the client side portion should show the login screen again?My sample code :
ContactDataServiceAsync contactDataService = GWT
.create(ContactDataService.class);
((ServiceDefTarget) contactDataService).setServiceEntryPoint(GWT
.getModuleBaseURL()
+ "contactDatas");
contactDataService.getContact(2,
new AsyncCallback<ContactData>() {
public void onFailure(Throwable caught) {
//code to show error if problem in connection or redirect to login page
}
public void onSuccess(ContactData result) {
displayContact(result);
}
});
If session expires only it has to show login screen, otherwise it wants to show some error using Window.alert().
How to do this and what are all the codes needed in server side and client side?
You could have the server throw an AuthenticationException to the client in case the user has been logged out.
This will be catched in the callbacks onFailure method, which then can redirect the user to the login-page.
Edit:
AuthenticationException is not a standard exception of course, i was just making an example. It might be best to stick with the standard exceptions.
To try if you caught an specific exception you could use the instanceof operator
public void onFailure(Throwable e) {
if(e instanceof AuthenticationException) {
redirecttoLogin();
}
else {
showError(),
}
}
This does not directly apply to those using RPC, but for those of you who are not using RPC, you should send a HTTP 401 from the server. Then you can check that status code in your RequestBuilder callback.
Client: All Callbacks extend a Abstract Callback where you implement the onFailur()
public abstract class AbstrCallback<T> implements AsyncCallback<T> {
#Override
public void onFailure(Throwable caught) {
//SessionData Expired Redirect
if (caught.getMessage().equals("500 " + YourConfig.ERROR_MESSAGE_NOT_LOGGED_IN)) {
Window.Location.assign(ConfigStatic.LOGIN_PAGE);
}
// else{}: Other Error, if you want you could log it on the client
}
}
Server: All your ServiceImplementations extend AbstractServicesImpl where you have access to your SessionData. Override onBeforeRequestDeserialized(String serializedRequest) and check the SessionData there. If the SessionData has expire then write a spacific error message to the client. This error message is getting checkt in your AbstrCallback and redirect to the Login Page.
public abstract class AbstractServicesImpl extends RemoteServiceServlet {
protected ServerSessionData sessionData;
#Override
protected void onBeforeRequestDeserialized(String serializedRequest) {
sessionData = getYourSessionDataHere()
if (this.sessionData == null){
// Write error to the client, just copy paste
this.getThreadLocalResponse().reset();
ServletContext servletContext = this.getServletContext();
HttpServletResponse response = this.getThreadLocalResponse();
try {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
try {
response.getOutputStream().write(
ConfigStatic.ERROR_MESSAGE_NOT_LOGGED_IN.getBytes("UTF-8"));
response.flushBuffer();
} catch (IllegalStateException e) {
// Handle the (unexpected) case where getWriter() was previously used
response.getWriter().write(YourConfig.ERROR_MESSAGE_NOT_LOGGED_IN);
response.flushBuffer();
}
} catch (IOException ex) {
servletContext.log(
"respondWithUnexpectedFailure failed while sending the previous failure to the client",
ex);
}
//Throw Exception to stop the execution of the Servlet
throw new NullPointerException();
}
}
}
In Addition you can also Override doUnexpectedFailure(Throwable t) to avoid logging the thrown NullPointerException.
#Override
protected void doUnexpectedFailure(Throwable t) {
if (this.sessionData != null) {
super.doUnexpectedFailure(t);
}
}

Resources