Jan K. Labanowski, Computational Chemistry List, Ltd.

Click on images to see them in the natural size

Eclipse and Maven

You may be pissed off that these brain dumps are so long. Of course, it is my personality. But in my previous life I was an academic teacher. And I have a sense that if you do not know the details, you do now the thing. You can only feel at home, when you know every corner. So it is not completely unconscious... The other goal is to remove the I am stuck... syndrome. Since I show you almost every screen shot, you can always click on [Back] and you will immediately see where you (or me) erred..

Eclipse is an Integrated Development Environment (IDE) that helps you develop software. You may find my approach to Eclipse installation at http://www.ccl.net/cca/software/JAVA/EclipseWindowsTomcat/index.html. However, the real power of Eclipse comes from different plugins. One of the must haves is Apache Maven if you develop Java applications. Apache Maven is a build and deployment tool. The most important features are:

The instructions for Maven are combined in a single pom.xml file that resides in the top directory of your project. Maven can do a lot more things, especially if you find suitable plugins (that are just dependencies and build instructions in the pom.xml). The thing that was a blessing for me when I started working on larger enterprise type projects, was a repository of archetypes, i.e., templates and examples for standard Java projects. You do not have to rediscover the correct directory layouts and search for exotic dependencies (i.e., libraries, in the old-fashioned computer speak). Many archetypes come with examples, and framework authors contribute the suitable archetypes to facilitate the use of their products. Read more about Maven at the its site: http://maven.apache.org/maven-features.html.

Maven is one of the most important plugins to install within Eclipse. But there are different ways to do it, and it is confusing. A reason for this is that Maven and Eclipse were developed over time in parallel, without much consultations, since Maven was (and still is) primarily a command line tool, while Eclipse is a GUI. While there is a way to install Maven directly inside Eclipse, I always take a route of installing Maven as a standalone application, and afterwards I incorporate it into Eclipse. Why? Because I often use Maven on command line, usually inside Cygwin, when I work on Windoz. This is not necessarily trivial, since Maven and Eclipse have quite a different approaches to compiling Java and use a different directory layout by default. Eclipse had incremental, instant approach. When you make a typo, the Red Cross (no, not this one) will show up immediately. Maven is like a batch processing, you need to click and wait. Do not lightly assume that instant is better than wait. Instant if fine if you have one project or package. But you will appreciate Maven when you have twenty packages to compile and test. You just start a shell script with Maven commands, and come back the next morning...

Before you follow my suggestions on how to install Maven on Windows, read my write-ups on Java Installation ( http://www.ccl.net/cca/software/JAVA/JavaOnWindows/index.html ) and Eclipse Installation ( http://www.ccl.net/cca/software/JAVA/EclipseWindowsTomcat/index.html ). Download Maven from its download site, http://maven.apache.org/download.cgi. The latest stable version at the time of writing it is 3.2.5. For Windows I suggest a Binary zip distribution.

-rwxr-xr-x+ 1 jkl None 8071373 Jan  8 17:11 apache-maven-3.2.5-bin.zip

Unpack it with 7-zip or whatever (even Windoz can unzip it if you right-click on the archive file), but as always, I suggest that your directory does not have spaces in its name. I work with Maven under Cygwin (http://www.ccl.net/cca/software/UNIX/cygwin/index.html), the Unix like environment for Windoz, and Unix does not like spaces in file names. Even Windoz does not like spaces in file names, so I am not sure why they use them.

As you can see above, I have Maven installed under C:\Program Files\apache-maven-3.2.5. So don't I eat my own dog food? I actually do what I say, but sometimes with a twist.

I created junctions, i.e., hard links for the Program Files stuff. In this case, I ran a command:
mklink /j C:\Program_Files "C:\Program Files"
in the Elevated Command Prompt window. More about it in my Cygwin write-up. This way I can do:

i.e., I do not need to put quotes around the directory name. The Program Files and Program_Files are totally equivalent, similar to hard links under Linux. As you can see the zip's top directory is a apache-maven-3.2.5 so the Maven Home is C:\Program_Files\apache-maven-3.2.5. Now, we need to add the Environment Variables to Windows. You can go there via Control Panel or by clicking on the keyboard shortcut WinKey/Pause

Then click on Advanced system settings, then on [Environment Variables] at the bottom, and in the dialog that appears, add a [New] variable M2_HOME to the block of System Variables

then click on [OK] (but use your own location, of course). If you are at it, you can also add default command line options to Maven. Suggested values are: MAVEN_OPTS=-Xms256m -Xmx512m

Then you need to append the location of the Maven's bin directory to the Windows %Path%. In my case I appended C:\Program_Files\apache-maven-3.2.5\bin, or you can append %M2_HOME%\bin

Remember to click on [OK]s until all opened dialogues are closed (or variables will not be saved otherwise) and reboot the box. If you do not have the Admin privileges, try to add/edit these variables as your User Variables. I describe how to do it in the write-up on Eclipse and Tomcat. Now, if everything worked you should see the variables defined in the DOS Command Prompt:

Of course, your particular %M2_HOME% and %PATH% will be different, and in my case, I appended Maven to %PATH long before I wrote this tutorial, so it is not at the very end of the %PATH%.

Now, let us check if Maven works on command line. Since typing command names in the DOS Command Prompt is a nightmare, I use Cygwin as my command line development environment under Windoz. I describe how to install it in http://www.ccl.net/cca/software/UNIX/cygwin/index.html. Maven has now well over the 1000 archetypes (sample projects) defined in its official repositories. But there are also repositories maintained by external groups. So it is overwhelming to use the regular approach to pick the one from the list. When using Maven as a command line tool (as opposed to Eclipse use) I first try to dump the names of available archetypes to a file, and then pick up the one by examining the file with a grep or inside the editor.

Note that in this case, you have to enter CTRL/C after starting Maven, since it waits for input (it prints the list of over 1200 archetypes to the STDOUT that you are dumping into a file, including a question: Which one you want? that you cannot see, since it is in the file). There is a way to filter this stuff, but let us adhere to the KISS principle. Namely, you need to type the following into the terminal (or the DOS Command Prompt).

mkdir My1stMavenProject
cd My1stMavenProject
mvn archetype:generate > archetype_list.txt
  # ... wait a few seconds and hit CTLR/C

The list of available archetypes has a format of Number: -> location (Description). We will try to pick up the simplest thing as a first exercise:

525: remote -> org.apache.maven.archetypes:maven-archetype-quickstart
     (An archetype which contains a sample Maven project.)

Now, let us run the Maven again without redirecting the STDOUT to the file (red stuff is what you entered):

$ mvn archetype:generate
[INFO] Scanning for projects...
[INFO]

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

[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------

[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) > generate-sources
 @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) < generate-sources
 @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom -
--
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven
.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> am.ik.archetype:msgpack-rpc-jersey-blank-archetype (Blank Project
for Spring Boot + Jersey)
2: remote -> am.ik.archetype:spring-boot-blank-archetype (Blank Project for Spr
ing Boot)
# ... gobs of stuff!!!!
1241: remote -> us.fatehi:schemacrawler-archetype-plugin-command (-)
1242: remote -> us.fatehi:schemacrawler-archetype-plugin-dbconnector (-)
1243: remote -> us.fatehi:schemacrawler-archetype-plugin-lint (-)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 525: 525
Choose org.apache.maven.archetypes:maven-archetype-quickstart version:
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6: 6
Define value for property 'groupId': : net.ccl
Define value for property 'artifactId': : HelloWorld
Define value for property 'version':  1.0-SNAPSHOT: : [Enter]
Define value for property 'package':  net.ccl: : [Enter]
Confirm properties configuration:
groupId: net.ccl
artifactId: HelloWorld
version: 1.0-SNAPSHOT
package: net.ccl
 Y: : Y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: C:cygwin64\home\jkl\My1stMavenProject
[INFO] Parameter: package, Value: net.ccl
[INFO] Parameter: groupId, Value: net.ccl
[INFO] Parameter: artifactId, Value: HelloWorld
[INFO] Parameter: packageName, Value: net.ccl
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:18 min
[INFO] Finished at: 2015-02-07T03:18:22-05:00
[INFO] Final Memory: 15M/309M
[INFO] ------------------------------------------------------------------------

After you typed the stuff in red, the Maven will let you go. You can see the following files in your project directory (HelloWorld) that Maven created for you:

$ cd HelloWorld
$ find .
.
./archetype_list.txt
./HelloWorld
./HelloWorld/pom.xml
./HelloWorld/src
./HelloWorld/src/main
./HelloWorld/src/main/java
./HelloWorld/src/main/java/net
./HelloWorld/src/main/java/net/ccl
./HelloWorld/src/main/java/net/ccl/App.java
./HelloWorld/src/test
./HelloWorld/src/test/java
./HelloWorld/src/test/java/net
./HelloWorld/src/test/java/net/ccl
./HelloWorld/src/test/java/net/ccl/AppTest.java

Basically, you see here:

Note that the Archetype Id that you entered is just a project name, i.e., the top directory of your project. The Group Id should be used as your top Java package name. There is a directory for your Java sources (src), the main subdirectory is for the stuff you develop while the test is for the JUnit tests. And under those, you see the name of programming language that is used for writing these source code. Once you have your project set up, you want to validate it.

$ cd HelloWorld  # cd to where the pom.xml file is
$ mvn validate
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloWorld 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.083 s
[INFO] Finished at: 2015-02-07T16:28:30-05:00
[INFO] Final Memory: 6M/309M
[INFO] ------------------------------------------------------------------------

No screw-aps yet. The project structure is fine. Now time to compile

$ mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloWorld 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ HelloWorld ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.894 s
[INFO] Finished at: 2015-02-07T16:31:16-05:00
[INFO] Final Memory: 13M/308M
[INFO] ------------------------------------------------------------------------

Let us check what is now under our HelloWorld project:

$ find .
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/net
./src/main/java/net/ccl
./src/main/java/net/ccl/App.java
./src/test
./src/test/java
./src/test/java/net
./src/test/java/net/ccl
./src/test/java/net/ccl/AppTest.java
./target
./target/classes
./target/classes/net
./target/classes/net/ccl
./target/classes/net/ccl/App.class
./target/maven-status
./target/maven-status/maven-compiler-plugin
./target/maven-status/maven-compiler-plugin/compile
./target/maven-status/maven-compiler-plugin/compile/default-compile
./target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
./target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

We see that the bunch of new files, namely, the App.class appeared (i.e., Maven ran javac for us) and the log of stuff that Maven did. BTW, your App.java is the simplest possible Java class you can have, namely:

package net.ccl;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

Then, you want to test it:

$ mvn test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloWorld 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ HelloWorld ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ HelloWorld ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ HelloWorld ---
[INFO] Surefire report directory: C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running net.ccl.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec

Results :

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

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.709 s
[INFO] Finished at: 2015-02-07T16:41:35-05:00
[INFO] Final Memory: 13M/264M
[INFO] ------------------------------------------------------------------------

And if we list files now, we see:

$ find .
.
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/net
./src/main/java/net/ccl
./src/main/java/net/ccl/App.java
./src/test
./src/test/java
./src/test/java/net
./src/test/java/net/ccl
./src/test/java/net/ccl/AppTest.java
./target
./target/classes
./target/classes/net
./target/classes/net/ccl
./target/classes/net/ccl/App.class
./target/maven-status
./target/maven-status/maven-compiler-plugin
./target/maven-status/maven-compiler-plugin/compile
./target/maven-status/maven-compiler-plugin/compile/default-compile
./target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
./target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
./target/maven-status/maven-compiler-plugin/testCompile
./target/maven-status/maven-compiler-plugin/testCompile/default-testCompile
./target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
./target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
./target/surefire-reports
./target/surefire-reports/net.ccl.AppTest.txt
./target/surefire-reports/TEST-net.ccl.AppTest.xml
./target/test-classes
./target/test-classes/net
./target/test-classes/net/ccl
./target/test-classes/net/ccl/AppTest.class

That is, the testing class (AppTest) has been compiled and test report has been generated. Actually, I encourage you to read the TEST-net.ccl.AppTest.xml to see how thorough (yet concise) the Maven is.
Time to create a package

$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloWorld 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ HelloWorld ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ HelloWorld ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ HelloWorld ---
[INFO] Surefire report directory: C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running net.ccl.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec

Results :

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

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ HelloWorld ---
[INFO] Building jar: C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\target\HelloWorld-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.660 s
[INFO] Finished at: 2015-02-07T16:47:53-05:00
[INFO] Final Memory: 11M/309M
[INFO] ------------------------------------------------------------------------

Note that Maven knows what has been done, and does not do it again. Let us see if jar was created:

$ find .
.
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/net
./src/main/java/net/ccl
./src/main/java/net/ccl/App.java
./src/test
./src/test/java
./src/test/java/net
./src/test/java/net/ccl
./src/test/java/net/ccl/AppTest.java
./target
./target/classes
./target/classes/net
./target/classes/net/ccl
./target/classes/net/ccl/App.class
./target/HelloWorld-1.0-SNAPSHOT.jar
./target/maven-archiver
./target/maven-archiver/pom.properties
./target/maven-status
./target/maven-status/maven-compiler-plugin
./target/maven-status/maven-compiler-plugin/compile
./target/maven-status/maven-compiler-plugin/compile/default-compile
./target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
./target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
./target/maven-status/maven-compiler-plugin/testCompile
./target/maven-status/maven-compiler-plugin/testCompile/default-testCompile
./target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
./target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
./target/surefire-reports
./target/surefire-reports/net.ccl.AppTest.txt
./target/surefire-reports/TEST-net.ccl.AppTest.xml
./target/test-classes
./target/test-classes/net
./target/test-classes/net/ccl
./target/test-classes/net/ccl/AppTest.class

And inside the jar we have our great compiled Java class together with our pom.xml that tells us what the project was. Note there are no sources, since the jar only collects the targetss for our project.

$ jar -tvf ./target/HelloWorld-1.0-SNAPSHOT.jar
     0 Sat Feb 07 16:47:54 EST 2015 META-INF/
   128 Sat Feb 07 16:47:52 EST 2015 META-INF/MANIFEST.MF
     0 Sat Feb 07 16:31:16 EST 2015 net/
     0 Sat Feb 07 16:31:16 EST 2015 net/ccl/
   529 Sat Feb 07 16:31:16 EST 2015 net/ccl/App.class
     0 Sat Feb 07 16:47:54 EST 2015 META-INF/maven/
     0 Sat Feb 07 16:47:54 EST 2015 META-INF/maven/net.ccl/
     0 Sat Feb 07 16:47:54 EST 2015 META-INF/maven/net.ccl/HelloWorld/
   774 Sat Feb 07 03:18:24 EST 2015 META-INF/maven/net.ccl/HelloWorld/pom.xml
   114 Sat Feb 07 16:47:54 EST 2015 META-INF/maven/net.ccl/HelloWorld/pom.properties

We can even run this thing:

$ java -cp ./target/HelloWorld-1.0-SNAPSHOT.jar net.ccl.App
Hello World!

And what did you expect? We did not ask for the .war file, and we did not get it. There are subsequent steps that we could run if we had the repository for our project set up, etc. But we do not. We could still verify if our project is complete and in good shape.

$ mvn verify
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloWorld 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ HelloWorld ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ HelloWorld ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ HelloWorld ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ HelloWorld ---
[INFO] Surefire report directory: C:\cygwin64\home\jkl\My1stMavenProject\HelloWorld\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running net.ccl.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec

Results :

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

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ HelloWorld ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.548 s
[INFO] Finished at: 2015-02-07T17:01:36-05:00
[INFO] Final Memory: 11M/309M
[INFO] --------------------------------------------------------

Now we will do what we should have done at the very beginning of the exercise... Lot at the heart of all this, the pom.xml that was created for us when we were downloading the archetype. It includes the entries of our conversation with Maven:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>net.ccl</groupId>
  <artifactId>HelloWorld</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>HelloWorld</name>
  <url>http://maven.apache.org</url>

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

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

As you can see, it is a very simple XML file in this case. The top element is <project...> that defines the XML schema and its location. Then we have elements that define the project naming. Finally, under dependencies we list Java JUnit and its version as a dependency (it is quite stale, however). Maven will get this stuff for us from its repositories automatically and save it locally, so it can reuse it for testing our project. Where does it save it? Actually, this requires some explanation. Before we go into it, list the files that are under your %M2_HOME%, i.e., Maven's top installation directory:

The process of setting the local user repository is convoluted for a good reason. When you install Maven it uses a default for a user repository. It creates a hidden directory, .m2 under the HOME directory. It is done on the first use. So what is the HOME for a user on Windoz? It is called User Profile and in most cases it is automatically set to C:\Users\UserName (unless your Admin wanted it elsewhere). In my case its is C:\Users\jkl. This location is stored in the Windoz %USERPROFILE% environment variable and it is easy to list with a echo %USERPROFILE%, either in DOS Command Prompt window or with a echo $USERPROFILE on Cygwin (note: this is not a Cygwin's HOME directory but Windoz HOME directory). By default, the repository directory is located under this hidden .m2 directory under the %USERPROFILE%. In my case, it is C:\Users\jkl\.m2\repository. Why not under the Maven home? Because Maven can be installed by the Admin, and the regular user would not have the write permissions to add to the repository. Can you put the repository in a different place? Sure you can, but you need to create a private settings.xml file to customize Maven. The entries in the %M2_HOME%\conf\setting.xml (the global configuration file) can be overridden by the user's own settings.xml (it is located under %USERPROFILE%\.m2 directory). Start with a default Maven's settings.xml and copy it to your own hidden .m2 directory. You can do it in the DOS Command Prompt window as:

or you can do it in the Cygwin's xterm:

(the yellow/green stuff is my prompt). You can see that I have a lot of stuff in my repository. If you just started, yours will be quite modest. I even have many versions of junit:

You can override the location of the repository in your %USERPROFILE%\.m2\settings.xml file by setting the localRepository element that is commented out by default.

 <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repository</localRepository>
  -->

Some admins set this path to %M2_HOME%\repository in the global settings.xml and give everyone write access to the global repository. The advantage is that the stuff will be available for everyone and needs to be downloaded only once. But they assume that there are no disgruntled employees in their company. While I am a completely disgruntled employee, I work for myself, and nobody else has access to this PC (or at least I do not know about it, and it is Windoz). To show how it works, I will do it on my PC, and see if it downloads the JUnit jar to the new repository that is empty on start up. I placed the following in the %M2_HOME%\repository\config\settings.xml

<localRepository>C:\Program_Files\apache-maven-3.2.5\local_repository>

and created the corresponding directory. I made it writable by all. Then I ran the Hello World project from above. Not to my surprise, Maven downloaded gazillion jar files to the new directory beside the junit.

$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloWorld 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins
        /maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom
....
Downloaded: https://repo.maven.apache.org/maven2/commons-lang
        /commons-lang/2.1/commons-lang-2.1.jar (203 KB at 540.9 KB/sec)
Downloaded: https://repo.maven.apache.org/maven2/org/codehaus/plexus
        /plexus-utils/3.0/plexus-utils-3.0.jar (221 KB at 328.5 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.208 s
[INFO] Finished at: 2015-02-07T22:04:23-05:00
[INFO] Final Memory: 11M/247M
[INFO] ------------------------------------------------------------------------
$ ls -l /cygdrive/c/Program_Files/apache-maven-3.2.5/local_repository/
total 0
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 backport-util-concurrent
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 classworlds
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 com
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 commons-cli
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 commons-lang
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 commons-logging
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 junit
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 log4j
drwxr-xr-x+ 1 jkl None 0 Feb  7 22:04 org

since Maven itself has a lot of dependencies that have dependencies that have dependencies... And you do not have to care about it.

Now you scratched the surface and you can be dangerous. To make you cool down, you need to learn more. RTFM at http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html and http://books.sonatype.com/mvnex-book/reference/index.html.

Now, we were supposed to add Maven to the Eclipse... So... Start the Eclipse. In my case I right click on my Eclipse executable:

and click on [Open]. Once it opens, I click under [Help], Eclipse Marketplace...

and get the Dialog that is the primary way to get plugins for Eclipse. I typed maven in the Find: field and clicked on [Go].

And now I see scores of plugins for Maven, and the problem is which one to pick. Remember the Word of wisdom from Jan: Never fetch anything before you know what it is. Read about the stuff, Google, ask, but do not install crap in your Eclipse. Some of it is actually fantastic, but if you are not going to use it, do not get it. In my case, I would scroll and pick this one: Maven Integration for Eclipse (Luna) 1.5.0. The problem is that it is already installed. It comes with the Eclipse JEE profile with scores of other plugins. You know about it, since there is an [Uninstall] button rather than [Install]. You must be disappointed at this moment, since you went through so much stuff, and all in vain. Actually not really.

You still need to tell Eclipse that you want to use another Maven rather the one that it configured for its own use during initial installation (the Embedded Maven). Click on [Window], [Preferences]:

and choose Maven, Installations.

Click on [Add], select the top directory where the Maven was installed (in my case: C:\Program_Files\apache-maven-3.2.5) and then click on [Finish].

Then select it on the Installation Dialog and click [OK].

Note that Embedded Maven is slightly older than the one I am providing as External Maven. Now, let us create a Maven Project by right-clicking on [New] and selecting MavenProject]:

The New Maven Project dialog appears. Do not change anything here, just click [Next]:

Now, click on [Configure] on the right site of [Catalog] menu and add catalogs:

The Archetypes dialog appears and you can add additional catalogs.

The dialog for entering additional catalogs appears. One catalog that is a must have is maven-central that is located at: http://repo1.maven.org/maven2/archetype-catalog.xml. Type Maven Central for description and enter the URL (they call it a Catalog File: since it can also be a local file://).

Click on [OK]

Click on [Add Remote Catalog...]. Another good site is the http://mvnrepository.com/artifact/org.wildfly.archetype that I described as Wildfly Catalog. After adding these, You should have something like:

Click on [OK] and on the New Maven Project choose [All Catalogs] and you should see this:

Now type a javaee7 in the Filter field and select the webapp from codehouse

This is a bleeding edge JEE environment not yet fully implemented in most popular commercial JEE Servers. Click on [Next] and then enter the fields that define your Maven project.

Group Id:    net.ccl        this will be your package
Artifact Id: MyJee7App      this will be your project name
Version:                    do not change
Package:     net.ccl        make it the same as Group Id

Now click on [Finish]. Oh well, you probably think that we are almost finished. The project is created but we have the error

When you click on the link [Plugin execution not covered...] the dialog will pop with explanations:

I chose the 3rd option [Discover new connector]:

After searching eclipse found m2e connector (this is pure luck since usually you have to Google for a few plugin for hours and manually edit the pom.xml. Moreover, there is about 12 millions of these things: http://marketplace.eclipse.org/. After buzzing for a while, the Eclipse found a needed piece:

And I could click on [Finish]. Then the connector (I would call it adapter but there may be some some deep reason for this term) was installed.

Now you click on the check-mark and confirm that you want it:

I clicked on [Next] (since the stuff was already selected), and finally accepted the License

After accepting the license, I could click on [Finish]. Eclipse was installing the software and warning me that the content is unsigned. I accepted the risk, since many 3rd party plugins are not signed.

Clicked on [OK] and it was downloading stuff, and finally asked me to restart Eclipse:

I agreed and clicked on [Yes] This is a typical behavior after installing new stuff, so do not worry. After all this, the error disappeared:

Now, let us look under the hood. First I expanded some folders under Project Explorer. Click on the pom.xml. You can only see the top of the pom.xml file. It is no longer simple and trivial.

Now, I right-clicked on the project and selected [Run as] ->[Maven Generate Sources]:

This did not do anything, since this archetype does not seem to have any downloads associated. But it did not hurt either... Then, I right-clicked on project and chose [Run] -> [Maven Test]

After downloading a ton of jar files (you can see them scrolling in the Console on the bottom panel) the project tested OK

Of course, the whole project consists of the index.html so there is no classes to test or compile, but all the dependencies need to be downloaded at this time. Then I run [Run] -> [Maven Install]:

and it created a war file under target folder in our Project

Of course, the whole war file in this case does not have anything in it beside the index.html with Hello World. But if we had some classes, servlets, etc., we would just created a deployable war file that you can just drop into the webapp directory on Tomcat. This can even be done in Eclipse (you drag the war into the Tomcat server either under Servers on Project Explorer panel, or under the Servers tab in the bottom panel. However, we will not be able to do it here. Maven and Eclipse can deploy the war files by using a plugin. While there is such a plugin for Tomcat7 called: tomcat7:deploy (google for it or look at https://tomcat.apache.org/maven-plugin-2.2/tomcat7-maven-plugin/deploy-mojo.html), no such thing was written yet for Tomcat 8. So we need to do it manually. The simplistic way is to just copy the war file to the Tomcat's webapps directory (namely, the %CATALINA_HOME%\webapps, and if you do not know what it is, find it in my http://www.ccl.net/cca/software/JAVA/EclipseWindowsTomcat/index.html write-up). Let us check first if we have the %CATALINA_HOME% environment variable defined. If not, we need to set it first, before running Tomcat. You can set up this environment variable permanently in the System variables by going either through Control Panel or clicking on WinKey/Pause shortcut or using the SETX DOS command. Since I have scores of Tomcats installed, I prefer to set this variable temporarily in the DOS Command Prompt via a SET (if you do not know what it is, type SET /? in the DOS Command Prompt window). For example:

is not a screw-up on my part, but a simple confirmation that the Tomcat is not currently running. When you look at the %CATALINA_HOME%\conf\server.xml you will see this port defined as 8005 unless you changed it:

<Server port="8005" shutdown="SHUTDOWN">

The Tomcat shuts down when you telnet to the shutdown port and type the SHUTDOWN password:

$ telnet 127.0.0.1 8005
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
SHUTDOWN
Connection closed by foreign host.

Of course, it is a major security vulnerability, as you can imagine. The easiest way is, of course, to change the password to something longer and hard to guess, like ShutTheDamnedThingUp but then some predefined things would stop working (but the shutdown scripts take parameters, read comments inside, google and RTFM docs). The other way is to protect this port with your firewall. Anyhow... Know about it, but this is a topic for another discussion.

But I want to show you how to deploy the war through Tomcat's Management console. I will be brief, but details are available at http://tomcat.apache.org/tomcat-8.0-doc/manager-howto.html. before you can do it, you need to create an admin user with appropriate rights (role).

There is a file in the %CATALINA_HOME%\conf directory called tomcat-users.xml. Most of this file is commented out to make sure that the Tomcat configured by default is safe, i.e., nobody can use the Management Console after the newbie installed Tomcat in the Cloud and feels happy. Backup the file and then change the fragment from:

<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
-->

to something like:

<user username="admin" password="XXXX"
    roles="manager-gui" />
<user username="scripter" password="YYYY"
    roles="manager-script" />

Of course, I would use something else than "XXXX" for password. If you forget what it is, it is easy enough to look up the file (there are other ways to do security on Tomcat, but let us keep it simple). Make sure that Tomcat is not running when you do it (to be damned sure, exit Eclipse and run %CATALINA_HOME%\bin\shutdown.bat in the DOS Command Prompt window as in the above pic). Then when you start the Tomcat by entering %CATALINA_HOME\bin\startup.bat you should see the familiar page stuff:

The Java Console should also show up in another window. Now you are ready to click on this link http://127.0.0.1:8080 . You should now see a beautiful page in the new browser window:

Time to click on gray buttons on the left. I will start from [Manager App]

If you messed up the tomcat-users.xml or already forgot your Admin password, you can click on [Cancel] and you will get a help page like:

If you did not mess up, you will see the rich Web Application Manager

If you scroll down, you will see a Deploy area:

We will pretend that we are doing it over the Internet from the remote computer, i.e., use the [Browse] button and fetch a file from the computer. You may be right about the file name... We will get back to it.

So I fished the war file from under my Eclipse project MyJee7App

And then clicked on [Deploy]. Now my Manager shows me that the application is not only deployed, but also running (the [Start] button is missing, while the [Stop] button is on), and the Context name is, as you suspected, /MyJee7App-0.0.1-SNAPSHOT, i.e., the name of the war file:

When I click on the link in the first column, I will see my laborious application:

And what would you expect? Of course, you should rename your war file, rather than take the default thing from Maven. You could do it directly in Maven, but modifying the pom.xml and adding a <finalName> element with the name for your war

save the file (remember to click on these diskettes), and [Run as] -> Maven install

And now you will see that the HelloWorld war file is there.

Now, if you picked this war file. and dropped it (sorry... deployed it via the Application Manager) into Tomcat, you would get the right Context name.

And if you clicked on it, you would get the Hello World from a different web application than before:

And if you checked under Tomcat's webapps you will see these war and the directories (named by their Contexts) where they were deployed.

jkl@root-PC /cygdrive/c/Tomcat/apache-tomcat-8.0.18/webapps
$ ls -l
total 36
drwxr-xr-x+ 1 jkl None    0 Feb  4 20:06 docs
drwxr-xr-x+ 1 jkl None    0 Feb  4 20:06 examples
drwxr-xr-x+ 1 jkl None    0 Feb 14 01:55 HelloWorld
-rwxr-xr-x+ 1 jkl None 2337 Feb 14 01:55 HelloWorld.war
drwxr-xr-x+ 1 jkl None    0 Feb  4 20:06 host-manager
drwxr-xr-x+ 1 jkl None    0 Feb  4 20:06 manager
drwxr-xr-x+ 1 jkl None    0 Feb 14 00:05 MyJee7App-0.0.1-SNAPSHOT
-rwxr-xr-x+ 1 jkl None 2317 Feb 14 00:05 MyJee7App-0.0.1-SNAPSHOT.war
drwxr-xr-x+ 1 jkl None    0 Feb  4 20:06 ROOT

jkl@root-PC /cygdrive/c/Tomcat/apache-tomcat-8.0.18/webapps
$

I wanted to follow up with some example of some more real Web application. However, I noticed that it is getting too long. Maybe next time...

If you think that it was useful, share... If you think that it was bad, bitch (to the address below).

Jan Labanowski

jkl at ccl dot net