I'm new to Java and aren't sure where to place the Java Dependencies which are required to run crawler4j. Do I put them in the same folder, or do I put them where Java is located on my machine, or what? Please help me.
Putting the dependent JARs in the same folder as your application JAR / bytecode files is a reasonable approach. As others mention, you need to ensure that the actual folder containing the JARs is on the classpath when the JVM is launched to run the application. The -cp argument is the recommended way to do this, and it is common practice to create a little shell script / batch file to launch the app with the appropriate JVM parameters.
Putting them into the Java installation is not a good idea for a couple of reasons.
It might have unforeseen side-effects on other applications run using that installation. This includes applications run by other users.
It will make upgrading your Java installation to the next patch level more difficult.
You need to put them on the CLASSPATH. If you're running your/the application from the command line you can specify your classpath using the -cp argument for java
You put them in your classpath. The classpath can be specified with the -cp argument when you run the java program.
java -cp depend1.jar;depend2.jar;etc... Class2Run
Related
Before when users were required to have a jre installed to run aps:
ProcessBuilder builder = new ProcessBuilder("java -jar execute.jar");
Now with jlink and jpackage being released .jars can be deployed with a bundled jre.
What is the correct method to start another .jar from a program that had been deployed with jlink/jpackage?
java -jar will not work as java is not installed on the end user anymore
see:
How to call an embedded jre from command line in order to run java applications
This is a similar problem but does not address creating the .jar with jlink/jpackage
If you have a main class defined, you should be able to run "java -jar HelloWorld.jar".
Otherwise seems like you can create a launcher pointing to a starting module.
From Redhat Reference:
https://access.redhat.com/documentation/en-us/openjdk/11/html/using_jlink_to_customize_java_runtime_environment/creating-custom-jre-modular
Create a custom JRE with the required modules and a custom application launcher for your application.
$ ./jdk-11/bin/jlink --launcher hello=sample/sample.HelloWorld --module-path sample-module --add-modules sample --output custom-runtime
$ ./custom-runtime/bin/hello
If you have to run the second JAR in its own JVM, then you have to have a JRE or JDK installed to do that.
Alternatively, you need to use jlink or jpackage or whatever to turn it into a self-contained application and distribute that instead of the second JAR. The user has to install that application in a place that your main application can find.
In either case, you run the second application as a separate process; i.e. as a separate JVM.
If it acceptable to run the second JAR in the current JVM, then it may be possible to do the following:
Open the JAR file to read its MANIFEST.
Fetch the Main-Class and Class-Path manifest attributes
Create a new classloader with a classpath that includes the second JAR and all of its dependencies. (This assumes that they are available ... at the locations specified by the Class-Path attribute.)
Use the classloader to load the main class.
Use reflection to find and call the main classes entry point method; i.e. the static void main(String[]) method. Pass it a String[] to represent the command line arguments.
There are a couple of problems with this approach.
The application you are running from the 2nd JAR will share the environment with your main application. The same standard input/output/error. The same current directory and environment variables.
If the second application misbehaves ... it can bring down the main application in various ways. A security sandbox might help, but it won't protect against everything.
If the main application has been distributed with a custom JRE, then it may not include all of the Java SE classes that the second application needs. If that is the case you will get classloader exceptions or errors.
Finally, this approach may not work at all if the packaging technology you use uses an AOT compiler to compile the main application + all classes that it uses to native code.
UPDATE - Now that I understand what you are actually doing here (you have a main app and an updater app), I think there is another way to do this. The jlink utility allows you to create a bundle which has multiple entry points. When this is installed, I would expect it to appear as commands with different names that are links to the same executable. They would (naturally) use the same embedded JRE.
Read the following for more information:
For jlink - Java Platform, Standard Edition Deployment Guide: Self-Contained Application Packaging: Supporting Multiple Entrypoints
For jpackage - Packaging Tool User's Guide: Support Application Requirements: Add Launchers
Note that doing it this way would address possible issues with functionality missing from the bundled JRE. The jlink or jpackage command should make sure that all classes / modules that are needed will be included.
Can someone please help me, I'm almost desperate because I can't find solutions for a Mac.
I have written two .java files that I would like to use as a library for all new projects.
For this I found out that I have to set the CLASSPATH.
The java files path:
/Users/thomas/Soft/IN_OUT/In.java
/Users/thomas/Soft/IN_OUT/Out.java
Don't bother with it. The concept of CLASSPATH is misguided in the first place (because you can run more than one java app, ever, on your system, setting the classpath globally is misguided as a concept), and on most platforms, libraries and tools, this isn't the intended way to configure classpaths.
For example, in IDEs, you configure classpaths on a per project basis.
When compiling code or with javac or running code with java, you can supply the classpath with the -classpath option (or shorten it to -cp). For running jar files (java -jar foo.jar, or double clicking a jar), the classpath is taken solely from the Class-Path manifest entry in that jar file; both the -cp and the global CLASSPATH variable are ignored.
I get that you want these files to be available to 'all projects', but that's just not how it works. If you update these files, all your old projects would break, or at least you'd have to consider if they might. You'd also be extending these files to eclipse, intellij, and any other java apps on your system which makes no sense. That's why this notion of 'make these available to everything' isn't a particularly sensible thing to want.
I was reading some documentation for db2jcc4.jar when something caught my attention in the following (emphasis added):
The following command will retrieve the JCC driver version if executed from the command line:
java com.ibm.db2.jcc.DB2Jcc -version
Or for drivers that are not yet installed:
java -cp ./db2jcc.jar com.ibm.db2.jcc.DB2Jcc -version
All I have is the db2jcc4.jar file - it didn't come with an installer or anything. I can run the second command and it works fine, but the first gives me this stack trace:
Exception in thread "main" java.lang.NoClassDefFoundError: com.ibm.db2.jcc.DB2Jcc
Caused by: java.lang.ClassNotFoundException: com.ibm.db2.jcc.DB2Jcc
at java.net.URLClassLoader.findClass(URLClassLoader.java:434)
at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:665)
at java.lang.ClassLoader.loadClass(ClassLoader.java:644)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:358)
at java.lang.ClassLoader.loadClass(ClassLoader.java:627)
Could not find the main class: com.ibm.db2.jcc.DB2Jcc. Program will exit.
This tells me that the jar is not yet installed. In all the time I've worked with Java, I've never heard of installing a jar. How can I make it so that the first command works instead of having this issue and printing a stack trace? How can I install a jar?
It looks to me like the second command includes a flag, -cp, which modifies the classpath. I'm guessing that means that all I need to do is move my jar file into a specific directory. I tried putting it in /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.33.x86_64/jre/lib but that didn't make it so the second command would work. I'm stumped and would appreciate any suggestions for where exactly I need to move this jar for it to be considered installed.
There is no such thing as "installing" a jar. To be used by a Java application, jars have to be accessible in the classpath. Take a look at this link:
http://docs.oracle.com/javase/tutorial/essential/environment/paths.html
By installing the java jar they meant that the jar is available to your program (physically present and found in your class path). If the Path to the jar was not setup then you have to options:
+ copy the jar file to your existing path
+ include the jar file in the command line
java -cp <path_to>/db2jcc.jar com.ibm.db2.jcc.DB2Jcc -version
It looks to me like the second command includes a flag, -cp, which modifies the classpath. I'm guessing that means that all I need to do is move my jar file into a specific directory.
I would say that you need to explicitly include the jar file itself on the classpath. Personally, I generally do not attempt to "install" a jar as you describe, but rather create some sort of script or executable jar file that will facilitate the establishment of the correct classpath.
EDIT: In the context of deploying code to an application server, then "installing" the jar would make sense--typically there's a shared lib folder available on an application server where you can simply drop the jar and the code will become available to all the applications running on the server--this can become a bit of a management headache, however and I often will prefer to have a completely self-contained deployment over sharing jar files between applications--YMMV, however.
You commented thus:
Your link has this comment - (Classes that are part of the JRE, JDK platform, and extensions should be defined through other means, such as the bootstrap class path or the extensions directory.) - How would I go about adding the jar through that?
That is a bad idea, for (at least) the following reasons:
Putting stuff into the extensions directory is going to potentially affect every Java application that you execute. Not just the application that you are trying to "install". In some cases, this may to lead to unexpected breakages due to conflicting versions, etcetera.
When you update the Java installation, the standard installer, RPM or whatever is going to create a new installation tree. But it won't copy anything from the existing installation. So a Java update is likely to break any application that depends on stuff in "extensions".
If you try to solve the above problems by "embedding" a Java installation, you risk losing track of where your Java installations are. This makes applying Java security patches problematic. And of course, embedded JREs take up a lot of disc space ... at ~100Mb a time.
I suspect that "Installing a JAR" is a poorly chosen terminology that likely means placing the jar on the JVM classpath" - i.e. in order to make it available to an application. The recommended ways of doing so vary depending on the Java platform (whether it is a server platform or a client side platform).
For example, on a Java EE server, you could package the jar file within the application, or define it as a shared library, and attach it to the server's classloader or the application's classloader to make it available to that application. Third party applications, such as various IBM products, will come with their own instructions as to how to 'install' a db2jcc4 driver.
I have some code in Java using Eclipse and I would like to deploy it to unix envirnment. The program is simple console program that just takes some arguments at the run time, read a file and print out some results.
My question that what is best approach to deploy and run it in unix envirnment. I was just thinking to copy all the classes file to the unix envirnment and create a batch file to run the main class file. Does this sound okay? Or, should I create a runnable jar file?
Also, where should i put the jar files that the prgram is referencing (in classpath)?
Thanks
I think an executable jar file will solve your purpose here.
You should be able to execute it as
java -jar <jarfilename> <arguement1> <arguement2> .... <arguementN>
You can execute the jar file from the current directory itself, just make sure your jar file has executable permissions.
chmod +x <jarfilename>
ls -la
Designing for easy deployment is important in my opinion.
In our case, there are some components:
store project in the source code management system (git). we break down source code as
the developing source code to dev branch
the stable source code to release branch
use build tool, such as ant or maven, and provide a deploy script in the project. (we will talk deploy script in 3.).
provide deploy script to:
fetch the latest stable source code in the build server
build to executable files in the build server (whatever you do)
send the package to the target server
launcher (close the old app and run the new app) in the target server (via remote ssh command)
Currently, you think how to package the java, but it is a simple thing just about building and runing. When you talk about deployment, make it as easy as possible. Each time we deploy just to invoke the release script.
PS. I don't like the executable jar. Using un-packaging jars and compiled class can be sending by rsync very efficiently.
It sounds Ok and will work for you. Just one fix: you are going to write shell script for unix, not batch file.
But you can do better. Typically java classes are packaged into jar file. Jar file is just a zip file with optional META-INF, directory, MANIFEST.MF and other stuff. So it is better to package your application into jar and then run it as: java -cp yourjar.jar YourMainClass.
To create jar file you can use any tool that can create zip or utility jar that is a part of your JDK. You can also create automatic build using ant, maven, gradle, bildr etc that will help you to package your application.
I would do the following:
create a dedicated directory for this program. Copy the dependent .jar files to that directory
write a (short) script that sets the classpath to point to these jars and then executes the main class
Given the above, it's largely a matter of style as to whether you create a runnable .jar or not. It'll be hidden from the user.
I'm suggesting a script because:
you can set regularly used JVM parameters easily (memory options etc.)
it's a pain (and hardly intuitive) to type java -jar {pathtojar} etc.
By copying the jars to a dedicated directory, you can then use different versions of jars for different scripts (e.g. you may have 2 programs that use two different versions of commons-lang)
You should also (probably) use this script to explicitly determine which version of Java you use to run the program with. As you install/upgrade you don't want to break your programs and the scripts can be configured to explicitly tie down this info.
I find this quickest of all:
First, create a jar, copy to unix server and change file permission just as dopplesoldner mentioned below.
You can put your library classes and or jar dependencies in a lib folder
Then execute the jar
java -Djava.ext.dirs=lib/ -classpath yourJar.jar com.yourPackage.yourClass
yourClass will be the class having main(String args[]) method you wanted to execute.
How do I import libraries in my Java program without using an IDE, like NetBeans?
In NetBeans I do it this way:
How can I achieve the same thing by just using Notepad++ or Programmer's Notepad.
As much as possible I don't want to use NetBeans because it would be overkill since I'm only working on simple projects.
Use:
javac -classpath external.jar myClass.java
If your main class is in a package,
package com.mycompany;
public class myClass
{
...
...
then you'll need
javac -classpath external.jar com/mycompany/myClass.java
And to run:
java -classpath external.jar com.mycompany.myClass
In addition to Bala R's post, adding multiple files and locations is perfectly OK too...
javac -cp location1/;location2/;file1.jar;file2.jar fileToCompile
Notes:
-cp and -classpath are the same thing.
If you're on Solaris (and some other Unix flavors), change the ';' to ':'.
All of the other posters are spot on; you just need to add the JAR file to your classpath.
Java offers many mechanisms for setting the classpath, including via the command line, via an environment variable, and through setting it in the MANIFEST.MF of an executable Java JAR file.
These are all a pain in the neck to manage. It's good to know the technique, and understand the basics. But it's really a bad idea to actually use them.
You should do this.
First, put all of your Java libraries in a single place on your system. C:\java\libraries, or whatever. Someplace that you remember, and someplace accessible by all of your projects.
Next, name all of your libraries using their version numbers. If you using Log4j v1.4.1, then put the JAR file in a log4j-1.4.1 directory in your library area. This gives you "free" library versioning.
Finally, learn Ant. For simple projects, Ant is simple. Use the Ant build.xml file to compile, test, and run your application.
Why? Several reasons.
Because once it's set up, adding a new library to your project is trivial; you add a line to your build.xml file. Ant lets you more easily handle simple abstractions (like where all of your libraries are located).
The build.xml file is self-contained. If you use, say, an environment variable for the classpath, then the classpath for one project may be different from that of another. That means resetting the environment variable. Continue this and you'll end up swearing at some "new problem" where it "worked before" when it's because you had your classpath set wrong. Set it once in the build.xml file, and forget it.
Ant is portable. It runs the same on Windows, on Linux, on Mac, on AS/400, it runs everywhere that Java runs, unlike shells scripts or BAT files.
It's lightweight. Simple Ant scripts are simple. They don't bring a lot of baggage with them, and you can always make them scary complicated. It's much simpler than Maven for just builds.
Most IDEs support Ant directly. If you decided to go back to an IDE, most can simply use your Ant build file with minimal configuration.
This is how you solve your classpath problem with Notepad++. Setting the classpath works, but it doesn't go far enough. It's a pain to administer and manage. Learning the basics of Ant will take you much farther with minimal work.
You should put them on your classpath, like
java -classpath someJar.jar YourMainClass
And, of course, you can do the same for javac.
If you need to have more than one JAR file or directory on your classpath, you'll need to use your platform's default path separator. For example, on Windows,
java -classpath someJar.jar;myJar.jar YourMainClass
On a side note, you might find it easier to use an IDE to manage this sort of stuff. I've personally used just my slightly scriptable editor and have managed fine. But it's good to know how to do this stuff by the command line.
Put the JAR files in your classpath. classpath is an environment variable.
Make sure the JAR file is in your classpath and you have the import statement.