following on from this question:
Apache Cayenne: user-defined tables: examples?
As part of my design, I'm intending to allow operations which modify the database schema at run time. As discussed in the above question, it does seem that Cayenne supports this.
I was interested in how I can supply my new project definition to the ServerRuntime, without using the file system.
After looking at the source it looks as though I have two options:
(1) Implement a custom classloader, set it as the thread-local class loader, and allow Cayenne to find it using ClassLoaderResourceLocator.
(2) Implement a custom ResourceLocator, and bind it in using injection.
It is pretty clear how I would do (1) but arguably (2) is a bit neater as it doesn't rely on the behaviour of ClassLoaderResourceLocator.
Is (2) reasonable, and how would I code this?
Assuming your dynamic project definition is still in XML, a custom ResourceLocator binding is pretty simple and is probably the way to go. So if you have your own XyzResourceLocator, you'd simply do this:
// using lambda for the Module interface (assumes java 8)
ServerRuntime r = new ServerRuntime(
"somelocation",
binder -> binder.bind(ResourceLocator.class)
.to(XyzResourceLocator.class));
How XyzResourceLocator is implemented depends on where your dynamically-generated project definition resides.
Also, looking at the source code I see a small caveat. ResourceLocator is (incorrectly IMO) used in a different context to load some of the internal Cayenne XML descriptors. So when you implement your own locator, you may need to do a check like this:
if(name.endsWith("types.xml")) { .. revert to ClassLoaderResourceLocator ..}
else { .. use your own algorithm .. }
We'll need to decouple these 2 uses in Cayenne eventually.