gradlerefactoringjavafx-8multi-projectgriffon

How should the gradle build scripts be to modularize this application?


I am trying to apply an example from the book Gradle in Action to learn how to separate a gradle application into subprojects. I did the example in the book and everything worked out fine.

I decided to apply the same concepts to a sample application from the Griffon Framework called minimalistic build, source code: sources. I selected this application because it follows the normal application structure instead of Griffon's, and I was trying to fill the gap (IMHO) in Griffon's documentation for multi project builds: it has one exaple that uses Open-Dolphin, Swing, JavaFX, Servlets that I felt it was too complicated to learn the basics.

Of course I hit the wall big time, multiple times...

Griffon's JavaFX application has the following structure:

├── build.gradle
├── config
│   └── HEADER
├── gradle
│   ├── functional-test.gradle
│   ├── integration-test.gradle
│   ├── javafx-plugin.gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src
    ├── functional-test
    │   └── java
    │       └── org
    │           └── example
    │               └── SampleFunctionalTest.java
    ├── integration-test
    │   └── java
    │       └── org
    │           └── example
    │               └── SampleIntegrationTest.java
    ├── main
    │   ├── java
    │   │   ├── Config.java
    │   │   └── org
    │   │       └── example
    │   │           ├── Launcher.java
    │   │           ├── SampleController.java
    │   │           ├── SampleModel.java
    │   │           ├── SampleService.java
    │   │           └── SampleView.java
    │   └── resources
    │       ├── application.properties
    │       ├── griffon-icon-128x128.png
    │       ├── griffon-icon-16x16.png
    │       ├── griffon-icon-24x24.png
    │       ├── griffon-icon-256x256.png
    │       ├── griffon-icon-32x32.png
    │       ├── griffon-icon-48x48.png
    │       ├── griffon-icon-64x64.png
    │       ├── griffon.png
    │       ├── log4j.properties
    │       ├── messages.properties
    │       ├── META-INF
    │       │   └── griffon
    │       │       ├── griffon.core.artifact.GriffonController
    │       │       ├── griffon.core.artifact.GriffonModel
    │       │       ├── griffon.core.artifact.GriffonService
    │       │       └── griffon.core.artifact.GriffonView
    │       ├── org
    │       │   └── example
    │       │       └── sample.fxml
    │       └── resources.properties
    └── test
        └── java
            └── org
                └── example
                    ├── SampleControllerTest.java
                    └── SampleServiceTest.java

The build.gradle file content is:

// tag::plugins[]
plugins {
    id 'java'
    id 'idea'
    id 'com.github.ben-manes.versions' version '0.12.0'
    id 'com.github.hierynomus.license' version '0.11.0'
}

apply from: 'gradle/javafx-plugin.gradle'
apply from: 'gradle/integration-test.gradle'
apply from: 'gradle/functional-test.gradle'
// end::plugins[]

// tag::javafx[]
javafx {
    mainClass = 'org.example.Launcher'
}
// end::javafx[]

// tag::dependencies[]

repositories {
    jcenter()
    mavenLocal()
}

dependencies {
    compile "org.codehaus.griffon:griffon-javafx:${griffonVersion}"
    compile "org.codehaus.griffon:griffon-guice:${griffonVersion}"

    runtime('log4j:log4j:1.2.17') {
        exclude group: 'ant',         module: 'ant-nodeps'
        exclude group: 'ant',         module: 'ant-junit'
        exclude group: 'ant-contrib', module: 'ant-contrib'
    }
    runtime 'org.slf4j:slf4j-log4j12:1.7.21'

    testCompile "org.codehaus.griffon:griffon-javafx-test:${griffonVersion}"
    testCompile 'pl.pragmatists:JUnitParams:1.0.5'
    testCompile 'org.mockito:mockito-core:2.0.59-beta'
}
// end::dependencies[]

// tag::resources[]
processResources {
    from(sourceSets.main.resources.srcDirs) {
        exclude '**/*.properties'
        exclude '**/*.xml'
    }
    from(sourceSets.main.resources.srcDirs) {
        include '**/*.properties'
        include '**/*.xml'
        filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
            'application.name'   : project.name,
            'application.version': project.version,
            'griffon.version'    : griffonVersion
            ])
    }
}
// end::resources[]

license {
    header = rootProject.file('config/HEADER')
    strictCheck = true
    ignoreFailures = true
    mapping {
        java = 'SLASHSTAR_STYLE'
        fxml = 'XML_STYLE'
    }
    ext.year = '2016'
    exclude '**/*.png'
}

And the structure I was trying to achieve is:

├── build.gradle
├── config
│   └── HEADER
├── gradle
│   ├── functional-test.gradle
│   ├── integration-test.gradle
│   ├── javafx-plugin.gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── launcher
│   ├── launcher-build.gradle
│   └── src
│       └── main
│           └── java
│               ├── Config.java
│               └── org
│                   └── example
│                       └── Launcher.java
├── resources
│   ├── resources-build.gradle
│   └── src
│       └── main
│           └── resources
│               ├── application.properties
│               ├── griffon-icon-128x128.png
│               ├── griffon-icon-16x16.png
│               ├── griffon-icon-24x24.png
│               ├── griffon-icon-256x256.png
│               ├── griffon-icon-32x32.png
│               ├── griffon-icon-48x48.png
│               ├── griffon-icon-64x64.png
│               ├── griffon.png
│               ├── log4j.properties
│               ├── messages.properties
│               └── resources.properties
├── service
│   ├── resources
│   │   └── META-INF
│   │       └── griffon
│   │           └── griffon.core.artifact.GriffonController
│   ├── service-build.gradle
│   └── src
│       ├── main
│       │   └── java
│       │       └── org
│       │           └── example
│       │               └── SampleService.java
│       └── test
│           └── java
│               └── org
│                   └── example
│                       └── SampleServiceTest.java
├── settings.gradle
└── view
    ├── src
    │   ├── functional-test
    │   │   └── java
    │   │       └── org
    │   │           └── example
    │   │               └── SampleFunctionalTest.java
    │   ├── integration-test
    │   │   └── java
    │   │       └── org
    │   │           └── example
    │   │               └── SampleIntegrationTest.java
    │   ├── main
    │   │   ├── java
    │   │   │   └── org
    │   │   │       └── example
    │   │   │           ├── SampleController.java
    │   │   │           ├── SampleModel.java
    │   │   │           └── SampleView.java
    │   │   └── resources
    │   │       ├── META-INF
    │   │       │   └── griffon
    │   │       │       ├── griffon.core.artifact.GriffonModel
    │   │       │       ├── griffon.core.artifact.GriffonService
    │   │       │       └── griffon.core.artifact.GriffonView
    │   │       └── org
    │   │           └── example
    │   │               └── sample.fxml
    │   └── test
    │       └── java
    │           └── org
    │               └── example
    │                   └── SampleControllerTest.java
    └── view-build.gradle

I don't know if that structure is the one that makes more sense, but is the one I first thought of.

Regardless everything I tried I could not build this project and I am wondering if anyone could tell me if I made a mistake with the selection of the subprojects and what should be the content for the build files.

I created a zip file with the rearranged source here keeping the original build.gradle file untouched, with a settings.gradle file that makes Gradle properly recognize the new structure.

Thanks!


Solution

  • The problem is caused by missing resource files in the service project. You'll find a similar problem in the view project. This is is because all resource files were moved to another location (the resources project). There was no problem before splitting the application into subprojects because all resources were at the right place.

    You can fix the build by following these steps:

    $ cd service
    $ mkdir -p src/test/resources
    $ touch src/test/resources/Config.properties
    $ mkdir -p src/main/resources
    $ mv ../resources/src/main/resources/messages.properties src/main/resources/
    
    $ cd ../view
    $ mkdir -p src/test/resources
    $ touch src/test/resources/Config.properties
    

    This should be enough to make the tests green again.