0

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?

Community
  • 1
  • 1
oggotron
  • 27
  • 3

1 Answers1

1

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.

andrus_a
  • 2,528
  • 1
  • 16
  • 10
  • This design basically worked for me. The slight complication was that, as well as my custom Resource and ResourceLocator implementations, I also needed to implement some custom URL-related implementations (URLConnection, URLStreamHandler, URLStreamHandlerFactory) in order to look up the resources. The resources are placed in a static map, which is populated by resource name before attempting to create the server runtime. The custom URL classes ultimately look up the resource content in the static map and supply it from there. – oggotron Jun 30 '15 at 17:21