You are here: Client-Server > Embedded

Embedded

From the API side, there's no real difference between transactions executing concurrently within the same VM and transactions executed against a remote server. To use concurrent transactions within a single VM, we just open a db4o server on our database file, directing it to run on port 0, thereby declaring that no networking will take place.

ClientServerExample.java: accessLocalServer
private static void accessLocalServer()  {
    ObjectServer server = Db4oClientServer.openServer(Db4oClientServer
        .newServerConfiguration(), DB4O_FILE_NAME, 0);
    try  {
      ObjectContainer client = server.openClient();
      // Do something with this client, or open more clients
      client.close();
    } finally  {
      server.close();
    }
  }

Again, we will delegate opening and closing the server to our environment to focus on client interactions.

ClientServerExample.java: queryLocalServer
private static void queryLocalServer(ObjectServer server)  {
    ObjectContainer client = server.openClient();
    listResult(client.queryByExample(new Car(null)));
    client.close();
  }

The transaction level in db4o is read committed. However, each client container maintains its own weak reference cache of already known objects. To make all changes committed by other clients immediately, we have to explicitly refresh known objects from the server. We will delegate this task to a specialized version of our listResult() method.

ClientServerExample.java: listRefreshedResult
private static<T> void listRefreshedResult(ObjectContainer container,
      List<T> result, int depth)  {
    System.out.println(result.size());
    for (T t : result)  {
      container.ext().refresh(t, depth);
      System.out.println(t);
    }
  }

ClientServerExample.java: demonstrateLocalReadCommitted
private static void demonstrateLocalReadCommitted(ObjectServer server)  {
    ObjectContainer client1 = server.openClient();
    ObjectContainer client2 = server.openClient();
    Pilot pilot = new Pilot("David Coulthard", 98);
    List<Car> result = client1.queryByExample(new Car("BMW"));
    Car car = result.queryByExample(0);
    car.setPilot(pilot);
    client1.store(car);
    listResult(client1.queryByExample(new Car(null)));
    listResult(client2.queryByExample(new Car(null)));
    client1.commit();
    listResult(client1.queryByExample(Car.class));
    listRefreshedResult(client2, client2.queryByExample(Car.class), 2);
    client1.close();
    client2.close();
  }

Simple rollbacks just work as you might expect now.

ClientServerExample.java: demonstrateLocalRollback
private static void demonstrateLocalRollback(ObjectServer server)  {
    ObjectContainer client1 = server.openClient();
    ObjectContainer client2 = server.openClient();
    List<Car> result = client1.queryByExample(new Car("BMW"));
    Car car = result.queryByExample(0);
    car.setPilot(new Pilot("Someone else", 0));
    client1.store(car);
    listResult(client1.queryByExample(new Car(null)));
    listResult(client2.queryByExample(new Car(null)));
    client1.rollback();
    client1.ext().refresh(car, 2);
    listResult(client1.queryByExample(new Car(null)));
    listResult(client2.queryByExample(new Car(null)));
    client1.close();
    client2.close();
  }

Download example code:

Java