I'm using the Java library for the Google Maps API but cannot find the code at runtime. I've added the repository and dependencies to build.gradle as detailed in the readme. Everything compiles fine, the import statement autocompletes, I can open the source code in Eclipse through "View Declaration," and I can see Google Maps in the Java build path.
import com.google.maps.GeoApiContext;
// Throws exception!
GeoApiContext.Builder builder = new GeoApiContext.Builder();
Why is this library visible at compile time but not runtime?
ETA: The application is packaged as an EAR file and deployed to a web server.
With the scarse details you provided, my guess is that you built a jar file and then ran java -jar myApplication.jar.
The default jar file only contains the classes of you own application, and not its dependencies. If you want to make an executable jar, you have several options. Some of the more popular are:
Use the shadow plugin, which will repackage the jar to make it "fat" with all its dependencies.
Use the standard distribution plugin that will create a zip (or tar) of your project and its dependencies. It will also a script for setting the classpath correctly.
Related
I have created a JavaFX application and have a generated Jar file (generated with Gradle) that will launch.
When the application does launch, it doesn't connect to the embedded database though. I feel as though I am missing something very simple but after a lot of research, I haven't been able to figure it out. When running the jar file from the command prompt, I get the following error:
java.lang.ClassNotFoundException: org.apache.derby.jdbc.EmbeddedDriver
From the reading I have done, I understand I may be able to add this to my classpath but I have not been successful with this after multiple attempts and I have made this application to be run on another computer. This is possible, right?
If possilbe, I would love to change something in my build.gradle file or surround the .jar in a folder or something like that that would make this simple for the person running the program. Program size is not a concern short of multiple gigabytes.
You've got two problems
The driver class is not in your app jar
If you embed that db into the app jar, you're not going to be able to write to it
You can make a 'fat jar' but the isn't going to solved the second problem. You really need to make an installer to do this, in order to leave the db in the file system, so it can be written to.
Problem
Part of what Gradle does is dependency management. That means it knows what dependencies you need and how to find them (based on configurations in the build script). When you execute/build your application via Gradle the tool will automatically search repositories, download+cache dependencies, and place those dependencies on the class-path/module-path. Once you deploy your JAR file Gradle is no longer involved, so your deployment is responsible for including the needed dependencies.
In other words, you need to ship your application's dependencies with your application JAR file.
Solutions
You basically just need to make sure you include your application's dependencies with your application. Here are at least three ways to do that.
Copy Dependencies
Copy the dependencies into a build folder as part of the build process. Here's an example of such a task, using the Kotlin DSL:
tasks {
val jar by existing(Jar::class)
val copyDependencies by registering(Copy::class) {
from(configurations.runtimeClasspath)
into(jar.get().destinationDirectory)
}
jar.configure {
finalizedBy(copyDependencies)
}
}
Now if you execute ./gradlew jar Gradle will create the JAR file and then copy the dependencies into the same directory as the JAR file. Then you just need to make sure all the JAR files are deployed together.
If I remember correctly, the default class-path is the working directory. But to specify the class-path you would use -cp, -classpath, or --class-path when executing your application. The module-path, if needed, is set with -p or --module-path.
Fat JAR
Create a so-called "fat" or "uber" JAR file. That's a JAR file that includes not just your own application code but all your application's dependencies as well. You could configure the jar task for this, but it would probably be easier for you to simply apply the Gradle Shadow Plugin.
// Kotlin DSL
plugins {
id("com.github.johnrengelman.shadow") version "<version>"
// other plugins...
}
And then you'd create the fat JAR with ./gradlew shadowJar. See the user guide for more information.
Self-Contained Application
Create a self-contained executable using a tool like jpackage. This tool gives you an application that has all its code and the JRE embedded, and then gives you an installer or native executable (e.g. exe on Windows). Here's the user guide for jpackage. There are Gradle plugins to make using jpackage from Gradle easier, such as The Badass JLink Plugin.
Note jpackage was added in Java 14 and was incubating until Java 16. Also note that jpackage can't "cross-package". That is to say, if you build your application on Windows then you can only create installers/executables for Windows; same for MacOS and Linux. If you need to package for multiple platforms then you'll need access to each platform.
JavaFX
Since you've tagged this question with JavaFX I want to give a note of caution. Though if you're not using JavaFX 9+ then this is not relevant to you.
Technically JavaFX only supports being loaded as named modules. That means it needs to be placed on the module-path, either via --module-path or by including it in the custom-runtime image built by jlink / jpackage. As of JavaFX 16 a warning is now emitted if JavaFX is loaded from unnamed modules (i.e. the class-path).
Executable JAR files are placed on the class-path. That includes fat JARs. And if you are not using a JDK that includes JavaFX—meaning you have Gradle pull in the JavaFX dependencies—then JavaFX will be included in your fat JAR and be placed on the class-path. Now, despite not being supported and now emitting a warning, nothing seems to currently break if JavaFX is on the class-path. Except for one caveat: Your main class must not be a subclass of javafx.application.Application. You'd have to create a separate main class that simply launches JavaFX.
Because of all this, I would highly recommend using jpackage to deploy JavaFX applications. You may want to read this Q&A as well.
I recently developed a simple JavaFX Game which used Simple Json. The dependency has been defined in Gradle dependencies and the game runs fine with Gradle run command. But when I create a jar file using - Gradle Jar and run it the following error shows up:
Caused by: java.lang.ClassNotFoundException: org.json.simple.parser.ParseException
Here is the picture of my build.gradle file:
How do i Fix this?
This is the default package behavior. The package phase of tools such as Gradle and Maven only copy the application sources (Java classes and resources from src directory), and NOT include files from dependencies.
Therefore the jar file produced by default does not have dependency classes or resources.
There are many solutions to run a java program from the jar file with dependencies:
Place the app jar as well as dependency jars in a directory (lib) and add it to the classpath when running the main class.
java -cp lib/*.jar com.game.MainClass
Create a fat (uber) jar. Gradle plugins like Shadow can generate a single jar with all dependencies packed in it. Just specify the main class in Manifest.
java -jar myAppFat.jar
Use plugins like Launch4J to generate Windows executables. This is great if you want to ship simple "click to run" apps to users.
I have a project that shares models with my android project. I have a separate eclipse project just for models and other shared code. I add this to my play project as a dependency in eclipse.
In eclipse, play compiles and starts without problem. However, I went to deploy to GAE and found that the compilation stage of play's packaging fails because it can't find the models.
I suspect I could hack the ant build files, but that seems brittle.
Is there a standard way to add extra directories to the play compilation source tree or the classpath?
Make a jar-file with your classes and put it in /lib. That's where I put my libraries.
Files in the application /lib folder is automatically added to the class path by Play Framework. See Classpath settings
From Anatomy: "The app directory contains all executable artifacts: Java and Scala source code, templates and compiled assets’ sources" ... and further: "You can of course add your own packages, for example an app/utils package"
You can copy java source files to make a hierarchy of packages under /app, e.g.:
/app/sharedcode/project2/models/domain1 and import that in WhateverController.scala as:
import sharedcode.project2.models.domain1._
with a grails project, do you put java code inside the same project or do you have to somehow import the java libraries you created from another java project?
I put any java source in the src/java directory and it gets automatically compiled when I run the app. When I have jar files with out associated code such as third party libraries or librarys from another group in the company I just drop them in the lib directory and grails automatically allows you to use them.
Both alternatives you mention work fine. IIRC, Grails even automatically creates a "java" source folder for your Java classes.
In addition, if you use Maven for the Java project, you can set pom=true in the BuildConfig.groovy file and create a dependency on the original JAR; it will get pulled in with each build.
I am using Netbeans IDE for a java project. In this project i need a jar file "htmlunit-2.6.jar".
I have included this jar file in the project libraries folder. I have instantiated one of its class "WebClient" but this class needs other classes of "commons-httpclient-3.1.jar" file.
Now I have also included "commons-httpclient-3.1.jar" file in the project libraries folder. But when I compiled my source file, it throws
ClassNotFoundException: org.apache.commons.httpclient.auth.CredentialsProvider
Kindly tell me how to handle this situation when one class in one jar file needs other classes in other jar file.
Simply put the required jar files on the classpath at compile-time and it should work. If you were doing it from the command-line then it would look like this:
javac -cp jar1:jar2 my.Application
If you are using NetBeans then you need to tell NetBeans that both of the JARs are on your classpath. It will be definable in a Project > Properties wizard as described here and also here from the tutorial
The ClassNotFoundException tells you that your libraries have some dependencies that you don't have included in your classpath at runtime. Your source is OK, because if you have used something not available, NB will tell you this at compile time (or before when editing).
So, welcome in the "dependency hell" of Java. For small projects you will be able to check all dependencies by hand with readme files, docs, etc and put them in the project config as oxbow_lakes said. For bigger things look at maven. It will do (most) everything for you !
(Maven is available in NB6)