I'm using Cayenne 3.1B2 at present as the persistence layer for some web services. There's a requirement for the services to expose one of several databases, all with the same schema, the database being determined when the service operation is invoked.
The decision on which database is used needs to be based on the identity of the client invoking the service.
How would I go about defining this and using it at runtime? It seems like I should define 2 datanodes, both referring to the same datamap since all my entities are the same between databases.
But at runtime, would I then somehow create two different Contexts, one for each datanode, and if so how would I specify that for each Context?
Any help is appreciated
Thanks
I would create a single project with a DataMap and single DataNode. Delete its "DataSource Factory" as we'd be specifying it in the code (never tried this, if leaving "DataSource Factory" empty causes any problems on startup, you can set it to any of the provided choices, e.g. JNDIDataSourceFactory, with an understanding that this is just placeholder and will be ignored in runtime).
Now start your 2 ServerRuntimes, each using the same single mapping project, but 2 distinct sets of properties for the DataSource. These properties cause Cayenne to ignore DataSource Factory set in XML.
Module m1 = new Module() {
@Override
public void configure(Binder binder) {
binder.bindMap(Constants.PROPERTIES_MAP)
.put(Constants.JDBC_DRIVER_PROPERTY, "com.my.Driver")
.put(Constants.JDBC_URL_PROPERTY, "jdbc://db1_url")
.put(Constants.JDBC_USERNAME_PROPERTY, "db1login")
.put(Constants.JDBC_PASSWORD_PROPERTY, "db1password");
}
};
Module m2 = new Module() {
@Override
public void configure(Binder binder) {
binder.bindMap(Constants.PROPERTIES_MAP)
.put(Constants.JDBC_DRIVER_PROPERTY, "com.my.Driver")
.put(Constants.JDBC_URL_PROPERTY, "jdbc://db2_url")
.put(Constants.JDBC_USERNAME_PROPERTY, "db2login")
.put(Constants.JDBC_PASSWORD_PROPERTY, "db2password");
}
};
ServerRuntime r1 = new ServerRuntime("cayenne-project.xml", m1);
ServerRuntime r2 = new ServerRuntime("cayenne-project.xml", m2);
r1 and r2 should be application singletons, and you can create ObjectContexts from either one as appropriate for each request. If you are reusing ObjectContexts between requests (e.g. this is a mostly read-only app), you can create 2 contexts from r1 and r2 and also cache them.