9. Cliente/Servidor


Ahora que hemos visto como trabajan conceptualmente las transacciones en db4o, estamos preparados para atacar las transacciones de ejecución concurrente.

Comenzamos preparando nuestra base de datos de la forma acostumbrada.


[setFirstCar]
Pilot pilot=new Pilot("Rubens Barrichello",99);
Car car=new Car("BMW");
car.setPilot(pilot);
db.set(car);



[setSecondCar]
Pilot pilot=new Pilot("Michael Schumacher",100);
Car car=new Car("Ferrari");
car.setPilot(pilot);
db.set(car);



    9.1. Servidor integrado


    Desde el lado de la API, no hay diferencia entre transacciones ejecutandose concurrentemente dentro de la misma VM y transacciones ejecutandose desde un servidor remoto. Para usar transacciones concurrentes dentro de una misma VM, simplemente abrimos un servidor db4o en nuestro archivo de base de datos, configurándolo para que corra sobre el puerto 0, de ese modo estamos declarando que no se va a llevar a cabo ningún tipo de conexión de red.


    [accessLocalServer]
    ObjectServer server=Db4o.openServer(Util.YAPFILENAME,0);
    try {
        ObjectContainer client=server.openClient();
        // Do something with this client, or open more clients
        client.close();
    }
    finally {
        server.close();
    }


    De nuevo, vamos a delegar la apertura y el cierre del servidor a nuestro ambiente para concentrarnos en las interacciones del cliente.


    [queryLocalServer]
    ObjectContainer client=server.openClient();
    listResult(client.get(new Car(null)));
    client.close();


    El nivel de transacción en db4o es cometido de lectura. Sin embargo, cada contenedor cliente mantiene su propio cache con referencias débiles a objetos ya conocidos. Para cometer todos los cambios por otros clientes inmediatamente, tenemos que refrescar explícitamente los objetos conocidos desde el servidor. Vamos a delegar esta tarea a una versión especializada de nuestro método listResult().


    public static void listRefreshedResult{
        System.out.println(result.size());
        while(result.hasNext()) {
            Object obj = result.next();
            container.ext().refresh(obj, depth);
            System.out.println(obj);
        }
    }



    [demonstrateLocalReadCommitted]
    ObjectContainer client1=server.openClient();
    ObjectContainer client2=server.openClient();
    Pilot pilot=new Pilot("David Coulthard",98);
    ObjectSet result=client1.get(new Car("BMW"));
    Car car=(Car)result.next();
    car.setPilot(pilot);
    client1.set(car);
    listResult(client1.get(new Car(null)));
    listResult(client2.get(new Car(null)));
    client1.commit();        
    listResult(client1.get(Car.class));
    listRefreshedResult(client2,client2.get(Car.class),2);
    client1.close();
    client2.close();


    Vueltas a estados anteriores simples funcionan como debería de esperarse ahora.


    [demonstrateLocalRollback]
    ObjectContainer client1=server.openClient();
    ObjectContainer client2=server.openClient();
    ObjectSet result=client1.get(new Car("BMW"));
    Car car=(Car)result.next();
    car.setPilot(new Pilot("Someone else",0));
    client1.set(car);
    listResult(client1.get(new Car(null)));
    listResult(client2.get(new Car(null)));
    client1.rollback();
    client1.ext().refresh(car,2);
    listResult(client1.get(new Car(null)));
    listResult(client2.get(new Car(null)));
    client1.close();
    client2.close();



    9.2. Gestión de red


    Desde acá es solo un pequeño paso hacia el operar db4o sobre una red TCP/IP. Simplemente especificamos un puerto de número mas alto que cero y creamos una o mas cuentas para nuestro(s) cliente(s).


    [accessRemoteServer]
    ObjectServer server=Db4o.openServer(Util.YAPFILENAME,PORT);
    server.grantAccess(USER,PASSWORD);
    try {
        ObjectContainer client=Db4o.openClient("localhost",PORT,USER,PASSWORD);
        // Do something with this client, or open more clients
        client.close();
    }
    finally {
        server.close();
    }


    El cliente se conecta enviando el servidor, puerto, nombre de usuario y contraseña.


    [queryRemoteServer]
    ObjectContainer client=Db4o.openClient("localhost",port,user,password);
    listResult(client.get(new Car(null)));
    client.close();


    Todo lo demás es absolutamente idéntico a los ejemplos locales de mas arriba.


    [demonstrateRemoteReadCommitted]
    ObjectContainer client1=Db4o.openClient("localhost",port,user,password);
    ObjectContainer client2=Db4o.openClient("localhost",port,user,password);
    Pilot pilot=new Pilot("Jenson Button",97);
    ObjectSet result=client1.get(new Car(null));
    Car car=(Car)result.next();
    car.setPilot(pilot);
    client1.set(car);
    listResult(client1.get(new Car(null)));
    listResult(client2.get(new Car(null)));
    client1.commit();
    listResult(client1.get(new Car(null)));
    listRefreshedResult(client2,client2.get(Car.class),2);
    client1.close();
    client2.close();



    [demonstrateRemoteRollback]
    ObjectContainer client1=Db4o.openClient("localhost",port,user,password);
    ObjectContainer client2=Db4o.openClient("localhost",port,user,password);
    ObjectSet result=client1.get(new Car(null));
    Car car=(Car)result.next();
    car.setPilot(new Pilot("Someone else",0));
    client1.set(car);
    listResult(client1.get(new Car(null)));
    listResult(client2.get(new Car(null)));
    client1.rollback();
    client1.ext().refresh(car,2);
    listResult(client1.get(new Car(null)));
    listResult(client2.get(new Car(null)));
    client1.close();
    client2.close();



    9.3. Conclusión


    Eso es todo amigos. No, por supuesto que no es así. A mucho mas sobre db4o que no hemos cubierto aun: esquema de evolución, persistencia personalizada para sus clases, como escribir sus propios objetos de consulta, etc.

    Este tutorial esta en construcción. Vamos a agregar capítulos exitosamente y a incorporar contribuciones de la comunidad en los capítulos existentes.

    Esperamos que este tutorial le haya ayudado a dar sus primeros pasos con db4o. Como debería continuar de ahora en mas ?

    -(Solo en versión interactiva)Mientras este tutorial es básicamente secuencial en naturaleza, intenta ir y venir por los capítulos y ejecutar los códigos de ejemplo en orden aleatorio. Durante este tiempo, estará usando la misma base de datos; a veces se estancará o hasta producirá excepciones, pero siempre puede reiniciar la base de datos vía consola.

    - Los ejemplos en los que hemos trabajado están incluidos en su distribución de db4o con todo su código fuente. Siéntase libre de experimentar con el.

    - Si se estanca, vea si el FAQ puede resolver su problema, navegue la informacion en nuestro sitio web, verifique si su problema ah sido registrado con Bugzilla o únase a nuestro grupo de noticias en news://news.db4odev.com/db4o.users.



    9.4. Fuente completo



    package com.db4o.f1.chapter5;

    import java.io.*;
    import com.db4o.*;
    import com.db4o.f1.*;


    public class ClientServerExample extends Util {
        private final static int PORT=0xdb40;
        private final static String USER="user";
        private final static String PASSWORD="password";
        
        public static void main(String[] args) throws IOException {
            new File(Util.YAPFILENAME).delete();
            accessLocalServer();
            new File(Util.YAPFILENAME).delete();
            ObjectContainer db=Db4o.openFile(Util.YAPFILENAME);
            try {
                setFirstCar(db);
                setSecondCar(db);
            }
            finally {
                db.close();
            }
            configureDb4o();
            ObjectServer server=Db4o.openServer(Util.YAPFILENAME,0);
            try {
                queryLocalServer(server);
                demonstrateLocalReadCommitted(server);
                demonstrateLocalRollback(server);
            }
            finally {
                server.close();
            }
            accessRemoteServer();
            server=Db4o.openServer(Util.YAPFILENAME,PORT);
            server.grantAccess(USER,PASSWORD);
            try {
                queryRemoteServer(PORT,USER,PASSWORD);
                demonstrateRemoteReadCommitted(PORT,USER,PASSWORD);
                demonstrateRemoteRollback(PORT,USER,PASSWORD);
            }
            finally {
                server.close();
            }
        }
            
        public static void setFirstCar(ObjectContainer db) {
            Pilot pilot=new Pilot("Rubens Barrichello",99);
            Car car=new Car("BMW");
            car.setPilot(pilot);
            db.set(car);
        }

        public static void setSecondCar(ObjectContainer db) {
            Pilot pilot=new Pilot("Michael Schumacher",100);
            Car car=new Car("Ferrari");
            car.setPilot(pilot);
            db.set(car);
        }

        public static void accessLocalServer() {
            ObjectServer server=Db4o.openServer(Util.YAPFILENAME,0);
            try {
                ObjectContainer client=server.openClient();
                // Do something with this client, or open more clients
                client.close();
            }
            finally {
                server.close();
            }
        }

        public static void queryLocalServer(ObjectServer server) {
            ObjectContainer client=server.openClient();
            listResult(client.get(new Car(null)));
            client.close();
        }

        public static void configureDb4o() {
            Db4o.configure().objectClass(Car.class).updateDepth(3);
        }
        
        public static void demonstrateLocalReadCommitted(ObjectServer server) {
            ObjectContainer client1=server.openClient();
            ObjectContainer client2=server.openClient();
            Pilot pilot=new Pilot("David Coulthard",98);
            ObjectSet result=client1.get(new Car("BMW"));
            Car car=(Car)result.next();
            car.setPilot(pilot);
            client1.set(car);
            listResult(client1.get(new Car(null)));
            listResult(client2.get(new Car(null)));
            client1.commit();        
            listResult(client1.get(Car.class));
            listRefreshedResult(client2,client2.get(Car.class),2);
            client1.close();
            client2.close();
        }

        public static void demonstrateLocalRollback(ObjectServer server) {
            ObjectContainer client1=server.openClient();
            ObjectContainer client2=server.openClient();
            ObjectSet result=client1.get(new Car("BMW"));
            Car car=(Car)result.next();
            car.setPilot(new Pilot("Someone else",0));
            client1.set(car);
            listResult(client1.get(new Car(null)));
            listResult(client2.get(new Car(null)));
            client1.rollback();
            client1.ext().refresh(car,2);
            listResult(client1.get(new Car(null)));
            listResult(client2.get(new Car(null)));
            client1.close();
            client2.close();
        }

        public static void accessRemoteServer() throws IOException {
            ObjectServer server=Db4o.openServer(Util.YAPFILENAME,PORT);
            server.grantAccess(USER,PASSWORD);
            try {
                ObjectContainer client=Db4o.openClient("localhost",PORT,USER,PASSWORD);
                // Do something with this client, or open more clients
                client.close();
            }
            finally {
                server.close();
            }
        }

        public static void queryRemoteServer(int port,String user,String password) throws IOException {
            ObjectContainer client=Db4o.openClient("localhost",port,user,password);
            listResult(client.get(new Car(null)));
            client.close();
        }

        public static void demonstrateRemoteReadCommitted(int port,String user,String password) throws IOException {
            ObjectContainer client1=Db4o.openClient("localhost",port,user,password);
            ObjectContainer client2=Db4o.openClient("localhost",port,user,password);
            Pilot pilot=new Pilot("Jenson Button",97);
            ObjectSet result=client1.get(new Car(null));
            Car car=(Car)result.next();
            car.setPilot(pilot);
            client1.set(car);
            listResult(client1.get(new Car(null)));
            listResult(client2.get(new Car(null)));
            client1.commit();
            listResult(client1.get(new Car(null)));
            listRefreshedResult(client2,client2.get(Car.class),2);
            client1.close();
            client2.close();
        }

        public static void demonstrateRemoteRollback(int port,String user,String password) throws IOException {
            ObjectContainer client1=Db4o.openClient("localhost",port,user,password);
            ObjectContainer client2=Db4o.openClient("localhost",port,user,password);
            ObjectSet result=client1.get(new Car(null));
            Car car=(Car)result.next();
            car.setPilot(new Pilot("Someone else",0));
            client1.set(car);
            listResult(client1.get(new Car(null)));
            listResult(client2.get(new Car(null)));
            client1.rollback();
            client1.ext().refresh(car,2);
            listResult(client1.get(new Car(null)));
            listResult(client2.get(new Car(null)));
            client1.close();
            client2.close();
        }
    }





    --
    generated by
    Doctor courtesy of db4objecs Inc.