{"id":1801,"date":"2017-10-20T19:23:50","date_gmt":"2017-10-20T19:23:50","guid":{"rendered":"http:\/\/blog.paranoidprofessor.com\/?p=1801"},"modified":"2017-10-20T19:23:50","modified_gmt":"2017-10-20T19:23:50","slug":"maven-simple-example","status":"publish","type":"post","link":"https:\/\/blog.paranoidprofessor.com\/index.php\/2017\/10\/20\/maven-simple-example\/","title":{"rendered":"Maven simple example"},"content":{"rendered":"<p>Maven was briefly described in my previous post. \u00a0In this post I will do a few small examples for actually using Maven.<\/p>\n<p>One of the\u00a0main things about Maven is the idea of the artifact. \u00a0The artifact is a file, which is usually a jar file. \u00a0This might be a jar that is a dependency or a jar, war or ear file that is generated by Maven. \u00a0All artifacts are described by three different key values.<\/p>\n<ul>\n<li>artifactId<\/li>\n<li>groupId<\/li>\n<li>version<\/li>\n<\/ul>\n<p>The artifactId is just a name. \u00a0The group id is also just a name but it is usually it is the reverse domain of the company. \u00a0The version number is just the version of that particular object.<\/p>\n<h2>Hello world &#8211; manual<\/h2>\n<p>The directory structure is fairly simple. \u00a0The program code will be under the src\/main directory structure while the unit tests will be under the main\/test directory.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nmkdir helloworld\r\ncd helloworld\r\n\r\nmkdir src\r\nmkdir src\/main\r\nmkdir src\/main\/java\r\nmkdir src\/test\r\nmkdir src\/test\/java\r\n<\/pre>\n<p>The structure is simple but must be strictly adhered to. \u00a0The structure is well defined so the project\u00a0object model (pom) file doesn&#8217;t need to contain much at all.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;project&gt;\r\n  &lt;modelVersion&gt; 4.0.0&lt;\/modelVersion&gt;\r\n  &lt;groupId&gt; de.acmesoft &lt;\/groupId&gt;\r\n  &lt;artifactId&gt; helloworld &lt;\/artifactId&gt;\r\n  &lt;version&gt; 1.0.0 &lt;\/version&gt;\r\n&lt;\/project&gt;\r\n<\/pre>\n<p>It is important to have the artifact keys in the pom file and they should be different than any other artifact keys. \u00a0This is important in case this artifact should end up in the repository.<\/p>\n<p>The modelVersion field is refers to the internal structures for Maven. \u00a0In future releases of Maven this version may change.<\/p>\n<p>The executable from Maven is mvn. \u00a0Simply pass in the phase that you are interested in and Maven will execute the lifecycle up to that point.<\/p>\n<p>For this sample I could simply compile the class files or go one step further and generate a jar file.<\/p>\n<pre>#: \/tmp\/mvn mvn compile \r\n[INFO] Scanning for projects...\r\n[INFO] \r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] Building helloworld 1.0.0\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] \r\n[INFO] --- maven-resources-plugin:2.3:resources (default-resources) @ helloworld ---\r\n[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!\r\n[INFO] skip non existing resourceDirectory \/home\/dock\/working\/content\/43-blog\/maven\/helloworld3\/src\/main\/resources\r\n[INFO] \r\n[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ helloworld ---\r\n[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!\r\n[INFO] Compiling 1 source file to \/home\/dock\/working\/content\/43-blog\/maven\/helloworld3\/target\/classes\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] BUILD SUCCESS\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] Total time: 2.974s\r\n[INFO] Finished at: Sun Dec 11 23:27:27 CET 2016\r\n[INFO] Final Memory: 10M\/119M\r\n[INFO] ------------------------------------------------------------------------<\/pre>\n<h3>Running hello world<\/h3>\n<p>Maven creates all of it&#8217;s output files into the target directory. \u00a0This is true for both the normal class files as well as the jar files (for simple java programs) that get created.<\/p>\n<p>If you want a quick test simply set the class path to point to the new jar file.<\/p>\n<pre>java -cp target\/helloworld-1.0.0.jar com.acmesoft.helloworld<\/pre>\n<p>If you look closely at the pom file above you will see that it is inconsistent from the pom file. The package in the source code actually does reflect the test command. \u00a0At the end of the day, the code will indeed have the final say.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\npackage com.acmesoft;\r\n\r\npublic class helloworld\r\n{\r\n  public helloworld()\r\n  {\r\n     System.out.println(&quot;hello world!&quot;);\r\n  }\r\n\r\n  public static void main (String[] args)\r\n  {\r\n     new helloworld();\r\n  }\r\n}\r\n<\/pre>\n<h2>Hello world &#8211; template<\/h2>\n<p>In my opinion the most convenient feature of Maven is the ability to create an empty project. \u00a0There is a list of thousands of different types of template projects. \u00a0With a simple command it is possible to create the entire project from scratch &#8211; just add code.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nmvn archetype:generate -DgroupId=de.acmesoft -DartifactId=helloworld -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false                                                                                                               \r\n[INFO] Scanning for projects...                                                                                                       \r\n[INFO]                                                                                                                                \r\n[INFO] ------------------------------------------------------------------------                                                       \r\n[INFO] Building Maven Stub Project (No POM) 1                                                                                         \r\n[INFO] ------------------------------------------------------------------------                                                       \r\n[INFO]                                                                                                                                \r\n[INFO] &amp;gt;&amp;gt;&amp;gt; maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom &amp;gt;&amp;gt;&amp;gt;                                                     \r\n[INFO]                                                                                                                                \r\n[INFO] &amp;lt;&amp;lt;&amp;lt; maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom &amp;lt;&amp;lt;&amp;lt;                                                     \r\n[INFO]                                                                                                                                \r\n[INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom ---                                                     \r\n[INFO] Generating project in Batch mode                                                                                               \r\n[INFO] ----------------------------------------------------------------------------                                                   \r\n[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0                       \r\n[INFO] ----------------------------------------------------------------------------                                                   \r\n[INFO] Parameter: basedir, Value: \/tmp                                                                                                \r\n[INFO] Parameter: package, Value: de.acmesoft                                                                                         \r\n[INFO] Parameter: groupId, Value: de.acmesoft                                                                                         \r\n[INFO] Parameter: artifactId, Value: helloworld\r\n[INFO] Parameter: packageName, Value: de.acmesoft\r\n[INFO] Parameter: version, Value: 1.0-SNAPSHOT\r\n[INFO] project created from Old (1.x) Archetype in dir: \/tmp\/helloworld\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] BUILD SUCCESS\r\n[INFO] ------------------------------------------------------------------------\r\n[INFO] Total time: 3.132s\r\n[INFO] Finished at: Sun Dec 11 23:46:15 CET 2016\r\n[INFO] Final Memory: 13M\/223M\r\n[INFO] ------------------------------------------------------------------------\r\n<\/pre>\n<p>The generate command not only creates the directory structure but also creates the pom.xml file. \u00a0You can see how the command line parameters end up in the appropriate location in the pom file, which is also created automatically.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot; xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd&quot;&gt;\r\n  &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n  &lt;groupId&gt;com.acmesoft.secondexample&lt;\/groupId&gt;\r\n  &lt;artifactId&gt;secondexample&lt;\/artifactId&gt;\r\n  &lt;packaging&gt;jar&lt;\/packaging&gt;\r\n  &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\r\n  &lt;name&gt;secondexample&lt;\/name&gt;\r\n  &lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\r\n  &lt;dependencies&gt;\r\n    &lt;dependency&gt;\r\n      &lt;groupId&gt;junit&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n      &lt;version&gt;3.8.1&lt;\/version&gt;\r\n      &lt;scope&gt;test&lt;\/scope&gt;\r\n    &lt;\/dependency&gt; \r\n  &lt;\/dependencies&gt;\r\n&lt;\/project&gt;\r\n<\/pre>\n<p>This pom file is actually also a very basic file. \u00a0The very minimum is the same as the manually created pom file in the manual section. \u00a0 \u00a0Maven automatically added Junit in order to allow the unit tests that it also created to compile.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage de.acmesoft;\r\n\r\nimport junit.framework.Test;\r\nimport junit.framework.TestCase;\r\nimport junit.framework.TestSuite;\r\n\r\n\/**\r\n * Unit test for simple App.\r\n *\/\r\npublic class AppTest \r\n    extends TestCase\r\n{\r\n    \/**\r\n     * Create the test case\r\n     *\r\n     * @param testName name of the test case\r\n     *\/\r\n    public AppTest( String testName )\r\n    {\r\n        super( testName );\r\n    }\r\n\r\n    \/**\r\n     * @return the suite of tests being tested\r\n     *\/\r\n    public static Test suite()\r\n    {\r\n        return new TestSuite( AppTest.class );\r\n    }\r\n\r\n    \/**\r\n     * Rigourous Test :-)\r\n     *\/\r\n    public void testApp()\r\n    {\r\n        assertTrue( true );\r\n    }\r\n}\r\n<\/pre>\n<p>The template also includes the source code for our hello world program as well.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage de.acmesoft;\r\n\r\n\/**\r\n * Hello world!\r\n *\r\n *\/\r\npublic class App \r\n{\r\n    public static void main( String[] args )\r\n    {\r\n        System.out.println( &quot;Hello World!&quot; );\r\n    }\r\n}\r\n<\/pre>\n<p>One small difference between the manual project that I created is that using the template creates the package, the pom file and the directory structure all consistent with each other.<\/p>\n<h2>Hello world &#8211; log4j<\/h2>\n<p>The generic hello world prints the output to the standard output and doesn&#8217;t use external libraries for any task. \u00a0Some applications or utilities might be this simple but it is uncommon for any but the most trivial application to not use external libraries for some purpose.<\/p>\n<p>To simulate such a case, I have modified the hello world application to use log4j for all output.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.acmesoft.secondexample;\r\n\r\nimport org.apache.log4j.PropertyConfigurator;                                                                      \r\nimport org.apache.log4j.Logger;                                                                                    \r\n\r\npublic class App                                                                                            \r\n{                                                                                                                  \r\n  public App()                                                                                              \r\n  {                                                                                                                \r\n     String cfgFileName = &quot;log4j.properties&quot;;                                                                      \r\n     PropertyConfigurator.configure(cfgFileName);                                                                  \r\n     Logger logfile = Logger.getLogger(App.class.getName());                                                \r\n                                                                                                                   \r\n     System.out.println(&quot;hello world!&quot;);                                                                           \r\n     logfile.info(&quot;hello world&quot;);                                                                                  \r\n  }                                                                                                                \r\n                                                                                                                   \r\n  public static void main (String[] args)                                                                          \r\n  {                                                                                                                \r\n     new App();                                                                                             \r\n  }                                                                                                                \r\n}\r\n<\/pre>\n<h3>Running hello world<\/h3>\n<p>My first test of the application failed for obvious reasons.<\/p>\n<pre>java -cp target\/helloworld-1.0.0.jar com.acmesoft.secondexample.App<\/pre>\n<p>The reason was NoClassDefFoundError was thrown. \u00a0The application uses log4j so it will not work\u00a0unless it is part of the classpath.<\/p>\n<pre>java -cp target\/secondexample-1.0-SNAPSHOT.jar:lib\/log4j-1.2.17.jar com.acmesoft.secondexample.App<\/pre>\n<p>Maven is just another way to compile an application, the Java basics don&#8217;t change. \u00a0Simply make sure that when running the program\u00a0that all necessary dependencies are provided. However, Java programs cannot be compiled unless the code that it is dependent on are provided. This is done by adding dependencies to the pom file.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot; xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd&quot;&gt;\r\n  &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n  &lt;groupId&gt;com.acmesoft.secondexample&lt;\/groupId&gt;\r\n  &lt;artifactId&gt;secondexample&lt;\/artifactId&gt;\r\n  &lt;packaging&gt;jar&lt;\/packaging&gt;\r\n  &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\r\n  &lt;name&gt;secondexample&lt;\/name&gt;\r\n  &lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\r\n  &lt;dependencies&gt;\r\n    &lt;dependency&gt;\r\n      &lt;groupId&gt;junit&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n      &lt;version&gt;3.8.1&lt;\/version&gt;\r\n      &lt;scope&gt;test&lt;\/scope&gt;\r\n    &lt;\/dependency&gt;\r\n    &lt;dependency&gt;\r\n      &lt;groupId&gt;log4j&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;log4j&lt;\/artifactId&gt;\r\n      &lt;version&gt;2.0.1&lt;\/version&gt;\r\n    &lt;\/dependency&gt; \r\n  &lt;\/dependencies&gt;\r\n&lt;\/project&gt;\r\n<\/pre>\n<p>The dependencies block contains both a dependency for JUnit and Log4j. \u00a0The JUnit dependency was automatically added when the application was created by Maven (in order to support the automated testing) but I manually added the Log4j block as it would be necessary for the program.<\/p>\n<h2>Hello world &#8211; log4j revised<\/h2>\n<p>The good news is that Maven can be configured to include the dependencies as part of the &#8220;package&#8221;. \u00a0This way it is possible to create the equivalent of a statically linked application that can simply be copied from directory to directory and it will still work.<\/p>\n<p>The list of dependencies don&#8217;t change but what does change is the new &#8220;build&#8221; block that embeds the dependencies into the resulting jar.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot; xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd&quot;&gt;\r\n  &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n  &lt;groupId&gt;com.acmesoft.firstexample&lt;\/groupId&gt;\r\n  &lt;artifactId&gt;firstexample&lt;\/artifactId&gt;\r\n  &lt;packaging&gt;jar&lt;\/packaging&gt;\r\n  &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\r\n  &lt;name&gt;firstexample&lt;\/name&gt;\r\n  &lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\r\n\r\n  &lt;dependencies&gt;\r\n    &lt;dependency&gt;\r\n      &lt;groupId&gt;junit&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n      &lt;version&gt;3.8.1&lt;\/version&gt;\r\n      &lt;scope&gt;test&lt;\/scope&gt;\r\n    &lt;\/dependency&gt;\r\n    &lt;dependency&gt;\r\n      &lt;groupId&gt;log4j&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;log4j&lt;\/artifactId&gt;\r\n      &lt;version&gt;1.2.17&lt;\/version&gt;\r\n    &lt;\/dependency&gt; \r\n  &lt;\/dependencies&gt;\r\n\r\n  &lt;build&gt;\r\n    &lt;plugins&gt;\r\n        &lt;plugin&gt;\r\n            &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n            &lt;artifactId&gt;maven-shade-plugin&lt;\/artifactId&gt;\r\n            &lt;version&gt;2.1&lt;\/version&gt;\r\n            &lt;executions&gt;\r\n                &lt;execution&gt;\r\n                    &lt;phase&gt;package&lt;\/phase&gt;\r\n                    &lt;goals&gt;\r\n                        &lt;goal&gt;shade&lt;\/goal&gt;\r\n                    &lt;\/goals&gt;\r\n                    &lt;configuration&gt;\r\n                        &lt;transformers&gt;\r\n                            &lt;transformer implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&gt;\r\n                                &lt;mainClass&gt;com.acmesoft.firstexample.App&lt;\/mainClass&gt;\r\n                            &lt;\/transformer&gt;\r\n                        &lt;\/transformers&gt;\r\n                    &lt;\/configuration&gt;\r\n                &lt;\/execution&gt;\r\n            &lt;\/executions&gt;\r\n        &lt;\/plugin&gt;\r\n    &lt;\/plugins&gt;\r\n&lt;\/build&gt;\r\n\r\n&lt;\/project&gt;\r\n<\/pre>\n<p>Once the dependencies are embedded inside the jar file, you can simply run the application without worrying about the rest of the dependencies.<\/p>\n<pre>java -cp target\/firstexample-1.0-SNAPSHOT.jar com.acmesoft.secondexample.App<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Maven was briefly described in my previous post. \u00a0In this post I will do a few small examples for actually using Maven. One of the\u00a0main things about Maven is the idea of the artifact. \u00a0The artifact is a file, which &hellip; <a href=\"https:\/\/blog.paranoidprofessor.com\/index.php\/2017\/10\/20\/maven-simple-example\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[20],"tags":[73,12],"_links":{"self":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/1801"}],"collection":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/comments?post=1801"}],"version-history":[{"count":39,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/1801\/revisions"}],"predecessor-version":[{"id":1948,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/1801\/revisions\/1948"}],"wp:attachment":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/media?parent=1801"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/categories?post=1801"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/tags?post=1801"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}