JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1...

54
JavaSE: First Simple Module Exercise A Basic Introduction to JavaSE and Maven Modules Revision: v2018-08-14 Built on: 2019-08-22 07:08 EST Copyright © 2019 jim stafford ([email protected]) This document contains an introductory exercise for building a Maven-based JavaSE project that is self-contained. The exercise takes a building-block approach that demystifies some of the Maven build concepts by breaking down many core concepts into files, directories, and individual commands prior to introducing the overall framework and its integration with an IDE.

Transcript of JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1...

Page 1: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

JavaSE: First Simple Module Exercise

A Basic Introduction to

JavaSE and Maven Modules

Revision: v2018-08-14Built on: 2019-08-22 07:08 EST

Copyright © 2019 jim stafford ([email protected])

This document contains an introductory exercise for building a Maven-based JavaSE project

that is self-contained. The exercise takes a building-block approach that demystifies some of the

Maven build concepts by breaking down many core concepts into files, directories, and individual

commands prior to introducing the overall framework and its integration with an IDE.

Page 2: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will
Page 3: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

iii

Purpose ............................................................................................................................ v

1. Goals .................................................................................................................... v

2. Objectives ............................................................................................................. v

1. Develop and Test Module using Command Line Tools (OPTIONAL!) ........................... 1

1.1. Summary ............................................................................................................ 5

2. Automate Build and Testing with Ant (OPTIONAL!) .................................................... 7

2.1. Summary .......................................................................................................... 14

3. Adding Logging ......................................................................................................... 15

3.1. Summary .......................................................................................................... 19

4. Creating Portable and Repeatable Project Builds with Maven ................................... 21

4.1. Summary .......................................................................................................... 33

5. Leverage IDE using Eclipse ....................................................................................... 35

5.1. Import a project into Eclipse .............................................................................. 35

5.2. Setup Eclipse to be able to execute Maven project goals ..................................... 39

5.3. Setup environment to enable interactive debugging ............................................. 42

5.4. Summary .......................................................................................................... 47

Page 4: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

iv

Page 5: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

v

Purpose

1. Goals• Identify the core use cases required to develop a Java Archive (JAR) module

• Demonstrate how Maven fits within the development of a JAR module

• Demonstrate how Maven integrates with a sample IDE

2. Objectives

At the completion of this topic, the student shall be able to:

• Create a module with directory structure and files to build a Java Archive (JAR)

• Create a Java class for inclusion in the JAR

• Create a unit test for the Java class

• Automate the build using Maven

• Import the Maven module into an IDE for development

• Use the IDE to interactively debug the Java class and unit test

Note

Some of the parts of this exercise are marked OPTIONAL! There is no need to

physically perform the details of these steps if you are already familiar with the

concepts presented. Skim the material and advance to the parts you are not familiar

with.

Page 6: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

vi

Page 7: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 1.

1

Develop and Test Module using

Command Line Tools (OPTIONAL!)In this chapter you will be introduced to a standard module file structure that contains a class we

intend to use in production and a unit test to verify the functionality of the production class. You

will be asked to form the directory structure of files and execute the commands required to build

and run the unit test.

Warning

This chapter is optional!!! It contains many tedious steps that are somewhat shell-

specific. The intent is to simply introduce the raw data structure and actions that

need to take place and then to later automate all of this through Maven. If you wish

to just skim the steps -- please do. Please do not waste time trying to port these

bash shell commands to your native shell.

Note

This part requires junit.jar. These should have been downloaded for you when you

built the class examples and can be located in $M2_REPO/junit/junit/(version)/.

Where M2_REPO is HOME/.m2/repository or the location you have specified in

the localRepository element of $HOME/.m2/settings.xml.

1. Set a few shell variables to represent root directories. For the purposes of the follow-on

steps, PROJECT_BASEDIR is the root directory for this exercise. In the example below, the user

has chosen a directory of $HOME/proj/784/exercises to be the root directory for all class

exercises and named the root directory for this project "ex1". An alternative for CLASS_HOME

might be c:/jhu/784. M2_REPO is the path to your Maven repository.

export CLASS_HOME=$HOME/proj/784

export PROJECT_BASEDIR=$CLASS_HOME/exercises/ex1

mkdir -p $PROJECT_BASEDIR

cd $PROJECT_BASEDIR

export M2_REPO=$HOME/.m2/repository

2. Create project directory structure. In this example, the developer used $HOME/proj/784 for all

work in this class.

$PROJECT_BASEDIR

|-- src

| |-- main

| | `-- java

| | `-- myorg

| | `-- mypackage

| | `-- ex1

| `-- test

Page 8: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 1. Develop and Test M...

2

| |-- resources

| `-- java

| `-- myorg

| `-- mypackage

| `-- ex1

`-- target

|-- classes

|-- test-classes

`-- test-reports

mkdir -p src/main/java/myorg/mypackage/ex1

mkdir -p src/test/java/myorg/mypackage/ex1

mkdir -p src/test/resources

mkdir -p target/classes

mkdir -p src/test/java/myorg/mypackage/ex1

mkdir -p target/test-classes

mkdir -p target/test-reports

3. Add the following Java implementation class to $PROJECT_BASEDIR/src/main/java/myorg/

mypackage/ex1/App.java

package myorg.mypackage.ex1;

public class App {

public int returnOne() {

System.out.println( "Here's One!" );

return 1;

}

public static void main( String[] args ) {

System.out.println( "Hello World!" );

}

}

4. Add the following Java test class to $PROJECT_BASEDIR/src/test/java/myorg/mypackage/

ex1/AppTest.java

package myorg.mypackage.ex1;

import static org.junit.Assert.*;

import org.junit.Test;

/**

* Unit test for simple App.

*/

public class AppTest {

@Test

public void testApp() {

System.out.println("testApp");

App app = new App();

assertTrue("app didn't return 1", app.returnOne() == 1);

Page 9: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

3

}

}

Note

Make sure you put AppTest.java in the src/test tree.

5. Compile the application and place it in target/ex1.jar. The compiled classes will go in target/

classes.

javac src/main/java/myorg/mypackage/ex1/App.java -d target/classes

jar cvf target/ex1.jar -C target/classes .

jar tf target/ex1.jar

$ javac src/main/java/myorg/mypackage/ex1/App.java -d target/classes

$ jar cvf target/ex1.jar -C target/classes .

added manifest

adding: myorg/(in = 0) (out= 0)(stored 0%)

adding: myorg/mypackage/(in = 0) (out= 0)(stored 0%)

adding: myorg/mypackage/ex1/(in = 0) (out= 0)(stored 0%)

adding: myorg/mypackage/ex1/App.class(in = 519) (out= 350)(deflated 32%)

$ jar tf target/ex1.jar

META-INF/

META-INF/MANIFEST.MF

myorg/

myorg/mypackage/

myorg/mypackage/ex1/

myorg/mypackage/ex1/App.class

6. Compile the JUnit test and place the compiled tests in target/test-classes.

export JUNIT_JARS="$M2_REPO/junit/junit/4.12/junit-4.12.jar:$M2_REPO/org/hamcrest/hamcrest-core/1.3/

hamcrest-core-1.3.jar"

javac -classpath "target/ex1.jar:$JUNIT_JARS" src/test/java/myorg/mypackage/ex1/AppTest.java -d target/test-

classes

7. Verify you have your "production" class from src/main compiled into target/classes directory,

your unit test class from src/test compiled into target/test-classes directory, and the Java archive

with the production class is in target directory.

target

|-- classes

| `-- myorg

| `-- mypackage

| `-- ex1

| `-- App.class

|-- ex1.jar

|-- test-classes

| `-- myorg

| `-- mypackage

| `-- ex1

Page 10: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 1. Develop and Test M...

4

| `-- AppTest.class

`-- test-reports

8. Run the JUnit test framework.

java -classpath "target/ex1.jar:$JUNIT_JARS:target/test-classes" org.junit.runner.JUnitCore

myorg.mypackage.ex1.AppTest

JUnit version 4.12

.testApp

Here's One!

Time: 0.003

OK (1 test)

9. Change add/remove a test that will fail, re-compile the test class, and re-run.

//AppTest.java

@Test

public void testFail() {

System.out.println("testFail");

App app = new App();

assertTrue("app didn't return 0", app.returnOne() == 0);

}

javac -classpath "target/ex1.jar:$JUNIT_JARS" src/test/java/myorg/mypackage/ex1/AppTest.java -d target/test-

classes

java -classpath "target/ex1.jar:$JUNIT_JARS:target/test-classes" org.junit.runner.JUnitCore

myorg.mypackage.ex1.AppTest

JUnit version 4.12

.testApp

Here's One!

.testFail

Here's One!

E

Time: 0.007

There was 1 failure:

1) testFail(myorg.mypackage.ex1.AppTest)

java.lang.AssertionError: app didn't return 0

at org.junit.Assert.fail(Assert.java:93)

at org.junit.Assert.assertTrue(Assert.java:43)

at myorg.mypackage.ex1.AppTest.testFail(AppTest.java:26)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

...

at org.junit.runner.JUnitCore.main(JUnitCore.java:45)

FAILURES!!!

Tests run: 2, Failures: 1

Page 11: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Summary

5

1.1. Summary

In this chapter of the exercise you setup, built, and tested a sample project with only command-line

commands. You did this to help show what higher level tools will need to do as well. Even though

the command line provides clarity, it doesn't scale and shell scripts aren't generally portable and

optimized (wrong tool for the job). Hopefully, after going through this, you have an understanding

of the low level structure and usecases and are now interested adding a build environment.

Page 12: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

6

Page 13: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 2.

7

Automate Build and Testing with Ant

(OPTIONAL!)This chapter demonstrates the basics of automating the manual steps in the previous chapter

using the Apache Ant build tool. If you just skim thru this step, please be sure to take note of

how everything gets explicitly defined in Ant. There are not many rules of the road and standard

defaults to live by. That will be a big contrast when working with Maven.

Note

All course examples and projects submitted will use Maven. Ant will be used

to wrap command lines for Java SE clients executed outside the normal build

environment. However, this exercise shows Ant only being used as part of the

artifact build and test environment as a stepping stone to understanding some of

the basic build and test concepts within Maven.

Note

If you do not have Ant installed on your system, it can be from http://ant.apache.org/

Warning

This chapter is optional!!! It contains many tedious steps to setup a module build

using the Ant build tool -- which will not be part of class. It is presented here as an

example option to building the module with shell scripts. If you wish to just skim the

steps -- please do. Please do not waste time trying to get Ant to build your Java

modules for this class.

1. Create a build.properties file in $PROJECT_BASEDIR. This will be used to define any non-

portable property values. Place the most non-portable base variables (.e.g, M2_REPO location)

towards the top and build lower-level paths from them. This makes the scripts much easier to

port to another environment. If you still have your maven repository in your $HOME directory,

you can make use of ${user.home} environment variable rather than a hard-coded path.

#ex1 build.properties

#M2_REPO=c:/jhu/repository

M2_REPO=${user.home}/.m2/repository

junit.classpath=${M2_REPO}/junit/junit/4.10/junit-4.10.jar

2. Create a build.xml file in $PROJECT_BASEDIR. Note the following key elements.

• project - a required root for build.xml files

• name - not significant, but helpful

• default - the target to run if none is supplied on command line

Page 14: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 2. Automate Build and...

8

• basedir - specifies current directory for all tasks

• property - defines an immutable name/value

• file - imports declarations from a file; in this case build.properties created earlier

• name/value - specifies a property within the script

• target - defines an entry point into the build.xml script. It hosts one or more tasks.

• name - defines name of target, which can be supplied on command line.

• echo - a useful Ant task to printout status and debug information. See Ant docs [https://

ant.apache.org/manual/Tasks/echo.html] for more information.

<?xml version="1.0" encoding="utf-8" ?>

<!-- ex1 build.xml

-->

<project name="ex1" default="" basedir=".">

<property file="build.properties"/>

<property name="artifactId" value="ex1"/>

<property name="src.dir" value="${basedir}/src"/>

<property name="build.dir" value="${basedir}/target"/>

<target name="echo">

<echo>basedir=${basedir}</echo>

<echo>artifactId=${artifactId}</echo>

<echo>src.dir=${src.dir}</echo>

<echo>build.dir=${build.dir}</echo>

<echo>junit.classpath=${junit.classpath}</echo>

</target>

</project>

3. Sanity check your build.xml and build.properties file with the echo target.

$ ant echo

Buildfile: /home/jim/proj/784/exercises/ex1/build.xml

echo:

[echo] basedir=/home/jim/proj/784/exercises/ex1

[echo] artifactId=ex1

[echo] src.dir=/home/jim/proj/784/exercises/ex1/src

[echo] build.dir=/home/jim/proj/784/exercises/ex1/target

[echo] junit.classpath=/home/jim/.m2/repository/junit/junit/4.10/junit-4.10.jar

BUILD SUCCESSFUL

Total time: 0 seconds

4. Add the "package" target to compile and archive your /src/main classes. Note the following

tasks in this target.

• mkdir - creates a directory. See Ant Mkdir docs [https://ant.apache.org/manual/Tasks/

mkdir.html] for more infomation.

• javac - compiles java sources files. See Ant Javac docs [https://ant.apache.org/manual/

Tasks/javac.html] for more information. Note that we are making sure we get JavaSE 8

classes compiled.

Page 15: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

9

• jar - builds a java archive. See Ant Jar Docs [https://ant.apache.org/manual/Tasks/jar.html]

for more information.

<target name="package">

<mkdir dir="${build.dir}/classes"/>

<javac srcdir="${src.dir}/main/java"

destdir="${build.dir}/classes"

debug="true"

source="1.8"

target="1.8"

includeantruntime="false">

<classpath>

</classpath>

</javac>

<jar destfile="${build.dir}/${artifactId}.jar">

<fileset dir="${build.dir}/classes"/>

</jar>

</target>

5. Execute the "package" target just added. This should compile the production class from src/

main into target/classes and build a Java archive with the production class in target/.

$ rm -rf target/; ant package

Buildfile: /home/jim/proj/784/exercises/ex1/build.xml

package:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/classes

[jar] Building jar: /home/jim/proj/784/exercises/ex1/target/ex1.jar

BUILD SUCCESSFUL

Total time: 2 seconds

Note

You may get the following error when you execute the javac task. If so, export

JAVA_HOME=(path to JDK_HOME) on your system to provide Ant a reference

to a JDK instance.

build.xml:26: Unable to find a javac compiler;

com.sun.tools.javac.Main is not on the classpath.

Perhaps JAVA_HOME does not point to the JDK.

It is currently set to ".../jre"

$ find . -type f

./src/main/java/myorg/mypackage/ex1/App.java

./src/test/java/myorg/mypackage/ex1/AppTest.java

./build.properties

./build.xml

./target/classes/myorg/mypackage/ex1/App.class

Page 16: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 2. Automate Build and...

10

./target/ex1.jar

6. Add the "test" target to compile your /src/test classes. Make this the default target for your

build.xml file. Note too that it should depend on the successful completion of the "package"

target and include the produced archive in its classpath.

<project name="ex1" default="test" basedir=".">

...

<target name="test" depends="package">

<mkdir dir="${build.dir}/test-classes"/>

<javac srcdir="${src.dir}/test/java"

destdir="${build.dir}/test-classes"

debug="true"

source="1.8"

target="1.8"

includeantruntime="false">

<classpath>

<pathelement location="${build.dir}/${artifactId}.jar"/>

<pathelement path="${junit.classpath}"/>

</classpath>

</javac>

</target>

7. Execute the new "test" target after clearing out the contents of the target directory. Note that

the target directory gets automatically re-populated with the results of the "compile" target and

augmented with the test class from src/test compiled into target/test-classes.

$ rm -rf target/; ant

Buildfile: /home/jim/proj/784/exercises/ex1/build.xml

package:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/classes

[jar] Building jar: /home/jim/proj/784/exercises/ex1/target/ex1.jar

test:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/test-classes

BUILD SUCCESSFUL

Total time: 3 seconds

> find . -type f

./src/main/java/myorg/mypackage/ex1/App.java

./src/test/java/myorg/mypackage/ex1/AppTest.java

./build.properties

./build.xml

./target/classes/myorg/mypackage/ex1/App.class

./target/ex1.jar

./target/test-classes/myorg/mypackage/ex1/AppTest.class

Page 17: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

11

8. Add the junit task to the test target. The junit task is being configured to run in batch mode

and write a TXT and XML reports to the target/test-reports directory. See Ant docs [https://

ant.apache.org/manual/Tasks/junit.html] for more details on the junit task. Make special note

of the following:

• printsummary - produce a short summary to standard out showing the number of tests run

and a count of errors, etc.

• fork - since Ant runs in a JVM, any time you run a task that requires a custom classpath, it is

usually required that it be forked into a separate process (with its own classpath).

• batchtest - run all tests found and write results of each test into the test-reports directory.

• formatter - write a text and XML report of results

<mkdir dir="${build.dir}/test-reports"/>

<junit printsummary="true" fork="true">

<classpath>

<pathelement path="${junit.classpath}"/>

<pathelement location="${build.dir}/${artifactId}.jar"/>

<pathelement location="${build.dir}/test-classes"/>

</classpath>

<batchtest fork="true" todir="${build.dir}/test-reports">

<fileset dir="${build.dir}/test-classes">

<include name="**/*Test*.class"/>

</fileset>

</batchtest>

<formatter type="plain"/>

<formatter type="xml"/>

</junit>

Note

A few years ago when I sanity checked this exercise I got the common error

below. I corrected the issue by downloading a full installation from the Ant

website and exporting my ANT_HOME to the root of that installation. (export

ANT_HOME=/opt/apache-ant-1.9.4) and adding $ANT_HOME/bin to the PATH

(export PATH=$ANT_HOME/bin:$PATH) ANT_HOME is required for Ant to

locate the junit task.

BUILD FAILED

/home/jim/proj/784/exercises/ex1/build.xml:57: Problem: failed to create task or type junit

Cause: the class org.apache.tools.ant.taskdefs.optional.junit.JUnitTask was not found.

This looks like one of Ant's optional components.

Action: Check that the appropriate optional JAR exists in

-/usr/share/ant/lib

-/home/jim/.ant/lib

-a directory added on the command line with the -lib argument

Do not panic, this is a common problem.

The commonest cause is a missing JAR.

Page 18: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 2. Automate Build and...

12

This is not a bug; it is a configuration problem

9. Execute the updated "test" target with the JUnit test.

$ rm -rf target; ant

package:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/classes

[jar] Building jar: /home/jim/proj/784/exercises/ex1/target/ex1.jar

test:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/test-classes

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-reports

[junit] Running myorg.mypackage.ex1.AppTest

[junit] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 15.143 sec

[junit] Test myorg.mypackage.ex1.AppTest FAILED

BUILD SUCCESSFUL

Total time: 17 seconds

$ find . -type f

./src/main/java/myorg/mypackage/ex1/App.java

./src/test/java/myorg/mypackage/ex1/AppTest.java

./build.properties

./build.xml

./target/classes/myorg/mypackage/ex1/App.class

./target/ex1.jar

./target/test-classes/myorg/mypackage/ex1/AppTest.class

./target/test-reports/TEST-myorg.mypackage.ex1.AppTest.txt

./target/test-reports/TEST-myorg.mypackage.ex1.AppTest.xml

Note

Note the 17 seconds it took to run/complete the test seems excessive. I was

able to speed that up to 0.001 sec by commenting out the XML report option

(which we will not use in this exercise).

10.Test output of each test is in the TXT and XML reports.

$ more target/test-reports/TEST-myorg.mypackage.ex1.AppTest.txt

Testsuite: myorg.mypackage.ex1.AppTest

Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 15.246 sec

------------- Standard Output ---------------

testApp

Here's One!

testFail

Here's One!

------------- ---------------- ---------------

Testcase: testApp took 0.007 sec

Testcase: testFail took 0.022 sec

Page 19: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

13

FAILED

app didn't return 0

junit.framework.AssertionFailedError: app didn't return 0

at myorg.mypackage.ex1.AppTest.testFail(AppTest.java:26)

11.Add a clean target to the build.xml file to delete built artifacts. See Ant docs [https://

ant.apache.org/manual/Tasks/delete.html] for details on the delete task.

<target name="clean">

<delete dir="${build.dir}"/>

</target>

12.Re-run and use the new "clean" target you just added.

$ ant clean test

Buildfile: /home/jim/proj/784/exercises/ex1/build.xml

clean:

[delete] Deleting directory /home/jim/proj/784/exercises/ex1/target

package:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/classes

[jar] Building jar: /home/jim/proj/784/exercises/ex1/target/ex1.jar

test:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/test-classes

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-reports

[junit] Running myorg.mypackage.ex1.AppTest

[junit] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 15.123 sec

[junit] Test myorg.mypackage.ex1.AppTest FAILED

BUILD SUCCESSFUL

Total time: 17 seconds

13.Comment out the bogus testFail and rerun.

$ cat src/test/java/myorg/mypackage/ex1/AppTest.java

...

//@Test

public void testFail() {

$ ant clean test

Buildfile: /home/jim/proj/784/exercises/ex1/build.xml

clean:

[delete] Deleting directory /home/jim/proj/784/exercises/ex1/target

package:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/classes

[jar] Building jar: /home/jim/proj/784/exercises/ex1/target/ex1.jar

Page 20: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 2. Automate Build and...

14

test:

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-classes

[javac] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/test-classes

[mkdir] Created dir: /home/jim/proj/784/exercises/ex1/target/test-reports

[junit] Running myorg.mypackage.ex1.AppTest

[junit] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 15.161 sec

BUILD SUCCESSFUL

Total time: 17 seconds

2.1. Summary

In this chapter you performed many of the same actions you did in the previous chapter except

that you implemented in a portable build tool called Ant. Ant is very powerful and open-ended.

You were shown these same steps in Ant as an intermediate towards Maven. Ant, being open-

ended, does not follow many conventions. Everything must be explicitely specified. You will find

that to be in significant contrast with Maven. Ant is a "build tool" and Maven is a "build system"

with conventions/rules.

Page 21: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 3.

15

Adding LoggingIn this chapter we will refine the use of print and debug statements by using a "logger". By adopting

a logger into your production and test code you can avoid print statements to stdout/stderr and be

able to re-direct them to log files, databases, messaging topics etc. There are several to choose

from (Java's built-in logger, Commons logging API, SLF's logging API, and log4j to name a few).

This course uses the SLF API and and the log4j implementation.

1. Change the System.out() calls in App and AppTest from Part A to use SLF logging API. The

slf4j-api Javadoc [https://www.slf4j.org/apidocs/org/slf4j/package-summary.html] and manual

[https://www.slf4j.org/manual.html] will be helpful in understanding this interface.

package myorg.mypackage.ex1;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class App {

private static Logger logger = LoggerFactory.getLogger(App.class);

public int returnOne() {

//System.out.println( "Here's One!" );

logger.debug( "Here's One!" );

return 1;

}

public static void main( String[] args ) {

//System.out.println( "Hello World!" );

logger.info( "Hello World!" );

}

}

package myorg.mypackage.ex1;

...

import static org.junit.Assert.*;

import org.junit.Test;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class AppTest {

private static Logger logger = LoggerFactory.getLogger(AppTest.class);

...

@Test

public void testApp() {

//System.out.println("testApp");

logger.info("testApp");

App app = new App();

assertTrue("app didn't return 1", app.returnOne() == 1);

}

}

Page 22: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 3. Adding Logging

16

2. Add a log4j.xml configuration file to the directory structure. Place this file in src/test/resources/

log4j.xml. This file is used to control logging output. Refer to the log4j manual [https://

logging.apache.org/log4j/1.2/manual.html] for possible information on how to configure and use

log4j. It doesn't matter whether you use a log4j.xml format or log4j.properties format. Of note,

the implementation we are using is based on "Log4j 1" -- which reached its end of life in 2015.

It still works but all energy in this area is within "Log4j 2".

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration

xmlns:log4j="http://jakarta.apache.org/log4j/"

debug="false">

<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">

<param name="Target" value="System.out"/>

<layout class="org.apache.log4j.PatternLayout">

<param name="ConversionPattern"

value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L) -%m%n"/>

</layout>

</appender>

<appender name="logfile" class="org.apache.log4j.RollingFileAppender">

<param name="File" value="target/log4j-out.txt"/>

<param name="Append" value="false"/>

<param name="MaxFileSize" value="100KB"/>

<param name="MaxBackupIndex" value="1"/>

<layout class="org.apache.log4j.PatternLayout">

<param name="ConversionPattern"

value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>

</layout>

</appender>

<logger name="myorg.mypackage">

<level value="debug"/>

<appender-ref ref="logfile"/>

</logger>

<root>

<priority value="info"/>

<appender-ref ref="CONSOLE"/>

</root>

</log4j:configuration>

Note

The log4j.xml is placed in the JVM classpath; where log4j will locate it by default.

However, it should not be placed in with the main classes (ex1.jar). Placing

it in a our JAR file would polute the application assembler and deployer's job

Page 23: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

17

of specifying the correct configuration file at runtime. Our test classes and

resources are not a part of follow-on deployment.

3. Add the slf4j-api.jar to the compile classpaths and the slf4j-api.jar, slf4j-log4j.jar, and log4j.jar

to the runtime classpath used during tests. Also add an additional task to copy the log4j.xml

file into target/test-classes so that it is seen by the classloader as a resource. Realize that your

classes have no compilation dependencies on log4j. Log4j is only used if it is located at runtime.

# ex1 build.properties

junit.classpath=${M2_REPO}/junit/junit/4.12/junit-4.12.jar:\

${M2_REPO}/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar

slf4j-api.classpath=${M2_REPO}/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar

slf4j-log4j.classpath=${M2_REPO}/org/slf4j/slf4j-log4j12/1.7.25/slf4j-log4j12-1.7.25.jar

log4j.classpath=${M2_REPO}/log4j/log4j/1.2.17/log4j-1.2.17.jar

<target name="echo">

...

<echo>slf4j-api.classpath=${slf4j-api.classpath}</echo>

<echo>slf4j-log4j.classpath=${slf4j-log4j.classpath}</echo>

<echo>log4j.classpath=${log4j.classpath}</echo>

</target>

<javac srcdir="${src.dir}/main/java"

destdir="${build.dir}/classes"

debug="true"

source="1.8"

target="1.8"

includeantruntime="false">

<classpath>

<pathelement path="${slf4j-api.classpath}"/>

</classpath>

</javac>

<javac srcdir="${src.dir}/test/java"

destdir="${build.dir}/test-classes"

debug="true"

source="1.8"

target="1.8"

includeantruntime="false">

<classpath>

<pathelement location="${build.dir}/${artifactId}.jar"/>

<pathelement path="${junit.classpath}"/>

<pathelement path="${slf4j-api.classpath}"/>

</classpath>

</javac>

<copy todir="${build.dir}/test-classes">

<fileset dir="${src.dir}/test/resources"/>

</copy>

<junit printsummary="true" fork="true">

Page 24: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 3. Adding Logging

18

<classpath>

<pathelement path="${junit.classpath}"/>

<pathelement location="${build.dir}/${artifactId}.jar"/>

<pathelement location="${build.dir}/test-classes"/>

<pathelement path="${commons-logging.classpath}"/>

<pathelement path="${log4j.classpath}"/>

</classpath>

...

4. Test application and inspect reports. All loggers inherit from the root logger and may only extend

its definition; not limit it. Notice that the root logger's priority filter "info" value allows log.info()

(warning and fatal) messages to printed to the console. The myorg.mypackage logger's level

filter allows log.debug() messages from the myorg.mypackage.* classes to appear in both the

console and logfile. This means that any Java classes not in our package hierarchy will only

have INFO or higher priority messages logged.

$ ant clean test

Buildfile: /home/jcstaff/proj/784/exercises/ex1/build.xml

clean:

[delete] Deleting directory /home/jcstaff/proj/784/exercises/ex1/target

package:

[mkdir] Created dir: /home/jcstaff/proj/784/exercises/ex1/target/classes

[javac] Compiling 1 source file to /home/jcstaff/proj/784/exercises/ex1/target/classes

[jar] Building jar: /home/jcstaff/proj/784/exercises/ex1/target/ex1.jar

test:

[mkdir] Created dir: /home/jcstaff/proj/784/exercises/ex1/target/test-classes

[javac] Compiling 1 source file to /home/jcstaff/proj/784/exercises/ex1/target/test-classes

[copy] Copying 1 file to /home/jcstaff/proj/784/exercises/ex1/target/test-classes

[mkdir] Created dir: /home/jcstaff/proj/784/exercises/ex1/target/test-reports

[junit] Running myorg.mypackage.ex1.AppTest

[junit] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 15.127 sec

BUILD SUCCESSFUL

Total time: 17 seconds

You won't see the output come to stdout when using Ant, but you can locate all output in the

FILE logger output defined to be in target/log4j-out.txt. This behavior will get a little better under

Maven.

$ more target/log4j-out.txt

INFO 13-08 18:24:21,983 [myorg.mypackage.ex1.AppTest] (AppTest.java:testApp:18) -testApp

DEBUG 13-08 18:24:21,986 [myorg.mypackage.ex1.App] (App.java:returnOne:11) -Here's One!

Your project structure should look like the following at this point.

> find . -type f

./src/main/java/myorg/mypackage/ex1/App.java

./src/test/java/myorg/mypackage/ex1/AppTest.java

./src/test/resources/log4j.xml

Page 25: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Summary

19

./build.properties

./build.xml

./target/classes/myorg/mypackage/ex1/App.class

./target/ex1.jar

./target/test-classes/myorg/mypackage/ex1/AppTest.class

./target/test-classes/log4j.xml

./target/test-reports/TEST-myorg.mypackage.ex1.AppTest.txt

./target/test-reports/TEST-myorg.mypackage.ex1.AppTest.xml

./target/log4j-out.txt

5. Change the logging level so that only the App class performs logs to the logfile. By extending

the logger name specification all the way to the class, we further limit which classes apply to

this logger.

<logger name="myorg.mypackage.ex1.App">

<level value="debug"/>

<appender-ref ref="logfile"/>

</logger>

After re-running the build you should notice the DEBUG for only the App is included because

of the change we made to the logger outside the code.

$ more target/log4j-out.txt

DEBUG 26-08 23:07:04,809 [myorg.mypackage.ex1.App] (App.java:returnOne:11) -Here's One!

6. Repeat after me. "I will never use System.out.println() in this class." Doing so will make it difficult

for your deployed components to have their logs controlled and accessible as it is instantiated

in unit testing, integration testing, and deployment environments.

3.1. Summary

In this chapter we added some sophistication to the production class and its unit test which

required additional compile-time and runtime resources. Please note that we added only a

dependency on slf4j-api to the javac compiler task because log4j was never directly referenced in

the source code. We added a runtime dependency on log4j (and the slf4j-log4j adapter) in order

to configure a logger implementation during the execution of tests. The distinction of resources

required for compile-time, test, and runtime required will become even more important when using

Maven. Use the explicit classpaths we created here to help you understand Maven dependency

scope when we get there.

Page 26: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

20

Page 27: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4.

21

Creating Portable and Repeatable

Project Builds with MavenIn this chapter you will automate the build using Maven by defining a simple Maven project

definition that will go with your project tree. In the previous chapters you worked with a reasonable

project tree that could have looked different in a number of ways and could have been accounted

for by different path constructs. However, why be different? The project tree we put together that

accounted for production classes, test classes, resource files, archives, unit tests, test reports, etc.

follows Maven's standard build tree almost exactly (with the exception of the name of the target/

test-reports directory). We will be able to add a Maven project definition without much effort.

Tip

The Maven community has a tremendous amount of documentation, examples,

and on-line discussions. This course has many examples that are more specific

for the work you will be actively performing. Many of these resources are a quick

google search away but know that I go out of my way to make sure you spend as

much time as possible on design and JavaEE aspects in class. If you are stuck

on Maven -- ask. I know what you are trying to do and can likely point you to an

example that is relevant to what you are doing in class. If you are still stuck on

Maven issues -- send it to me. I will fix it personally. There is nothing more irritating

for you than to be fighting with the builds when you want to be spending more time

understanding, designing, trying, and mastering the product of what is being built.

Note

Using Maven requires only an initial download and installation. Plugins

and dependencies will be downloaded from remote repositories as needed.

Connectivity to the internet is required until all dependencies have been satisfied.

Note

Maven will automatically go out and download any missing dependencies and

recursively download what they depend upon. If you are running Maven for the first

time, this could result in a significant amount of downloading and may encounter an

occasional connection failure with repositories. Once a non-SNAPSHOT version

is downloaded (e.g., 1.3), Maven will not re-attempt to download it. Maven will,

however, go out and check various resources to stay in sync. If you know you

already have everything you need, you can run in off-line mode using the "-

o" flag on the command line or its equivalent entry within the settings.xml file.

This can save you seconds of build time when disconnected from the Internet. If

you want to make sure that all dependencies have been resolved, use the mvn

dependency:go-offline goal to eagerly resolve all dependencies.

Page 28: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4. Creating Portable ...

22

1. Create a pom.xml file in project basedir. This will be used to define your entire project. Refer

to the Maven POM Reference [http://maven.apache.org/ref/current/maven-model/maven.html]

for details about each element.

• modelVersion - yes; its required

• groupId - just as it sounds, this value is used to group related artifacts. groupId is a

hierarchical value and the individual names are used to form a directory structure in the

Maven repository (e.g., artifacts in the myorg.myproject.foo groupId will be located below the

HOME/.m2/repository/myorg/myproject/foo directory).

• version - Maven has a strong versioning system and versions appended with the word

SNAPSHOT are handled differently. Projects with a version ending in -SNAPSHOT are

thought to be in constant change, with no official release yet available. Projects with a version

lacking the -SNAPSHOT ending are meant to be an official release, with no other variants

available with the same tag.

• dependency.scope - this is used to define the scope the dependency gets applied. It defines

the visibility within the project for the dependency and whether it is carried along with the

module through transitive dependency analysis. With open-source software, a typical JavaEE

application could have 10s to 100s of individual modules it dependends upon and the proper

use of transitive dependencies makes this manageable.

• scope=compile is the default and is used to describe artifacts that the src/main directory

depends upon and will also be visible by classes in src/test. These dependency artifacts

will be brought along with the module when transitive dependencies are evaluated.

• scope=test is used to define artifacts which src/test depends upon. These will be made

available during testing, but will not be visible to classes in src/main and will not be

considered a dependency for downstream users of the module. Consult the maven

documentation for other scopes, but one other that is commonly used in class is

scope=provided.

• scope=provided is similar to scope=compile in that the src/main tree can see it, however

like scope=test, it is not carried forward. Each downstream module is required to know

about the dependency and provide a replacement. This is common when using JavaEE

APIs that have been packaged by different vendors used by different module developers.

• maven-compiler-plugin - this declaration is only necessary to if we need to override the

default Java version -- like what we did in our Ant script.

• properties.project.build.sourceEncoding - this defines the default handling of file content

for all plugins within a module. The default is platform-specific if left unspecified and we

avoid an annoying warning by specifying it.

Note

Although the m2e Eclipse plugin reads the pom dependency and creates a

classpath within Eclipse, it does not honor the differences between the different

scope values. All dependencies are blended together when inside the IDE. The

result is that something may compile and run fine within Eclipse and report a

missing class when built at the command line. If that happens, check for classes

Page 29: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

23

using artifacts that have been brought in as scope=test or for classes incorrectly

placed within the src/main tree.

<?xml version="1.0"?>

<project>

<modelVersion>4.0.0</modelVersion>

<groupId>myorg.myproject</groupId>

<artifactId>ex1</artifactId>

<name>My First Simple Project</name>

<version>1.0-SNAPSHOT</version>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.7.25</version>

<scope>compile</scope>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.12</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.7.25</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.7.0</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

</configuration>

Page 30: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4. Creating Portable ...

24

</plugin>

</plugins>

</build>

</project>

Your project tree should look like the following at this point.

> find . -type f

./src/main/java/myorg/mypackage/ex1/App.java

./src/test/java/myorg/mypackage/ex1/AppTest.java

./src/test/resources/log4j.xml

./build.properties

./build.xml

./pom.xml

2. Note that the pom.xml file is not required to have an assigned schema. However, adding one

does allow for XML editing tools to better assist in creating a more detailed POM. Replace the

project element from above with the following declarations to assign an XML schema.

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

3. Run the package "phase" and watch the project compile, assemble, and test. Maven has many

well-known phases that correspond to the lifecycle of build steps that goes into validating,

preparing, building, testing, and deploying artifacts of a module. You can find out more

about Maven phases here [http://maven.apache.org/guides/introduction/introduction-to-the-

lifecycle.html#Lifecycle_Reference] I refer to this page very often.

$ mvn package

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JavaSE::Simple Module Exercise Solution 5.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ firstSimpleModuleEx ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory /home/jim/proj/784/exercises/ex1/src/main/resources

[INFO]

[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ firstSimpleModuleEx ---

[INFO] Changes detected - recompiling the module!

[INFO] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ firstSimpleModuleEx ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ firstSimpleModuleEx ---

[INFO] Changes detected - recompiling the module!

[INFO] Compiling 1 source file to /home/jim/proj/784/exercises/ex1/target/test-classes

[INFO]

Page 31: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

25

[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ firstSimpleModuleEx ---

[INFO] Surefire report directory: /home/jim/proj/784/exercises/ex1/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running myorg.mypackage.ex1.AppTest

INFO 13-08 19:03:19,264 (AppTest.java:testApp:18) -testApp

DEBUG 13-08 19:03:19,267 (App.java:returnOne:11) -Here's One!

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.13 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]

[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ firstSimpleModuleEx ---

[INFO] Building jar: /home/jim/proj/784/exercises/ex1/target/firstSimpleModuleEx-5.0.0-SNAPSHOT.jar

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1.553 s

[INFO] Finished at: 2018-08-13T19:03:19-04:00

[INFO] Final Memory: 19M/309M

[INFO] ------------------------------------------------------------------------

[WARNING] The requested profile "h2db" could not be activated because it does not exist.

Ignore WARNING for Non-existent Profile

You were asked to declare a h2db profile as active within $HOME/.m2/

settings.xml during the software installation instructions. Maven will warn you

about any profile you request but is not found within the module to help identify

spelling errors. In this case, we simply do not need the profile and have not

defined it.

4. The contents of your development tree should look as follows.

> find . -type f

./build.xml

./build.properties

./pom.xml

./target/surefire-reports/TEST-myorg.mypackage.ex1.AppTest.xml

./target/surefire-reports/myorg.mypackage.ex1.AppTest.txt

./target/log4j-out.txt

./target/maven-archiver/pom.properties

./target/ex1-1.0-SNAPSHOT.jar

./target/test-classes/myorg/mypackage/ex1/AppTest.class

./target/test-classes/log4j.xml

./target/classes/myorg/mypackage/ex1/App.class

./target/maven-status/...

./src/test/resources/log4j.xml

./src/test/java/myorg/mypackage/ex1/AppTest.java

./src/main/java/myorg/mypackage/ex1/App.java

Page 32: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4. Creating Portable ...

26

• src/main/java classes were built in the target/classes directory by convention by the maven-

compiler plugin that is automatically wired into JAR module builds. We didn't have to configure

it because we structured our project using Maven directory structure and used the default

packaging=jar module type (since packaging=jar is the default, it could be left unspecified).

Many of the standard features are enacted when for modules with packaging=jar type.

• src/test/java classes where built in the target/test-classes directory by convention by the

maven-compiler plugin.

• src/test/resources where copied to the target/test-classes directory by convention by the

maven-resources-plugin that is automatically wired into JAR module builds.

• test cases were run and their reports were placed in target/surefire-reports by convention by

the maven-surefire-plugin that is automatically wired into JAR module builds.

• The build.xml and build.properties file from our work with Ant is still allowed to exist. We could

even delegate from Maven to Ant using the maven-antrun-plugin if we had legacy build.xml

scripts that we wanted to leverage.

5. For *fun*, lets add a README that could be used to describe something about your project

and have it be processed as part of the documentation for the module. You do not need to

do this for class projects, but walking through this may be helpful in understanding how the

course website is created from the source you have on your disk. Maven supports a couple

of documentation generation languages, but lets just use HTML to keep this simple. Place the

following content to src/site/resources/README.html

mkdir -p src/site/resources

$ cat src/site/resources/README.html

<?xml version="1.0"?>

<html>

<head>

<title>My First Project</title>

</head>

<body>

<section><h1>My First Project</h1></section>

<p/>

This is my first project. Take a look at

<p/>

<ul>

<li>this ....</li>

<li>that ....</li>

<li>or <a href="./index.html">go home</a></li>

</ul>

</section>

</body>

</html>

6. The above is enough to provide the page. Now add a link to it from the project menu. Add the

following content to src/site/site.xml

$ cat src/site/site.xml

Page 33: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

27

<?xml version="1.0" encoding="UTF-8"?>

<project name="${project.name}">

<body>

<menu name="Content">

<item name="README" href="README.html"/>

</menu>

</body>

</project>

You must also specify a version# for the maven-site-plugin and maven-project-info-reports-

plugin in the pom.xml. Maven is extremely version-aware.

<plugins>

...

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-site-plugin</artifactId>

<version>3.4</version>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-project-info-reports-plugin</artifactId>

<version>2.8</version>

</plugin>

</plugins>

> find . -type f

./src/main/java/myorg/mypackage/ex1/App.java

./src/test/java/myorg/mypackage/ex1/AppTest.java

./src/test/resources/log4j.xml

./src/site/resources/README.html

./src/site/site.xml

./build.properties

./build.xml

./pom.xml

7. Build the site and open target/site/index.html in your browser. You should see a link to the

README on the left side.

$ mvn site

[INFO] Scanning for projects...

...

[INFO] BUILD SUCCESS

$ find target/site/ -name *.html

target/site/plugin-management.html

target/site/index.html

target/site/mail-lists.html

target/site/issue-tracking.html

target/site/license.html

target/site/project-info.html

Page 34: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4. Creating Portable ...

28

target/site/dependency-info.html

target/site/README.html

target/site/dependencies.html

target/site/team-list.html

target/site/source-repository.html

target/site/integration.html

target/site/distribution-management.html

target/site/project-summary.html

target/site/plugins.html

Note

If you use the posted firstSimpleModuleEx as a starting point for your work you

will need to re-enable site generation under the maven-site-plugin. This was

turned off since the posted examples do not contain enough information to be

posted with the rest of the class examples.

<!-- exclude this modules from site generation -->

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-site-plugin</artifactId>

<version>3.4</version>

<configuration>

<skip>false</skip>

<skipDeploy>false</skipDeploy>

</configuration>

</plugin>

8. Okay, that was a lot of work to just copy an html file. Now lets add javadoc to our project and

create a link to it. Add the following contents to the bottom of the pom.xml file.

...

</build>

<reporting>

<plugins>

<plugin>

<artifactId>maven-javadoc-plugin</artifactId>

<groupId>org.apache.maven.plugins</groupId>

<version>3.0.1</version>

<configuration>

<detectLinks>false</detectLinks>

<detectOfflineLinks>true</detectOfflineLinks>

<show>private</show>

<source>1.8</source>

<additionalparam>-Xdoclint:none</additionalparam>

<failOnError>false</failOnError>

<links>

<link>http://download.oracle.com/javase/8/docs/api/</link>

<link>https://javaee.github.io/javaee-spec/javadocs/</link>

</links>

</configuration>

</plugin>

Page 35: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

29

</plugins>

</reporting>

9. We could create a link the the apidocs/index.html like we did with README.html, but that would

be something we'd keep having to update each time we added a new report. Lets add a property

to the site.xml menu so a link to Javadoc and other reports can drop in automatically.

# src/site/site.xml

<?xml version="1.0" encoding="UTF-8"?>

<project name="${project.name}">

<body>

<menu name="Content">

<item name="README" href="README.html"/>

</menu>

<menu ref="reports"/>

</body>

</project>

10.Re-generate the site documentation with the site target. Open the target/site/index.html page

and you should now see a menu item for "Project Reports" -> "JavaDocs". Our App class should

be included in the Javadoc.

11. Note

The pom.xml file is the main configuration source for 99% of what you

develop with Maven. There is an additional $HOME/.m2/settings.xml file where

you can specify build site-specific properties. These will be available to all

pom.xml files. You want to be careful not to over-populate the settings.xml

file (taking advantage of its re-usable specification) since it will make you

pom.xml files too dependent on a particular build location. Refer to the Settings

Descriptor [http://maven.apache.org/maven-settings/settings.html] for detailed

information on settings.xml. The following provides a step-wise generation of

the settings.xml file you put in place during Development Environment Setup.

Read thru this for reference since you likely already have everything in place

you need.

Let's start a settings.xml file to store properties that are specific to our build site. You can find

details about each setting at the following URL [http://maven.apache.org/settings.html].

cat $HOME/.m2/settings.xml

<?xml version="1.0"?>

<settings xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

</settings>

Page 36: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4. Creating Portable ...

30

12.If your $HOME directory path contains spaces, you will want to provide an override for the

localRepository. Provide a custom path that does not contain spaces. This value will default to

a "$HOME/.m2/repository" directory.

<!-- this overrides the default $HOME/.m2/repository location. -->

<localRepository>c:/jhu/repository</localRepository>

13.Add the following specification to either the settings.xml file or the local pom.xml file. If you

specify it to the local pom.xml file -- it will only apply to that project. If you specify it in the

settings.xml file -- it will be global to all projects in your area. More will be covered on this later.

However, it should be noted that this profile is not active unless someone specifically asks for

it (-Pdebugger) or the "debugger" environment variable is set (-Ddebugger=(anything)).

<profiles>

<profile>

<id>debugger</id>

<!-- this should only be activated when performing interactive

debugging -->

<activation>

<property>

<name>debugger</name>

</property>

</activation>

<properties>

<surefire.argLine>-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -

Djava.compiler=NONE</surefire.argLine>

</properties>

</profile>

</profiles>

14.Although not needed for this class -- at times you will need access to a dependency that is not

available in a Maven repository. COTS libraries are generally not available at ibiblio.org. You

must download it and manually install it locally.

This step will go though importing a stand-alone archive into the repository to resolve any

dependencies. Start by declaring a dependency before we do the import. Note that a new scope

property was added. See the Dependency Mechanism Intro Page [http://maven.apache.org/

guides/introduction/introduction-to-dependency-mechanism.html] for a discussion of scope,

but in this case it is indicating that it should only be present on the command line and not the

runtime classpath.

<dependency>

<groupId>foo</groupId>

<artifactId>bar</artifactId>

<version>1.1</version>

<scope>provided</scope>

</dependency>

15.Attempt the build the module with the missing dependency. The build should fail but note that

Maven attempted all known external repositores.

Page 37: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

31

> mvn package

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building My First Simple Project 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

Downloading: http://webdev.apl.jhu.edu/~jcs/maven2/foo/bar/1.1/bar-1.1.pom

Downloading: http://webdev.apl.jhu.edu/~jcs/maven2-snapshot/foo/bar/1.1/bar-1.1.pom

Downloading: http://repo1.maven.org/maven2/foo/bar/1.1/bar-1.1.pom

[WARNING] The POM for foo:bar:jar:1.1 is missing, no dependency information available

Downloading: http://webdev.apl.jhu.edu/~jcs/maven2/foo/bar/1.1/bar-1.1.jar

Downloading: http://webdev.apl.jhu.edu/~jcs/maven2-snapshot/foo/bar/1.1/bar-1.1.jar

Downloading: http://repo1.maven.org/maven2/foo/bar/1.1/bar-1.1.jar

[INFO] ------------------------------------------------------------------------

[INFO] BUILD FAILURE

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1.437s

[INFO] Finished at: Wed Feb 02 12:20:51 EST 2011

[INFO] Final Memory: 2M/15M

[INFO] ------------------------------------------------------------------------

[ERROR] Failed to execute goal on project ex1: Could not resolve dependencies for project

myorg.myproject:ex1:jar:1.0-SNAPSHOT:

Could not find artifact foo:bar:jar:1.1 in webdev-baseline (http://webdev.apl.jhu.edu/~jcs/maven2) -> [Help 1]

16.The old error message provided for Maven 2 was much better if a manual install is what you

really needed. The newer (Maven 3) one does not provide instruction. In this case, manually

install a jar file that represents the declaration. Assign it a groupId of foo, an artifactId of bar,

and a version of 1.1. Don't forget to add the -DgeneratePom=true or you will get a download

warning everytime you try to build. All we need is a valid .jar file. If you don't have one laying

around, just create one with valid structure.

$ touch bar.jar

$ mvn install:install-file -DgroupId=foo -DartifactId=bar -Dversion=1.1 -Dpackaging=jar -Dfile=bar.jar -

DgeneratePom=true

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building My First Simple Project 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ ex1 ---

[INFO] Installing /home/jim/proj/784/exercises/ex1/bar.jar to /home/jim/.m2/repository/foo/bar/1.1/bar-1.1.jar

[INFO] Installing /tmp/mvninstall5322334237902777597.pom to /home/jim/.m2/repository/foo/bar/1.1/bar-1.1.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

17.After successfully installing the dummy archive, you should be able to locate the JAR and other

supporting files in the local repository. Be sure to look where you have directed localRepository

in $HOME/.m2/settings.xml

Page 38: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 4. Creating Portable ...

32

$ find /home/jim/.m2/repository/foo/bar/

/home/jim/.m2/repository/foo/bar/

/home/jim/.m2/repository/foo/bar/1.1

/home/jim/.m2/repository/foo/bar/1.1/bar-1.1.pom.lastUpdated

/home/jim/.m2/repository/foo/bar/1.1/_remote.repositories

/home/jim/.m2/repository/foo/bar/1.1/bar-1.1.jar.lastUpdated

/home/jim/.m2/repository/foo/bar/1.1/bar-1.1.jar

/home/jim/.m2/repository/foo/bar/1.1/bar-1.1.pom

/home/jim/.m2/repository/foo/bar/maven-metadata-local.xml

18.Notice that Maven always makes sure there is a POM file present -- whether it had to generate

it or not.

$ more /home/jim/.m2/repository/foo/bar/1.1/bar-1.1.pom

<?xml version="1.0" encoding="UTF-8"?>

<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/

maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<modelVersion>4.0.0</modelVersion>

<groupId>foo</groupId>

<artifactId>bar</artifactId>

<version>1.1</version>

<description>POM was created from install:install-file</description>

</project>

19.Now try running "mvn package" and it should successfully resolve the fake dependency on

the bar.jar.

20.One last thing...Maven pulls in definitions from many places in the build environment. If you

ever want to know what the total sum of those sources are (the "effective POM"), the execute

the help:effective-pom goal.

$ mvn help:effective-pom

[INFO] Scanning for projects...

...

<project xmlns...

<modelVersion>4.0.0</modelVersion>

<groupId>myorg.myproject</groupId>

<artifactId>ex1</artifactId>

<version>1.0-SNAPSHOT</version>

<name>My First Simple Project</name>

<properties>

<jboss.home>/opt/wildfly-13.0.0.Final</jboss.home>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>foo</groupId>

<artifactId>bar</artifactId>

<version>1.1</version>

Page 39: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Summary

33

<scope>provided</scope>

</dependency>

...

4.1. Summary

During this exercise, you were able to establish a project which was understood by Maven. Once

Maven-compliant, each plugin can be added to perform different tasks for development. By the

time we start adding databases, building EARs, and deploying to application servers, we can use

all the plugin help we can get.

Page 40: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

34

Page 41: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5.

35

Leverage IDE using EclipseIn this chapter we will be importing the project into the Eclipse IDE, running a few project goals,

and demonstrating a debug session. IDEs provide very useful code navigation and refactoring

tools to name only a few features. However, one of the unique tools offered by the IDEs is the

ability to step through the code in a debugging session. Please do not end this exercise before

becoming comfortable with the ability to use the debugger.

Note

Maven/Eclipse integration was once the most volatile aspects of the environment.

However, over the years the two have been designed to work well together as long

as you keep things Maven-centric.

Warning

The Maven/Eclipse integration is a Maven-first approach where the Eclipse project

always follows the Maven pom.xml. That is on of the main reasons this exercise

started you with a pom.xml file first and progressed later to the IDE. It is wrong (or at

least non-portable) to manually adjust the build path of a project within Eclipse. You

must adjust the build path of a project by editing the pom.xml and having Eclipse

automatically detect and follow that change.

5.1. Import a project into Eclipse

ex1 ~= firstSimpleModuleEx

The exercise asked you to name your module "ex1". This portion of the exercise

demonstrates actions within Eclipse in a posted solution in your examples tree call

"firstSimpleModuleEx". You may/should continue to use your "ex1" solution from

the previous chapters but know that firstSimpleModuleEx (as posted) has a few

minor tweeks to its pom.xml to allow it to be distributed with the rest of the class

examples as part of the class site.

1. Select File->Import->Maven->Existing Maven Projects, navigate to the directory with the project

you have been working with and select OK.

Page 42: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5. Leverage IDE using...

36

Figure 5.1. Import Existing Maven Project

2. The project should successfully import. Note that Eclipse has imported the project configuration

from the Maven POM and has done at least the following...

Page 43: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Import a project into Eclipse

37

Figure 5.2. Imported Project

• Created three build packages; src/main/java, src/test/java, and src/test/resources. Had there

been a src/main/resources we would have had a fourth build package added.

• Defined the project for use with Java 8.

• Added five Maven dependencies. Notice how the path to these dependencies are from the

localRepository.

• Four of these dependencies (slf-api, junit, slf-log4j, and log4j) were through direct references.

The fifth (hamcrest-core) is through a transitive dependency from junit. You can visualize this

transitive dependency by opening the pom.xml and selecting the dependency hierarchy tab

at the bottom of the window.

Page 44: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5. Leverage IDE using...

38

Figure 5.3. Visualizing Dependency Hierarchies

• You can get a text version of the dependency heirarchy using the Maven dependency:tree

goal.

$ mvn dependency:tree

...

[INFO] ------------------------------------------------------------------------

[INFO] Building JavaSE::Simple Module Exercise Solution 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ firstSimpleModuleEx ---

[INFO] myorg.myproject:firstSimpleModuleEx:jar:5.0.0-SNAPSHOT

[INFO] +- org.slf4j:slf4j-api:jar:1.7.25:provided

[INFO] +- junit:junit:jar:4.12:test

[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test

[INFO] +- org.slf4j:slf4j-log4j12:jar:1.7.25:test

[INFO] \- log4j:log4j:jar:1.2.17:test

• Make a small edit to the pom.xml and notice the change in the Maven Dependencies within

Eclipse. Switch back and forth between these two settings and watch the value under Maven

Dependencies follow the edits (be sure to save the file between edits).

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

Page 45: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Setup Eclipse to be able to execute Maven project goals

39

<version>1.2.17</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.16</version>

<scope>test</scope>

</dependency>

Figure 5.4. Maven/Eclipse Dependency Coordination

5.2. Setup Eclipse to be able to execute Maven project

goals

1. Right-click on the pom.xml file or project folder and execute Run As->"Maven install". You can

also get back to this window through the Run As option on the toolbar once you have the project

selective. This mode runs the JUnit test you wrote within the context of the full maven project.

All pre-test and post-test setup and teardown you wired into the Maven command line build

will be executed.

Page 46: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5. Leverage IDE using...

40

Figure 5.5. Run As Targets

Note that you can create a separate window for any of the Eclipse tabs. Using dual monitors --

I commonly display the IDE on one page the the Console output on another when using debug

statements.

Page 47: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Setup Eclipse to be able to execute Maven project goals

41

Figure 5.6. Run As: Maven Install Output

2. Rerun the tests as a JUnit test. This mode runs the JUnit test raw within Eclipse. This is very

efficient for making and testing Java code changes but will not run any maven setup or teardown

plugins (which is not always required or can be avoided).

Page 48: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5. Leverage IDE using...

42

Figure 5.7. Run As: JUnit Test Results

Always Make Projects Eclipse/JUnit-Friendly

Maven is a very useful and powerful tool. However, there is a point where the

information from Maven has been captured by the IDE and we don't need to

run full Maven builds (e.g., RunAs: Maven Install). As you saw from the RunAs:

JUnit test we were able to run the unit test and run it exceptionally fast without

Maven. I strongly recommend making your unit tests Eclipse/JUnit-friendly so

that you can work efficiently in certain areas. That means hard-code reasable

defaults without relying on the maven-surefire-plugin passing in properties from

the outside environment. Allow overrides, but code in a usable default into the

test.

5.3. Setup environment to enable interactive debugging

There are two primary ways to use the debugger; separate/remote process and embedded (within

Eclipse). The second is much easier to use but is limited by what you can execute within the

Eclipse IDE. The first takes a minor amount of setup but can be re-used to debug code running

within application servers on your local and remote machines.

1. Lets start with a remote debugging session by recalling the profile you were asked to add to

either your pom.xml or settings.xml. If you have not done so, you can add it to either at this time.

Page 49: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Setup environment to enable interactive debugging

43

<profiles>

<profile> <!-- tells surefire to run JUnit tests with remote debug -->

<id>debugger</id>

<activation>

<property>

<name>debugger</name>

</property>

</activation>

<properties>

<surefire.argLine>-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -

Djava.compiler=NONE</surefire.argLine>

</properties>

</profile>

</profiles>

2. Add a definition for the "surefire.argLine" within the maven-surefire-plugin declaration. Surefire

is already being pulled into the project, this declaration just specifies the extra configuration

along with a specific version. Maven will start complaining ig you leave off that version.

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire--plugin</artifactId>

<version>2.17</version>

<configuration>

<argLine>${surefire.argLine}</argLine>

</configuration>

</plugin>

3. Uncomment (or re-add) your failure test in AppTest.java.

@Test

public void testFail() {

//System.out.println("testFail");

log.info("testFail");

App app = new App();

assertTrue("app didn't return 0", app.returnOne() == 0);

}

4. Execute a Run As Maven test. My selecting the project, right clicking and chosing the right

target. You should see the following error in the console.

Running myorg.mypackage.ex1.AppTest

INFO 28-08 23:52:31,809 (AppTest.java:testApp:17) -testApp

DEBUG 28-08 23:52:31,821 (App.java:returnOne:11) -Here's One!

INFO 28-08 23:52:31,829 (AppTest.java:testFail:25) -testFail

DEBUG 28-08 23:52:31,831 (App.java:returnOne:11) -Here's One!

Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.409 sec <<< FAILURE!

testFail(myorg.mypackage.ex1.AppTest) Time elapsed: 0.016 sec <<< FAILURE!

java.lang.AssertionError: app didn't return 0

at org.junit.Assert.fail(Assert.java:93)

at org.junit.Assert.assertTrue(Assert.java:43)

Page 50: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5. Leverage IDE using...

44

at myorg.mypackage.ex1.AppTest.testFail(AppTest.java:27)

5. Click on the hyperlink to one of the lines in the project source code in the failure stack trace.

Place a breakpoint at that line by double-clicking on the line number. A blue ball should appear

to the left of the numbers.

6. Debug As->Maven build..., change the base directory to a re-usable ${project_loc} variable,

assign the "test" goal, and activate the "debugger" profile. Click "Debug" when finished. It will

automatically save.

Figure 5.8. Setting up Maven/Eclipse Remote Debugging

You should see the Maven build start but pause before executing the first JUnit test. Think of

this as the "server-side" of the debugger session.

[INFO] --- maven-surefire-plugin:2.17:test (default-test) @ firstSimpleModuleEx ---

[INFO] Surefire report directory: /home/jcstaff/workspaces/ejava-class/ejava-student/javase/firstSimpleModuleEx/

target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Listening for transport dt_socket at address: 8000

7. Start the "client-side" of the debugger session by clicking on the bug pulldown at the top of

the window. Select debug configurations, double click on Remote Java Application, select your

Page 51: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Setup environment to enable interactive debugging

45

project, and notice the localhost:8000 that came up agrees with your server-side configuration.

Press "Debug" when you are ready and answer the prompt to change you view.

Figure 5.9. Setting up Maven/Eclipse Client Side

8. The IDE should switch to a debugger view and be waiting at the line you set the breakpoint

on. From here you can look at the state of any variables (we don't have any) and step into

the next call.

Page 52: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Chapter 5. Leverage IDE using...

46

Figure 5.10. Debugger Breakpoint

9. Once you are done with the debugging session you can click continue (agreen right arrow at

top) or detach from the server (red swiggly line at top).

10.Terminate the debugger session, retun to one of the JavaEE or Java-based views. Select a

specific JUnit test, test method, package, or entire application and click Debug As JUnit test.

11.Note the IDE again switches to the Debug view and is stopped at the breakpoint. You may

step into the call, look at the state of any variable, or terminate the program (red square at

top of window).

Debug-As Junit Test Is Even Easier

I walked you through the harder debugging session setup that is only necessary

when the problem is occurring in code running in a remote JVM. If the code can

be executed using "Run-As -> JUnit Test", then simply set a breakpoint and use

"Debug-As -> JUnut Test"

Page 53: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

Summary

47

5.4. Summary

In this chapter, you were able to integrate your Maven and Eclipse environments. This allows you

to leverage the Maven plugins as your core build system and leverage Eclipse for developing the

content.

As mentioned, Eclipse will be the primary demonstration environment in class, but you may use

other IDEs, like NetBeans, to match personal preferences. It is my belief that anything Eclipse can

do -- the other leading IDEs can do as well. There have been many occasions where students

very familiar with an alternate IDE have picked up the Maven aspects and handled the integration

with their IDE without issue.

You have now completed this exercise and as a part of it you were able to create a project tree,

build/test the project manually, build/test the project using Ant build tool, build/test the project

using the Maven build system, and integrate the project with an IDE for faster and more detailed

development. We have covered a lot but clearly we have only touched a small amount of what

can be done. Luckily one doesn't have to know how to do it all right away in order to be productive.

Page 54: JavaSE: First Simple Module Exercisejcs/ejava-javaee/coursedocs/content/pdf/... · Chapter 1. 1 Develop and Test Module using Command Line Tools (OPTIONAL!) In this chapter you will

48