Using Java Packages, Jar Files and Ant Files

Part 1: Packages

Packages are used to help distinguish one class with the same name from another class with the same name. For example Homer Simpson might write a class called Circle and Peter Griffin might write a class called Circle, how will our program decide which is the correct one to use? That is where packages come in handy.

It is also helpful to understand the classpath variable and what it is used for. The classpath variable tells the system which directories to look in to find the .class files to run with the java command. Thus, even if the current directory that we are in contains a class called Runme.class and we type: java Runme IF THE CLASSPATH IS NOT POINTING AT THE CURRENT DIRECTORY (the .) then this file will not run.

Let's try playing around with packages and the classpath variable on Gaul:

Understanding the Classpath variable

  1. When doing this workshop, I occasionally have you purposely cause an error. If you get an error and you think you did the step correctly, read ahead to the next step incase the error was expected.
  2. Log onto gaul and type the unix command: echo $CLASSPATH. The classpath tells java which directories to check in when looking for .class files to run. One of the directories in the list should be . This is the current directory. That is why when you make a simple little java file and compile it, the resulting .class file almost always runs.
  3. Make a directory called cs2212package
  4. cd to the cs2212package
  5. In this directory, create a program called Put the following code into the file:

    public class HelloWorld {
       public static void main ( String[] args ){
           System.out.println("Hello World");
  6. Compile (javac
  7. Run HelloWorld.class (java HelloWorld) --> The program should run with no problems
  8. Now make a new directory called test inside of cs2212package. But do not cd into the next directory
  9. Type the following unix command: set CLASSPATH = "./test"
  10. Now type the following unix command: setenv CLASSPATH "./test"
  11. Type echo $CLASSPATH to make sure that the environment variable was set (if this command didn't work try export CLASSPATH="./test" )
  12. Run HelloWorld.class again. This time you should get an error because the ONLY place the JVM will look for class files is in the subdirectory test of the current directory. Because we changed the CLASSPATH variable, it doesn't even look in the current directory.
  13. This time run HelloWorld again but give a classpath when you run the program as follows: java -classpath "." HelloWorld. This time the program should run.
  14. MAKE SURE YOU UNDERSTAND WHAT WE JUST DID AND HOW THE CLASSPATH ENVIRONMENT VARIABLE WORKS. Remember, the classpath tells the system where to look to find the .class files.
  15. Let's put the classpath back to what it should be by logging off Gaul and logging back on again. Then cd to the folder cs2212package folder again.
  16. Now edit the file called Put the following line at the very top of the program: package;
  17. This is saying that we are going to put the executable HelloWorld.class into a package to avoid naming conflicts (although really, in this made up scenario, there likely wouldn't be another class called HelloWorld :-) that we would have to worry about conflicting with). The default is to use your companies website name in reverse order (in our case: ca.uwo.csd), along with the name of your package. We will call our package world.
  18. Compile the program again. It should compile correctly.
  19. Run the program again, you should get an error that says:
    Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld (wrong name: ca/uwo/csd/world/HelloWorld)
    This time, it is finding the .class file. So the classpath name is correct BUT NOW the JVM expects to find the HelloWorld executable code in the package but right now, it is in the directory cs2212package. Packages have a hierarchical naming scheme and we MUST have the correct hierarchy of folders for the run to work correctly. This is the Sun definition of a package:

    A package is a namespace that organizes a set of related classes and interfaces. Conceptually you can think of packages as being similar to different folders on your computer. You might keep HTML pages in one folder, images in another, and scripts or applications in yet another. Because software written in the Java programming language can be composed of hundreds or thousands of individual classes, it makes sense to keep things organized by placing related classes and interfaces into packages.

    What we need to do is to pick a directory to be the root. In our case, lets say that the folder cs2212package is the root. (this is also called the base directory in java). Make sure you are in the "root" directory cs2212package and now let's create the package hierarchy as follows: Create a subdirectory called bin and a subdirectory called source. cd into the source directory and inside the source subdirectory, make another subdirectory called ca, then inside ca make another subdirectory called uwo, then inside uwo make another subdirectory called csd, then inside of csd make another subdirectory called world. Move the file from the root directory to the directory cs2212package/source/ca/uwo/csd/world.
  20. Now move back up to the root directory: cs2212package and move into bin. Inside bin, create a subdirectory called ca, inside ca make a subdirectory called uwo, inside uwo make a subdirectory called csd, inside csd make a subdirectory called world. Move back to the root directory.
  21. Delete the file called HelloWorld.class from cs2212package
  22. Your directory structure should now look like this:
    Package Description
  23. Move to the root folder called cs2212package

Compiling Issues with Packages:

  1. Compile again with the following command:
    javac -d bin   source/ca/uwo/csd/world/
    NOTE: in this case -d stands for destination, so we are telling the compiler where to put the .class file when it is created. The first line of your, the package line (package;) tells the compiler to put the .class file into the correct package (i.e.into ca/uwo/csd/world within bin). The part where we have source/ca/uwo/csd/world/ tells the compiler where to find the sourse code. cd into bin/ca/uwo/csd/world and you should now see the file HelloWorld.class
  2. Now let's experiment a little. cd into the bin directory and type this unix command:
    rm -R ca

    to remove all the directories and the .class file from the bin directory. Then do cd .. to move back to cs2212package.
  3. Make sure you are in the directory called cs2212package and type the compile command again as before:
    javac -d bin   source/ca/uwo/csd/world/
    notice that the -d option not only tells where the .class file should go, it also, if the package subdirectories do NOT exist, will automatically create the subdirectories with the correct hierarchy (You should now see all the correct subdirectories in the bin directory as well as the HelloWorld.class file).
  4. Again move into the directory bin and type the unix command:
    rm -R ca
    to remove all the directories and the .class file from the bin directory.
  5. Now again move to our so called root directory: cs2212package and type the compile command:
    javac  source/ca/uwo/csd/world/
    Now see if you can figure out where the HelloWorld.class file was put when the -d (for destination) was NOT used with the javac command! Once you find it, you should realize it is in the wrong location so delete the file HelloWorld.class
  6. Make sure you are in the directory called cs2212package and type the compile command again as before:
    javac -d bin   source/ca/uwo/csd/world/
    so that we have the HelloWorld.class file in the correct location

Running Issues when using Packages

  1. Make sure you are in the root directory called cs2212package.
  2. cd to cs2212packages/bin/ca/uwo/csd/world and run the HelloWorld.class file by typing the command:
    java HelloWorld
  3. You should get an error. Hmmm, why? The .class file is this directory, and the classpath is set to "." but still we get an error??? This is because the package for the .class file sort of becomes part of the .class file name. Thus the .class file is not called HelloWorld.class anymore, it is now:
  4. Move back up to the root directory cs2212packages
  5. Now try running the program by typing the following command:
    java bin/ (YOU WILL STILL GET AN ERROR!)
  6. You should still get an error because you need to tell the CLASSPATH variable, that the executable.class file is in the bin directory and to look in the bin directory for the .class file. You also need to indicate that the program is inside a package by saying changing the name of the executable from just the executable name to package.executable name. For example in our case, the program is now called Thus, the command we must type from the root directory to run the program is:
    java -classpath bin
  7. HURRAY, the program ran!!!
  8. Things to note:
    1. We could permanently set the classpath variable to be the bin directory, then we would not need to use the -classpath option on the java command
    2. the package hierarchy is considered part of the name of the program NOT part of the classpath

    The previous steps should have taken about 40 minutes to complete.


Bigger Example

So what's the point of packages? Why even use them? There will be times when you "accidentally" picked the same name for a class as someone else, perhaps even a class name that the Sun people are using in the java api. For example you might want to call a class "Color" well, if you are American :-) but there is already a Color class in the package java.awt: Our classes won't conflict as long as we don't import java.awt but what if we DO need to import that class?

To illustrate this scenario we are going to purposely conflict with the very common String class. We are going to make our own class called String and put some silly code in it. Then we will create another program that uses both String classes. How will the compiler know which of the two it should use? Let's try to cause a conflict with the class names:

  1. Go to the root directory cs2212packages, then go (cd) to source/ca/uwo/csd/world and make a file called Put the following code in that file:

      public class String {
          private int value;
          public String()
               System.out.println( "This is a cs2212 string" );
              value = 99;
         public int getValue ()
            return value;


  2. cd back to the root directory cs2212package, then cd to only to the directory source. Create a file called Put the following code in that file:


    public class WhichString {
       public static void main (String[] args ){
             String x;
             String y;
             x = new String();
             y = new String("I am Y");
            System.out.println( "In main of WhichString" + x.getValue() + y );


  3. Now go back to the root directory cs2212packages and compile the new String class we just made with the following command:
    javac -d bin source/ca/uwo/csd/world/
    remember that the -d command will put the String.class file into bin/package, i.e. String.class will go into bin/ca/uwo/csd/world
  4. Now compile the file WhichString with the following command:
    javac -d bin -classpath bin source/
  5. You will get errors because the program WhichString doesn't know which String it should use, the java.lang String or your new String that you imported in the first line of You need to add the package names to the Strings, thus you need to declare x and y with either java.lang.String OR not just something like String x; You will need to declare like this instead --> x; In this case the variable x should be the new String we created and variable y should be a java.lang String. cd to the source directory and then try to fix the WhichString code yourself and get it compiling without errors. HINT: don't forget that the public static void main line also refers to a String and it will need the appropriate package name to proceed that String as well.
  6. Now we need to run it. The WhichString.class file is in cs2212package/bin. so try to run it with the following unix command:
    java bin/WhichString
    This doesn't work :-( Remember we need to set the classpath, so now try this command:
    java -classpath bin WhichString
  7. Okay, now the problem is we are getting lots of directories and files to keep track of, can we simplify a bit?

    The previous steps should have taken about 10 minutes to complete.


Part 2: Jar files

Zipping the files up

Using our example from above, right now we only have 3 java files:,, and BUT what if we are building a bigger system and have lots of files to manage or our program depends on some other files, we end up dealing with lots of files and directories. A jar file allows us to zip everything up together. Always remember: a jar file is exactly the same as a zip file, you can even change the extension from .jar to .zip and the file should unzip properly. First, let's assume we are going to just zip up the executable class files, java files and a small readme.txt for someone else to unzip.

  1. cd to the root directory cs2212package
  2. Create a file called readme.txt. put the following content into readme.txt

    To run HelloWorld, go to the directory containing the jar file and type: java -jar myfirstjar.jar
    To run WhichString, go to the directory containing the jar file and type: java -jar myfirstjar.jar WhichString

  3. In the root directory, at the unix prompt type:
    jar -vcf myfirstjar.jar readme.txt source/
    The jar command puts the file readme.txt and the file into the jar file called myfirstjar.jar
    1. the c option on the jar command stands for create a new jar file
      the v option on the jar command stands for verbose (tell us which files you are adding)
      the f option on the jar commands stands for file name, after the f there must be the name of the new jar file, ours is myfirstjar.jar
    2. we can put any type of file in a jar file. Usually they have .class files in them but we can put .doc files, .xls files, .jpg files, any type of file can go in a jar file!
  4. Now let's put all the files into myfirstjar.jar, type the following command:
    jar -vcf myfirstjar.jar *.txt source bin
    You should see all the files that are going into the jar file
  5. Now copy the file myfirstjar.jar into the directory cs2212packages/test
  6. To see the files from a jar file, you need the -tf option.
    cd to the test directory, then type the following command in the cs2212packages/test directory:
    jar -tf myfirstjar.jar
    1. NOTE:
      t means list the files included in the jar file
      f means this is the name of the jar file
  7. To extract the files from your jar file, you need the -x option. NOTE that it will create all the subdirectories also. Type this command:
    jar -xvf myfirstjar.jar
    in the cs2212package/test directory and everything should extract out into the test directory. Enter the ls command just to double check
  8. cd up to the cs2212package directory and delete the test directory and all its contents -->rm -R test


Running a java application from a jar file

Your can run applications right from the jar files but you have to tell the jar file which program is the main file inside the jar file. The way you tell the java command which file to start with (the static void main one) is by creating a manifest file. The manifest file tells which .class file is the main method AND which directory to look for it in. Let's first try it out for the HelloWorld file. Remember it is contained in cs2212package/bin/ca/uwo/csd/world AND it is in a package called

  1. Go to the root directory cs2212package
  2. Create a file called Manifest.txt and put the following text in it:

    Class-Path: ./bin/


  3. Make sure the file Manifest.txt ends with a blank line! THERE MUST BE A BLANK LINE AT THE END OF THE FILE.
    -you must use the exact same case as above.
    -the first line tells the JVM what is the name of the class containing the static void main method
    -the second line tells the JVM where to find the .class file RELATIVE to the base directory (root directory)
    -it took me quite a while to figure out I needed a / at the END of the bin directory, don't forget that one :-)
    -make sure the third line is a blank line!
  4. Save the file Manifest.text
  5. In the root directory cs2212package, type the following command:
    jar -cfmv myfirstjar.jar Manifest.txt source bin
    NOTES: if you put the f option first in -cfmv,then the .jar file name must be first, if you put the m option first, for example -cmfv then the Manifest.txt filename must follow the options BEFORE the .jar filename.
  6. Type the command:
    java -jar myfirstjar.jar
    and you should see Hello World

Now let's try getting WhichString to work:

  1. Go to the root directory cs2212package
  2. Edit the file called Manifest.txt and change it to:

    Main-Class: WhichString
    Class-Path: ./bin/


  3. Save the file Manifest.txt, make sure to remember the blank line at the end
  4. In the root directory cs2212package type the following command:
    jar -cfmv myfirstjar.jar Manifest.txt source bin
  5. Now type the command:
    java -jar myfirstjar.jar
  6. Okay, now, can we simplify it EVEN MORE! YES, with the use of apache ant files!

    The previous section should have taken about 30 minutes to complete.

Part 3: Apache Ant Build Files

Apache Ant files will allow you to make a file containing commands that will clean up directories, recompile but only when necessary, create jar files and run your program all in one simple script. Let's see how to use them:

Setting up Ant on a Windows Machine

  1. Ant files allow you to set up a list of commands sort of similar to a batch file. It is a tool that lets you automate the building process (compiling, running tests, deploying the system, running the software). The cool thing is that it is platform independent, once you make the build file, you can likely use it on a Unix platform or on a Windows platform. NOTE: WE WILL BE TRYING ANT OUT ON GAUL FOR THE PURPOSES OF THIS LAB (Apache Ant is already installed on Gaul).

Creating the build file and running it

  1. Ant build files are just text files using XML format. On Gaul, make sure you are in our root directory: cs2212package and create a file called build.xml put the following text in it:

    <project name="LetsPlay">
         <property name="msg" value="Comp Sci at Western"/>
         <target name="PrintSomeStuff">

         <!-- this is a comment, message 1 -->
         <echo message="embedded message"/>

         <!-- message 2 -->
         <echo>a longer message
         over two lines

          <!-- message 3 -->
         <echo message="${msg}" />


  2. Save the file. Type the following command to run it at the gaul prompt: ant PrintSomeStuff
    1. notice that the target name is called PrintSomeStuff. So when we said ant PrintSomeStuff we were actually saying "look inside the build.xml file, find a target (or command) called PrintSomeStuff and do EVERYTHING that is inside (between <target name="PrintSomeStuff"> and </target>
    2. msg is a variable and is given the value--> "Comp Sci at Western" To use this variable, you need to type "${msg}"
    3. variables go at the top, right after the the <project> tag and are created with the property tag
    4. every build file must start with the tag <project> at the beginning and a </project> at the end of the file
    5. every build file must have at least one <target>, a target consists of tasks to be done. In the above case it printed some data to the screen
    6. echo is a predefined ant command with some parameters such as message. When you use this command on one line you MUST end it with />. If you use it over several lines, you start with <echo> and must end it with </echo>
  3. Edit the file build.xml again, after the line </target>, add a new target with the name: MyName. (look at the current target PrintSomeStuff to figure out the syntax for the target line) Make sure you remember to put another </target> to end it. Add the following:
    1. Add a variable called firstname, give it the value of your first name (make sure you put your variables at the top, use the syntax of the property name to make the variable)
    2. Add another variable called lastname, give it the value of your last name
    3. In between the <target ...> and the </target>, make an echo task to print your first name on one line and your last name on the next line
    4. Save the file and close it
  4. At the gaul prompt enter the command: ant MyName
  5. Now at the gaul prompt, just type: ant
    It should just say something like: Build Successful but not do anything
  6. If you want one of the target commands to be done no matter what, you must give the project a default command. For example, edit build.xml and change the project line to be <project name="LetsPlay" default="MyName">, save and close the file and again type the command: ant
  7. Sometimes you will have tasks that depend on previous tasks being completed successfully. For example, you cannot run your code unless it compiled successfully, so the run would depend on the compile. Supposed for our example that we did not want our name to be printed out UNLESS the first set of messages we set up were printed first. In this case MyName depends on PrintSomeStuff. To demonstrate this you need to edit build.xml and change the target line for MyName to <target name="MyName" depends="PrintSomeStuff"> Save the file and then type the command: ant
  8. Suppose you want to remove the readme.txt file and all the .class files from directories and subdirectories. You can do this with the delete task. After the second </target> but before the </project>, add the following:
    <target name="clean">
       <delete file="readme.txt"/>
       <delete dir="bin" includes="**/*.class" />

  9. At the command prompt, type the command: ant clean
  10. cd into the bin directory, noticed that the empty subdirectories are still there. To remove the subdirectories also, change the delete task as follows:
    <target name="clean">
       <delete file="readme.txt"/>
       <delete includeemptydirs="true">
            <fileset dir="bin" includes="**/*" />

     NOTE: you have to change the includes part to be "**/*" because a recursive delete can't just do .class files anymore if you are also deleting the directories. Run this build file (ant clean) and make sure the subdirectories in bin were removed.
    Be VERY CAREFUL with this command, for example <delete dir="."/> WILL DELETE EVERYTHING IN THE CURRENT DIRECTORY, include the SOURCE directory. Make sure you watch your syntax with this command!
  11. There are LOTS of other commands you can do in an Ant build file. The list of commands and how they work can be found at: Then click on Ant Tasks in the left column, and then click on Core Tasks and then pick one of the commands to look at, such as Delete (the one we just used). NOTE: these commands are what makes ant build.xml files work on any operating system, because they use their own set of commands so ant translates the delete command into rm and rmdir when the build.xml is run on a unix system but on a Mac it would translate the delete into the command that Macs use to delete files and folders.


Creating the build file to compile, jar and run java programs

  1. Get into the root directory cs2212package. Edit a text file called build2.xml and put the following text into it:

    <project name="HelloEarth">
       <!-- Variable for the package file hierarchy -->
             <property name="package" value="ca/uwo/csd/world" />

      <!--Clean up the bin directory -->
          <target name="clean">
               <delete dir="./bin" />
               <mkdir dir="./bin" />

        <!-- Compile the HelloWorld program -->
             <target name="compile" depends="clean">
                     <javac srcdir="./source/${package}" destdir ="./bin" />

  2. Run the build2.xml file at the gaul prompt. NOTE: because this file does not have the default name (build.xml), we need to give the name of the buildfile when we run it, so the command would be: ant -f build2.xml compile
    1. Make sure you understand what the commands are doing:
      1. clean is deleting the bin directory from the current directory and then recreating it using a make directory ant command (mkdir)
      2. compile is dependent on the clean AND it is compiling from the source/ca/uwo/csd/world directory AND it is putting the executable class (the HelloWorld.class file) into the bin directory AND the package command at the top of will force the subdirectories in bin to be created called ca/uwo/csd/world and HelloWorld.class will go into the world directory.
    2. Note that our project doesn't have a default target yet, so you have to say compile or clean after the ant command
    3. Try to run the HelloWorld now with the command:
      java -classpath bin
      This will likely not work because in our HelloWorld program, in the static void main (String[] args) line references a String (the String[] args) and we had created that silly little class called which is screwing up HelloWorld.
  3. To avoid the issues with Strings, edit the build2.xml file and change the compile target command as follows, this will stop the from being compiled and thus the static void main(String args[]) line in HelloWorld will not get confused about which String class to use.
    <!-- Compile the HelloWorld program -->
    <target name="compile" depends="clean">
      <javac srcdir="./source/${package}/" destdir="./bin">
        <include name="**/"/>
        <exclude name="**/" />


  4. Notice the areas in bright red above, make sure you removed the / on the javac line. Run the buildfile again to do the compile and then try running the HelloWorld program again now and it should work:
    java -classpath bin
  5. There are two ways you could run the file from the build2.xml file: either just running the class OR with a jar file, let's try the first way.Before the </project> but after the last </target>, add the following lines to your build2.xml:
    <!-- Run the HelloWorld program -->
    <target name="run1">
       <java classname="" classpath="./bin"/>
  6. Now run the HelloWorld program as follows, at the unix prompt type: ant -f build2.xml run1
  7. Now lets put the and the into a jar file and run the WhichString file but lets run it from the jar file. First lets set up the compile correctly and get it running without a jar file. Create a new file called build3.xml and put the following code in it:

    <project name="WhichStringIsIt">

    <!-- Variable for the package file hierarchy -->
    <property name="package" value="ca/uwo/csd/world" />

    <!--Clean up the bin directory -->
       <target name="clean">
          <delete dir="./bin" />
          <mkdir dir="./bin" />

    <!-- Compile the WhichString required classes -->
       <target name="compile" depends="clean">
          <javac srcdir="./source" destdir="./bin/">
                <include name="**/*.java"/>
                <exclude name="**/" />

    <!-- Run the WhichString program -->
       <target name="run2" depends="compile">
          <java classname="WhichString" classpath="./bin"/>


  8. To run WhichString, just type the following at the command prompt: ant -f build3.xml run2
  9. Edit build3.xml and add the following the project line: <project name="WhichStringIsIt" default="run2"> and then save the file. Remember that: the default command says if the user doesnt specify which target to run, run the default one. So now instead of typing: ant -f build3.xml run2,you can just type: ant -f build3.xml
  10. Now lets add the required lines to create the jar file. Edit the build3.xml file and make the changes indicated in red:

    <project name="WhichStringIsIt" default="run2">

    <!-- Variable for the package file hierarchy -->
    <property name="package" value="ca/uwo/csd/world" />

    <!--Clean up the bin directory -->
       <target name="clean">
          <delete dir="./bin" />
          <mkdir dir="./bin" />

    <!-- Compile the WhichString required classes -->
       <target name="compile" depends="clean">
          <javac srcdir="./source" destdir="./bin/">
                <include name="**/*.java"/>
                <exclude name="**/" />

    <!-- Make jar file, just add the .class files -->
       <target name="jar" depends="compile">
          <jar destfile="MyJarFile.jar"
                <attribute name="Main-Class" value="WhichString" />

    <!-- Run the WhichString program -->
       <target name="run2" depends="jar">
          <java jar="MyJarFile.jar" classpath="./bin" fork="true"/>


    1. the manifest section above tells the jar file which class contains the starting point (i.e. the static void main ...)
    2. the default = run2 on the first line tells the system that if you forget to put which target, by default, it will do the run2 target
    3. when you run from a jar file, you need fork to be true ...don't ask Laura what fork means, she just knows it has to be true! :-)
  11. Now test your new build file by typing the following at the command prompt: ant -f build3.xml
  12. If you need more information about apache ant commands, go to this website: and click on Ant Tasks in the left hand column and then click on Core Tasks.
  13. NOTE: if you are running Windows, the following instructions will help you setup Ant on your Windows machine:
    1. Download and unzip the windows version of Apache Ant by clicking here . Install it and find the folder it is in, likely: C:\apache-ant-1.7.1
    2. Right-click on "My Computer", click the "Advanced" tab. Click the Environment Variables" button on the bottom left. Click the "New" button to create a new environment variable. Create one called ANT_HOME whose value is C:\apache-ant-1.7.1 .
    3. Then "Edit" the PATH variable and add to the end of it *;*C:\apache-ant-1.7.1\bin . Then make sure you have an environment variable called JAVA_HOME which points to the JDK you want to use (e.g. C:\Program Files\Java\jdk1.6.0_06 ). Then click "Ok" on the "Environment Variables" window and then again "Ok" on the "System Properties" window.
    4. Start your command prompt on Windows. If typing the following command at the dos prompt works--> ant -version (i.e. shows the version of ant you are using) then it was set-up correctly.