Loopj Android Async Http - onFailure not fired - java

I am using the great async http library from loopj, but I have run into a small snag.
If the user has no internet connection or loses their connection, the app just won't return anything. This part is expected, but it also doesn't fire the onFailure method.
Also, the code I have used when there is an internet connection does work so there is no problem on the server end.
Here is some code that is stripped down to the minimum. It also doesn't work (I have tested this too)
String url = getString(R.string.baseurl) + "/appconnect.php";
client.getHttpClient().getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
client.get(url, null, new JsonHttpResponseHandler()
{
#Override
public void onSuccess(JSONArray response)
{
Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Throwable e, JSONArray errorResponse)
{
Toast.makeText(getApplicationContext(), "Failure", Toast.LENGTH_SHORT).show();
}
});
Thanks,
Ashley

You can try this:
In AsyncHttpRequest->makeRequestWithRetries(), add a catch to SocketException like this:
while (retry) {
try {
makeRequest();
return;
} catch (UnknownHostException e) {
if(responseHandler != null) {
responseHandler.sendFailureMessage(e, "can't resolve host");
}
return;
} catch (SocketException e){
// Added to detect no connection.
if(responseHandler != null) {
responseHandler.sendFailureMessage(e, "can't resolve host");
}
return;
} catch (IOException e) {
cause = e;
retry = retryHandler.retryRequest(cause, ++executionCount, context);
} catch (NullPointerException e) {
// there's a bug in HttpClient 4.0.x that on some occasions causes
// DefaultRequestExecutor to throw an NPE, see
// http://code.google.com/p/android/issues/detail?id=5255
cause = new IOException("NPE in HttpClient" + e.getMessage());
retry = retryHandler.retryRequest(cause, ++executionCount, context);
}
}

Yeah, unfortunately the loopj Android library isn't very well designed. If you implement the other onFailure callbacks one of them should fire:
#Override
public void onFailure(Throwable e) {
Log.e(TAG, "OnFailure!", e);
}
#Override
public void onFailure(Throwable e, String response) {
Log.e(TAG, "OnFailure!", e);
}
#Override
public void onFailure(Throwable e, JSONArray errorResponse) {
Log.e(TAG, "OnFailure!", e);
}

Try this:
#Override
protected Object parseResponse(byte[] responseBody) throws JSONException {
return super.parseResponse(responseBody);
}

Related

Handle rest template errors

I developed a service, using resttemplate and using this service(clientproject) in another project(server), I am trying to throw the exception from resttemplate and handle at server project,but it is not working.
Here is my code:
public class UserService{
public long createUser(Long servcieId){
long userId =0L;
try
{
response = restTemplate.exchange(url,HttpMethod.POST, request, Object.class);
userId = response.getBody().getUser().getId();
}
catch(RestClientException e){
throw e;
}
return userId;
}
}
Here is my service code:
public Long createUserInPortal(Long serviceId){
try
{
Long userId=userService.createUser(serviceId);
}
catch(RestClientException e){
if(e instanceof HttpStatusCodeException){
String errorResponse=((HttpStatusCodeException)e).getResponseBodyAsString();
logger.error("the error in user service is:"+errorResponse);
}
}
I am getting the following error,"resulted in 422 (Unprocessable Entity); invoking error handler".
I am trying to see the response string in the catch block but it is not reaching this catch block.
well may be its getting inside catch block but gets filtered by
if(e instanceof HttpStatusCodeException){ condition
May be e instance is not of type HttpStatusCodeException there are other possibilities like
} catch (HttpClientErrorException e) {
success = false;
Log.e(TAG, command+" was rejected for URL: "+url, e);
resultCode = e.getStatusCode().value();
response = e.getResponseBodyAsString();
} catch (HttpServerErrorException e) {
success = false;
Log.e(TAG, command+" could not be completed for URL: "+url, e);
resultCode = e.getStatusCode().value();
response = e.getResponseBodyAsString();
} catch (ResourceAccessException e) {
if (attemptsLeft > 0) {
Log.w(TAG, command+" failed I/O, retrying.", e);
return simplePut(baseUrl, url, b, command, payload, attemptsLeft);
}
success = false;
Log.e(TAG, command+" failed I/O for URL: "+url, e);
resultCode = 499;
} catch (RestClientException e) {
success = false;
Log.e(TAG, command+" failed for URL: "+url, e);
resultCode = 599;
}

Issue while importing file using FileOutputStream, Vaadin 8 and Jetty to localhost

Basically I have been using Vaadin Designer to design my UI. One of my use cases asks me to upload an iCalendar file, I use a grammar (ANTLR) to get from it what I need. I came across my issue when after seeing the Vaadin Upload documentation and applying it to my use case when running it, nothing would happen and no exception would be thrown. After a bit of research and debugging I believe this is due to the Thread for the upload being shutdown for some reason.
Here is my code, any help?
private void uploadLogic() {
class IcalendarUploader implements Upload.Receiver, Upload.SucceededListener, Upload.FinishedListener, Upload.FailedListener {
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
try {
//We'll store the uploadad file as temporary file.
tempFile = File.createTempFile("temp", ".ics");
fos = new FileOutputStream(tempFile);
} catch (IOException e) {
Notification.show(e.getMessage(), Notification.Type.WARNING_MESSAGE);
return null;
}
}
#Override
public void uploadFinished(Upload.FinishedEvent event) {
try {
controller.importIcalendar(tempFile);
tempFile.delete();
Notification.show("Uploaded iCalendar file with :\n" + controller.iCalendarDetails(),
Notification.Type.HUMANIZED_MESSAGE);
} catch (IOException e) {
Notification.show(e.getMessage(), Notification.Type.WARNING_MESSAGE);
}
}
#Override
public void uploadSucceeded(Upload.SucceededEvent event) {
try {
if(controller.saveTimeSlot()){
Notification.show("Uploaded iCalendar file with :\n" + controller.iCalendarDetails()
+"\nSaved time slot with success",
Notification.Type.HUMANIZED_MESSAGE);
}else {
Notification.show("Uploaded iCalendar file with :\n" + controller.iCalendarDetails()
+ "\nTime slot has an overlapp!",
Notification.Type.WARNING_MESSAGE);
}
} catch (DataConcurrencyException e) {
Notification.show(e.getMessage(), Notification.Type.WARNING_MESSAGE);
} catch (DataIntegrityViolationException e) {
Notification.show(e.getMessage(), Notification.Type.WARNING_MESSAGE);
}
}
#Override
public void uploadFailed(Upload.FailedEvent event) {
Notification.show("Upload failed", Notification.Type.ERROR_MESSAGE);
}
}
IcalendarUploader receiver = new IcalendarUploader();
upload.setReceiver(receiver);
}

Why ListView updates only if scrolled on device, but works fine on virtual device?

I recently started learning android development (am new to java as well) and I am currently working on a chat/messenger application
The problem I am facing, as the title says, is that the listview in which the messages are shown does not update on the device, unless scrolled, but it works fine on the virtual machine. I only tested on LG Optimus l5 II so far, but i need to fix this anyway.
I think it has something to do with multithreading, because this didn't happen until i added some new threads, so the adapter for listview, android manifest and rest I say are set up correctly. I can add them if it helps.
The 2 threads i added that might cause this:
Checks the connection status and if disconnected tries to reconnect.
The thread used for communicating with the server.
I tested running only with the second thread on, and the problem still occurs.
I want to specify this is the first time I try something like this (servers-client, multithreading, java, android (I'm still in college and they don`t teach us these kinds of stuff there) ), and had no documentation ahead regarding how I should set up the communication between the server and the client. This is the most efficient way I could think of.
this is at the end of onCreate:
StartConnectingRoutine(); // so you know where it all starts
and the code for it:
private void StartConnectingRoutine()
{
Thread t = new Thread()
{
#Override
public void run()
{
while(true)
{
if(!connected)
{
if( connect != null)
{
if(!connect.isAlive())
{
ConnectListener();
}
}
else
{
ConnectListener();
}
}
try {
sleep(CONNECTION_CHECK_TIME_MS); // this is set to 10000 (10 seconds)
} catch (InterruptedException e) {
Log.e("Intrerrupted", e.toString());
}
}
}
};
t.start();
}
and the connectListener():
private void ConnectListener()
{
Log.d("Connecting", "Connecting...");
connect = new Thread()
{
JSONObject info = new JSONObject();
String receivedMessage;
#Override
public void run()
{
try {
info.put("Name", user.GetName());
info.put("PORT", MY_PORT);
info.put("IPv4", getIpAddress());
} catch (JSONException e1) {
Log.e("JSON", "JSON error: " + e1.toString());
}
try
{
ServerSocket = new Socket(SERVER_IP, SERVER_PORT);
dis = new DataInputStream(ServerSocket.getInputStream());
dos = new DataOutputStream(ServerSocket.getOutputStream());
dos.writeUTF(info.toString());
dos.flush();
String response = dis.readUTF();
if(response.equals("connected"))
{
Log.d("Connect", "Connected!");
connected = true;
}
else
Log.d("Connect", "Failed to connect!");
while(connected)
{
receivedMessage = dis.readUTF();
DisplayNewMessage(new MMessage(receivedMessage, MMessage.MessageType.Received));
}
}catch(SocketException e)
{
try {
if(connected)
{
ServerSocket.close();
dis.close();
dos.close();
connected = false;
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
catch(Exception e)
{
Log.d("Connect", "Failed to connect");
Log.e("Connect", e.toString());
connected = false;
}
}
};
connect.start();
}
Fixed:
Reconnecting thread (i tried using asyncTask for this too, but it wouldn`t open the other asyncTask, even if I tried to open it from onProgressUpdate()-which it is supposed to be able to run ui thread components):
private void startConnectingRoutine()
{
Thread t = new Thread()
{
#Override
public void run()
{
Log.d("ConnectingRoutine", "Started connecting routine.");
while(true)
{
if(!connected)
{
startListener();
}
try {
sleep(CONNECTION_CHECK_TIME_MS);
} catch (InterruptedException e) {
Log.e("Intrerrupted", e.toString());
}
}
}
};
t.start();
}
Listener thread:
private void startListener()
{
new Listener().execute();
}
.
private class Listener extends AsyncTask<Long, String, Long>
{
#Override
protected Long doInBackground(Long... params) {
Log.d("Connecting...", "Connecting...");
JSONObject info = new JSONObject();
String receivedMessage;
try {
info.put("Name", user.GetName());
info.put("PORT", MY_PORT);
info.put("IPv4", getIpAddress());
} catch (JSONException e1) {
Log.e("JSON", "JSON error: " + e1.toString());
}
try
{
serverSocket = new Socket(SERVER_IP, SERVER_PORT);
dis = new DataInputStream(serverSocket.getInputStream());
dos = new DataOutputStream(serverSocket.getOutputStream());
dos.writeUTF(info.toString());
dos.flush();
String response = dis.readUTF();
if(response.equals("connected"))
{
Log.d("Connect", "Connected!");
connected = true;
}
else
Log.d("Connect", "Failed to connect!");
while(connected)
{
receivedMessage = dis.readUTF();
publishProgress(receivedMessage);
}
}
catch(Exception e)
{
Log.d("Connect", "Failed to connect");
Log.e("Connect", e.toString());
return null;
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
displayNewMessage(new MMessage(values[0], MMessage.MessageType.Received));
}
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
connected = false;
try{
if(serverSocket != null)
serverSocket.close();
if(dis != null)
dis.close();
if(dos != null)
dos.close();
}catch(Exception e)
{
Log.e("Listener", "There was a problem closing the connection: " + e.toString());
}
}
}
There are perhaps multiple things going wrong here, but two that jump out are:
You're calling DisplayNewMessage() from outside the UI thread.
You're not notifying the adapter that its dataset has changed.
I urge you to look in to better mechanisms for executing tasks in the background than simply creating a Thread. Using AsyncTasks would be a good start, but you'll need to take special care to handle tasks between configuration changes (such as rotating the device).
Furthermore, your code is very difficult to read as you capitalize your method names. This is against Java code conventions. You will make things easier for yourself by formatting your code neatly (a good IDE helps with that) and learning to follow conventions!

socket.io-java-client cookies / custom headers

I'm doing a mobile app for a website and they use Socket.io and Websocket to comunicate.
I'm using socket.io-java-client on Android to connect to the Socket.io server, the problem is, i don't know how to set custom headers / cookies with it.
here is how the code looks like:
public void runIO(){
try {
SocketIO socket = new SocketIO("http://192.168.1.60:1337");
socket.connect(new IOCallback() {
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
});
// This line is cached until the connection is establisched.
socket.send("Hello Server!");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In fact there are simple functions that can be used to set headers before connection:
addHeader(String key, String value) and setHeaders(Properties headers)
You can also use SocketIO(final String url, Properties headers) (instead of SocketIO(final String url) that i was using):
// Haeader Properties initiation
private Properties headers = new Properties();
and then for exemple to set cookies:
headers.setProperty("Cookie","key=data;key2=data2");
Finally when connecting replace
this.socket = new SocketIO(val);
by
this.socket = new SocketIO(val,this.headers);

Code not working when running normally, but working in debug (eclipse)

I'm really confused by this: some of my code is not working when i run my program normally in eclipse, but it does wok when i run through each step separately using the debug mode.
Code:
public void showConnectDialog() {
ConnectDialog connectDialog = new ConnectDialog();
connectDialog.setVisible(true);
//Until here, code runs
while(! connectDialog.getConnected()) {};
//The next line does only run in debug
JOptionPane.showMessageDialog(connectDialog, "Connected", "Connected", JOptionPane.INFORMATION_MESSAGE);
}
The connector (is started (as a thread) as soon as the user hits 'connect' in the dialog):
private class ServerConnector implements ActionListener, Runnable {
#Override
public void actionPerformed(ActionEvent e) {
if (! IP_field.getText().equals("")) {
if (! isConnecting) {
new Thread(new ServerConnector(), "ServerConnector").start();
}
}
else {
JOptionPane.showMessageDialog(dialog,
"Enter an IP address",
"Enter IP",
JOptionPane.WARNING_MESSAGE);
}
}
#Override
public void run() {
try {
setConnecting(true);
Socket socket = connect();
if (socket != null) {
ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream());
if (login(oOut, oIn)) {
isConnected = true;
setConnecting(false);
}
else {
socket.close();
}
setConnecting(false);
}
}
catch (RSPException e) {
e.printStackTrace();
System.exit(1);
}
catch (Exception e) {
//If an exception occurs, setConnecting() will be true. This
//not good, so it has to be set to false
e.printStackTrace();
setConnecting(false);
}
}
private boolean login(ObjectOutputStream oOut, ObjectInputStream oIn)
throws ClassNotFoundException, IOException, RSPException {
//Send login request action:
oOut.writeObject(new LoginAction(ActionSender.CLIENT, getID(),
getPassword()));
Object obj = oIn.readObject();
if (obj instanceof LoginActionResult) {
LoginActionResult result = (LoginActionResult) obj;
if (result.getResult() == LoginResults.SUCCES) {
return true;
}
else if (result.getResult() == LoginResults.FAIL_ON_ID) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.FAIL_ON_PASSWORD) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.SERVER_FULL) {
JOptionPane.showMessageDialog(dialog,
"Couldn't connect: \n" +
"Server is full",
"Failed to connect",
JOptionPane.WARNING_MESSAGE);
return false;
}
else {
return false;
}
}
else {
System.out.println(obj);
throw new RSPException("Server is not following the protocol.");
}
}
private void setConnecting(boolean connecting) {
if (connecting) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setEnabled(false);
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setText("Connecting...");
}
});
}
else {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setText("Connect");
}
});
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
connectButton.setEnabled(true);
}
});
}
isConnecting = connecting;
}
private String getAddressFromTextField() {
return IP_field.getText();
}
private InetAddress getInetAddress(String fullAddress) {
try {
if (fullAddress.contains(":")) {
String[] splitAddress = fullAddress.split(":");
return InetAddress.getByName(splitAddress[0]);
}
else {
return InetAddress.getByName(fullAddress);
}
}
catch (UnknownHostException e) {
return null;
}
}
private int getPort(String fullAddress) {
try {
String[] splittedAddress = fullAddress.split(":");
return Integer.valueOf(splittedAddress[1]);
}
catch (NumberFormatException ex) {
return -1;
}
catch (NullPointerException
| ArrayIndexOutOfBoundsException
| PatternSyntaxException ex) {
//Returning default port value: 25566, because no port was given
return 25566;
}
}
#SuppressWarnings("resource")
private Socket connect() {
Socket socket = null;
InetAddress address = null;
if ((address = getInetAddress(getAddressFromTextField())) == null) {
return null;
}
int port = getPort(getAddressFromTextField());
try {
socket = new Socket(address, port);
}
catch (ConnectException e ) {
Socket retrySocket = null;
if ((retrySocket = retryConnect(address, port)) == null) {
JOptionPane.showMessageDialog(dialog,
"Connection timed out",
"Failed to connect",
JOptionPane.ERROR_MESSAGE);
setConnecting(false);
}
else {
socket = retrySocket;
}
}
catch(IOException e) {
e.printStackTrace();
}
return socket;
}
private Socket retryConnect(InetAddress address, int port) {
Thread waitThread = new Thread(new Runnable() {
#Override
public void run() {
try {
//Will wait 15(000) (milli)seconds before stopping with
//trying to connect.
//One second (1000 millis) is for debugging and testing
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waitThread.start();
while (waitThread.isAlive()) {
try {
return new Socket(address, port);
}
catch (ConnectException e) {
//Do nothing, will re-attempt to connect.
}
catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private String getID() {
return ID_field.getText();
}
private String getPassword() {
if (getID().equals("master")) {
return "masterPassword";
}
else {
return new String(passwordField.getPassword());
}
}
}
getConnected() returns true as soon as it's connected to the server. The connector is running on a separate thread.
EDIT: I tried to put code in the getConnected() while block, and then it works. Why does it works then and not else?
I had the same Problem, but with some more specification. The code was working fine in 32bit but I had this issue in 64bit (I am using native library so I need to maintain both).
The solution I found is to add Thread.sleep() in the while loop. I don't know why it works, so your guess is as good as mine.
A better solution would probably to implement an Observer Pattern instead of having an infinite loop. But that would require some re-factoring.
Using Thread.sleep(), as the other answers have suggested, should solve the problem but it is not a very good approach. Instead, we should be using Thread.yield().
Why yield and not sleep?
Refer:
Difference between Thread.Sleep(0) and Thread.Yield() and Are Thread.sleep(0) and Thread.yield() statements equivalent?
Why this works?
When we just run the threads, the OS puts them to "idle" state and when it is expected to "wake-up", it does not. On the other hand, in debug mode, we have a controlled environment. The OS has little control over it as everything goes on step-by-step, slowly. If we run the debug a few times without any break-points, after a few successful runs, we should see the same effect.
I had a very similar problem with a "while" loop that wouldn't run and that loop was my main routine. How I got the loop to run was that the very first thing that was done in the loop was a sleep:
try
{Thread.sleep(0);}
catch (Exception e)
{e.printStackTrace();}
This was enough to get everything going.
I had same problem in UIAutomator with UiObject2 wait(Until.findObject(),20) .
Thread.yield() - works for me

Categories