okhttp NoClassDefFoundError when running project - java

I've created the build.gradle file which looks like this:
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.12.1'
}
then I have a simple helloWorld class which uses the sample code from the okhttp website:
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class helloWorld{
public static void main(String[] args){
System.out.println("Hello World!");
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("www.google.com")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("SUCCESSS---->"+response.body().string());
} catch (IOException e){
System.out.println("......error thrown");
}
}
}
When I try to run the compiled class file I get the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: okhttp3/OkHttpClient at helloWorld.main(helloWorld.java:6)
Caused by: java.lang.ClassNotFoundException: okhttp3.OkHttpClient at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.
ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
If I remove the lines
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("www.google.com")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("SUCCESSS---->"+response.body().string());
} catch (IOException e){
System.out.println("......error thrown");
}
then the class runs correctly. So I think that maybe the jar isn't being imported correctly?
To be clear, the project is being compiled correctly, the issue only occurs if I try to run the compiled class file.

Gradle doesn't include the dependencies when creating the jar by default.
You can use shadow to create a jar with all dependencies https://github.com/johnrengelman/shadow
like this:
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '4.0.4' . <----- add shadow dependency
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.12.1'
}
when you build, shadow will add another file named {your_project}-shadow.jar in your build directory or something similar. Execute that and you should see it run.

Related

Why FileUtils can not be used in a common gradle transform code?

I just write a class which extends Transform class like this:
package com.example.plugin;
import org.gradle.internal.impldep.org.apache.commons.io.FileUtils;
import ...;
public class MyTransform extends Transform{
...
#Override
public void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
Collection<TransformInput> inputs = transformInvocation.getInputs();
TransformOutputProvider outputProvider = transformInvocation.getOutputProvider();
inputs.forEach(transformInput -> {
transformInput.getJarInputs().forEach(jarInput -> {
File dest = outputProvider.getContentLocation(jarInput.getName(), jarInput.getContentTypes(), jarInput.getScopes(), Format.JAR);
try {
// System.out.println(jarInput.getName());
FileUtils.copyFile(jarInput.getFile(), dest);
} catch (IOException e) {
e.printStackTrace();
}
});
transformInput.getDirectoryInputs().forEach(directoryInput -> {
File dest = outputProvider.getContentLocation(directoryInput.getName(), directoryInput.getContentTypes(), directoryInput.getScopes(), Format.DIRECTORY);
try {
// System.out.println(directoryInput.getName());
FileUtils.copyDirectoryToDirectory(directoryInput.getFile(), dest);
} catch (IOException e) {
e.printStackTrace();
}
});
});
}
}
However, when I use it on other gradle application, it got error with gradle build:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:transformClassesWithMr_Spade is coming.ForDebug'.
> org/gradle/internal/impldep/org/apache/commons/io/FileUtils
It seems that the class FileUtils has some problems, but I just don't know what's wrong.
Here is the build.gradle of plugin:
plugins {
// Apply the Java Gradle plugin development plugin to add support for developing Gradle plugins
id 'java-gradle-plugin'
id 'maven-publish'
}
dependencies {
implementation 'org.testng:testng:7.4.0'
// Use JUnit Jupiter for testing.
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
implementation 'com.android.tools.build:gradle:7.1.3'
implementation "androidx.navigation:navigation-safe-args-gradle-plugin:2.4.2"
// implementation 'org.ow2.asm:asm:9.2'
// implementation 'org.ow2.asm:asm-tree:9.2'
implementation 'org.apache.commons:commons-io:1.3.2'
}
gradlePlugin {
// Define the plugin
plugins {
greeting {
id = 'com.example.plugin.greeting'
implementationClass = 'com.example.plugin.Plugin_project_namePlugin'
}
}
}
publishing {
publications {
maven(MavenPublication) {
groupId = 'aaa.bbb'
artifactId = 'ccc.ddd'
version = '1.0'
from components.java
}
}
repositories {
maven {
// change to point to your repo, e.g. http://my.org/repo
url = layout.buildDirectory.dir('../../repo')
}
}
}
...
build.gradle of application:
plugins {
id 'com.android.application'
id 'com.example.plugin.greeting'
}
...
dependencies {
// implementation gradleApi() //gradle sdk
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
// implementation 'org.apache.commons:commons-io:1.3.2'
...
}
By the way, since my plugin folder and app folder are in the same folder, so i will use command like "build"(for plugin)->"publish"(for plugin)->"build"(for app), and the fact is the first two step is success, but the last step is failed. Just like that the plugin itself do not have problem but occurs some problem when it work on the app :(

Jar file and resource file returning null

I have a simple program that reads a text file (test.txt) line by line and prints each line to the console. In intellij it works just fine.
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.File;
public class testing {
public static void main(String[] args) {
testing main= new testing();
main.handleData("test.txt");
// handleData();
//System.out.println("hello world");
}
public void handleData(String fileName) {
System.out.println("Testing");
File file= new File(getClass().getResource(fileName).getPath());
try {
Scanner scanner = new Scanner(file);
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
I am trying to build it with gradle and when i run the jar command java -jar out/artifacts/helloTestingWorld_jar/helloTestingWorld.jar I get an error saying the path is null
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.net.URL.getPath()" because the return value of "java.lang.Class.getResource(String)" is null
at testing.handleData(testing.java:22)
at testing.main(testing.java:12)
My build.gradle file looks like this
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
jar {
manifest {
attributes "Main-Class": "src.main.java.testing"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
test {
useJUnitPlatform()
}
My resource folder is marked as the resource root and my java folder that contains my main class is marked as the source root. I am thinking that I might have to add the text file as a dependency in the jar file?
I have had a look at all of the other suggestions on here and the all lead to the same result. I have tried rebuilding the project from scratch and still the same result.
I have also tried using InputStream instead of File
InputStream in = getClass().getResourceAsStream(fileName);
When I use InputStream I get this error
Exception in thread "main" java.lang.NullPointerException
at java.base/java.io.Reader.<init>(Reader.java:168)
at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:76)
at java.base/java.util.Scanner.<init>(Scanner.java:566)
at testing.handleData(test.java:23)
at testing.main(test.java:10)

How to include the client from openapi-generator in a gradle java application?

I want to create a gradle java application that generates a client from an openAPI specification file and uses that client.
So I created a java application with gradle init (type:application, language:Java, DSL:groovy, test-framework:Junit Jupiter, project-name:simple-java-app, package-structure:a.aa).
Small example of what works:
I can create a new source folder second/loc/src/main/java with a package b.bb and a class Foo.
And with the following build.gradle
plugins {
id 'java'
id 'application'
}
repositories {
jcenter()
}
sourceSets {
second {
java {
srcDir 'second/loc/src/main/java'
}
}
}
compileJava {
source += sourceSets.second.java
}
dependencies {
implementation 'com.google.guava:guava:29.0-jre'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}
application {
mainClassName = 'a.aa.App'
}
test {
useJUnitPlatform()
}
The main class can access Foo:
package a.aa;
import b.bb.Foo;
public class App {
public static void main(String[] args) {
System.out.println(new Foo().sayFoo());
}
}
What doesn't work
Now I try the same for generated code by openapi-generator:
Under plugins I add id "org.openapi.generator" version "4.3.1"
And I add a new task:
openApiGenerate {
generatorName = "java"
inputSpec = "$rootDir/specs/petstore.yaml".toString()
outputDir = "$buildDir/generated".toString()
apiPackage = "org.openapi.example.api"
invokerPackage = "org.openapi.example.invoker"
modelPackage = "org.openapi.example.model"
configOptions = [
dateLibrary: "java8"
]
}
Then I execute the task openApiGenerate and confirm in the file system that the sources have been generated(eclipse won't show the build folder).
Now I use the same method as above resulting in below build.gradle
plugins {
id 'java'
id 'application'
id "org.openapi.generator" version "4.3.1"
}
repositories {
jcenter()
}
openApiGenerate {
generatorName = "java"
inputSpec = "$rootDir/specs/petstore.yaml".toString()
outputDir = "$buildDir/generated".toString()
apiPackage = "org.openapi.example.api"
invokerPackage = "org.openapi.example.invoker"
modelPackage = "org.openapi.example.model"
configOptions = [
dateLibrary: "java8"
]
}
sourceSets {
client {
java {
srcDir '$buildDir/generated/src/main/java'
}
}
}
compileJava {
source += sourceSets.client.java
}
dependencies {
implementation 'com.google.guava:guava:29.0-jre'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}
application {
mainClassName = 'a.aa.App'
}
test {
useJUnitPlatform()
}
But when I try to use the classes now:
package a.aa;
import org.openapi.example.model.Pet;
public class App {
public static void main(String[] args) {
Pet p = new Pet(0L);
System.out.println(p.getId());
}
}
neither import nor Pet can be resolved.
> Task :compileJava FAILED
C:\...\simple-java-app\src\main\java\a\aa\App.java:6: error: package org.openapi.example.model does not exist
import org.openapi.example.model.Pet;
^
C:\...\simple-java-app\src\main\java\a\aa\App.java:14: error: cannot find symbol
Pet p = new Pet(0);
^
symbol: class Pet
location: class App
C:\...\simple-java-app\src\main\java\a\aa\App.java:14: error: cannot find symbol
Pet p = new Pet(0);
^
symbol: class Pet
location: class App
3 errors
FAILURE: Build failed with an exception.
I don't know how to debug this, frankly I'm unsure if source sets are even the right way. All openapi-generator tutorials seem to use them, I haven't tried subprojects yet, the openApiGenerate task seems to create a complete project with build.gradle and everything.
You need to add the sources from the generated code to your project. One example from one of my projects:
sourceSets.main.java.srcDir "${buildDir}/generated/src/main/java"
After generation make sure you refresh gradle and project.
With build.gradle.kts and gradle 7+ I used in Kotlin DSL:
configure<SourceSetContainer> {
named("main") {
java.srcDir("$buildDir/generated/src/main/java")
}
}
To add the java generated sources to the project's source.

Gradle NoClassDefFoundError when running jar

I'm trying to set up a Gradle project with some Velocity functions in it.
So far I have the following files:
src/main/java/com/veltes/velotest.java:
package com.veltes;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import java.io.*;
public class velotest {
public static void main(String[] args) {
try {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();
VelocityContext context = new VelocityContext();
context.put("name", "World");
Template t = ve.getTemplate("com/veltes/velotest.vm");
StringWriter writer = new StringWriter();
t.merge(context, writer);
System.out.println(writer.toString());
File logFile = new File("C:/users/xxxx/Desktop/velotest.html");
try {
writeFile(logFile, t, context);
}
catch (IOException io) {
}
} catch (Exception e) {
}
}
private static void writeFile(File logFile, Template t, VelocityContext context) throws IOException {
Writer logWriter;
logWriter = new BufferedWriter(new FileWriter(logFile));
try {
t.merge(context, logWriter);
}
catch (ResourceNotFoundException rnfe) {
}
catch (ParseErrorException pee) {
}
catch (MethodInvocationException mie) {
}
catch (Exception e) {
}
logWriter.flush();
logWriter.close();
}
}
build.gradle:
group 'velocitytest'
version '1.0-SNAPSHOT'
apply plugin: 'groovy'
apply plugin: 'java'
sourceCompatibility = 1.5
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile group: 'junit', name: 'junit', version: '4.11'
compile 'velocity:velocity:1.4'
}
Now, when I run gradle assemble and gradle build everything is fine, but when I try to run the project (same for running the built jar in build/libs/ and for running the velotest class in IntelliJ), I get the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/ExtendedProperties
at org.apache.velocity.runtime.RuntimeInstance.< init >(RuntimeInstance.java:183)
at org.apache.velocity.app.VelocityEngine.(VelocityEngine.java:60)
at com.veltes.velotest.main(velotest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.ExtendedProperties
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 8 more
It's a bit strange that there is no jar in build/tmp/
Does anyone of you knows a solution?
You need to create a runnable jar if you want to be able to run it.
You can use shadojar plugin or extend the jar task to pack the runtime deps into an artifact.
jar {
archiveName = 'Name.jar'
manifest {
attributes 'Main-Class': 'your.main.class',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' '),
'Implementation-Version': project.version
}
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {}
}
For intelliJ problem:
apply plugin: 'idea'
Then run gradle idea task, this will refresh .iws .ipr .iml files in your project and sync the classpaths. Or if you use intelliJ support (which is not yet ideal) try to refresh it there. I think in version 2017.1.3 the gradle integration is a bit better.
Adding
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {} to build.gradle file fixed it for me, like this:
jar {
manifest {
attributes(
'Main-Class': 'gradle22.Library'
)
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}

Java: Connect Gradle with Velocity

I'm trying to connect Velocity with Gradle builder. So I created a Gradle project in IntelliJ, put the Gradle-Velocity-Plugin into the project directory, imported the Velocity jar and created the following files:
build.gradle:
group 'xxxxx'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.5
repositories {
mavenCentral()
jcenter()
}
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'org.anarres.gradle:gradle-velocity-plugin:[1.0.0,)'
}
}
apply plugin: 'velocity'
jar {
manifest {
attributes 'Main-Class': 'test.HelloWorld'
}
}
HelloWorld.java:
package test;
import java.io.StringWriter;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
public class HelloWorld
{
public static void main(String[] args)
{
try {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();
VelocityContext context = new VelocityContext();
context.put("name", "World");
Template t = ve.getTemplate( "helloworld.vm" );
StringWriter writer = new StringWriter();
t.merge( context, writer );
System.out.println( writer.toString() );
}
catch (Exception e) {
System.out.println("failed");
}
}
}
Now, when I execute gradle tasks, everything is fine, but when I execute gradle assemble, I get errors, that the velocity packages do not exist.
Does anyone of you got an idea how to fix this?
Thank you.

Categories

Resources