Gradle - java.lang.NoClassDefFoundError - error when run or debug, when I build everything is ok


(piotr.ludwiniak) #1

Hello.

I’m new in gradle. I work on project which use free standalone library from site: http://www.openmuc.org/ The one I use is openiec61850-0.14.4.tgz. This libs are using gradle. This is embedded project for energetics. I use it for about two months. I use netbeans 7.2.1 with gradle plugin 1.2.0. Until now I have used netbeans to write code and compile. I have run it with runSampleServer.bat which is in the project path: {project}/src/sample/sampleServer/runSampleServer.bat. ILibrary uses slf4j so I have log on console. I didn’t use debug option. Now I need. And I can’t cause when I clean/build project everything is fine but when I run or debug using this netbeans buttons I have got this message “java.lang.NoClassDefFoundError: org/openiec61850/StandaloneServer” I know that I can debug gradle project because I made single projects, root and subprojects and all of them I can debug with netbeans. I have added this: if (!hasProperty(‘mainClass’)) {

ext.mainClass = ‘org.openiec61850.StandaloneServer’ } to my root build.gradle and I was trying different paths but result is always the same.

I should also mention that I am quite a novice in Java mostly I program in C (sometimes assembler) for embedded. Does anybody have any suggestions?

Thanks in advance for help.


(René Groeschke) #2

Not sure I understand you correctly. What your saying is that the project builds fine with gradle but you’re not able to run it via netbeans? How do you import it to netbeans? I had a quick look at the library and I don’t think

if (!hasProperty('mainClass')) {
 ext.mainClass = 'org.openiec61850.StandaloneServer'
 }

will do anything as no mainClass property is used anywhere in the gradle build


(piotr.ludwiniak) #3

Well again.

I can import project to netbeans. I can clean and build project with netbeans. I can’t run and debug this project with netbeans. When I run/debug this project I got message: java.lang.NoClassDefFoundError: org/openiec61850/StandaloneServer

I made simple gradle projects to check if I can debug them and I can, so probably problem is with my gradle scripts. I’m not sure how, where and what write (I assume that in build.gradle) something to let gradle see my main class.

Thank you for your interest.


(Attila Kelemen) #4

NetBeans automatically adds “run” and “debug” tasks if they are not present relying on the “mainClass” property (via init scripts). So the above code should be fine.

I believe that you attempt to run the wrong project. That is, you have to run the approriate subproject (e.g.: sample) and not the root project.

Anyway opening the project, I could see that renaming of projects somehow prevented NetBeans from properly detecting the classpaths. I will check the cause of this problem. In the mean time you have to remove the “openiec61850-” string from each ‘build.gradle’ and ‘settings.gradle’ in order to prevent classpath errors in the editor.


(piotr.ludwiniak) #5

I did what you sad. Deleted all “openiec61850-” from build.gradle and settings.gradle

My main class is ‘StandaloneServer.java’ in subproject ‘server’

I was running root project as you sad. Now I was trying to run this subproject ‘server’ I got message: “Cannot execute run because the property “mainClass” is not defined or empty.” When I add to server subproject to build.gradle this: if (!hasProperty(‘mainClass’)) {

ext.mainClass = ‘StandaloneServer’ } program are compiling but after that I have another error: java.lang.NoClassDefFoundError:StandaloneServer

Still can’t run/debug. But build works well.


(Attila Kelemen) #6

The previous code you added to the script was correct, so you should add this code to the build script of the project you attempt to run (i.e., you have to specify the fully qualified classname).

if (!hasProperty('mainClass')) {
   ext.mainClass = 'org.openiec61850.StandaloneServer'
 }

Other than this you can right click on the class you want to run and choose “Run File”. In this case no code needed to be added to the build script (adding the above code is fine too).


(piotr.ludwiniak) #7

It is better. I don’t have this class not found error anymore. But I have got another error: ‘SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.’

My build file looks like this:

if (!hasProperty('mainClass')) {
   ext.mainClass = 'org.openiec61850.StandaloneServer'
 }
  dependencies {
  compile project(':common')
  compile project(':jmms')
  compile group: 'org.slf4j', name: 'slf4j-api', version: '1.6.1'
  testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '0.9.29'
}

Also my server need to take input files. Normally with batch file it’s easy but I’m not sure how to pass java commands to gradle

Can I just add to gradle arguments this line from batch file:

java -Dlogback.configurationFile=logback.xml -Djava.ext.dirs=%LIBDIR% org.openiec61850.StandaloneServer sampleServer.properties

? Is it in subproject properties/manage built-in tasks? where %LIBDIR% is my lib path

I assume that I can debug whole project, not only subprojects, am I right?


(Attila Kelemen) #8

Sadly, there is no direct support for adding arguments to ‘run’ and ‘debug’ tasks. So you have to define your own ‘run’ and ‘debug’ tasks. For example, add this after specifying the ‘mainClass’ property:

private void configJavaExec(JavaExec task) {
    task.main = mainClass
    task.classpath = sourceSets.main.runtimeClasspath
    task.standardInput = System.in
    task.jvmArgs = ['-Dlogback.configurationFile=logback.xml', '-Djava.ext.dirs=' + System.getProperty('LIBDIR')]
    task.args = ['sampleServer.properties']
}
  task run(dependsOn: classes, type: JavaExec) {
    configJavaExec(it)
}
  task debug(dependsOn: classes, type: JavaExec) {
    configJavaExec(it)
    debug = true
}

I’m not sure what you mean by “I can debug whole project, not only subprojects”. Debug simply executes the ‘debug’ Gradle task (by default) and attaches to the started process. You should be able to step into any project which is a dependency of the started project.


(piotr.ludwiniak) #9

I have pasted this code into build.gradle. It looks like this code is going to work.

But I still have errors. I can’t set classpath for org.slf4j. I got this error:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".

This error redirected me to this page: http://www.slf4j.org/codes.html#StaticLoggerBinder

Second is got another error:

org.openiec61850.server.data.ConfigurationException: Exception instantiating DataSource: org.openiec61850.sample.DummyDataSourcejava.lang.ClassNotFoundException: org.openiec61850.sample.DummyDataSource

When I run program from cmd (all program input files are in folder server) it works, so I don’t think that my path are wrong. But I got this error, that can’t find the class. My path is:

System.getProperty('../../build/libs')

Netbeans shows error:“unable to resolve class JavaExec” - to argument of function configJavaExec

How can I check from where I invoke this run program and path seen from the gradle side? Is it from server directory? I attached printscreen of netbean’s


(piotr.ludwiniak) #10

Hello again. It works. I can run and debug this project. I just changed

this
task.jvmArgs = ['-Dlogback.configurationFile=logback.xml', '-Djava.ext.dirs=' + System.getProperty('LIBDIR')]
to this:
task.jvmArgs = ['-Dlogback.configurationFile=logback.xml', '-Djava.ext.dirs=../../build/libs']

Thank you very much for your help.

I just have one more question. How can I stop this server? Stopping it from netbeans doesn’t help. I have to kill process. Is there any way to stop running program?


(Attila Kelemen) #11

slf4j needs to be bound to either the logger of the JDK or Log4J. If you don’t bind it, it will simply not ouput logs. To fix this you have to add the approiate jar to the runtime classpath of the project. For example: ‘runtime ‘org.slf4j:slf4j-jdk14:1.7.2’’.

‘JavaExec’ is marked as not found for two reasons. First, you have to specify the Gradle installation in the global settings (Tools/options/misc/Gradle). Second, the Groovy editor of NetBeans currently knows nothing about the default imports of Gradle, so if you mind the red curly, then you have to specify the fully qualified class name: ‘org.gradle.api.tasks.JavaExec’ or add the import manually (‘import org.gradle.api.tasks.*’) to the beginning of the file.


(Attila Kelemen) #12

I just wanted to read the environment variable “LIBDIR” which should be ‘System.getenv(“LIBDIR”)’ rather than ‘System.getProperty’.

It is not possible to kill the build (i.e., the run task in this case) from NetBeans because the API in Gradle does not yet support cancellation. This issue is tracked in GRADLE-1539. So, currently you can either implement a way to stop the server or kill the approriate java process (good luck in guessing which one :)) manually.


(Attila Kelemen) #13

I have checked the classpath problems as promised. Actually, it is not renaming of projects what matters (although for some unknown reason it works when they are not renamed but I’m sure this is unreliable). What matters is that ‘src/mms/jositransport’ does not have a ‘build.gradle’ and this prevents NetBeans from recognizing that directory as a Gradle project. So a simplier fix would be to add an empty ‘build.gradle’ rather than edit all the build scripts.

Anyway, it is recommended to have ‘build.gradle’ for every project for seemless integration with NetBeans.


(piotr.ludwiniak) #14

I added build.gradle to be in every projects. Addint org.gradle.api.tasks.JavaExec or import org.gradle.api.tasks.* in the top of build.gradle doesn’t help with not showing errors but it doesn’t matter to me so I live it as is. For know I don’t have any implementation to stop the server so I just kill process. Thank you very much for your help! Everything what I need works well! I’m closing topic.