Gradle sets incorrect (unexpected?) classpath on running task - java

I have my project structured in this way:
projectRoot
+-src
+-main
| +-java
| | +-package/java files go here
| +-resources
| +-config
| +-files go here
+-test
+-java
| +-package/java files go here
+-resources
+-config
| +-files go here
+-features
+-files go here
When this project is built, it produces the following output structure:
projectRoot
+-out
+-production
| +-classes
| | +-package/classes in here
| +-resources
| +-config
| +-files in here
+-test
+-classes
| +-package/classes in here
+-resources
+-config
| +-files in here
+-features
+-files in here
This is all as expected. I have a task defined to run cucumber tests, which looks like this:
task runCucumber() {
doLast {
javaexec {
main = "cucumber.api.cli.Main"
args += ['--plugin', 'pretty', '--plugin', 'html:out/reports/cucumber/', '--plugin', 'json:out/reports/cucumber/report.json',
'--glue', 'com.example.mypackage.cucumber', 'classpath:features'
, '--tags', 'not #ignore']
systemProperties['http.keepAlive'] = 'false'
systemProperties['http.maxRedirects'] = '20'
systemProperties['env'] = System.getProperty("env")
systemProperties['envType'] = System.getProperty("envType")
classpath = configurations.cucumber + configurations.compile + configurations.testCompile + sourceSets.main.runtimeClasspath + sourceSets.test.runtimeClasspath
}
}
}
When I execute this task, my classes are not found and neither are features. Clearly, this is due to classpath not being set correctly. If I run the task with --info, I can see that the classpath is set using the parameter I indicated, however instead of out directories, it contains build directories. I expected the classpath to be:
<all dependencies>:/projectRoot/out/production/classses:/projectRoot/out/production/resources:/projectRoot/out/test/classes:/projectRoot/out/test/resources
Yet, the classpath contains the following:
<all dependencies>:/projectRoot/build/classes/java/main:/projectRoot/build/classes/java/test:
Interestingly, directory build is not produced at all under the project root. How can I set the classpath so that classes and resources can be found?

Ok, turned out the issue was not with Gradle but with IntelliJ IDEA. IDEA was overriding standard gradle paths and saving output in a different path from the one that gradle expected. Then, when the next gradle task ran, the output wasn't there. Compiling directly using gradle instead of IDEA solved the problem.

Related

Moving packages in IntelliJ IDEA

I have a problem moving packages in IntelliJ IDEA. I have created Maven project with multiple modules and each of those modules has a package with the same name. Now whole project becomes a mess if I try to rename some of the packages.
My current project structure is something like this:
--parent-module
|
|--module-one
| |--src
| |--main
| |--java
| |--somepackage
| |--someotherpackages
|--module-two
| |--src
| |--main
| |--java
| |--somepackage
| |--somemorepackages
|--module-three
|--src
|--main
|--java
|--somepackage
|--someevenmorepackages
Notice that somepackage is present in all maven modules.
After MANY created classes in all of those modules and packages I have finally realised what have I done. Now I need to put somepackage into another package under java so I can have something like com.example.moduleone.somepackage.
I have tried renaming package but it renames it in all modules and that creates hailstorm of errors in the code. Also, IntelliJ IDEA renames it to com.example.moduleone.somepackage in all of the modules.
Any help would be highly appreciated.
Might be easiest to create the new package first and then move the classes you want to move into it and then delete somepackage once everything have been moved around
So first add moduleone, then move all of the classes you want to move, then do the same for the other modules, then delete somepackage
Right click to Project name > New> Module..> chose java version and set name for new module.
Drag your packpage your want move to new-module/src > OK > Refactor.
Rebuild project. Find erro : java: packpage dose not exist. Fix it by: Go to erro code > Atl+Enter > Add depedency on module..

Create production configuration with additional compile dependency in Gradle

I am trying to define build script for my production versions.
Below is project structure, all projects are java plugin.
wrapper (parent)
|--frontend (child)
| |--src
| | |--js (raw ES6 modules)
| | |--sass (raw)
| |--build
| |--lib
| | |--production-front.jar
| |--dist
| |--js (bundled)
| |--css (compiled production)
|--backend (child) (spring boot)
|--build
|--lib
|--RELEASE.jar
Now what happens here is that by default (sourceSets.main.resources.srcDirs) of backend is linked directly to:
raw :frontent/src/js
generated :frontent/build/dist/css.
This way when you run it, by default it will be in dev mode. Here it means that it will:
use generated scss->css files (which are resource so for example if you run background gulp-sass that compiles it every time you change scss, css will update and boom, fast dev cycle).
use raw JS which is compiled directly in browser (JSPM, SystemJS, Babel) - so you only need to edit :frontent/src/js and refresh page.
Okay, so while dev is love, I also need to compile for production. Project structure mentioned above also shows where :frontend generates production-front.jar.
Here is default java build tree with my notes.
EDIT
I need to make dependency that will compile production-front.jar into RELEASE.jar and ommit mentioned attached resources.
Note that I need to only ommit those resources, not any others in main.resources.srcDirs.
What is proper way to solve this (one that is not making tasks that e.g remove dev resources from .jar and then throw in other production-front.jar instead)? I cannot grasp how would i make multiple sourceSets or configurations that work here.
After very in-depth Gradle learning for over past week (this topic was created because I was close to my demise) I've finally found very satisfying solution.
I'd like to share what were my goals and final solution:
Have smallest possible build.gradle
Have possibility to develop with build --continuous
Make it so that eclipse plugin (probably also other IDEs) can perfectly mirror pure command line Gradle development with their own build system.
This is a multi-project with one of them being Spring Boot application with DevTools.
wrapper (parent)
|--frontend (child)
| |--src-client
| | |--static
| | | |--img (images)
| | | \--js (raw ES6 modules)
| | \--sass (raw, note not in static folder)
| \--build
| |--lib
| | \--front.jar
| |--dist
| | |--js (bundled, minimized)
| | \--css (compiled production, minimized)
| \--dev
| \--css (compiled dev, compact readable format)
\--backend (child) (spring boot)
|--src
| |--main/java
| |--main/resources
| \--test/java
\--build
\--lib
\--application.jar
As I described, goals were to:
Have bootRun run with raw sources for js and compiled css, but also with every resource that is included in backend's main.
Have bootJar compile into production with dependency on compiled front.jar instead of everything that is used in dev (previous point).
I've used combination of configurations, sourceSets and bootRun properties (+ a lot of time).
Here are files (stripped down):
wrapper/build.gradle
wrapper.gradleVersion '5.0-milestone-1'
allprojects {
apply plugin: 'eclipse'
}
wrapper/front/build.gradle
plugins {
id 'java' // possibly use java-base or just custom zip task, since client doesn't actually compile java
}
jar {
dependsOn buildProduction // task that compiles my stuff into build/dist
baseName 'front'
classifier 'SNAPSHOT-' + new Date().format('yyyyMMddHHmmss')
from(buildDir.absolutePath + '/dist') {
into 'static'
}
}
// Note there is a lot of other tasks here that actually compile my stuff, like gulp-sass and JSPM bundling with babel transpiler.
wrapper/backend/build.gradle
buildscript {
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.1.0.RC1'
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
sourceCompatibility = 10 // eclipse has (or had) problems with Java 11
targetCompatibility = 10
sourceSets {
// 'java' plugin adds default main sourceSet
dev {
resources.srcDirs = [
project(':front').projectDir.absolutePath + '/src-client',
project(':front').buildDir.absolutePath + '/dev'
]
}
}
bootJar {
baseName 'application'
classifier 'SNAPSHOT-' + new Date().format('yyyyMMddHHmmssSSS')
// I used bootArchives since it was already there and my stuff fits description, you can also define your own configuration and extend runtime one.
classpath configurations.bootArchives
}
bootRun {
sourceResources sourceSets.dev // I make bootRun (dev) use dev sourceSet
}
dependencies {
runtime 'org.springframework.boot:spring-boot-devtools'
// Since bootArchives configuration is used only by bootJar (not bootRun), this will be only in final fat .jar
bootArchives project(':front')
...
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
Some link that helped:
http://mrhaki.blogspot.com/2014/09/gradle-goodness-adding-dependencies.html
Note that client's source folder is called src-client: This is key for making "perfect mirror" in eclipse. If we would name it src which is already being used by main in backend eclipse would vomit with name clash (which probably can be fixed by configurating eclipse plugin, but then again - we wanted to keep it simple, without IDE configurations).
As final result we get very nice command line development with gradle's continuous building and also EXACTLY mirrored behaviour in eclipse which defaults its configuration to work in the same way (but use eclipse's builder instead of gradle's). We also get nice linked folders in backend project to sources used from front. Same would probably apply to IDEA :).

Building with Intellij 2017.2 /out directory duplicates files in /build directory

After updating to Intellij 2017.2, building my project creates an /out directory that contains generated source files and resource files. These files duplicate files that are already contained in /build and result in duplicate class compiler errors for the generated classes. Any ideas on a fix I need in Gradle or IntelliJ?
IntelliJ IDEA is no longer sharing the output with Gradle, please see this ticket for details.
You can either override it via the following configuration:
allprojects {
apply plugin: 'idea'
idea {
module {
outputDir file('build/classes/main')
testOutputDir file('build/classes/test')
}
}
if(project.convention.findPlugin(JavaPluginConvention)) {
// Change the output directory for the main and test source sets back to the old path
sourceSets.main.output.classesDir = new File(buildDir, "classes/main")
sourceSets.test.output.classesDir = new File(buildDir, "classes/test")
}
}
or delegate the build to Gradle: File | Settings | Build, Execution, Deployment | Build Tools | Gradle | Runner => Delegate IDE build/run actions to gradle.
File | Project Structure | Project Settings | Modules | Paths tab | Compiler output
Select 'Inherit project compile output path' to continue using /build for build artifacts
Here is my understanding:
Basically, this is a work-around for an incompatibility issue between
Gradle build path and IDEA output path.
the issue is - https://github.com/gradle/gradle/issues/2315
the solution is - keep these two directories seperate, therefore you have two (out/ and build/) https://youtrack.jetbrains.com/issue/IDEA-189063

Build jar and put in resources that are built into another jar with gradle

So I have two gradle projects: P1 and P2. P2 does not depend on P1 to build, however, during the build phase of P2, I want to build P1, add it to my resources folder and then add that folder to P2's jar.
I am still new to the whole gradle thing, so I am looking for an example build.gradle that would do something like this.
Thanks!
EDIT: It should be noted that P1 and P2 are both modules within the same project.
My project structure looks like this:
Root Project
Root Project
|
|__P1
| |
| |__build.grdale
|
|__P2
| |
| |__build.gradle
|
|__settings.gradle
My settings.gradle looks like this:
include 'P1', 'P2'
So I ended up finding a similar question here: Gradle: how to copy subproject jar to another subproject when task is run?
The build gradle should end up looking something like this:
task fix(dependsOn: ':P1:jar', type: Copy) {
from tasks.getByPath(':P1:jar')
into 'path/to/resources'
}
build.dependsOn fix

Scaffolding in Gradle

Whenever I start a new Java+Gradle project, I create the following directory structure manually:
project-name
|
|--- build.gradle
|
|--- .gitignore
|
|--- src
|--- main
| |---java
|
|--- test
|---java
Since this is a fairly standard structure, I imagine there must be a plugin/command/task for Gradle that would do this scaffolding for me. Is there such a plugin/command/task available? If not, can I write a task for that?
The following does the trick:
gradle init --type java-library
The task is provided by the init plugin
I achieved this kind of scaffolding using an init script. Have a look at my blog post about it.
There is a templates plugin available on github

Categories

Resources