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 <[email protected]> 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 <[email protected]> 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 <[email protected]>
>> 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 <[email protected]> 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 <[email protected]>
>>> 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
>>>>> 
>>>>> 
>>> 
>>> 

Reply via email to