JVM-based scripting language with Maven dependency resolution - shell

I am looking for a simple way write short shell scripts that call into jar files.
Having to keep track of (and installing) all those jar files for the runtime classpath partly defeats the purpose using a script (as opposed to building a runnable jar file in Eclipse). I'd like Maven (or something equivalent) to manage this.
Image:
#!/usr/bin/the-cool-shell
use org.apache.commons/lang/3.0.0
use org.json/json
import org.json.*;
new JSONObject("{}");
And this should get the required artifacts from Maven automatically (at basically zero overhead after downloading it for the first time).
What are my options?

If you were using Groovy and Groovy Shell you could be using the Grape infrastructure.
#!/usr/bin/env groovy
#Grab( 'log4j:log4j:1.2.14' )
import org.apache.log4j.Level
import org.apache.log4j.Logger
def logger = Logger.getLogger(GroovyShell.class)
Logger.rootLogger.level = Level.INFO
logger.info 'I am using the Log4j library by using Grape'
As for your exact example this would work:
#!/usr/bin/env groovy
#Grapes([
#Grab('org.apache.commons:commons-lang3:3.0'),
#Grab('org.json:json:20090211')
])
import org.json.*
new JSONObject('{}')
In this case I was using the Groovy syntax but ordinary Java syntax is also fine.
Taken from the Javadoc of #Grapes annotation:
Sometimes we will need more than one grab per class, but we can only add
one annotation type per annotatable node. This class allows for multiple
grabs to be added.

You could try Gradle, it's a build management tool, but it uses Groovy for its build scripts, and it uses the Maven dependency model. So your script could be a Gradle 'build' script, that just did something different than building software.

Related

Is there a simple way to access project resource files from a gradle task?

I am working on a Gradle task for a java project. The task needs to read files from a subfolder of the project’s resources directory. I was expecting to find a standard way for Gradle to access project resources but have been unable to find one. Does Gradle provide simple way to find and import resource files? Maybe through a plugin?
If you mean the src/main/resources folder, then no. That is by convention used by the Java plugin to hold resources for the actual module and not the build classpath. But if you just want to read a file in it from a task, just use normal Java, Groovy or Kotlin APIs. You don't need a plugin for that.
Here is one for Groovy:
task printMyResource {
doLast {
logger.quiet(file("src/main/resources/subfolder/my_file.txt").text)
}
}
(The file method resolves a path to a File object relative to the project folder.)

Use Groovy app and test code in combination with jlink solution for bundling JavaFX

This follows on from this excellent solution to the question of how to get Gradle to bundle up JavaFX with your distributions.
NB specs: Linux Mint 18.3, Java 11, JavaFX 13.
That stuff, involving jlink and a module-info.java, is beyond my pay grade (although I'm trying to read up on these things).
I want to move to using Groovy in my app and test code (i.e. Spock) rather than Java. The trouble is, the minute I include the "normal" dependency in my build.gradle i.e.
implementation 'org.codehaus.groovy:groovy-all:2.5.9'
and try to build, I get multiple errors:
mike#M17A ~/IdeaProjects/TestProj $ ./gradlew build
> Configure project :
Found module name 'javafx.jlink.example.main'
> Task :compileTestJava FAILED
error: the unnamed module reads package org.codehaus.groovy.tools.shell.util from both org.codehaus.groovy.groovysh and org.codehaus.groovy
[...]
error: the unnamed module reads package groovy.xml from both org.codehaus.groovy and org.codehaus.groovy.xml
[...]
error: module org.codehaus.groovy.ant reads package groovy.lang from both org.codehaus.groovy and org.codehaus.groovy.test
error: module org.codehaus.groovy.ant reads package groovy.util from both org.codehaus.groovy.xml and org.codehaus.groovy.ant
100 errors
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileTestJava'.
Yes, 100 errors... probably more! By commenting out various things I think I've come to the conclusion that some Groovy dependency is being injected by the jlink stuff. Fine, I can live with that (although it'd be nice to know what version of Groovy it is).
The trouble is, even if I omit the Groovy dependency line, the same errors occur when I try to introduce the Spock dependency:
testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'
Has anyone got any idea what's going on here and what to do about it?
I searched for an answer. I didn't find a good solution.
According to this, it seems that Groovy is currently not really compatible with Java modules. It is due to the fact that some packages are contained by multiple jars of the library (not compatible with modules). You will have to wait for Groovy 4 for a compatible version.
I discovered that the JavaFX plugin use this plugin internally. This plugin seems to consider that all dependencies are modules (it is not the default Gradle behaviour).
To make your application works, it seems that you have to:
force Gradle to put Groovy in the classpath instead of the modulepath (it will not be considerered as a module, but seems impossible if you use the javafx plugin)
use the "patch-module" system: it allows Gradle to make a fusion of the library jars into a single module, to prevent the problem of packages that are in different jars
I searched the Groovy jars with IDEA (Project structure/Libraries), and I tried to use the syntax offered by the plugin to use "patch-module":
patchModules.config = [
"org.codehaus.groovy=groovy-ant-3.0.1.jar",
"org.codehaus.groovy=groovy-cli-picocli-3.0.1.jar",
"org.codehaus.groovy=groovy-console-3.0.1.jar",
"org.codehaus.groovy=groovy-datetime-3.0.1.jar",
"org.codehaus.groovy=groovy-docgenerator-3.0.1.jar",
"org.codehaus.groovy=groovy-groovydoc-3.0.1.jar",
"org.codehaus.groovy=groovy-groovysh-3.0.1.jar",
"org.codehaus.groovy=groovy-jmx-3.0.1.jar",
"org.codehaus.groovy=groovy-json-3.0.1.jar",
"org.codehaus.groovy=groovy-jsr-3.0.1.jar",
"org.codehaus.groovy=groovy-macro-3.0.1.jar",
"org.codehaus.groovy=groovy-nio-3.0.1.jar",
"org.codehaus.groovy=groovy-servlet-3.0.1.jar",
"org.codehaus.groovy=groovy-sql-3.0.1.jar",
"org.codehaus.groovy=groovy-swing-3.0.1.jar",
"org.codehaus.groovy=groovy-templates-3.0.1.jar",
"org.codehaus.groovy=groovy-test-junit-3.0.1.jar",
"org.codehaus.groovy=groovy-test-3.0.1.jar",
"org.codehaus.groovy=groovy-testng-3.0.1.jar",
"org.codehaus.groovy=groovy-xml-3.0.1.jar"
]
It only works with a single line "org.codehaus.groovy=X.jar", but a bug prevents it to work with all of the library jars (Look at this issue on Github).
So you have multiple choices:
Use Java instead of Groovy
Wait for a new Groovy release, or new releases of plugins (modules-plugin, and a version of javafx-plugin that use this one internally)
Use old javafx configuration: dependencies are not module by default, and you have to specify manually in build.gradle that JavaFX dependencies should be considered as a module (check my "obsolete" answer to this question)

Gradle: Unable to get plugin class in scope in build script

I've been creating my own gradle plugin for the last few days (partly for learning, and partly to clean up some gradle build scripts I have laying around), however I've run into a problem that I can't figure out how to fix. In my plugin jar there is an interface named me.alxandr.gradle.bintray.maven.MavenPackage, yet when I try to import it I get an error saying that it can't be found. This is really weird, because the plugin is obviously running (I'm seeing output from it, and it's tasks are registering).
Currently I've done a hack to get around this as following:
project.ext.MavenPackage = MavenPackage
This just makes MavenPackage an available name in the buildscript, which works, but I loose any editor support for it cause it's entirely dynamic. Is there any way I can (from my plugin) get the buildscript to import a package when it's applied? Like how MavenPublication is in scope without me needing to import it. If not, why can I not import classes from my plugin package?
The entire source code is available at https://github.com/Alxandr/gradle-utils. You can see an attempted here: https://github.com/Alxandr/gradle-utils/blob/master/gradle/publish.gradle#L1. The current code works as is (with the hack explained above), but I'm just looking for a better way to do this.
In order to use a class from your plugin in your Gradle script, you must add the plugin JAR to the buildscript classpath.
Here's how to do just that:
buildscript {
repositories { /* where to get your plugin jar from, e.g. mavenLocal() */ }
dependencies {
classpath 'some_group:me.alxandr.plugin:1.0.0'
}
}
import me.alxandr.gradle.bintray.maven.MavenPackage
You can find more information in the Gradle User Guide about using external dependencies in your build script

Exception in compiling groovy & java using maven

My groovy file contains:
#Grapes([
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7'),
#Grab('org.apache.httpcomponents:httpmime:4.5.1')
])
.......code
I am trying to compile groovy and java code. But I am getting below error:
java.lang.RuntimeException: Transform groovy.grape.GrabAnnotationTransformation#69bda33a cannot be run
This works for me, note that I did change HttpBuilder to v.0.7.1:
#Grapes([
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1'),
#Grab(group='org.apache.httpcomponents', module='httpmime', version='4.5.1')
])
Likely way too late for you to care, but I saw the same error just now.
I suspect the problem is that the #Grab annotation can't take effect because Maven is controlling the dependencies, or perhaps because Maven is trying to compile both Groovy and Java code, and the class loader created by the #Grab annotation can't influence the Java code.
Upshot is, I suspect you (and I) need to move the dependency out of the Groovy class in question, and put it into the pom.xml file Maven is using.

How to work with JMeter and Junit

I am very new to JMeter
I am trying to use Junit Request sampler in JMeter.In my project we have a class called PayloadProcessorTest.java. from these class methods i am calling some other class methods.It has lot of dependencies
How can i create jar file for PayloadProcessorTest.java with dependencies
I saw many examples for JMeter with Junit Request sampler. But, those all examples are independent classes
Can any one please help me
There are several ways of creating a .jar file:
Using Maven
Using Ant
Using Eclipse
.jar files are basically ZIP archives so you can just compile your PayloadProcessorTest.java and put resulting PayloadProcessorTest.class into /lib/junit/test.jar file keeping package structure. After restart JMeter will pick up the class. Don't forget to add any 3rd-party jars used in PayloadProcessorTest (if any) to JMeter classpath. For more information check out How to Use JUnit With JMeter guide.
If you want to get the dependencies with Maven you can run
mvn install dependency:copy-dependencies, which will create a folder inside your target folder called 'dependency' filled with the dependencies. To speed this up you can add the command as External Tool in Eclipse using Run > External Tools > External Tools Configurations.
Or if you want to use Eclipse you can choose File > Export > Java > Runnable JAR file and select the option 'Copy required libraries into a sub folder next to the generated JAR'. However to do this you will need to add a main class, and run it once as a Java Application before trying to export. The Main class can be empty or not.
package test;
public class Main {
public static void main(String[] args) {
}
}
Really, it depends what packaging capabilities you have.
You need to compile your classes in one or more jars, and then put them in the %JMETER_HOME%/lib/ext folder.
Or use maven to do it all for you.

Resources