java.util.scanner throws NoSuchElementException when application is started with gradle run - java

I have a created a simple java "echo" application that takes a user's input and shows it back to them to demonstrate the issue. I can run this application without trouble using IntelliJ's internal "run" command, and also when executing the compiled java file produced by gradle build. However, if I try to execute the application using gradle run, I get a NoSuchElementException thrown from the scanner.
I think gradle or the application plugin specifically is doing something strange with the system IO.
Application
package org.gradle.example.simple;
import java.util.Scanner;
public class HelloWorld {
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
String response = input.nextLine();
System.out.println(response);
}
}
build.gradle
apply plugin: 'java'
version '1.0-SNAPSHOT'
apply plugin: 'java'
jar {
manifest {
attributes 'Main-Class': 'org.gradle.example.simple.HelloWorld'
}
}
apply plugin: 'application'
mainClassName = "org.gradle.example.simple.HelloWorld"
sourceCompatibility = 1.5
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
}
Any ideas how to make this application work using gradle run?

You must wire up default stdin to gradle, put this in build.gradle:
run {
standardInput = System.in
}
UPDATE: 9 Sep 2021
As suggested by nickbdyer in the comments run gradlew run with --console plain option to avoid all those noisy and irritating prompts
Example
gradlew --console plain run
And if you also want to completely get rid of all gradle tasks logs add -q option
Example
gradlew -q --console plain run

In addition to the accepted answer: If you who are using the Gradle Kotlin DSL instead of the normal Groovy DSL, you have to write the following:
tasks {
run {
standardInput = System.`in`
}
}
Additional note: I had a similar problem in a Spring Boot application. There, I had to modify the bootRun task instead of the run task.

I'm learning to use Gradle with Kotlin DSL and what worked for me was answered here before.
// build.gradle (Groovy syntax)
run {
standardInput = System.in
}
// build.gradle.kts (Kotlin syntax)
tasks.named<JavaExec>("run") {
standardInput = System.`in`
}
The solution provided by #MarkusWeninger didn't worked for me.

Related

Add parameter to a Gradle plugin

I'm new to Gradle and I'm working on a Liferay project. I'm trying to use the Liferay javadoc gradle plugin without success. I'm working on the Liferay IDE (Eclipse) and I already have the javadoc task available to execute. The problem is, after the excution (which completes successfully) I can't find the created docs.
I read the documentation which says there is destinationDir property but I'm unable to set it using Gradle.
I tried following this SO question in order to create a custom Gradle task but without success.
How can I set the destinationDir in order to get the generated docs?
Edit:
The (automatic generated) settings.gradle is:
buildscript {
dependencies {
classpath group: "com.liferay", name: "com.liferay.gradle.plugins.workspace", version: "1.5.0"
classpath group: "net.saliman", name: "gradle-properties-plugin", version: "1.4.6"
}
repositories {
maven {
url "https://cdn.lfrs.sl/repository.liferay.com/nexus/content/groups/public"
}
}
}
apply plugin: "net.saliman.properties"
apply plugin: "com.liferay.workspace"
I'm pretty sure that com.liferay.gradle.plugins.workspace includes the javadoc plugin. Furthermore, Liferay also automatically creates an empty build.gradle where I put:
apply plugin: 'java'
task api(type: Javadoc) {
source = sourceSets.main.allJava
destinationDir = new File(buildDir, "/api")
}
Launching the api Gradle task the javadoc plugin is not executed

Using Apache Commons IO in a Gradle project

I'm writing a Java program - a plain command line program, not Android or anything like that - using Gradle, and trying to include Apache Commons IO. Per https://mvnrepository.com/artifact/commons-io/commons-io/2.6 I ended up with build.gradle like this:
apply plugin: 'application'
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
// https://mvnrepository.com/artifact/commons-io/commons-io
compile group: 'commons-io', name: 'commons-io', version: '2.6'
}
mainClassName = 'Main'
Gradle seems to download the package happily enough, but import statements referring to apache or commons get a not found error; this is true even when I run gradle build from the command line, omitting any IDE. What am I missing? (Previous similar discussions have been for Android or Eclipse projects; the instructions for those haven't worked here.)
I don't see any problems with your Gradle script, so at first glance, I'm thinking of two possible explanations:
you import a class that cannot be found in the artifact (e.g. a previous version of commons-io deprecated it and now they removed it)
your project's structure is set up incorrectly
I copied the exact contents of your script in a build.gradle file, created a src/main/java directory structure in the same directory, and wrote a small application Main.java under that directory with the following:
import org.apache.commons.io.IOCase;
public class Main {
public static void main(String[] args) {
System.out.println(IOCase.SENSITIVE.checkEndsWith("abcd1234", "1234"));
}
}
The code compiles successfully, so I need more context to troubleshoot your problem.

groovy.lang.MissingPropertyException: Could not set unknown property 'versionKey' for project ':flamingo' of type org.gradle.api.Project

I have this error while trying to compile the flamingo graphic tools for java, using intelliJ.
here is the build.gradle file for the error's project :
import javax.swing.SwingUtilities
dependencies {
compile project(":trident")
compile group: 'org.tmatesoft.svnkit', name: 'svnkit', version:'1.2.3.5521'
compile group:'org.apache.xmlgraphics', name:'batik-swing', version:'1.7'
compile (group:'org.apache.xmlgraphics', name:'batik-transcoder', version:'1.7') {
exclude group:'xml-apis'
exclude group:'xalan'
exclude group:'commons-io'
exclude group:'commons-logging'
exclude group:'org.apache.avalon.framework'
}
testCompile group: 'com.jgoodies', name: 'forms', version: '1.2.0'
testCompile group: 'junit', name: 'junit', version: '4.3.1'
testCompile group: 'org.easytesting', name: 'fest-assert', version: '1.2'
testCompile group: 'org.easytesting', name: 'fest-reflect', version: '1.2'
testCompile group: 'org.easytesting', name: 'fest-swing', version: '1.2.1'
testCompile group: 'org.easytesting', name: 'fest-swing-junit', version: '1.2.1'
testCompile group: 'org.easytesting', name: 'fest-swing-junit-4.3.1', version: '1.2.1'
}
sourceSets {
main
test
}
test {
// if we are headless, don't run our tests
enabled = !Boolean.getBoolean("java.awt.headless")
}
jar {
manifest {
attributes(
"Flamingo-Version": version,
"Flamingo-VersionName": versionKey,
)
}
}
task testJar(type: Jar) {
classifier = 'tst'
from sourceSets.test.classes
manifest {
attributes(
"Flamingo-Version": version,
"Flamingo-VersionName": versionKey,
)
}
}
uploadArchives {
try {
def x = [deployUsername, deployPassword]
} catch (Exception e) {
deployUsername = 'unset'
deployPassword = ''
}
repositories {
mavenDeployer {
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
authentication userName: deployUsername, password: deployPassword
}
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
authentication userName: deployUsername, password: deployPassword
}
configurePOM(pom)
}
}
}
install {
configurePOM(repositories.mavenInstaller.pom)
}
private def configurePOM(def pom) {
configureBasePom(pom)
pom.project {
name "flamingo"
description "A fork of #kirilcool's flamingo project"
url "http://insubstantial.github.com/peacock"
}
// deal with a gradle bug where transitive=false is not passed into the generated POM
pom.whenConfigured {cpom ->
cpom.dependencies.each {it
switch (it.artifactId) {
case 'trident':
it.classifier = 'swing'
break
}
}
}
}
I don't know what to add for the version key, nor where.
The project is on GitHub : it's a fork of the original project flamingo.
Here is the build.gradle file inside the root directory:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'de.huxhorn.gradle:de.huxhorn.gradle.pgp-plugin:0.0.3'
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'maven'
try {
def test = pgpSecretKeyRingFile // exception will throw if not set
apply plugin: 'sign'
apply plugin: de.huxhorn.gradle.pgp.PgpPlugin
} catch (Exception ignore) {}
group = 'com.github.insubstantial'
version = '6.3-SNAPSHOT'
versionKey = "6.3-defender"
release = "internal"
sourceCompatibility = 1.6
targetCompatibility = 1.6
configurations {
maven { extendsFrom archives }
}
repositories {
mavenRepo urls: 'https://oss.sonatype.org/content/groups/staging'
mavenCentral()
mavenRepo urls: new File(System.getProperty('user.home'), '.m2/repository').toURI().toString()
}
task sourceJar(type: Jar) {
from sourceSets.main.java
from sourceSets.main.resources
classifier = 'sources'
}
task javadocJar(type: Jar) {
dependsOn javadoc
from javadoc.destinationDir
classifier = 'javadoc'
}
artifacts {
maven sourceJar
maven javadocJar
}
uploadArchives {
try {
def x = [deployUsername, deployPassword]
} catch (Exception e) {
deployUsername = 'unset'
deployPassword = ''
}
configuration = configurations.maven
repositories {
mavenDeployer {
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
authentication userName: deployUsername, password: deployPassword
}
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
authentication userName: deployUsername, password: deployPassword
}
}
}
}
install {
configuration = configurations.maven
}
configureBasePom = { pom ->
pom.project {
modelVersion '4.0.0'
packaging 'jar'
scm {
connection 'scm:git:git#github.com:Insubstantial/insubstantial.git'
developerConnection 'scm:git:git#github.com:Insubstantial/insubstantial.git'
url 'scm:git:git#github.com:Insubstantial/insubstantial.git'
}
developers {
developer {
name 'Kirill Grouchnikov'
email 'kirillcool#yahoo.com'
roles {
role 'author'
role 'developer'
}
}
developer {
name 'Danno Ferrin'
email 'danno.ferrin#shemnon.com'
roles {
role 'maintainer'
}
}
}
}
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.0-milestone-2'
}
moreover, the main build.gradle contains the word "Exception" which raise an error from intelliJ.
Well, your main problem is that - and both of these are valid statements, you can select for yourself which you find more appealing - the project is designed for a too old Gradle version for usage with a current Gradle integration and / or your IntelliJ version (or rather its Gradle integration) is too new for usage with that project.
To be more technically precise, the IDE Gradle plugins use the Gradle Tooling API to interact with the Gradle build (run it, get information about source paths, dependencies, tasks, ...). The current version of the Tooling API that is used in the IDE plugins is compatible with builds down to Gradle 1.2 which is really quite ancient already. Your build though is designed for being run with Gradle 1.0-milestone-2 - which is not even a productive release - and defines this in its Gradle wrapper settings.
This means, that if you run Gradle from the commandline, 1.0-milestone-2 is used automatically and the build is working as designed (that's the cool magic of the wrapper). If you try to import the project with the Gradle integration of IntelliJ and tell it to use the projects default wrapper (the default choice and always the best idea and if a project does not use the wrapper, tell them to add it), IntelliJ tells you The project is using an unsupported version of Gradle. Please point to a supported Gradle version in the project's Gradle settings or in the project's Gradle wrapper (if applicable.). I guess you then discarded the message dialog and told IntelliJ to use some local Gradle installation instead and then you get the error you mentioned. (Btw. you should have mentioned that you followed this way, makes helping much easier)
When there are major version bumps in Gradle version, they remove stuff they deprecated long enough before according to their deprecation and removal policy and builds might break with these changes which is exactly what you are exhibiting, as you use a Gradle version that this build is not designed for and is not compatible with.
So what you can do is two things.
Either you do not use the Gradle integration in IntelliJ with this project but use Gradle only from the commandline. You can add allprojects { apply plugin: 'idea' } to your build.gradle and then use ./gradlew idea to generate properly configured IntelliJ project files that you then can open with IntelliJ and work with the project.
The other option - and I would really recommend it, even if it is more work - is to update the build to be compatible with current Gradle versions and configure the wrapper to use that new version, then the integration works flawlessly and you also benefit from all development that was done in Gradle since that really old version. You can read the release notes for important changes and breaking changes and interesting changes. To just get it done it should also be sufficient to update to the latest 1.x version, fix all deprecated warnings, update to the latest 2.x version, fix all deprecated warnings, update to the latest 3.x version, fix all deprecated warnings and then update to the latest 4.x version. This should at least make the build working with the latest version in a guided way, even though the build might not be the best one, not using some of the new things that were added to Gradle in the meantime. But this could at least be used as a starter.
You might be tempted to think you can also do a middle-thing and just set the wrapper to use 1.2. As it is in the same major version, the build should work with it and as I said before, 1.2 is currently the oldest version that is working with the integration. At least partly. Things like cancelling a build will e. g. not work as 1.2 does not yet support this, even if the tooling API does. But this won't work, because the build as it is does not even with 1.0. As 1.0-milestone-2 was only a pre-release, there the stability guarantees of course did not hold yet and there was a change between that and 1.0 that breaks your build.
Regarding the actual two errors you got, the first, the one with the unknown property is exactly one of the breaking changes I mentioned. Previously you could simply set any new property by doing foo = 'value'. The problem is, that people often mistyped properties, e. g. wrote fop = 'value' instead and then wondered why it doesn't work, not getting any helpful error message. So dynamically defined properties were forbidden and you have to do it in the ext namespace like ext { foo = 'value' } or ext.foo = 'value', but only on the first occurrence. This defines the new custom property and later on you can get and set it only by its name. If it shouldn't have been a property of the object in question (the project in your case) in the first place, but just a local variable in the build script, it should simply be defined as local variable like def foo = 'value' like always in Groovy which Gradle is based on.
Regarding the second error, the Exceptions IntelliJ is complaining about. Mine does not complain at all, I don't know what inspections you maybe have enabled or whatever, but if it is ok for Gradle it should be ok for IntelliJ if it is not, you should report it as bug to JetBrains, but as I said, here it is not red. But using exceptions for flow control like in that build script is very bad practice anyway, not only in build scripts, but in Java or even in programming at all.
try {
def test = pgpSecretKeyRingFile // exception will throw if not set
apply plugin: 'sign'
apply plugin: de.huxhorn.gradle.pgp.PgpPlugin
} catch (Exception ignore) {}
could e. g. be written like
if (project.hasProperty('pgpSecretKeyRingFile')) {
apply plugin: 'sign'
apply plugin: de.huxhorn.gradle.pgp.PgpPlugin
}
and
try {
def x = [deployUsername, deployPassword]
} catch (Exception e) {
deployUsername = 'unset'
deployPassword = ''
}
could e. g. be written like
if (!(project.hasProperty('deployUsername') && project.hasProperty('deployPassword'))) {
deployUsername = 'unset'
deployPassword = ''
}
without changing the meaning of the code

Spring boot executable jar with init.d launching as root instead of user

HELP!
I'm using the built-in launch script with SpringBoot 1.3.6 and Gradle. Oh, and the distZip task to zip things up.
At one point not long ago, this was all working quite well... then I did -- I know not what -- to screw it up.
I've installed the package (unzipped the Zip, basically) on my raspberry Pi, and checked the ownership and permissions. Everything is owned by the user I want to run the app as (user "appservice" group "pi") and confirmed that the permissions for the files are -- if anything, too permissive (755 for the myapp/bin/myapp script and pretty much everything else).
I've put a symlink in /etc/init.d pointing to ~appservice/myapp/bin/myapp and I've run update-rc.d myapp defaults to get it into the system. Note the symlink itself is owned by root/root, but I believe it's supposed to be, isn't it?
I'm seeing two problems, that I think are interrelated.
First, no matter how I launch the script (on boot with init.d or manually with "sudo service myapp start"), it appears to run as root (specifically, paths that the app is trying to use to access files come out as /root/myapp/files instead of /home/appservice/myapp/files).
Second, the app will crash... specifically I get the syslog message "myapp.service start operation timed out. Terminating." followed by what looks like an orderly shutdown of the app. Oh, and related... if I launch with "sudo service myapp start" the command never returns. Which is new...
Third, the application log output is going to /var/log/syslog instead of to /var/log/myapp.log which seems counter to what the Spring Boot documentation says.
I'm in final regression testing of deployment for this, and (famous last words) I haven't changed anything recently... :) No, really, the most recent change relevant to distribution was adding the src/main/dist directory, and it was working after that (launching at boot as the correct user).
I'd post the launch script but AFAIK it's the default script provided by Spring Boot when you use the springBoot { executable = true } task.
Here's my full build.gradle file... I don't see anything amiss, but maybe you will.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'application'
apply from: 'gradle/gradle/helpers.gradle'
mainClassName = 'app.Application'
if (!hasProperty('mainClass')) {
ext.mainClass = 'app.Application'
}
springBoot {
executable = true
}
repositories {
mavenCentral()
}
sourceSets {
main {
java { srcDir 'src/main/java' }
resources { srcDir '/src/main/resources' }
}
test {
java { srcDir 'src/test/java' }
resources { srcDir 'src/test/resources' }
}
}
project.ext {
applicationVersion = "0.1.5-alpha"
applicationRelease = isApplicationRelease()
applicationDate = new Date()
applicationRevision = getRevision()
applicationVersionSnapshot = (!applicationRelease) ? "+SNAPSHOT.${asUTC(applicationDate, 'yyMMddHHmm')}.git${applicationRevision}" : ""
applicationVersionFull = "${applicationVersion}${applicationVersionSnapshot}"
}
jar {
baseName = 'myapp'
version = '0.9.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile group: 'com.sun.mail', name: 'javax.mail', version: '1.5.2'
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.6'
compile group: 'commons-cli', name:'commons-cli', version: '1.3.1'
compile group: 'org.json', name:'json', version: '20140107'
compile "commons-codec:commons-codec:1.10"
compile("org.springframework.boot:spring-boot-starter-hateoas")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-starter-mail")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework:spring-web")
compile("org.springframework:spring-messaging")
compile("joda-time:joda-time:2.2")
compile("com.fasterxml.jackson.core:jackson-databind")
compile("com.googlecode.json-simple:json-simple")
compile("org.jdom:jdom:2.0.0")
compile("org.hibernate:hibernate-validator")
compile("org.apache.tomcat.embed:tomcat-embed-el")
compile("org.apache.commons:commons-io:1.3.2")
compile("org.kamranzafar:jtar:2.3")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4")
compile("com.jcraft:jsch:0.1.53")
compile("javax.jmdns:jmdns:3.4.1")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
task wrapper(type: Wrapper) {
gradleVersion = '2.14'
}
I would recommend to run and manage your application with systemd.
This makes it very easy to run the application under a specific user.
To do so, go on as follows:
First, create a service definition file /etc/systemd/system/myapp.service with this content:
[Unit]
Description=My App
[Service]
User=nobody
# The configuration file application.properties should be here:
WorkingDirectory=/home/appservice/myapp/files
ExecStart=/usr/bin/java -Xmx256m -jar myapp.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
Then, notify systemd of the new service file:
systemctl daemon-reload
and enable it, so it runs on boot:
systemctl enable myapp.service
At the end you can use the following commands to start/stop your new service:
systemctl start myapp
systemctl stop myapp

how to run after compiling thru gradle?

I am using the java plugin in my build.gradle.
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'xyz:xyz:4.11'
}
sourceSets {
test {
java {
srcDir 'agent'
}
}
}
I am generating the .class files by doing
$ gradle compileJava
Now that the .class files have been generated in build/, how do I run my code? One of the class files contains the main. I want to do something like this from a gradle task:
CLASSPATH=./mysql-connector-java-commercial-5.1.13-bin.jar:. $JAVA_HOME/bin/java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10000 Collector arg1
You may want to take a look at Gradle Application Plugin.
With it, you will be able to run your application just using a run task.
Based on ghik's answer, I add these to my gradle.build script:
apply plugin:'application'
....
dependencies {
....
runtime 'mysql:mysql-connector-java-commercial:5.1.13'
}
mainClassName = "Collector"
run {
args 'arg1'
jvmArgs '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10000'
}

Categories

Resources