Package not found; javac - java

This is annoying.
I have a directory structure like this
-lib
--some jar files
-packageName
--Main.java
--SomeOtherPackage
--SomeOtherJavaClass.java
Main.java imports SomeOtherPackage. And both java files uses jars in the lib.
What I do is add the jar files independently in the CLASSPATH. And then run as:
javac packageName/Main.java
but it gives the error that Package not found SomeOtherPackage . Shouldn't it automatically realize the dependency and build SomeOtherPackage as well? What would be the javac command and the classpath for the above case?
Thanks

The normal practice is to add the package root to the classpath.
When you're already in the package root, use -cp .. E.g.
cd /path/to/all/packages
javac -cp . packageName/Main.java
If you want to include JAR files as well, use the ; (or in *nix, the :) as classpath path separator:
javac -cp .;lib/file.jar packageName/Main.java
To save the time in repeating all the typing of shell commands, use a .bat (or in *nix a .sh) file. Or just an IDE if you're already familiar with java/javac and so on.

You need to add packageName to the CLASSPATH so it can find SomeOtherPackage

Related

Java run without jar

I wonder if it's possible to run a program without packaging it into a jar.
For instance we have this:
-AppRoot
Main.class
-Misc
Math.class
OtherTools.class
-YetAnotherFolder
UsefulFunctions.class
Is this possible? The main method should be executed from command line or similar.
You can run this way from the AppRoot directory
javac -cp Misc/*:YetAnotherFolder/* Main.java //To compile
java -cp Misc/*:YetAnotherFolder/* Main // To run
Below is some documentation
-classpath classpath
-cp classpath
Specifies a list of directories, JAR archives, and ZIP archives to search for class files. Class
path entries are separated by colons (:). Specifying -classpath or -cp overrides any setting of the
CLASSPATH environment variable.
If -classpath and -cp are not used and CLASSPATH is not set, the user class path consists of the cur-
rent directory (.).
Add all (sub-)directories containing class files to classpath and use the class with the main method as argument of the java executable.
The directory structure is your package structure.
java -cp ./:./AppRoot:./AppRoot/Misc:./AppRoot/YetAnotherFolder AppRoot.Main
This should work if all dependencies are resolved and on the classpath.

Compiling a java file using javac and the command line

I am trying to learn more about javac and how to use developer tools for Java using the command line.
As far as I understood, the option -classpath is needed to specify the path where javac searches for our classes and resource files, if we are not in the current directory, because usually the class path is set to our current working directory.
This is my current working directory:
/Users/user1/Desktop
And I am trying to compile a .java file which is in:
/Users/user1/Desktop/PF/
and the file is called MainClass.java.
I am trying to compile it using the following command:
javac -classpath /PF MainClass.java
But it does not seem to work, in fact I keep receiving the following:
javac: file not found: MainClass.java
Usage: javac <options> <source files>
use -help for a list of possible options
What am I doing wrong?
Classpath is for .class files, not for .java files.
javac command needs correct path to the .java file to compile it. So
javac ./PF/MainClass.java
Will create the class file in current directory.
If your MainClass.java depends on any class files to compile correctly, then you put those class/jar files in classpath.
That isn't how the classpath works. You use the classpath to point to classes that your Java file needs in order to compile. You don't use the classpath to point to the Java file itself.
Either go into the PF directory and do this:
javac MainClass.java
That will create the MainClass.class file inside the PF directory. If instead you want to create the MainClass.class file on your desktop, then from your desktop, do this:
javac PF/MainClass.java
-classpath
Specifies the path javac uses to look up classes needed to run javac
or being referenced by other classes you are compiling. Overrides the
default or the CLASSPATH environment variable if it is set.
Directories are separated by colons. It is often useful for the
directory containing the source files to be on the class path. You
should always include the system classes at the end of the path.
class path is used to specify the compiled sources that need to be used in your class. For example in this code if you are accessing another class then you should specify the location of the compiled sources of the that class.
In your case if don't have any class dependency then simply remove classpath option and compile using[navigate inside folder]
javac Mainclass.java
Remove the -classpath. And if you are in the place where the java file is required (which currently you arent) you can remove that PF/ too.

Using JAR Files

So I'm still a noob in Java and I'm experimenting around with a few things.
I recently created a .jar file for my class using jar cvf <name>.jar <source files> and then used that jar to compile my driver class (javac -cp <name>.jar Driver.java) though how do I now run that class using the jar?
I've tried the following 2 commands:
java Driver and,
java -cp <name>.jar Driver.
The first gives me a NoClassDefFoundError for the class used, whereas the latter just gave me a single line error.
Error: Could not find or load man class Driver
What am I doing wrong? Is it possible I'm confusing this for something else?
I'm trying to do as much as I can without the use of any IDE.
You should put jar file and compiler output into classpath and specify main class:
java -classpath "<name.jar>;classes" Driver
EDIT (thanks to Kayaman):
If you are running command from linux/unix you have to use ":" as separator (in Windows works ";"). "classes" is a path to folder containing compiler output.
When creating an executable jar ( jar which contain a class with the main method) you should tell the jar which is the mainClass to be executed and for that you should create a file called 'Manifest.mf'.
The file should contain this:
Main-Class: MyPackage.MyClass
And when creating the jar you should use this to include your manifest:
jar cfm MyJar.jar Manifest.mf MyPackage/*.class
And for launching your jar :
java -jar MyJar.jar

Is it possible to use relative path when compiling the java files?

Hi I am trying to learn to compile a java class with make file. My make file looks like this:
build:
javac test_java.java
clean:
rm -rfv *~ test_java.class
run:
java test_java
Now I have moved the test_java.java into a folder, called classes I am trying to compile the file using a relative path, is it possible?
I have tried:
javac -d classes test_java.java
but I am getting errors:
javac -d classes test_java.java
javac: file not found: test_java.java
Usage: javac <options> <source files>
use -help for a list of possible options
I have also tried: -d ./classes and also -d /home/the/whole/path (but I would like to have the relative path), and the errors are the same. It seems to work only the
javac classes/test_java.java
What am I doing wrong?
Update: The original answer here was completely wrong. You must specify the path to your source files. -sourcepath is for another purpose:
Specify the source code path to search for class or interface
definitions. As with the user class path, source path entries are
separated by semicolons (;) and can be directories, JAR archives, or
ZIP archives. If packages are used, the local path name within the
directory or archive must reflect the package name.
Note that there are many other build tools for Java applications that are very mature and well regarded. Maven, Gradle, and Ant are the ones that spring to mind immediately. If you don't have to use make I would take a look at one of those.

Use my own classes in a servlet (Java/Tomcat/Linux)

For the last 3 days I couldn't find a single answer for this problem. I need to be able to use my own classes in my servlets.
I am pretty sure that my files hierarchy is correct:
|-WEB-INF/
|---classes/
|------com/
|---------myProject/
|------------user/
|---------------User.java
|---------------Location.java
|---------------Comment.java
|------------servlet/
|---------------DoComment.java
Since User.java, Location.java and Comment.java are defined in one package as com.myProject.user I know I should go to the main root of the java project and compile them this way:
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo javac com/myProject/user/Location.java
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo javac com/myProject/user/User.java
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo javac com/myProject/user/Comment.java
However, javac cannot identify the other objects (cannot find symbol error) when I use a classpath in my compilation.
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo javac -cp /usr/share/tomcat6/lib/servlet-api.jar com/myProject/servlet/DoComment.java
Please help!
You're putting java source in a location where compiled java classes are expected. Try compiling the source and then adding the class files (.class vs .java) where you're putting them currently.
For this to work, you'd have to be sure that the classes have no dependencies and that the package declaration of your classes match up with the folder hierarchy you're placing them under.
Even so, this generally isn't how web projects are put together. You would be better off packaging the classes into a JAR and placing the JAR in your WEB-INF/lib folder.
For more information on creating a JAR, check this out: http://docs.oracle.com/javase/tutorial/deployment/jar/build.html
From the javac manpage:
-cp classpath
Sets the user class path, overriding the user class path in the CLASSPATH environment
variable. If neither CLASSPATH or -class-
path is specified, the user class path consists of the current
directory.
Basically, you are overriding the classpath when you use the -cp flag, so you need to make sure you specify ALL the required classes in your classpath. The delimiter for classpath entries is a : and it takes wildcards.
Problem solved!
I created a JAR file for the com.myProject.user package and saved it in the WEB-INF/lib. Than I compiled the servlet using two classpath seperated by a colon.
Here is the code:
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo jar cvf myproject-user.jar com/myProject/user/User.class com/myProject/user/Location.class com/myProject/user/Comment.class
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ mv myproject-user.jar ../lib/myproject-user.jar
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo service tomcat6 restart
/var/lib/tomcat6/webapps/ROOT/WEB-INF/classes$ sudo javac -cp /usr/share/tomcat6/lib/servlet-api.jar:../lib/myproject-user.jar com/myProject/servlet/DoComment.java
Thank you durron597 and kwikness your answers combined was the correct answer.
Have a nice day.

Categories

Resources