Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Detectar TimeOut en un objeto URL o URLConnection

Saludos:

Tengo un objeto URL que hace una consulta a un servicio web que devuelve un JSON. El servicio web es (creo) muy doméstico y no pretende adherirse a ningún estándar tipo SOAP, REST ni similar. Simplemente es una URL con los parámetros pasados por GET y devuelve un JSON.

Pretendo incorporarlo a una aplicación de escritorio para hacer consultas en segundo plano, por lo que necesitaría que el timeout en caso de que no responda el sitio web sea bastante corto y, en todo caso, que sea interrumpible. Como lo estoy haciendo extendiendo SwingWorker lo segundo creo que lo tengo resuelto "de serie", pero querría detectar en el objeto URLConnection (porque con URL creo que no puedo) si se ha superado un tiempo máximo en torno a 1 segundo.

Está el método URLConnection.setTimeout(int timeout), pero en una prueba con setTimeout(1000) no funcionó. Más exactamente, la prueba que hice fue apagar mi router ADSL dejando levantada la conexión WiFi del portátil. Aparentemente, el sistema operativo esperó en torno a un minuto antes de notificarle a Java que la conexión no era posible, pero eso, lógicamente, no me sirve. Dejando de lado la posibilidad de usar las capacidades de SwingWorker para interrumpir el servicio, ¿a alguien se le ocurre otra manera de hacerlo?

Gracias por anticipado.

julio 30, 2013 | Registered Commenterrickiees

¿Te funciona con ésto: http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#setReadTimeout(int)?

julio 30, 2013 | Registered Commenterchoces


¿Te funciona con ésto: http://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#setReadTimeout(int)?

Muchas gracias por contestar. Perdón, escribí de memoria el método y puse uno que no existe. :-) Había probado con URLConnection.setConnectTimeout(int); ahora he añadido URLConnection.setReadTimeout(int), en ambos casos con 1000 milisegundos, y el comportamiento sigue siendo igual. Aclaro, además, que parece que no hay un límite real; he tenido desconectado el router más de 5 minutos y no ha habido ninguna excepción, al menos escupida por la ventana Output de NetBeans. Incluso he tirado abajo la conexión WiFi del portátil y la he vuelto a levantar, sin ningún cambio (el resto del sistema sí se ha dado por enterado; por ejemplo, Dropbox ha perdido la conexión y la ha recuperado).

El código relevante es éste:


protected List<TransvisionResultPair> doInBackground() throws Exception {
InputStream is;
BufferedReader br;
String inputLine;
String sourceLocale;
String targetLocale;
URL transvisionURL;
URLConnection conn;
StringBuilder sb;

sb = new StringBuilder();

transvisionURL = new URL("http://transvision.mozfr.org/?sourcelocale=en-US"
+ "&locale=es-ES&repo=central&search_type=strings&recherche="
+ textToLookup.replace(" ", "+") + "&json");

conn = transvisionURL.openConnection();
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.connect();
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is));

inputLine = br.readLine();
while (inputLine != null) {
sb.append(inputLine);
inputLine = br.readLine();
}
br.close();

// More stuff
}

Probablemente debería probar en Windows (normalmente uso Linux) para confirmar si el problema es de mi código o de las respuestas que da el sistema operativo, ¿verdad?

Gracias de nuevo.

julio 30, 2013 | Registered Commenterrickiees

Prueba a poner esta línea: conn.setReadTimeout(1000);
después de ésta: is = conn.getInputStream();

julio 30, 2013 | Registered Commenterchoces


Prueba a poner esta línea: conn.setReadTimeout(1000);
después de ésta: is = conn.getInputStream();

Perdón por el retraso. Ayer lo probé y lo tuve como tres cuartos de hora esperando el timeout, sin éxito. Probé tanto tirando abajo la conexión WiFi como apagando el router.

He buscado en distintos sitios y mucha gente parecía tener el mismo problema pero, o bien era en Android y se debía a una API defectuosa en las API Level 5 a 8, si no recuerdo mal, o lo que les pasaba es que obtenían el objeto URLConnection para establecer los timeouts, pero luego hacían la conexión desde el objeto URL directamente.

Y a mí seguía sin funcionarme... hasta que ejecutando en modo de depuración y revisando de nuevo alguna documentación de SwingWorker he descubierto el problema. :-)

El problema que tenía yo (como siempre, el problema al final era yo) :-) es que el código que puse lo tenía en el método que declaré con "throws Exception", asumiendo que la excepción aparecería en la consola. Pero no, la excepción la recogía SwingWorker y se limitaba a cancelar el hilo sin más.

Al meter esa parte del código en un try {} catch, ya me aparecen las excepciones. He conseguido obtener dos distintas, una indicando que el host no era conocido (porque conecto a un nombre DNS y tenía la red caída, por lo que el sistema no podía resolverlo) y que la red no es accesible, una vez he metido el nombre DNS y su IP en /etc/hosts y he vuelto a tirar la conexión.

Lo que también he leído durante mis indagaciones, y eso parece que sí que es un fallo una característica de Java, es que si la conexión se abre y se comienzan a recibir datos antes de que se supere el valor de getReadTimeout(), si a continuación el servidor deja de responder ya no se corta la conexión. En ese caso sí sería necesario usar un hilo "vigilante" que forzara la detención en caso necesario, o si se lanza con un SwingWorker, utilizar cancel() o get(long timeout, TimeUnit unit).

Gracias por la ayuda y perdón por haberte hecho perder el tiempo.

julio 31, 2013 | Registered Commenterrickiees