I am trying to run a Java class as a gradle task.
I have added this to my build.gradle:
task(downloadKeystore, dependsOn: 'classes', type: JavaExec) {
main = 'com.orbitbenefits.keystore.KeystoreDownloader'
}
However, when I run on the command line gradle downloadKeystore, it fails with the following error:
:Noa:downloadKeystoreError: Could not find or load main class com.orbitbenefits.keystore.KeystoreDownloader
So I have added a classpath to my task as specified in this question:
task(downloadKeystore, dependsOn: 'classes', type: JavaExec) {
main = 'com.orbitbenefits.keystore.KeystoreDownloader'
classpath = sourceSets.main.runtimeClasspath
}
However, this is large legacy project with extremely long classpath, so when I run gradle downloadKeystore I get another error:
Caused by: java.io.IOException: Cannot run program "C:\Program Files\Java\jdk1.8.0_77\bin\java.exe" (in directory "C:\Users\pawlakj\IdeaProjects\noa\Noa"): CreateProcess error=206, The filename or extension is too long
So I have modified my sourceSets in build.gradle so it now looks like this:
sourceSets {
main {
java {
srcDirs(...)
}
resources {
srcDirs(...)
}
}
keystore {
java {
srcDirs = ['src/test/java/com/orbitbenefits/keystore']
}
}
test {
java {
srcDirs(...)
}
resources {
srcDirs(...)
}
}
}
...
task(downloadKeystore, dependsOn: 'classes', type: JavaExec) {
main = 'com.orbitbenefits.keystore.KeystoreDownloader'
classpath = sourceSets.keystore.runtimeClasspath
}
This works on the command line, however when I run gradle refresh in IntelliJ, it generally breaks the project. It looks like this:
But it should look like this:
I have tried manually setting test/src root directories but it doesn't really work and also I don't want other developers to have to do this.
I have also tried setting classpath manually using something like:
classpath = classpath('src/test/java/com/orbitbenefits/keystore')
But I couldn't make it work (gradle doesn't like it).
Question
I need to solve only one of these two problems:
How can I define classpath manually?
OR
How can I make IntelliJ to not mess up project structure when using its gradle refresh button?
Your IntelliJ is having a problem with srcDirs = ['src/test/java/com/orbitbenefits/keystore'] because src/test/java is already a folder containing some source.
One solution could be to define a new folder sibling to src where you have your KeystoreDownloader class and then import the keystore as follows:
keystore {
java {
srcDirs = ['keystore']
}
}
Related
I know this should be pretty simple, but there's obviously something that I'm just not getting.
I have a gradle application setup in the following in build.gradle:
plugins {
id 'application'
}
application {
mainClass = 'com.my.Main'
}
dependencies {
implementation 'other project 1'
implementation 'other project 2'
}
The source is set up
src/
main/
java/
resources/
I want to have a different distribution (for local development) that has different files for the resources directory, but for this 'dev' distribution, I want to keep the mainClass and the dependencies from the main distribution.
If I add a 'dev' distribution, I can package up files from the src/dev/... directory, but I don't have the application dependencies.
distributions {
dev {
contents {
// something here to add the compiled java and dependencies from main
// but not the resources?
}
}
main {
}
}
Also, gradle only seems to have one 'run' task that runs the main distribution. Is it possible to define a run for the dev distribution?
You need to define a SourceSet called dev:
sourceSets {
main {
}
dev {
resources {
exclude ...
}
}
}
And also the corresponding directory (that's not even required, when only excluding files):
mkdir -p ./modulename/src/dev/resources
I'm trying to generate Protobufs in a Java project that are defined in another Git repository that I'd like to add as a Git submodule. My build.gradle contains
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:4.0.0-rc-2"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code.
sourceSets {
main {
java {
srcDirs 'build/generated/source/proto/main/grpc'
srcDirs 'build/generated/source/proto/main/java'
}
}
}
and I've included the protobufs repository (called my-protobufs) in the src/main/proto directory. The Protobufs are in turn located in a proto subdirectory of my-protobufs. A partial directory structure looks like this:
src/main/proto/edm-grpc-protobufs/proto
├── mypackage
│ └── v1
│ ├── bar.proto
│ └── foo.proto
The foo.proto file has an import statement like this:
import "mypackage/v1/bar.proto";
That is because in that repository, the Protobuf path is the proto directory. The problem is that when I try to ./gradlew build, I get an error like the following:
> Task :generateProto FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':generateProto'.
> protoc: stdout: . stderr: mypackage/v1/bar.proto: File not found.
my-protobufs/proto/mypackage/v1/foo.proto:5:1: Import "axmorg/v1/bar.proto" was not found or had errors.
my-protobufs/proto/mypackage/v1/foo.proto:10:5: "SourceType" is not defined.
The problem is basically that the --proto_path (in the parlance of protoc) or the directory in which to search for imports is not correctly defined, so protobuf-gradle-plugin doesn't know where to find them. Is is possible to update the build.gradle to specify this path?
I found this in die documentation:
https://github.com/google/protobuf-gradle-plugin#customizing-source-directories
sourceSets {
main {
proto {
// In addition to the default 'src/main/proto'
srcDir 'src/main/protobuf'
srcDir 'src/main/protocolbuffers'
// In addition to the default '**/*.proto' (use with caution).
// Using an extension other than 'proto' is NOT recommended,
// because when proto files are published along with class files, we can
// only tell the type of a file from its extension.
include '**/*.protodevel'
}
java {
...
}
}
test {
proto {
// In addition to the default 'src/test/proto'
srcDir 'src/test/protocolbuffers'
}
}
}
I ended up working around this problem: the packages containing relative Protobuf imports actually weren't needed for the Java project whereas the ones that were needed did not contain relative imports, so I modified the sourceSets in build.gradle to be like
sourceSets {
main {
java {
srcDirs 'build/generated/source/proto/main/grpc'
srcDirs 'build/generated/source/proto/main/java'
}
proto {
exclude '**/*.proto'
include 'my-protobufs/proto/mypackage/**/*.proto'
}
}
}
which circumvented the issue with the Protobuf path as there are no longer any imports. I'm still curious how I would specify the Protobuf path, though.
We are migrating from Ant to Gradle. In the starting Gradle looked promising, when I started migrating targets from Ant to Gradle, facing similar issues, earlier having with Ant.
The Ant Build Flow looks like -
We have a Java application - Ant used to clean, compile and build jar of the project.
Next we have few targets to copy built jar and some other resources files to windows server.Its just a windows server not a nexus like repo.
These copy targets are release based(internally using macrodefs) - if alpha, it has to copy to different folder and for stable release different folder.
Another macrodef was to just backup the existing files present in server to a backup folder before copying new files there.
Migrating to Gradle-
I liked the way Gradle does the tasks of clean, compile and build. I am using Java plugin for this.
I am facing issues in next tasks to copy files to windows server and taking backup of old files before copying new files.
In Gradle I created few custom tasks like copyJarAlpha, copyJarStable,backupJarAlpha,backupJarStable etc..
Internally they are doing the same thing just copying files from source to destination and some print statements. But it looks repetitive. I was looking for ways like macrodef in ant.
task deployAlpha {
doFirst {
isJenkinsAvailable(deployDirAlpha)
}
doFirst {
if(isDeployLibsTaskRequired(outputDir,deployDirAlpha)) {
tasks.findByName('deployLibsAlpha').execute()
}
}
doLast {
println "Deploying corejar jar to : ${deployDirAlpha}"
copy {
from "${outputDir}/${corejar}"
into "${deployDirAlpha}"
}
println "Deploying evan-core jar to : ${deployDirAlpha}/lib"
copy {
from "${externalLibsDir}/core2.jar"
into "${deployDirAlpha}/lib"
}
println "Deploying test resource files to : ${deployDirAlpha}"
copy {
from "./test-resources/logback-test.xml", "./test-resources/JUnit-TestSuiteResults.xsl"
into "${deployDirAlpha}"
}
}
}
I have similar snippets at few places. Its not looking nice.
Is there any way we can reuse methods/functions in gradle? or I am assuming wrong things here.. Or I am trying to use gradle for things its not inteded for? What could be the best way to accomplish these tasks of copying and backing up files if not using custom tasks in gradle?
Here's a couple of options.
Create a plugin (See writing custom plugins)
public class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.with {
apply plugin: 'x'
dependencies {...}
task deployAlpha{...}
}
}
}
Usage
apply plugin: MyPlugin
Or a script plugin
apply from: 'path/to/script.gradle'
You can also attach functions to domain objects via the ext of a domain object (see ExtraPropertiesExtension)
allprojects {
ext.doProjectStuff = { String arg -> return "project${arg}"}
dependencies.ext.doSependenciesStuff = { String arg -> return "dependencies${arg}"}
}
Usage
def foo = doProjectStuff('x')
dependencies {
def bar = doDependenciesStuff('y')
}
I'm attempting to use "HTTPBuilder" within my simple Groovy script. When I use '#Grab' to import the dependency, everything works fine. Though, I'd like to keep the jar within a different directory and import it using the classLoader function. I've copied the 'http-builder-0.7.jar' that '#Grab' placed into my grapes directory and pasted it into the same directory my Groovy script is running (on Windows). I then comment out the '#Grab' statement and include the classLoader, but get this error:
org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed: C:\Groovy Scripts\test.groovy: 9: unable to resolve
class HTTPBuilder
Any ideas why the classLoader wouldn't be working in the script? I printed out the path of the jar when importing with '#Grab' and it's definitely using the one within the grape directory. If I uncomment the '#Grab' statement, it works again. Here's the small script...
//#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7')
this.getClass().classLoader.rootLoader.addURL(new File("http-builder-0.7.jar").toURL())
//return new File(groovyx.net.http.HTTPBuilder.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
def http = new HTTPBuilder('http://httpbin.org/get')
As mentioned, you would be wise to use another method, such as Gradle's application plugin.
However, this is one way to do what you're asking.
First, to get the jar and all dependencies, consider the following Gradle build.gradle script:
apply plugin: 'java'
dependencies {
compile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7'
}
repositories {
jcenter()
}
clean {
doLast {
ant.delete(dir: 'runtime')
}
}
task getDeps(type: Copy) {
from sourceSets.main.runtimeClasspath
into 'runtime/'
doFirst {
ant.delete(dir: 'runtime')
ant.mkdir(dir: 'runtime')
}
}
If you run gradle getDeps, it will write all of the jars into runtime.
Then, in a Unix terminal (for example), you could set the classpath with this (using wildcard syntax from Java 6+, and assuming the path is the same runtime as above):
export CLASSPATH=.:"/user/foo/some/path/runtime/*"
In the same terminal, this will work:
import groovyx.net.http.*
def http = new HTTPBuilder('http://httpbin.org/get')
println "Ready."
my application is in java and the IDE used is Eclipse.
I am facing below mentioned issue on refreshing my gradle project.
[Cannot nest
'MyApp-Service/src/test/java/com/mycompany/mymodule/myservice/functional' inside 'MyApp-Service/src/test/java'. To enable the nesting exclude 'com/' from 'MyApp-Service/src/test/java']
here is my folder structure
main folder structure
MyApp-Service/src/main/java/com/mycompany/mymodule/myservice/controller
test folder structure
MyApp-Service/src/test/java/com/mycompany/mymodule/myservice/functional
Below is my build.gradle code snipet
sourceSets {
functionalTest {
java {
srcDir file('src/test/java/com/mycompany/mymodule/myservice/functional')
}
}
}
Most confusing part is if i set the funtionalTest gradle source dir to any other path even if give some junk path the gradle builds fine.
For eg
sourceSets {
functionalTest {
java {
srcDir file('NotAvalidPath')
}
}
}
Please help me to resolve the issue . Thanks in advance.