GWT + Jsonp + push server stuck after time out - java

I have been building my GWT app, using JSONP to communicate with a push server (my own code, based on Netty library). The communication function of the GWT app looks like the following, which sends queries stored in in queryList and processes received data from server via function processDataFromServer. You may notice that right after a fail or a success of communicating, the function calls itself again for keeping connection with server:
ArrayList<String>queryList;
boolean querying = false;
public void queryJsonpServer() {
if (querying) {
return;
}
querying = true;
String jsonString = queryList.isEmpty() ? “” : queryList.remove(0);
String url = postUrl + (!jsonString.isEmpty() ? “?jsonp=" + URL.encodeQueryString(jsonString) : "");
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.setTimeout(60 * 1000);
jsonp.requestObject(url, new AsyncCallback<MyJsonpObject>() {
#Override
public void onFailure(Throwable caught) {
querying = false;
queryJsonpServer();
}
#Override
public void onSuccess(MyJsonpObject o) {
processDataFromServer(o);
querying = false;
queryJsonpServer();
}
});
}
The code works fine if the communication are successes (onSuccess called).
However, once it fails (onFailure called, because of timeout for example), even the function (queryJsonpServer) is called again (I am sure a new query is sent, server receives that query and sends back new data), the function is stuck to receive that new data (onSuccess has not been called since that fail). After a while onFailure called again because of timeout. The problem repeats: query via onFailure, receive nothing, onFailure called again...
Anyone has idea about that problem? Thanks

Related

Not able to print the XML Response from a SOAP webservice

I am not able to print the response from a Soap Webservice.
Seen few solutions by editing the generated stub code. But I cant edit the generated code as it gets restored to original form on every build. Looking for a solution where I can get the solution printed without change in generated code.
I am consuming the SOAP service from a Spring Boot microservice.
ServiceContext serviceConxt = omsSchedulingService._getServiceClient().getServiceContext();
OperationContext operationContext = serviceConxt.getLastOperationContext();
MessageContext inMessageContext = operationContext.getMessageContext("Out");
log.info(inMessageContext.getEnvelope().toString());
You can add a message handler for the soap message.
Then once you intercept the message with the handler, you can print out the response.
You will need to add the handler to the handler chain, depending on your project you can do that programatically or with config.
final class MyMessageHandler implements SOAPHandler<SOAPMessageContext>{
#Override
public void close(MessageContext context) {
handle(context);
}
private boolean handle(MessageContext context) {
if (context != null) {
try {
Object httpResponseCodeObj = context.get(SOAPMessageContext.HTTP_RESPONSE_CODE);
if (httpResponseCodeObj instanceof Integer)
httpResponseCode = ((Integer) httpResponseCodeObj).intValue();
if (context instanceof SOAPMessageContext) {
SOAPMessage message = ((SOAPMessageContext) context).getMessage();
ByteArrayOutputStream byteOut = new ByteArrayOutputStream(512);
message.writeTo(byteOut);
String messageStr = byteOut.toString(getCharacterEncoding(message));
boolean outbound = Boolean.TRUE.equals(context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY));
Logger.info(loggingPrefix, outbound ? "SOAP request: " : "SOAP response: ", replaceNewLines(messageStr));
}
} catch (SOAPException e) {
Logger.error(e, loggingPrefix, "SOAPException: ", e.getMessage(), NEWLINE);
} catch (IOException e) {
Logger.error(e, loggingPrefix, "IOException: ", e.getMessage(), NEWLINE);
}
}
return true;
}
}
If you don´t want to implement an interceptor the easiest way is to use the logging via vm arguments:
JAVA_OPTS=-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.httpclient.wire=debug -Dorg.apache.commons.logging.simplelog.log.org.apache.commons.httpclient=debug
This way you should see the logging of your request / response with headers in console.
First you can get AxisConfiguration from client stub.
AxisConfiguration axisConf = stub._getServiceClient().getAxisConfiguration();
Processing incoming and outgoing messages is divided into phases. There is a list of phases (a flow) which is processed when everything works correctly (without errors) and also another for situations when some fault occurs e.g. when an exception is thrown during message processing. Every flow maybe incoming or outgoing so there are 4 flows altogether.
List<Phase> phasesIn = axisConf.getInFlowPhases(); // normal incoming communication i.e. response from webservice
List<Phase> phasesOut = axisConf.getOutFlowPhases(); // normal outgoing communication
List<Phase> phasesFaultIn = axisConf.getInFaultFlowPhases(); // faulty incoming communication e.g. when an exception occurs during message processing
List<Phase> phasesFaultOut = axisConf.getOutFaultFlowPhases(); // faulty outgoing communication
Some but not all phase names are defined in org.apache.axis2.phaseresolver.PhaseMetadata.
For example "Security" phase processed in Rampart module (module for Web Service Security) won't be found in PhaseMetadata.
You can add a handler to every phase, e.g.
for (Phase p : phasesOut) {
if (PhaseMetadata.PHASE_TRANSPORT_OUT.equals(p.getName())) {
p.addHandler(new MessageContentLoggerHandler());
}
}
Handler is a class which extends org.apache.axis2.handlers.AbstractHandler.
You just have to implement
public InvocationResponse invoke(MessageContext msgContext).
There you have access to MessageContext. Of course, you can get whole SOAP envelope like this:
msgContext.getEnvelope().toString()
and for example print it to your logs or save as a separate file.
Remember to put
return InvocationResponse.CONTINUE;
at the end of invoke method for a situation when handler processes the message successfully. Otherwise processing stops in this handler and a whole process won't get to any another phase.
If you need to see whole message with WSS headers, you can add your own phase. For example this adds your custom phase as the last in processing of outgoing message (so also after Rampart's security phase)
Phase phase = new Phase("SomePhase");
phase.addHandler(new SomeCustomHandler());
axisConf.getOutFlowPhases().add(phase);
Of course logging (and exposing in any other way) security headers in production environment is a very bad idea. Do it only for debugging purposes in some test environment.

How to retrieve all results (more than 100) using batch on gmail

I am using Gmail API with the java client library.
I want to batch a bulk of queries to get a list of messages.
I make a test for only one query.
Here is the snippet of the code :
Gmail client = getClient();
BatchRequest batch = client.batch();
// Create the callback.
JsonBatchCallback<ListMessagesResponse> callback = new JsonBatchCallback<ListMessagesResponse>() {
public void onSuccess(ListMessagesResponse listMessagesResponse, HttpHeaders responseHeaders) {
System.out.println(listMessagesResponse.getMessages().size());
System.out.println(listMessagesResponse.getNextPageToken());
}
#Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
System.out.println("Error Message: " + e.getMessage());
}
};
client.users().messages().list("me#gmail.com").queue(batch, callback);
batch.execute();
The problem is that it retrieves only 100 messages. I don't want to get the last token and reuse it for the next query, it does not make a sense since I want to use batch.
So How is it posssible to bypass the limitation (100) in order to retrieve all messages in one batch request ?
Thanks

Handle android server communication after errors

My android app is using a http connection to send data to a server. If the server received the data the app marks the data as successfully transmitted in its own database.
Sometimes external problems may occur, so that the transmission cannot be completed. The app should try sending the data again later.
What is a good possibility to make sure, that the data reaches the server? I only can think of a service, which checks periodically for not transmitted data, but I don't like this approach.
Heres some psuedo code..
1.Create a AcknowledgementManager which waits for acknowledgement of each request.
2.The acknowledgement manager posts a runnable which will run after TIME_OUT interval.
public void startListeningForTimeOut(CallContext callContext) {
TimeOutRunnable timeOutRunnable = new TimeOutRunnable(callContext);
mMapRunnables.put(callContext, timeOutRunnable);
mHandler.postDelayed(timeOutRunnable, TIMEOUT_DURATION);
Slog.d(TAG,
"started listening for timeout for token: " + callContext + " at: "
+ System.currentTimeMillis());
}
3.1 If the AcknowledgementManager receives acknowledgement for the data it cancels the runnable for that data and make necessary updates in database.
public void stopListeningForTimeOut(CallContext callContext) {
mHandler.removeCallbacks(mMapRunnables.get(callContext));
mMapRunnables.remove(callContext);
Slog.d(TAG,
"stopped listening for timeout for token: " + callContext + " at: "
+ System.currentTimeMillis());
}
3.2 If the acknowledgement is not received the runnable raises a "timeout" to the AcknowledgementManager.The AcknowledgementManager retries sending data.
public class TimeOutRunnable implements Runnable {
private static final String TAG = "TimeOutThread rupesh";
CallContext mToken;
// String mCallback;
public TimeOutRunnable(CallContext callContext) {
mToken = callContext;
// mCallback = callbackTBD;
// FIXME send proper callback class
}
#Override
public void run() {
Slog.d(TAG, "timeout occured for data id: " + mToken + " at: " + System.currentTimeMillis());
mToken.onTimeOutOccurred();
}
}
Please note:
1.Before syncing the data please make the entry of data in db so that the data does not get lost between app restart.
2.Before you start the syncing process query the db to get the data which is not being transmitted.Based on the data size,make sure you keep the data to be transmitted in memory to avoid hitting the db everytime.
3.Once you get acknowledgement for a data item,make necessary changes for that entry in db.
4.You can also have 'retry' flag in db so that you keep track of no of retries.

Android Websockets onMessage() never being called even on connection

I'm using websockets to make a multiplayer game and I need to send multiple types of data across the server but when I connect to the server it's supposed to send back a name and number ("type") and ("data") respectively from the websocket library on connection. I don't need the type but ("data") is vital for the game logic to actually work.
Below is the code I have in my websockets onMessage() function:
#Override
public void onMessage(String message)
{
try
{
JSONObject json = new JSONObject(message);
if(json.has("type") && json.has("data"))
{
Log.d(TAG, json.getString("type"));
Log.d(TAG, json.getString("data"));
playerNum = Integer.parseInt(json.getString("data"));
Log.d(TAG,"Received... Type : " +json.getString("type")+" Data : "+json.getString("data"));
}
if(json.has("Player1TurnOver"))
{
player1TurnOver = json.getBoolean("Player1TurnOver");
}
if(json.has("Word"))
{
String b = json.getString("Word");
bWord = new char[b.length()];
for(int i = 0; i < b.length(); i++)
{
bWord[i] = b.charAt(i);
}
wordLength = bWord.length;
}
}
catch(JSONException e)
{
}
}
But this is never called from the server even though the client has a listener as such:
mClient = new WebSocketClient(URI.create("ws://some_ip:8080/wstest"), new WebSocketClient.Listener()){
And the listener is initialised within the websocket library class
public interface Listener {
public void onConnect();
public void onMessage(String message);
public void onMessage(byte[] data);
public void onDisconnect(int code, String reason);
public void onError(Exception error);
}
I can't seem to figure out why this isn't working properly. As it has worked before...
Sometimes it is not correctly detected when a device looses internet connection (Java is not that smart in this case ;) )
Apart from this. Could you maybe activate the debug printouts with WebSocketImpl.DEBUG = true;
The lib will automatically send pings to the endpoints at specific interval and if no ping was received it assumes that the endpoint got disconnected!

Does Smack work well in Java EE

Does Smack function properly in Java EE?? I am having issues with presence.
I get the credentials from the login form via doPost method..I can able to successfully authenticate as well as connection.getRoster() also works.Next I want to show only users who are online so when I get the presence of user,presence object stores default value "unavailable" for all users even when they are available!!
The whole chat app works without flaw in a normal java class without any change..
String userName = request.getParameter("username");
String password = request.getParameter("password");
HttpSession session=request.getSession();
session.setAttribute("username", userName);
SmackAPIGtalkServlet gtalk = new SmackAPIGtalkServlet();
ConnectionConfiguration config = new ConnectionConfiguration(
"talk.google.com", 5222, "gmail.com");
connection = new XMPPConnection(config);
config.setSASLAuthenticationEnabled(false);
try {
connection.connect();
} catch (XMPPException e) {
e.printStackTrace();
}
try {
connection.login(userName, password);
} catch (XMPPException e) {
e.printStackTrace();
}
System.out.println(connection.isAuthenticated());
boolean status = connection.isAuthenticated();
if (status == true) {
gtalk.displayOnlineBuddyList();
response.sendRedirect("Roster.jsp");
}
else
{
response.sendRedirect("Failed.jsp");
}
}
public void displayOnlineBuddyList() {
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
int count1 = 0;
int count2 = 0;
for (RosterEntry r : entries) {
Presence presence = roster.getPresence(r.getUser());
if (presence.getType() == Presence.Type.unavailable) {
// System.out.println(user + "is offline");
count1++;
} else {
System.out.println(name+user + "is online");
count2++;
}
}
roster.addRosterListener(new RosterListener() {
// Ignored events public void entriesAdded(Collection<String>
// addresses) {}
public void entriesDeleted(Collection<String> addresses) {
}
public void entriesUpdated(Collection<String> addresses) {
}
public void presenceChanged(Presence presence) {
System.out.println("Presence changed: " + presence.getFrom()
+ " " + presence);
}
#Override
public void entriesAdded(Collection<String> arg0) {
// TODO Auto-generated method stub
}
});
}
I am stuck with this and not able to get the code working with servlets..Can anyone help me out??
Will Smack work inside of Java EE, yes and no.
Smack will work inside of a web container, but since it creates its own threads it will NOT work inside of an EJB container. So it will work depending on where you are running it.
To understand some of your issues, you have to understand that the lifecycle of your objects in a servlet is tied to the request/response cycle of each request. This is not the same as a standard java app where the objects will typically live as long as you need them to, since you control their lifecycle.
For example, in the code you have shown, you create the connection for each request (I assume, since not all the code is shown). Therefore registering listeners against that connection will be pointless since it will pass out of scope as soon as you leave the method, and eventually get garbage collected. You will have to maintain the connections outside of the scope of the servlet requests for this to work, otherwise you will be opening and closing connections for each request.
XMPP is completely asynchronous by nature whereas servlet requests are synchronous. You have to put some effort in to making them work together, so don't expect code that works in a standalone app to simply work in this environment.
You have to implement the RosterListener interface in which you have to override the presenceChanged method in that you can get the presence of the users.
It works for me.
When you are getting the rosters of GTalk all will have status as unavailable.
But after sometime their presence changes and the presence can be get from the presenceChanged method in the RosterListner but for that you have to implement the RosterListener's presenceChnaged method.
And ya it works well in Java EE, Android as well as WAP.
Does Smack function properly in Java EE?? I am having issues with presence. I get the credentials from the login form via doPost method..I can able to successfully authenticate as well as connection.getRoster() also works.Next I want to show only users who are online so when I get the presence of user,presence object stores default value "unavailable" for all users even when they are available!! here my code
<%
Roster rst = roster;
rst.addRosterListener(new RosterListener() {
public void entriesAdded(final Collection args) {}
public void entriesDeleted(final Collection<String> addresses) {}
public void entriesUpdated(final Collection<String> addresses) {}
public void presenceChanged(final Presence presence) {
final Presence prsence1 = presence;
prsenceChanged(prsence1);
if (prsence1.isAvailable()) {
System.out.println("Is Available: " + presence.isAvailable());
}
}
});
%>
<%!void prsenceChanged(Presence presence){ if(null != presence){%>
<script language="javascript">
alert("hai");
</script>

Categories