style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Haciendo un pequeño Callback

Bien ahora que tengo un poco de tiempo describiré que es y como funciona un Callback, que en pocas palabras es una técnica que consiste en crear un objeto y que el objeto creado obtenga una referencia de quien lo instanció y pueda enviarle una respuesta.

Más fácil, los callbacks permiten a un objeto A asignar una tarea a un objeto B, es entonces cuando el objeto B puede notificar al objeto A (de manera asincrónica) cuando la tarea es completada.

Con esto separamos muy bien las responsabilidades entre objetos y mejoramos el uso de recursos :-)

Clase A - Cliente.java

package hss;

public class Cliente {
   
    Cliente(){
        Lanza lanza = new Lanza(this, 8);
        lanza.run();
    }
   
    public static void main(String args[]){
        new Cliente();
    }
   
    public void lanzada(){
        System.out.println("Lanzada!!!");
    }

}

Clase B - Lanza.java

package hss;

public class Lanza {
   
    int intervalo;
    Cliente cliente;
   
    Lanza(Cliente cliente, int intervalo){
        this.intervalo = intervalo;
        this.cliente = cliente;
    }
   
    void run(){
        for (int i = 0; i < intervalo; i++){
            cliente.lanzada();
        }
    }

}

Voy a explicarlo como si corriera en modo de debug, es decir tal cual es el flujo del programa.

Cliente.java - Método main()

    public static void main(String args[]){
        new Cliente();
    }

El método main por default es el primer método invocado, y crea una nueva instancia de la clase Cliente (crea una instancia de la misma clase en la que está)

Cliente.java - Constructor default

    Cliente(){
        Lanza lanza = new Lanza(this, 8);

Al ser instanciada la clase Cliente, el constructor por default es ejecutado, quien a su vez crea una nueva instancia de la clase Lanza y de nombre 'lanza', a quien le manda como parámetros 'this' (que es nuestro objeto Client actual, es como si se enviara él mismo) y un entero (8).

Lanza.java - Constructor que recibe Cliente y entero

    Lanza(Cliente cliente, int intervalo){
        this.intervalo = intervalo;
        this.cliente = cliente;
    }

El constructor de Lanza es ejecutado, recibe el objeto Cliente enviado con 'this' desde el objeto Client y el número entero, luego los copia a el 'Cliente' e 'intervalo' locales.

Cliente.java - Constructor default
        lanza.run();

la ejecución regresa al objeto Cliente y continúa con la siguiente línea en donde ejecuta el método run() del objeto lanza instanciado.

Lanza.java - Método run()

    void run(){
        for (int i = 0; i < intervalo; i++){
            cliente.lanzada();
        }
    }

Se ejecuta el método run() y tomamos la variable 'intervalo' que ya había guardado el constructor para iterar el número de veces que le dijimos.

Cliente.java - Método lanzada()

    public void lanzada(){
        System.out.println("Lanzada!!!");
    }

En cada iteración utilizamos el objeto Cliente que recibió el constructor para lanzar su método 'lanzada()' y reportar a Cliente que Lanza hizo ya lo que tenía que hacer, es aqui donde se realiza el Callback desde la clase instanciada hacia la clase que la instanció!

:::

Como verán, es un poco enredoso el seguimiento de un Callback, pero les sugiero que prueben el código en modo de debug en su IDE preferido para que lo vean correr paso a paso :-P

Espero que esta técnica les sea de utilidad, saludos!

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Interfaces

En la práctica, el autor de Lanza habría hecho una interfaz con el método lanzada(). La clase Cliente tendría que implementar dicha interfaz y así es como funcionan realmente los callbacks. Además es un buen ejemplo del uso de interfaces; a la clase Lanza no le interesa qué otra cosa sepa hacer su callback, solamente necesita que implemente el método lanzada(). Y puede que la clase Lanza venga dentro de una biblioteca de clases que el autor de la clase Cliente está utilizando, de modo que la clase Lanza no sabe nada de la clase Cliente porque de hecho ni siquiera existía cuando la escribieron.

Imagen de Shadonwk

callback en web services

Una disculpa de antemano por revivir el tema pero me gustaría saber si esto es aplicable a web services, ya que específicamente me encuentro en un problema:

Mi aplicación envía información a un servicio web que debe procesarla y la cual tardará algunos minutos en procesar, no deseo que mi cliente se quede esperando hasta que termine sino mas bien que continué el flujo y que cuando el web service termine la chamba notifique al cliente los resultados, creo que la solución es crear un callback pero no encuentro algún ejemplo.

Imagen de ezamudio

no es lo mismo

Shadonwk, no es lo mismo. Tu problema es muy diferente. Lo que sirve en esos casos es que la primera llamada sea a un método que te devuelva un ID con el cual puedas consultar el status de tu operación, llamando otro método al cual le pasas el ID que te dieron y te dice si ya quedó (y te devuelve los resultados) o si todavía no, o si falló, o lo que sea. Ese lo puedes estar llamando periódicamente para ver qué ha pasado.

Imagen de WinDoctor

Server-Sent Event

Puedes utilizar Server-Sent Event para informar al cliente cuando la petición se procese.

Por ejemplo, si estás utilizando Spring, puedes marcar al método con @Async ó utilizar la clase ExecutorService.

En mi blog puedes ver justamente este ejemplo que tu necesitas.

https://windoctor7.github.io/Spring-SSE.html

Imagen de ale_imp

Excelente Post

Muchas gracias, excelente post WinDoctor

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">