-
Notifications
You must be signed in to change notification settings - Fork 270
/
Copy pathindex.apt
1225 lines (995 loc) · 49.3 KB
/
index.apt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
----
Maven Getting Started Guide
-----
Jason van Zyl
Vincent Siveton
-----
2006-11-01
-----
Maven Getting Started Guide
This guide is intended as a reference for those working with Maven for the first time, but is also intended to serve as
a cookbook with self-contained references and solutions for common use cases. For first time users, it is recommended
that you step through the material in a sequential fashion. For users more familiar with Maven, this guide endeavours
to provide a quick solution for the need at hand. It is assumed at this point that you have downloaded Maven and
installed Maven on your local machine. If you have not done so please refer to the
{{{../../download.html}Download and Installation}} instructions.
Ok, so you now have Maven installed and we're ready to go. Before we jump into our examples we'll very briefly go over
what Maven is and how it can help you with your daily work and collaborative efforts with team members. Maven will, of
course, work for small projects, but Maven shines in helping teams operate more effectively by allowing team members
to focus on what the stakeholders of a project require. You can leave the build infrastructure to Maven!
Sections
%{toc|section=0|fromDepth=2|toDepth=3}
* What is Maven?
At first glance Maven can appear to be many things, but in a nutshell Maven is an attempt <to apply patterns to
a project's build infrastructure in order to promote comprehension and productivity by providing a clear path in the
use of best practices>. Maven is essentially a project management and comprehension tool and as such provides a way to
help with managing:
* Builds
* Documentation
* Reporting
* Dependencies
* SCMs
* Releases
* Distribution
[]
If you want more background information on Maven you can check out {{{../../background/philosophy-of-maven.html}The Philosophy of Maven}} and
{{{../../background/history-of-maven.html}The History of Maven}}. Now let's move on to how you, the user, can benefit from
using Maven.
* How can Maven benefit my development process?
Maven can provide benefits for your build process by employing standard conventions and practices to accelerate your development
cycle while at the same time helping you achieve a higher rate of success.
Now that we have covered a little bit of the history and purpose of Maven let's get into some real examples to
get you up and running with Maven!
* How do I setup Maven?
The defaults for Maven are often sufficient, but if you need to change the cache location or are behind a HTTP proxy,
you will need to create configuration. See the {{{../mini/guide-configuring-maven.html} Guide to Configuring Maven}} for
more information.
* How do I make my first Maven project?
We are going to jump headlong into creating your first Maven project!
To create our first Maven project we are going to use Maven's archetype mechanism. An archetype is defined as
<an original pattern or model from which all other things of the same kind are made>. In Maven, an archetype is a template
of a project which is combined with some user input to produce a working Maven project that has been tailored to the
user's requirements. We are going to show you how the archetype mechanism works now, but if you would like to know more
about archetypes please refer to our {{{../introduction/introduction-to-archetypes.html}Introduction to Archetypes}}.
On to creating your first project! In order to create the simplest of Maven projects, execute the following from
the command line:
-----
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false
-----
Once you have executed this command, you will notice a few things have happened. First, you will notice that
a directory named <<<my-app>>> has been created for the new project, and this directory contains a file named
<<<pom.xml>>> that should look like this:
+-----+
<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>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.11.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<!-- Optionally: parameterized tests support -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
... lots of helpful plugins
</pluginManagement>
</build>
</project>
+-----+
<<<pom.xml>>> contains the Project Object Model (POM) for this project. The POM is the basic unit
of work in Maven. This is important to remember because Maven is inherently project-centric in that everything revolves
around the notion of a project. In short, the POM contains every important piece of information about your project and
is essentially one-stop-shopping for finding anything related to your project. Understanding the POM is important and
new users are encouraged to refer to the {{{../introduction/introduction-to-the-pom.html}Introduction to the POM}}.
This is a very simple POM but still displays the key elements every POM contains, so let's walk through each of them
to familiarize you with the POM essentials:
* <<project>> This is the top-level element in all Maven <<<pom.xml>>> files.
* <<modelVersion>> This element indicates what version of the object model this POM is using. The version of the
model itself changes very infrequently but it is mandatory in order to ensure stability of use if and when
the Maven developers deem it necessary to change the model.
* <<groupId>> This element indicates the unique identifier of the organization or group that created the project.
The groupId is one of the key identifiers of a project and is typically based on the fully qualified
domain name of your organization. For example <<<org.apache.maven.plugins>>> is the designated groupId for
all Maven plugins.
* <<artifactId>> This element indicates the unique base name of the primary artifact being generated by this project.
The primary artifact for a project is typically a JAR file. Secondary artifacts like source bundles also use
the artifactId as part of their final name. A typical artifact produced by Maven would have the form
\<artifactId\>-\<version\>.\<extension\> (for example, <<<myapp-1.0.jar>>>).
* <<version>> This element indicates the version of the artifact generated by the project. Maven goes a long way
to help you with version management and you will often see the <<<SNAPSHOT>>> designator in a version, which
indicates that a project is in a state of development. We will discuss the use of
{{{./index.html#what-is-a-snapshot-version}snapshots}} and how they work further on in this guide.
* <<name>> This element indicates the display name used for the project. This is often used in Maven's
generated documentation.
* <<url>> This element indicates where the project's site can be found. This is often used in Maven's
generated documentation.
* <<properties>> This element contains value placeholders accessible anywhere within a POM.
* <<dependencies>> This element's children list {{{/pom.html#dependencies}dependencies}}. The cornerstone of the POM.
* <<build>> This element handles things like declaring your project's directory structure and managing plugins.
[]
For a complete reference of what elements are available for use in the POM please refer to our {{{/ref/current/maven-model/maven.html}POM Reference}}.
Now let's get back to the project at hand.
After the archetype generation of your first project you will also notice that the following directory structure
has been created:
-----
my-app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- mycompany
| `-- app
| `-- App.java
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
-----
As you can see, the project created from the archetype has a POM, a source tree for your application's sources and
a source tree for your test sources. This is the standard layout for Maven projects (the application sources
reside in <<<$\{project.basedir\}/src/main/java>>> and test sources reside in <<<$\{project.basedir\}/src/test/java>>>, where <<<$\{project.basedir\}>>>
represents the directory containing <<<pom.xml>>>).
If you were to create a Maven project by hand this is the directory structure that we recommend using. This is a
Maven convention and to learn more about it you can read our
{{{../introduction/introduction-to-the-standard-directory-layout.html}Introduction to the Standard Directory Layout}}.
Now that we have a POM, some application sources, and some test sources you are probably asking...
* How do I compile my application sources?
Change to the directory where <<<pom.xml>>> is created by archetype:generate and execute the following command to compile
your application sources:
-------
mvn compile
-------
Upon executing this command you should see output like the following:
-----
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to <dir>/my-app/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.899 s
[INFO] Finished at: 2020-07-12T11:31:54+01:00
[INFO] ------------------------------------------------------------------------
-----
The first time you execute this (or any other) command, Maven will need to download all the plugins and related
dependencies it needs to fulfill the command. From a clean installation of Maven, this can take quite a while (in
the output above, it took almost 4 minutes). If you execute the command again, Maven will now have what it needs,
so it won't need to download anything new and will be able to execute the command much more quickly.
As you can see from the output, the compiled classes were placed in <<<$\{project.basedir\}/target/classes>>>, which is
another standard convention employed by Maven. So, if you're a keen observer, you'll notice that by using the
standard conventions, the POM above is very small and you haven't had to tell Maven explicitly where any of
your sources are or where the output should go. By following the standard Maven conventions, you can get
a lot done with very little effort! Just as a casual comparison, let's take a look at what you might have had to do
in {{{http://ant.apache.org}Ant}} to accomplish the same {{{../../ant/build-a1.xml}thing}}.
Now, this is simply to compile a single tree of application sources and the Ant script shown is pretty much the same
size as the POM shown above. But we'll see how much more we can do with just that simple POM!
* How do I compile my test sources and run my unit tests?
Now you're successfully compiling your application's sources and now you've got some unit tests that you want to compile
and execute (because every programmer always writes and executes their unit tests *nudge nudge wink wink*).
Execute the following command:
------
mvn test
------
Upon executing this command you should see output like the following:
----
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to <dir>/my-app/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.881 s
[INFO] Finished at: 2020-07-12T12:00:33+01:00
[INFO] ------------------------------------------------------------------------
----
Some things to notice about the output:
* Maven downloads more dependencies this time. These are the dependencies and plugins necessary for executing the tests
(it already has the dependencies it needs for compiling and won't download them again).
* Before compiling and executing the tests Maven compiles the main code (all these classes are up to date because
we haven't changed anything since we compiled last).
If you simply want to compile your test sources (but not execute the tests), you can execute the following:
------
mvn test-compile
------
Now that you can compile your application sources, compile your tests, and execute the tests, you'll want to move
on to the next logical step so you'll be asking ...
* How do I create a JAR and install it in my local repository?
Making a JAR file is straight forward enough and can be accomplished by executing the following command:
~~ How to skip tests ... jvz
------
mvn package
------
You can now take a look in the <<<$\{project.basedir\}/target>>> directory and you will see the generated JAR file.
Now you'll want to install the artifact you've generated (the JAR file) in your local repository
(<<<$\{user.home\}/.m2/repository>>> is the default location). For more information on repositories you can refer to our
{{{../introduction/introduction-to-repositories.html}Introduction to Repositories}} but let's move on to installing our artifact!
To do so execute the following command:
------
mvn install
------
Upon executing this command you should see the following output:
----
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ my-app ---
[INFO] Installing <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar to <local-repository>/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar
[INFO] Installing <dir>/my-app/pom.xml to <local-repository>/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.678 s
[INFO] Finished at: 2020-07-12T12:04:45+01:00
[INFO] ------------------------------------------------------------------------
----
Note that the surefire plugin (which executes the test) looks for tests contained in files with a particular naming convention. By default
the tests included are:
* <<<\*\*/\*Test.java>>>
* <<<\*\*/Test\*.java>>>
* <<<\*\*/\*TestCase.java>>>
[]
And the default excludes are:
* <<<\*\*/Abstract\*Test.java>>>
* <<<\*\*/Abstract\*TestCase.java>>>
[]
You have walked through the process for setting up, building, testing, packaging, and installing a typical Maven project.
This is likely the vast majority of what projects will be doing with Maven and if you've noticed, everything you've been
able to do up to this point has been driven by an 18-line file, namely the project's model or POM. If you look at
a typical Ant {{{../../ant/build-a1.xml}build file}} that provides the same functionality that we've achieved thus
far you'll notice it's already twice the size of the POM and we're just getting started! There is far more
functionality available to you from Maven without requiring any additions to our POM as it currently stands. To
get any more functionality out of our example Ant build file you must keep making error-prone additions.
So what else can you get for free? There are a great number of Maven plugins that work out of the box with
even a simple POM like we have above. We'll mention one here specifically as it is one of the highly
prized features of Maven: without any work on your part this POM has enough information to generate
a web site for your project! You will most likely want to customize your Maven site but if you're pressed for
time all you need to do to provide basic information about your project is execute the following command:
------
mvn site
------
There are plenty of other standalone goals that can be executed as well, for example:
------
mvn clean
------
This will remove the <<<target>>> directory with all the build data before starting so that it is fresh.
* What is a SNAPSHOT version?
Notice the value of the <<version>> tag in the <<<pom.xml>>> file shown below has the suffix: <<<-SNAPSHOT>>>.
+-----+
<project xmlns="http://maven.apache.org/POM/4.0.0"
...
<groupId>...</groupId>
<artifactId>my-app</artifactId>
...
<version>1.0-SNAPSHOT</version>
<name>Maven Quick Start Archetype</name>
...
+-----+
The <<<SNAPSHOT>>> value refers to the 'latest' code along a development branch, and provides no guarantee the
code is stable or unchanging. Conversely, the code in a 'release' version (any version value without the suffix <<<SNAPSHOT>>>)
is unchanging.
In other words, a SNAPSHOT version is the 'development' version before the final 'release' version.
The SNAPSHOT is "older" than its release.
During the {{{../../plugins/maven-release-plugin/}release}} process, a version of <<x.y-SNAPSHOT>> changes to
<<x.y>>. The release process also increments the development version to <<x.(y+1)-SNAPSHOT>>.
For example, version <<1.0-SNAPSHOT>> is released as version <<1.0>>, and the new development version is
version <<1.1-SNAPSHOT>>.
* How do I use plugins?
Whenever you want to customise the build for a Maven project, this is done by adding or reconfiguring plugins.
For this example, we will configure the Java compiler to allow JDK 5.0 sources. This is as simple as
adding this to your POM:
+----+
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
...
+----+
You'll notice that all plugins in Maven look much like a dependency - and in some ways they are.
This plugin will be automatically downloaded and used - including a specific version if you request it
(the default is to use the latest available).
The <<<configuration>>> element applies the given parameters to every goal from the compiler plugin.
In the above case, the compiler plugin is already used as part of the build process and this just changes the
configuration. It is also possible to add new goals to the process, and configure specific goals. For information on
this, see the {{{../introduction/introduction-to-the-lifecycle.html} Introduction to the Build Lifecycle}}.
To find out what configuration is available for a plugin, you can see the {{{../../plugins/} Plugins List}} and navigate
to the plugin and goal you are using. For general information about how to configure the available parameters of a
plugin, have a look at the {{{../mini/guide-configuring-plugins.html}Guide to Configuring Plugins}}.
* How do I add resources to my JAR?
Another common use case that can be satisfied which requires no changes to the POM that we have
above is packaging resources in the JAR file. For this common task, Maven again relies on the
{{{../introduction/introduction-to-the-standard-directory-layout.html}Standard Directory Layout}}, which means by using
standard Maven conventions you can package resources within JARs simply by placing those resources in a standard
directory structure.
You see below in our example we have added the directory <<<$\{project.basedir\}/src/main/resources>>> into which we place
any resources we wish to package in our JAR. The simple rule employed by Maven is this: any directories or files
placed within the <<<$\{project.basedir\}/src/main/resources>>> directory are packaged in your JAR with the exact same
structure starting at the base of the JAR.
----
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| `-- application.properties
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
----
So you can see in our example that we have a <<<META-INF>>> directory with an <<<application.properties>>> file
within that directory. If you unpacked the JAR that Maven created for you and took a look at it you would
see the following:
----
|-- META-INF
| |-- MANIFEST.MF
| `-- application.properties
| `-- maven
| `-- com.mycompany.app
| `-- my-app
| |-- pom.properties
| `-- pom.xml
`-- com
`-- mycompany
`-- app
`-- App.class
----
As you can see, the contents of <<<$\{project.basedir\}/src/main/resources>>> can be found starting at the base of the
JAR and our <<<application.properties>>> file is there in the <<<META-INF>>> directory. You will also notice some other files there
like <<<META-INF/MANIFEST.MF>>> as well as a <<<pom.xml>>> and <<<pom.properties>>> file. These come standard with
generation of a JAR in Maven. You can create your own manifest if you choose, but Maven will generate one by
default if you don't. (You can also modify the entries in the default manifest. We will touch on this
later.) The <<<pom.xml>>> and <<<pom.properties>>> files are packaged up in the JAR so that each artifact
produced by Maven is self-describing and also allows you to utilize the metadata in your own application
if the need arises. One simple use might be to retrieve the version of your application. Operating on the POM
file would require you to use some Maven utilities but the properties can be utilized using the standard
Java API and look like the following:
----
#Generated by Maven
#Tue Oct 04 15:43:21 GMT-05:00 2005
version=1.0-SNAPSHOT
groupId=com.mycompany.app
artifactId=my-app
----
To add resources to the classpath for your unit tests, you follow the same pattern as you do for adding resources to the JAR
except the directory you place resources in is <<<$\{project.basedir\}/src/test/resources>>>. At this point you would have a
project directory structure that would look like the following:
-----
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| |-- application.properties
`-- test
|-- java
| `-- com
| `-- mycompany
| `-- app
| `-- AppTest.java
`-- resources
`-- test.properties
-----
In a unit test you could use a simple snippet of code like the following to access the resource required for
testing:
+----+
...
// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/test.properties" );
// Do something with the resource
...
+----+
* How do I filter resource files?
Sometimes a resource file will need to contain a value that can only be supplied at build time. To accomplish this in
Maven, put a reference to the property that will contain the value into your resource file using the syntax <<<$\{<property name>\}>>>.
The property can be one of the values defined in your <<<pom.xml>>>, a value defined in the user's <<<settings.xml>>>, a property
defined in an external properties file, or a system property.
To have Maven filter resources when copying, simply set <<<filtering>>> to true for the resource directory in your <<<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
+----+
You'll notice that we had to add the <<<build>>>, <<<resources>>>, and <<<resource>>> elements which weren't there before.
In addition, we had to explicitly state that the resources are located in the <<<src/main/resources>>> directory. All of this
information was provided as default values previously, but because the default value for <<<filtering>>> is false, we had
to add this to our <<<pom.xml>>> in order to override that default value and set <<<filtering>>> to true.
To reference a property defined in your <<<pom.xml>>>, the property name uses the names of the XML elements that define the value,
with "pom" being allowed as an alias for the project (root) element. So <<<$\{project.name\}>>> refers to the name of the project,
<<<$\{project.version\}>>> refers to the version of the project, <<<$\{project.build.finalName\}>>> refers to the final name of the file created
when the built project is packaged, etc. Note that some elements of the POM have default values, so don't need to be explicitly
defined in your <<<pom.xml>>> for the values to be available here. Similarly, values in the user's <<<settings.xml>>> can be referenced
using property names beginning with "settings" (for example, <<<$\{settings.localRepository\}>>> refers to the path of the user's
local repository).
To continue our example, let's add a couple of properties to the <<<application.properties>>> file (which we put in the
<<<src/main/resources>>> directory) whose values will be supplied when the resource is filtered:
------
# application.properties
application.name=${project.name}
application.version=${project.version}
------
With that in place, you can execute the following command (process-resources is the build lifecycle phase where the resources are
copied and filtered):
------
mvn process-resources
------
and the <<<application.properties>>> file under <<<target/classes>>> (and will eventually go into the jar) looks like this:
------
# application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT
------
To reference a property defined in an external file, all you need to do is add a reference to this external file in your <<<pom.xml>>>.
First, let's create our external properties file and call it <<<src/main/filters/filter.properties>>>:
------
# filter.properties
my.filter.value=hello!
------
Next, we'll add a reference to this new file in the <<<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
+----+
Then, if we add a reference to this property in the <<<application.properties>>> file:
------
# application.properties
application.name=${project.name}
application.version=${project.version}
message=${my.filter.value}
------
the next execution of the <<<mvn process-resources>>> command will put our new property value into <<<application.properties>>>.
As an alternative to defining the my.filter.value property in an external file, you could also have defined it in the <<<properties>>>
section of your <<<pom.xml>>> and you'd get the same effect (notice I don't need the references to <<<src/main/filters/filter.properties>>> either):
+----+
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<my.filter.value>hello</my.filter.value>
</properties>
</project>
+----+
Filtering resources can also get values from system properties; either the system properties built into Java (like <<<java.version>>> or
<<<user.home>>>) or properties defined on the command line using the standard Java -D parameter. To continue the example, let's change
our <<<application.properties>>> file to look like this:
------
# application.properties
java.version=${java.version}
command.line.prop=${command.line.prop}
------
Now, when you execute the following command (note the definition of the command.line.prop property on the command line), the
<<<application.properties>>> file will contain the values from the system properties.
------
mvn process-resources "-Dcommand.line.prop=hello again"
------
* How do I use external dependencies?
You've probably already noticed a <<<dependencies>>> element in the POM we've been using as an example.
You have, in fact, been using an external dependency all this time, but here we'll talk about how this
works in a bit more detail. For a more thorough introduction, please refer to our
{{{../introduction/introduction-to-dependency-mechanism.html}Introduction to Dependency Mechanism}}.
The <<<dependencies>>> section of the <<<pom.xml>>> lists all of the external dependencies that our project needs
in order to build (whether it needs that dependency at compile time, test time, run time, or whatever). Right
now, our project is depending on JUnit only (I took out all of the resource filtering stuff for clarity):
+----+
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
+----+
For each external dependency, you'll need to define at least 4 things: groupId, artifactId, version, and scope. The groupId,
artifactId, and version are the same as those given in the <<<pom.xml>>> for the project that built that dependency. The scope
element indicates how your project uses that dependency, and can be values like <<<compile>>>, <<<test>>>, and <<<runtime>>>.
For more information on everything you can specify for a dependency, see the {{{/ref/current/maven-model/maven.html}Project Descriptor Reference}}.
~~DJ: Does this link work? I can't find the document.
For more information about the dependency mechanism as a whole, see
{{{../introduction/introduction-to-dependency-mechanism.html}Introduction to Dependency Mechanism}}.
With this information about a dependency, Maven will be able to reference the dependency when it builds the project. Where does
Maven reference the dependency from? Maven looks in your local repository (<<<$\{user.home\}/.m2/repository>>> is the default location) to find
all dependencies. In a {{{How_do_I_create_a_JAR_and_install_it_in_my_local_repository}previous section}}, we installed the artifact
from our project (my-app-1.0-SNAPSHOT.jar) into the local repository. Once it's installed there, another project can reference that jar
as a dependency simply by adding the dependency information to its <<<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.mycompany.app</groupId>
<artifactId>my-other-app</artifactId>
...
<dependencies>
...
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
+----+
What about dependencies built somewhere else? How do they get into my local repository? Whenever a project references a dependency
that isn't available in the local repository, Maven will download the dependency from a remote repository into the local repository. You
probably noticed Maven downloading a lot of things when you built your very first project (these downloads were dependencies for the
various plugins used to build the project). By default, the remote repository Maven uses can be found (and browsed) at
{{https://repo.maven.apache.org/maven2/}}. You can also set up your own remote repository (maybe a central repository for your company) to
use instead of or in addition to the default remote repository. For more information on repositories you can refer to the
{{{../introduction/introduction-to-repositories.html}Introduction to Repositories}}.
Let's add another dependency to our project. Let's say we've added some logging to the code and need to add log4j as a dependency.
First, we need to know what the groupId, artifactId, and version are for log4j. The appropriate directory on Maven Central is called
{{{https://repo.maven.apache.org/maven2/log4j/log4j/}/maven2/log4j/log4j}}. In that directory is a file called maven-metadata.xml. Here's what the maven-metadata.xml for
log4j looks like:
+----+
<metadata>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.1.3</version>
<versioning>
<versions>
<version>1.1.3</version>
<version>1.2.4</version>
<version>1.2.5</version>
<version>1.2.6</version>
<version>1.2.7</version>
<version>1.2.8</version>
<version>1.2.11</version>
<version>1.2.9</version>
<version>1.2.12</version>
</versions>
</versioning>
</metadata>
+----+
From this file, we can see that the groupId we want is "log4j" and the artifactId is "log4j". We see lots of different version values
to choose from; for now, we'll just use the latest version, 1.2.12 (some maven-metadata.xml files may also specify which version is
the current release version: see {{{/ref/current/maven-repository-metadata/repository-metadata.html}repository metadata reference}}).
Alongside the maven-metadata.xml file, we can see a directory corresponding to each version of the
log4j library. Inside each of these, we'll find the actual jar file (e.g. log4j-1.2.12.jar) as well as a pom file (this is the <<<pom.xml>>>
for the dependency, indicating any further dependencies it might have and other information) and another maven-metadata.xml file.
There's also an md5 file corresponding to each of these, which contains an MD5 hash for these files. You can use this to authenticate
the library or to figure out which version of a particular library you may be using already.
Now that we know the information we need, we can add the dependency to our 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
+----+
Now, when we compile the project (<<<mvn compile>>>), we'll see Maven download the log4j dependency for us.
~~DJ: Current
* How do I deploy my jar in my remote repository?
For deploying jars to an external repository, you have to configure the repository url in the <<<pom.xml>>>
and the authentication information for connecting to the repository in the <<<settings.xml>>>.
Here is an example using scp and username/password authentication:
+----+
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.0.4</version>