Java Projects

CS 1331

Java Projects

You know the basics of Java. Today you'll learn a few basic properties of professional Java projects, including

  • the classpath
  • separating source and compiler output
  • project directory layout
  • packages
  • jar files

The Classpath

Just as your operating system shell looks in the PATH environment variable for executable files, JDK tools (such as javac and java) look in the CLASSPATH for Java classes.

A classpath specification is a list of places to find .class files and other resources. Two kinds of elements in this list:

  • directories in which to find .class files on the filesystem, or
  • .jar files that contain archives of directory trees containing .class files and other files (more later).

Specifying a Classpath

To specify a classpath:

  • set an environment variable named CLASSAPTH, or
  • specify a classpath on a per-application basis by using the -cp switch. The classpath set with -cp overrides the CLASSPATH environment variable.

Don't use the CLASSPATH environment variable. If it's already set, clear it with (on Windows):

C:\> set CLASSPATH=

or (on Unix):

$ unset CLASSPATH

Using -cp

To compile and run a program with compiler output (.class files) in the current directory and a library Jar file in the lib directory called util.jar, you'd specify the classpath like this:

$ ls -R # -R means recursive (show subdirectory listings)
MyProgram.java     AnotherClass.java

./lib:
util.jar
$ javac -cp .:lib/util.jar *.java # : separates classpath elements
$ java -cp .:lib/util.jar MyProgram # would be ; on Windows

Notice that you include the entire classpath in the -cp, which includes the current directory (. means ``current directory'').

Separating Compiler Output

To reduce clutter, you can compile classes to another directory with -d option to javac

$ mkdir classes
$ javac -d classes HelloWorld.java
$ ls classes/
HelloWorld.class

Specify classpath for an application with the -cp option to { java}.

$ java -cp ./classes HelloWorld
Hello, world!

Separating Source Files

If you really want to keep your project's root directory clean (and you do), you can put your source code in another directory too, like src.

$ mkdir src
$ mv HelloWorld.java src/
$ javac -d ./classes src/HelloWorld.java
$ java -cp ./classes HelloWorld
Hello, world!

Standard Directory Layout

Source Directories

  • src/main/java for Java source files
  • src/main/resources for resources that will go on the classpath, like image files

Output Directories

  • target/classes for compiled Java .class files and resources copied from src/main/resources

There's more, but this is enough for now. More details on the de-facto standard Java project directory layout can be found at Maven's directory layout guide.

Organizing your Code in Packages

All professional Java projects organize their code in packages. The standard package naming scheme is to use reverse domain name, followed by project specific packages. For a CompanyGUI application we could use the package name

package edu.gatech.cs1331.companygui;

and source files would be located in a directory under your src/ directory as follows

src/edu/gatech/cs1331/companygui/

And if you tell javac to put compiler output in target/classes then the compiled .class file would end up in:

target/edu/gatech/cs1331/companygui

Ant

Ant is a build automation tool, like make. Install it however you want (like with homebrew on a Mac), then put this in a file named build.xml in the root directory of your companygui project:

<?xml version="1.0" encoding="UTF-8"?>
<project name="companygui" default="default" basedir=".">
  <path id="classpath">
    <fileset dir="target" includes="**/*.class"/>
  </path>

  <target name="init" depends="clean">
    <mkdir dir="target"/>
  </target>

  <target name="compile" depends="init">
    <javac srcdir="src"
           destdir="target"
           classpathref="classpath"
           source="1.7"
           target="1.7" />
  </target>
</project>

Compiling with Ant

Invoke the compile target to compile the project:

$ ant compile
Buildfile: /Users/chris/work/vcs/github/software-design-practice/code/blackjack/build.xml

init:
...
compile:
...
BUILD SUCCESSFUL
Total time: 0 seconds

This will produce class files in target/classes. How would you run the Blackjack class?

Jar Files

A jar archive, or jar file, is a Zip-formatted archive of a directory tree. Java uses jar files as a distribution format for libraries.

  • To create a JAR file: jar cf jar-file input-file(s)
  • To view the contents of a JAR file jar tf jar-file
  • To extract the contents of a JAR file: jar xf jar-file or unzip jar-file
  • To extract specific files from a JAR file: jar xf jar-file archived-file(s)
  • To run an application packaged as a JAR file (requires the Main-class manifest header): java -jar app.jar

See Oracle's Jar file guide for more details.

Runnable Jar Files

The hard way: Oracle's Jar file guide

The easy way: add this to your build.xml:

  <target name="package" depends="compile">
    <jar destfile="target/blackjack.jar">
      <fileset dir="target/classes"/>
      <manifest>
        <attribute name="Main-class" value="Blackjack"/>
      </manifest>
    </jar>
  </target>

Then you can do:

$ ant package
...
BUILD SUCCESSFUL
Total time: 0 seconds
$ java -jar target/blackjack.jar

Gradle

Gradle uses Java project conventions to make things much easier than with Ant. Here's a minimal Gradle build file for a Java project:

apply plugin: 'java'

The java plugin assumes the Maven Sandard Directory Layout and provides many useful tasks "out of the box". To list them, do:

gradle tasks

See Gradle's Java Quickstart for details.