Gradle and Maven both have great support for loading resources from the classpath by convention. *These resources should be placed in "src/main/resources".*
The current/working directory makes no difference since everything is loaded from the classpath by default. I'd recommend setting your database connection info using a module for BOTH test AND production in order to externalize this information from the project file. If you insist on loading the project file from the filesystem directly instead, it is supported as well, but I don't have experience doing it. This way is deprecated, but here you go: A ResourceLocator that can locate resources in the filesystem. Instances of FilesystemResourceLocator are explicitly created by the user and then bound to a DI registry. E.g.: class MyModule implements Module { public void configure(Binder binder) { File dir1 = ... File dir2 = ... binder.bind(ResourceLocator.class). toInstance(new FilesystemResourceLocator(dir1, dir2); } On Thu, Jul 18, 2019 at 12:12 PM Joe Baldwin <jfbald...@earthlink.net> wrote: > Mike, > > status: tried everyone’s recommendations and gradle & cayenne are still > fighting each other > root problem: appears to be connection properties & cayenne config file > path (gradle & cayenne fighting each other) > Question: has anyone actually combined gradle and cayenne together for > both unit & integrated test successfully - if so, what is the best practice > (easy config, and durable)? > > What I have done so far (based on community comments): > > ----------------------------------------------------------------------------------- > > > under Cayenne 3.1, I am using this to provide different connection > properties depending on whether it's a production system, a dev system, > running tests, etc. > > Yes, that was my original strategy, but then John Huss commented: > > "You should only have one project file. You can change the DB connection > properties using a module passed to the runtime. Here's some info: > https://stackoverflow.com/questions/18948418/set-database-path-in-cayenne" > > Of course that link is really old and the code doesn’t work with 4.0.1. > So I hacked a demo with the 4.0.1 classes. Then extrapolated what I > think John Huss was suggesting (in his short comment), and put my > connection properties in a gradle properties file. I could then quickly > set test/integ-test config values from the properties file. > > If I understand John’s implied strategy, here is working-code I hobbled > together (note: CayenneConfPath & ServerModule): > > ServerRuntime cayenneRuntime = ServerRuntime.builder() > .addConfig(CayenneConfPath) > .addModule(binder -> > ServerModule.contributeProperties(binder) > .put(Constants.JDBC_DRIVER_PROPERTY, > driverStr) > .put(Constants.JDBC_URL_PROPERTY, urlStr) > .put(Constants.JDBC_USERNAME_PROPERTY, > userStr) > .put(Constants.JDBC_PASSWORD_PROPERTY, > passwordStr) > ) > .build(); > > Seemed ‘all good’ but not so … Gradle has a “convention over > configuration” stated-philosphy, while Cayenne as a “just dump it into the > classpath root” policy (both are "opinionated"), so the relative paths are > set to the test directories, and if you try to put the cayenne config files > in a single dir (say “main”), then cayenne (via junit5) can’t find the > project files (i.e. CayenneConfPath - which by convention points > Cayenne-Runtime to the Datsource Map). > > OK, so now I have to go “spelunking” … I print out the Gradle “test" & > “main" (main is the production conventions). The paths can be overridden > but it is not recommended - and doing so is problematic (i.e. it is easy to > make mistakes given Gradle-path-convention-behavior). > > So currently, I have added in John’s “Module” suggestion, (which appears > to assume the .addConfig() files are still in the CLASSPATH so as to load > the project-MAP). Thus, I still have to have two versions of the cayenne > config files because Gradle enforces a test-path policy, while Cayenne > enforces a relative-classpath-only policy. > > It appears I am back where I started from. So then I thought this is ‘in > - fricking - sane’ .. there has to be a better way. :) > > The root-cause of the problem (based on experimentation), is that Gradle > has a relative-path convention that does not play-well with cayenne’s > root-classpath convention. (The only way I have found around this problem > is to have multiple copies of cayenne config files (one for each Gradle > context), and then ignore Cayenne-Runtime warnings.) > > Question: > ------------- > Has anyone actually got Cayenne & Gradle working together smoothly (for > automated unit & integration test contexts)? If so, please post some > working examples. > > Thanks > Joe > > > > > > On Jul 17, 2019, at 12:16 PM, Mike Kienenberger <mkien...@gmail.com> > wrote: > > > > For what it's worth, under Cayenne 3.1, I am using this to provide > > different connection properties depending on whether it's a production > > system, a dev system, running tests, etc. This does require that all > > of the config files are in the same package (or are on the classpath > > somewhere) rather than using absolute paths. > > > > String configurationLocation = "com/xyz/cayenne/model/ebpp/" + > > getCayenneXmlFileName(); > > [...] > > runtime = new ServerRuntime( > > configurationLocation, > > moduleArray); > > > > On Wed, Jul 17, 2019 at 12:10 PM John Huss <johnth...@gmail.com> wrote: > >> > >> You should only have one project file. You can change the DB connection > >> properties using a module passed to the runtime. Here's some info: > >> > https://stackoverflow.com/questions/18948418/set-database-path-in-cayenne > >> > >> > >> On Wed, Jul 17, 2019 at 11:01 AM Joe Baldwin <jfbald...@earthlink.net> > >> wrote: > >> > >>> John, > >>> > >>>> What are you trying to override for testing? If it's the database > >>> connection properties there are better ways to do that. > >>> > >>> > >>> The context is automated testing. (i.e. unit and integrated > testing). I > >>> am using the project file to set the connection properties (i.e. mysql, > >>> server-ip). The unit testing will be on a different server from > >>> integrated testing. > >>> > >>> The initial idea is to have gradle perform the unit tests, while have > >>> jenkins orchestrate the integrated testing. > >>> > >>> I assumed that this could be handled via a simple change to the project > >>> file connection parameters. However, with the addConfig assumption of > >>> classpath (disallowing explicit path), coupled with gradle defaults of > >>> adding both main resources AND test resources, cayenne runtime is > >>> complaining that it is finding two project files. In the short run, > I am > >>> relying on Cayenne preferring the first project file found. > >>> > >>> However, this is a short term solution - I would like to replace it > with a > >>> more durable solution. I would like to be able to build various > testing > >>> databases as the need requires and apply connection properties (in a > >>> deterministic but simple-to-modify manner). > >>> > >>>> The typical approach is to put the project file in the root of the > >>> classpath. > >>> > >>> > >>> That is indeed an “approach” but as I summarized in the previous > email, it > >>> disallows explicitly setting the path - so it looks like the *only* > >>> approach - at least based on my experimentation with addConfig() - and > one > >>> that cayenne runtime is complaining about in this case. > >>> > >>> I am trying to come up a connection configuration strategy that uses > >>> cayanne best practices, as well as conforms to gradle and jenkins > >>> capabilities. Just relying on “classpath” is causing problems right > now, > >>> and it does not look reliable (based on the complaints by cayenne > runtime). > >>> > >>> Joe > >>> > >>> > >>> > >>>> On Jul 17, 2019, at 10:54 AM, John Huss <johnth...@gmail.com> wrote: > >>>> > >>>> The typical approach is to put the project file in the root of the > >>>> classpath. > >>>> > >>>> What are you trying to override for testing? If it's the database > >>>> connection properties there are better ways to do that. > >>>> > >>>> On Wed, Jul 17, 2019 at 9:25 AM Joe Baldwin <jfbald...@earthlink.net> > >>> wrote: > >>>> > >>>>> Goal: > >>>>> My goal is to provide an unambiguous (deterministic) path to my > project > >>>>> xml file to ServerRuntime during automated testing (the plan is to > have > >>>>> multiple stages of testing). > >>>>> > >>>>> My understanding is that 4.0.1 uses: > >>>>> ServerRuntime.builder().addConfig() > >>>>> to accomplish this normally. > >>>>> > >>>>> Problems: > >>>>> 1. While trying to understand the behavior of .addConfig(), I have > had > >>> to > >>>>> rely primarily on experiments (i.e. hacking), since I have found no > >>>>> documentation in JavaDocs (addConfig() JavaDoc has no comments). > >>>>> > >>>>> 2. So it appears from my experiments that addConfig() assumes > CLASSPATH > >>>>> referencing and will not accept an explicit path. > >>>>> Example: > >>>>> org.apache.cayenne.configuration.server.DataDomainLoadException: > >>> [v.4.0.1 > >>>>> Dec 20 2018 11:02:32] Configuration resource > >>>>> > "/webdev/cms/src/main/resources/config/cayenne/cayenne-CMSDomain.xml" is > >>>>> not found. > >>>>> Note: > >>>>> If I understand the behavior, addConfig() *only* allows > >>> project-file-path > >>>>> specification relative to one of the paths already specified in the > >>>>> CLASSPATH, and will not accept a full path entry. > >>>>> > >>>>> 3. To further complicate this, during testing, cayenne is complaining > >>> that > >>>>> multiple project files are found in the classpath (gradle, by > default, > >>>>> appears to create a complex classpath that include multiple resource > >>>>> directories that contain the two project files). > >>>>> > >>>>> Note: > >>>>> Currently, I have the test-resources earlier in the classpath > (cayenne > >>>>> runtime appears to select based on classpath positioning). I would > >>> prefer > >>>>> a more explicit solution. > >>>>> > >>>>> > >>>>> Questions: > >>>>> 1. With not much info in the JavaDocs on usage-options, does anyone > have > >>>>> an online reference that could provide more insight (i.e. > alternatives, > >>>>> use-case examples, etc)? > >>>>> > >>>>> 2. Does anyone know of a simpler way to accomplish my goal (i.e. > >>>>> deterministically or explicitly provide the project file to cayenne > >>>>> runtime)? > >>>>> > >>>>> > >>>>> Thanks > >>>>> Joe > >>>>> > >>>>> > >>> > >>> > >