Thursday, September 21, 2017

Hello World, Maven!

This year, I am demanding students to manage their projects using Maven. Around 2015 or 2016, I started to see an increasing usage of IntelliJ among students to the detriment of Eclipse. This raised a problem, as I am much more experienced with Eclipse than with IntelliJ, and I'm not willing to master both (as some students kept loyal to Eclipse). Hence, I pretty much saw Maven as an opportunity to settle the differences. Working with Maven is also a great opportunity for students to gain and practice a competence they might well need in their future jobs.

The disadvantage is that Maven might be truly painful to configure, use and debug and might well stand in the way of inexperienced users, easily consuming more time than its fair share.

The first thing to understand about Maven is that, by default, it always tries to do something like compiling, testing, etc. To see this, let's first create a Maven project based on the "Maven Quickstart Archetype". This archetype is available both on Eclipse and IntelliJ. This archetype creates the following structure (see here):

project
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- App.java
    `-- test
        `-- java
            `-- AppTest.java

and, if I specify the groupId to be 'blog' and the artifact id to be 'example', I get the following pom.xml:

<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>blog</groupId>
  <artifactId>example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>example</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>


This Archetype brings an App.java file in the blog.example package in the src/main/java folder that will run the classic "Hello World!" program.

package blog.example;

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

}


Now, in my Eclipse installation, I immediately get a warning, because my project sets up the J2SE-1.5 JRE system library, and I don't have any JRE compatible with that version. This must be fixed, and this fix should help us to exactly understand how Maven works.

The first thing to notice is that we haven't specified anything about compilation in the pom.xml. Hence, Maven will assume a default compilation phase, which as of September 2017 uses Java version 5 as input and output. That's why we see this issue in the project (with the 1.5 JRE). To make the problem more evident let's include a feature in our program that was not available in Java 5: streams.

package blog.example;

import java.util.stream.IntStream;

public class App 
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
IntStream.range(1, 4)
.forEach(System.out::println);
}

}


Now, we have errors, instead of a simple warning. We need to change our compiler from version 5 to version 8 (or whatever last version is available). In Eclipse (and IntelliJ) projects, we would use the mouse, navigate menus and so on, to change the installed libraries. We will do it in Maven now, by specifying a plugin that changes the default behavior of the compilation phase.

<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>blog</groupId>
<artifactId>example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>example</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>

<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>
</plugin>
</plugins>
</build>

</project>


We can see the different options of the maven-compiler-plugin in the appropriate web site (click here). I just changed the source and the target, but I've seen cases with some students, where it was necessary to specify the location of the Java compiler in a slightly more complicated configuration, also available in the page I mentioned. This plugin will change the way Maven behaves, when going through the compilation of our project. But, in the case of Eclipse, the errors in the project persist, because Eclipse still doesn't know about the changes we did to the pom.xml. We need to update the project, to put the pom.xml and the Eclipse project in sync or 'updated' (this is available in the context menu over the name of the project, under the title 'Maven'). In IntelliJ, a step like this is also necessary and may be configured to run automatically.

Note that we don't need to do a Maven update or, in other words, to put the project in sync, to compile the project with Maven or run any other phase of the Maven lifecycle, like packaging. We do this for the sake of working in a clean IDE environment, and for being able to get the benefits of using the IDE. If we don't update, and the project is kept with errors, Eclipse (or IntelliJ) won't be able to compile your source code on the fly. If everything is in sync, both Eclipse and yourself (manually via Maven) will be able to compile the source code and generate the classes. So, an update is clearly useful.

Eclipse (and IntelliJ) will compile the source code on their own and run the program if necessary. To do this ourselves in Eclipse, we need to specify a goal for the Maven build. In this case it is compile, as you can see in the 'Goals' box:



If you press the 'Run' button, what you actually get is a compilation, not an execution. You should get something along the lines:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building example 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/filipius/aulas/2017-18/IS/code/example/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ example ---
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.815 s
[INFO] Finished at: 2017-09-21T15:47:45+01:00
[INFO] Final Memory: 8M/155M

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

The way to execute the program will depend on the IDE. If you now run the program, you should get:

Hello World!
1
2
3

The funny thing and the true power of Maven comes from the fact that we now may do the same thing in the command line, as long as we install Maven (although a different version of Maven, compared to that used by Eclipse/IntelliJ might cause some glitches). Just change directory to the folder where the pom.xml is and run the following command. Note that this is optional, as Eclipse/IntelliJ should do this for you:

mvn compile

We should get the same thing as before:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building example 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ example ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/filipius/aulas/2017-18/IS/code/example/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ example ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/filipius/aulas/2017-18/IS/code/example/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.659 s
[INFO] Finished at: 2017-09-21T15:52:57+01:00
[INFO] Final Memory: 13M/155M
[INFO] ------------------------------------------------------------------------


This action will generate the new App.class, if necessary, under the target directory. No Eclipse and no IntelliJ. Everything is ready for command line automation!

Of course, Maven can get much more complicated than this, especially as projects become larger and we need additional control. For now, there are two important things to learn. 1- there are more lifecycle phases than compile; 2 - we can add up dependencies, aka libraries to our project.

Regarding lifecycles, it's unnecessary to repeat what is available here, but I will list the most important ones for convenience:

  • validate - validate the project is correct and all necessary information is available
  • compile - compile the source code of the project
  • test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
  • package - take the compiled code and package it in its distributable format, such as a JAR.
  • verify - run any checks on results of integration tests to ensure quality criteria are met
  • install - install the package into the local repository, for use as a dependency in other projects locally
  • deploy - done in the build environment, copies the final package to the remote repository for sharing with other developers and projects.
For example, you might want to generate a .jar package using Maven. Therefore,  a phase with that same name exists for that purpose. How do you control the packaging process? Through a plugin. Configuring plugins, as we saw in the case of compile, might be relatively complicated, but there should be a lot of documentation around.

To include libraries in our project, we just need to add another <dependency>, under the <dependencies> element, like this, if you need jsoup, for example:

<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.3</version>

</dependency>

You can look for the last versions of the dependencies in the Maven Repository. You can look for more details regarding dependencies here, although I'm afraid that this seemingly introductory page is incredibly complicated for beginners.

22 comments:

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete
  5. This comment has been removed by a blog administrator.

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete
  7. This comment has been removed by a blog administrator.

    ReplyDelete
  8. It would have been the happiest moment for you,I mean if we have been waiting for something to happen and when it happens we forgot all hardwork and wait for getting that happened.

    devops online training

    aws online training

    data science with python online training

    data science online training

    rpa online training

    ReplyDelete
  9. Woah this blog is wonderful i like studying your posts. Keep up the great work! You understand, lots of persons are hunting around for this info, you could help them greatly.
    Microsoft Azure online training
    Selenium online training
    Java online training
    Python online training
    uipath online training

    ReplyDelete
  10. Nice and very useful blog. A great and very informative post, Keep up the good work!


    ExcelR Data Science Course in Bangalore

    ReplyDelete
  11. Excellent Blog! I would like to thank for the efforts you have made in writing this post. I am hoping the same best work from you in the future as well. I wanted to thank you for this websites! Thanks for sharing. Great websites!
    date analytics certification training courses
    data science courses training

    ReplyDelete
  12. Really impressive post. I read it whole and going to share it with my social circules. I enjoyed your article and planning to rewrite it on my own blog.
    data analytics course malaysia

    ReplyDelete
  13. I have to search sites with relevant information on given topic and provide them to teacher our opinion and the article.
    rpa training in malaysia

    ReplyDelete
  14. Study ExcelR Data Analytics Course in Bangalore where you get a great experience and better knowledge.
    Data Analytics Course in Bangalore

    ReplyDelete
  15. I just got to this amazing site not long ago. I was actually captured with the piece of resources you have got here. Big thumbs up for making such wonderful blog page!

    Simple Linear Regression

    ReplyDelete
  16. It has fully emerged to crown Singapore's southern shores and undoubtedly placed her on the global map of residential landmarks. I still scored the more points than I ever have in a season for GS. I think you would be hard pressed to find somebody with the same consistency I have had over the years so I am happy with that.
    machine learning courses in bangalore

    ReplyDelete
  17. Excellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking Best data science courses in hyerabad

    ReplyDelete
  18. I wanted to leave a little comment to support you and wish you a good continuation. Wishing you the best of luck for all your blogging efforts.
    machine learning courses in bangalore

    ReplyDelete
  19. Informative blog. Useful to many people. Thanks for sharing with us.
    Data Science Training Institute in Hyderabad

    ReplyDelete
  20. I’m happy I located this blog! From time to time, students want to recognize the keys of productive literary essays. Your first-class knowledge about this good post can become a proper basis for such people. nice one
    data analytics training in hyderabad

    ReplyDelete
  21. Great post I would like to thank you for the efforts you have made in writing this interesting and knowledgeable article.
    data science course fee in hyderabad

    ReplyDelete
  22. A decent blog consistently concocts new and energizing data and keeping in mind that perusing I have feel that this blog is truly have each one of those quality that qualify a blog to be a one. 360digitmg bangalore

    ReplyDelete