├── .gitignore
├── .travis.yml
├── LICENSE
├── Nexus Indexer from Eclipse.adoc
├── README.adoc
├── pom.xml
└── src
└── main
└── resources
├── META-INF
└── maven
│ └── archetype-metadata.xml
└── archetype-resources
├── .gitignore
├── pom.xml
└── src
├── main
├── java
│ └── App.java
└── resources
│ └── logback.xml
└── test
└── java
└── MyTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .project
3 | .classpath
4 | .settings/
5 |
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | git:
3 | depth: 1
4 | dist: xenial
5 | cache:
6 | directories:
7 | - "$HOME/.m2"
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Olivier Cailloux
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Nexus Indexer from Eclipse.adoc:
--------------------------------------------------------------------------------
1 | = Nexus Indexer from Eclipse
2 |
3 | To access archetypes using Nexus Indexer from within Eclipse, look at `File` / `New` / `Maven Project`, select `Nexus Indexer` as a catalog. On my install nothing appeared under `Nexus Indexer`, by default. Let’s see how to solve this. (Informations valid for Eclipse Neon JavaEE.)
4 |
5 | * Open the `Maven Repositories` view, then under `Global Repositories`, right-click `central`, choose `Rebuild index` (leaving `Minimum Index Enabled` checked).
6 | ** See the m2eclipse https://books.sonatype.com/m2eclipse-book/reference/repository-sect-repo-view.html[book].
7 | * Indexing takes a _long_ time. (5 min using a fast computer, 28 min using an older computer (56 min, another try).)
8 | ** The indexing process may seem to hang, because Eclipse progress indicator gets stuck at 0%. And the Maven console within Eclipse only says when indexing starts and when it ends. It is working however.
9 | ** The index gets built (according to my observations) in `~/.m2/repository/.cache/m2e/1.7.0/someid`, then part of it gets duplicated into `eclipse workspace/.metadata/.plugins/org.eclipse.m2e.core/nexus/someid`.
10 | ** On my older computer, nothing seemed to happen for 9 minutes (11 minutes another try), then suddenly a 293 MB `nexus-maven-repository-index.gz` appeared within the m2 cache folder. Then, nothing again until 20 minutes (48 minutes) after start of indexing, where further big files appeared in a `min` subfolder of the m2 cache folder. The folder grew over 4 GB, then, 27 minutes (55 minutes) after start, shrank to 2 GB.
11 | At that point the biggest file (1.7 GB) from that folder got copied into the Eclipse workspace nexus folder.
12 | * According to my observations the m2 cache folder can be deleted once indexing is finished, with no apparent effect on Eclipse. (While deleting the Eclipse workspace nexus folder removes the index from Eclipse.)
13 | * Populating the list of archetypes from the Nexus Indexer (only first time it is triggered after each start of Eclipse) takes 15 sec on a fast computer, 26 sec on an older computer.
14 |
15 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | = Java Archetype
2 | :toc:
3 | :toc-placement: preamble
4 | :sectanchors:
5 | :groupId: io.github.oliviercailloux
6 | :artifactId: java-archetype
7 | :repository: {artifactId}
8 |
9 | image:https://travis-ci.com/oliviercailloux/{repository}.svg?branch=master["Build Status", link="https://travis-ci.com/oliviercailloux/{repository}"]
10 | image:https://maven-badges.herokuapp.com/maven-central/{groupId}/{artifactId}/badge.svg["Artifact on Maven Central", link="http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22{groupId}%22%20a%3A%22{artifactId}%22"]
11 |
12 | A simple maven https://maven.apache.org/guides/introduction/introduction-to-archetypes.html[archetype] with reasonable defaults for quickly starting modern Java projects.
13 |
14 | == Usage
15 |
16 | * Type `mvn archetype:generate -DarchetypeGroupId=io.github.oliviercailloux -DarchetypeArtifactId=java-archetype`.
17 | * Enter your desired `groupId` and `artifactId`, press enter to accept the suggested package name, enter to confirm.
18 | ** You have to change the suggested package name if the default one has invalid characters, such as hyphens! (Due to a https://issues.apache.org/jira/browse/ARCHETYPE-490[bug] in Maven archetypes, it seems difficult to support this use case. Please consider up-voting the bug, or commenting if you know anything relevant.)
19 | * Your project gets created in a subfolder of your current position, named from your `artifactId`.
20 |
21 | === Other usages
22 |
23 | * Use `org.apache.maven.plugins:maven-archetype-plugin:3.2.1:generate` instead of `archetype:generate` to use a specific (possibly more recent) version of the https://search.maven.org/artifact/org.apache.maven.plugins/maven-archetype-plugin[`archetype`] plugin
24 | * `mvn archetype:generate -DarchetypeGroupId=io.github.oliviercailloux -DarchetypeArtifactId=java-archetype -DinteractiveMode=false -DgroupId=mygroupid -DartifactId=myartifactid` also indicates the desired group and artifact ids and remove the prompts.
25 |
26 | === From Eclipse
27 | Eclipse looks at your local archetype catalog. You need to make this archetype appear there.
28 |
29 | * Invoke this archetype using one of the commands above. Maven will download it in your local repository (you should now see it under `~/.m2/repository/io/github/oliviercailloux/`).
30 | * `mvn archetype:crawl -Dcatalog=/home/username/.m2/archetype-catalog.xml` asks Maven to create (or update) your local archetype catalog (http://maven.40175.n5.nabble.com/archetype-catalog-xml-location-archetype-crawl-versus-archetype-generate-td113741.html[more] https://issues.apache.org/jira/browse/ARCHETYPE-142[info]).
31 | * In Eclipse: `File` / `New` / `Maven Project`, select this archetype.
32 |
33 | === From Eclipse (alternatives)
34 | The following procedure uses the remote archetype catalog instead of the local one. The drawback is that it takes about 15 seconds each time you want to use this archetype, as Eclipse downloads the (huge) remote archetype catalog again each time. (Tested with Eclipse Neon, Oxygen and Photon.)
35 |
36 | * `Window` / `Preferences` / `Maven` / `Archetypes` / `Add Remote Catalog…`, give it the url http://repo1.maven.org/maven2/archetype-catalog.xml, Description: Remote archetypes catalog.
37 | * `File` / `New` / `Maven Project`, type `cailloux` in the filter box. Select this archetype.
38 |
39 | Instead of using the Maven local or remote archetypes catalog as indicated above, you may prefer the `Nexus Indexer`: `File` / `New` / `Maven Project`, select `Nexus Indexer` as a catalog, type `cailloux` in the filter box. Select this archetype. (Tested under Eclipse Oxygen.) (On my install nothing appeared under `Nexus Indexer`, by default. Follow link:Nexus%20Indexer%20from%20Eclipse.adoc[this] to solve that problem.)
40 |
41 | == Generated projects
42 | Projects generated from this archetype have the following characteristics.
43 |
44 | * The https://github.com/oliviercailloux/java-archetype/blob/master/src/main/resources/archetype-resources/pom.xml[pom] has recent versions of:
45 | ** https://github.com/google/guava[Guava]
46 | ** http://www.slf4j.org/[SLF4J] with http://logback.qos.ch/[Logback]
47 | ** JUnit Jupiter.
48 | * The project contains:
49 | ** a starter https://github.com/oliviercailloux/java-archetype/blob/master/src/main/resources/archetype-resources/src/main/java/App.java[class] with a main
50 | ** a JUnit test https://github.com/oliviercailloux/java-archetype/blob/master/src/main/resources/archetype-resources/src/test/java/MyTests.java[case]
51 | ** a configuration https://github.com/oliviercailloux/java-archetype/blob/master/src/main/resources/archetype-resources/src/main/resources/logback.xml[file] for Logback
52 | ** a https://github.com/oliviercailloux/java-archetype/blob/master/src/main/resources/archetype-resources/.gitignore[.gitignore] file.
53 |
54 | == How it works
55 |
56 | * I published this project to http://search.maven.org/#search|ga|1|g:io.github.oliviercailloux%20a:java-archetype[Maven Central] (source on Maven Central visible https://repo.maven.apache.org/maven2/io/github/oliviercailloux/java-archetype/[here]).
57 | * A few days later, the https://repo1.maven.org/maven2/archetype-catalog.xml[remote archetypes catalog] indexed it.
58 | * When starting the https://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html[`archetype:generate`] goal, maven uses the `org.apache.maven.plugins:maven-archetype-plugin` plugin, which (by default) searches for archetypes in the remote archetypes catalog (see http://maven.apache.org/archetype/maven-archetype-plugin/specification/archetype-catalog.html[Archetype Catalog]; you can also try `mvn org.apache.maven.plugins:maven-archetype-plugin:3.2.1:generate -DarchetypeCatalog=local` or `mvn org.apache.maven.plugins:maven-archetype-plugin:3.2.1:generate -DarchetypeCatalog=internal` for comparison).
59 | * One week later than publication, the Maven http://maven.apache.org/repository/central-index.html[Central Index] was updated. (Thus, there might be a delay between availability from maven command line invocation and availability within https://github.com/oliviercailloux/Java-Archetype#from-eclipse[Eclipse], depending on the way you access archetypes.)
60 |
61 | == Alternatives
62 | === The official quickstart archetype
63 | The official archetype (mentioned by Apache’s http://maven.apache.org/guides/getting-started/index.html#how-do-i-make-my-first-maven-project[Maven Getting Started Guide] and by the https://subscription.packtpub.com/book/web_development/9781785286124/1/ch01lvl1sec14/Creating-a-simple-project-with-Maven[Apache Maven Cookbook]) for simple Java projects is https://maven.apache.org/archetypes/maven-archetype-quickstart[`maven-archetype-quickstart`], or `org.apache.maven.archetypes:maven-archetype-quickstart` in full.
64 |
65 | It should, IMHO, be considered deprecated, as it suffers several weaknesses.
66 |
67 | * An important problem is that it creates projects https://github.com/apache/maven-archetypes/blob/maven-archetype-bundles-1.4/maven-archetype-quickstart/src/main/resources-filtered/archetype-resources/pom.xml#L21-L28[that depend on JUnit 4]. The current version, https://junit.org/junit5/[JUnit 5], differs significantly, providing among other an improved API.
68 | * Minor weaknesses: its default version is 1.0-SNAPSHOT, which should be 1.0.0-SNAPSHOT to follow the recommended and usual scheme.
69 | * Another minor weakness: it creates projects https://github.com/apache/maven-archetypes/blob/maven-archetype-bundles-1.4/maven-archetype-quickstart/src/main/resources-filtered/archetype-resources/pom.xml#L17-L18[configured for a 1.7 JVM]. This may be appropriate if you particularly need to support old installs, but opting for a reasonably recent JVM is a more reasonable default rule for new projects. For example, Java 8 https://www.oracle.com/java/technologies/javase/8-whats-new.html[introduced] lambda expressions, which you probably do not want to miss out.
70 |
71 | My archetype also provides logging by default, which I think is useful, scales better than sysout and does not hurt, and Guava, which usefully enriches Java.
72 |
73 | === Other quickstart archetypes in Maven Central
74 | In order to join efforts if possible and avoid wasteful duplication, I actively searched for other archetypes that would have the same aim as this one: provide a simple archetype with reasonable defaults to easily start a modern Java project. (This was mostly done around June 2020.)
75 |
76 | A general search on the internet https://stackoverflow.com/a/49399420[led me] to https://thepracticaldeveloper.com/archetypes/[The Practical Developer]. When contacted, he wrote to me (by e-mail) that he does not work on https://github.com/thepracticaldeveloper/archetype-java-basic[his archetype] regularly and therefore preferred to decline collaborating on such a project.
77 |
78 | As searches on the net did not reveal other useful results, and as I found no specialised search tool suitable for my needs, I implemented a simple https://github.com/oliviercailloux/archetypes-browser[archetype browser]. It lists all the archetypes available in Maven Central. There are far too many to review manually, thus, I selected those whose groupId and artifactId existed since at least three years and have been updated during the last year, in hope of finding projects that are maintained on the long run, which I suppose indicates more probably a good quality project. (Of course this filter may have missed good quality archetypes that perfectly match the stated goal; I have no way to know. As a case in point, this very archetype does not pass that filter as I have changed its artifactId over time.)
79 |
80 | I then filtered manually the https://github.com/oliviercailloux/archetypes-browser/raw/master/Archetypes%20grouped.ods[resulting list] on the basis of the archetypes descriptions found in their POM, and gave a further look (on the official website, typically) for a few promising archetypes among them. Only https://github.com/ngeor/archetype-quickstart-jdk8[`com.github.ngeor
81 | :archetype-quickstart-jdk8`] revealed to be a suitable candidate. But its author https://github.com/ngeor/archetype-quickstart-jdk8/issues/17#issuecomment-663838745[wrote to me] that he is “not really using/maintaing the archetype much these days”.
82 |
83 | Please https://github.com/oliviercailloux/java-archetype/issues[open an issue] if you know other archetypes that aim at fulfilling a similar goal as this one.
84 |
85 | == Clean POM
86 | I value clean configuration files, and this archetype provides a clean POM. By this, I mean that I value having as few configuration entries (or lines in my POM) as possible. This is important because the POM, as a fundamental description of your project, may be a source of subtle problems if it contains some incorrect entry; and such mistakes are much easier to notice when the file is very short.
87 |
88 | This is one reason for not following the usual practice of defining the versions of all plugins that a project uses. (Another reason is spelled out below.) A counter-argument may be that such configuration lines can be moved away, for example in a parent POM, but this does not solve the problem of increased complexity; you still have as many (or more) total configuration entries in your project, only, with some of them hidden. Also, I do not define version properties, I rather keep the version where the dependency itself is declared, unless the property is required to avoid redundancy (see also https://github.com/ngeor/archetype-quickstart-jdk8/issues/17[this discussion]).
89 |
90 | === About specifying versions
91 | Here is a bit more rationale about my adoption of a “loose plugin dependency” strategy. By this, I mean that I do not specify precisely the versions of all plugins that I use. It is opposed to the “tight plugin dependency” strategy (example https://github.com/apache/maven-archetypes/blob/maven-archetype-bundles-1.4/maven-archetype-quickstart/src/main/resources-filtered/archetype-resources/pom.xml#L31-L73[here]).
92 | In general, the rationale of the tight dependency strategy is as follows: you tested your software with component C at version X; therefore, you declare that your software depends exactly on version X of component C, rather than declaring simply that it depends on (any sufficiently recent version of) component C.
93 |
94 | The “tight dependency” strategy is usually recommended in order to avoid falling under a bug of a later version. Indeed, this is an advantage of that strategy. But I consider that this strategy should remain an exception rather than the norm. We ought to write software that relies on components described by general specifications, meaning, software that will work under future (or simply different) implementations of those specifications. We should not be content with guaranteeing only that our software works under this and that specific environment and version. Thus, we ought to write software that works with, for example, any future version of the `maven-resources-plugin`, not just one that works with version 2.6 of that plugin. Or, software that will work under future versions of the JVM. Or of Windows. (That is, as long as these components provide backwards compatibility.) The tight dependency strategy leads to extreme waste of resources, as it obliges end-users to have multiple versions of components available when their installed softwares require different versions of a single component. It also goes against the very spirit of program design by specification: future versions may improve performance or correct bugs, and specifying tight dependencies prevent your software from automatically benefitting from such improvements.
95 |
96 | I admit that the industry tends, more and more, to apply the tight dependency strategy rather than the loose dependency strategy. I believe that this is an instance of a tragedy of the commons: it is better for an enterprise, locally, to specify dependencies tightly as it reduces the validity claims of its production; but it is worst for the ecosystem in general when actors behave in such a way.
97 |
98 | To summarize, I believe that applying a loose dependency strategy produces higher quality software, and is doing the right thing for users and for good resource use. (Reasonable exceptions exist, of course, as always with such rules of thumb.)
99 |
100 | == References
101 | * https://www.overops.com/blog/the-top-100-java-libraries-in-2016-after-analyzing-47251-dependencies/[The most popular Java libraries used by GitHub’s most popular projects (2016)]
102 | * https://mvnrepository.com/popular[Popularity ranking by MvnRepository]
103 |
104 | (The reason I included Guava, JUnit and SLF4J in this archetype is because I personally think that these libraries are must-have in most projects, but it is good to see that popularity arguments go in the same direction.)
105 |
106 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | io.github.oliviercailloux
5 | java-archetype
6 | 0.0.14-SNAPSHOT
7 | maven-archetype
8 | Java Archetype
9 | A maven archetype with reasonable defaults for starting Java projects.
10 | https://github.com/oliviercailloux/java-archetype
11 |
12 |
13 | MIT License
14 | https://opensource.org/licenses/MIT
15 |
16 |
17 |
18 |
19 | Olivier Cailloux
20 | olivier.cailloux@dauphine.fr
21 | http://www.lamsade.dauphine.fr/~ocailloux/
22 | Paris-Dauphine
23 | http://www.dauphine.fr
24 |
25 |
26 |
27 | scm:git:git://github.com/oliviercailloux/java-archetype.git
28 | scm:git:ssh://github.com/oliviercailloux/java-archetype.git
29 | https://github.com/oliviercailloux/java-archetype
30 |
31 |
32 | UTF-8
33 | true
34 |
35 |
36 |
37 | ossrh
38 | https://oss.sonatype.org/content/repositories/snapshots
39 |
40 |
41 |
42 |
43 |
44 |
45 | org.apache.maven.archetype
46 | archetype-packaging
47 | 3.2.1
48 |
49 |
50 |
51 |
52 |
53 |
54 | org.apache.maven.plugins
55 | maven-resources-plugin
56 | 3.0.1
57 |
58 |
60 | false
61 |
62 |
63 |
64 | maven-archetype-plugin
65 | 3.2.1
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | release
74 |
75 |
76 | ossrh
77 | https://oss.sonatype.org/content/repositories/snapshots
78 |
79 |
80 | ossrh
81 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
82 |
83 |
84 |
85 |
86 |
87 | maven-source-plugin
88 | 3.0.1
89 |
90 |
91 | attach-sources
92 |
93 | jar-no-fork
94 |
95 |
96 |
97 |
98 |
99 | org.apache.maven.plugins
100 | maven-gpg-plugin
101 | 1.6
102 |
103 |
104 | sign-artifacts
105 | verify
106 |
107 | sign
108 |
109 |
110 |
111 |
112 |
113 | org.sonatype.plugins
114 | nexus-staging-maven-plugin
115 | 1.6.8
116 | true
117 |
118 | ossrh
119 | https://oss.sonatype.org/
120 | true
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/maven/archetype-metadata.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | 0.0.1-SNAPSHOT
10 |
11 |
12 | ${groupId}.${artifactId}
13 |
14 |
15 |
16 |
17 | src/main/java
18 |
19 | **/*.java
20 |
21 |
22 |
23 | src/test/java
24 |
25 | **/*.java
26 |
27 |
28 |
29 | src/main/resources
30 |
31 | *
32 |
33 |
34 |
35 |
36 |
37 | .gitignore
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/main/resources/archetype-resources/.gitignore:
--------------------------------------------------------------------------------
1 | out.log
2 |
3 | target/
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/archetype-resources/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | ${groupId}
7 | ${artifactId}
8 | ${version}
9 |
10 |
11 | UTF-8
12 | 17
13 |
14 |
15 |
16 |
17 |
21 |
22 | maven-surefire-plugin
23 | 2.22.2
24 |
25 |
30 |
31 | maven-compiler-plugin
32 | 3.10.1
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.slf4j
40 | slf4j-api
41 | 2.0.13
42 |
43 |
44 | com.google.guava
45 | guava
46 | 33.2.1-jre
47 |
48 |
49 |
50 | ch.qos.logback
51 | logback-classic
52 |
53 | 1.5.6
54 | runtime
55 | true
56 |
57 |
58 |
59 | org.junit.jupiter
60 | junit-jupiter-engine
61 | 5.9.3
62 | test
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/main/resources/archetype-resources/src/main/java/App.java:
--------------------------------------------------------------------------------
1 | package ${package};
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | public class App {
7 | @SuppressWarnings("unused")
8 | private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
9 |
10 | public static void main(String[] args) throws Exception {
11 | new App().proceed();
12 | }
13 |
14 | public void proceed() {
15 | LOGGER.info("Hello World!");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/resources/archetype-resources/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
8 |
9 |
10 |
11 | INFO
12 |
13 |
14 |
15 |
16 | out.log
17 | false
18 |
19 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/main/resources/archetype-resources/src/test/java/MyTests.java:
--------------------------------------------------------------------------------
1 | package ${package};
2 |
3 | import static org.junit.jupiter.api.Assertions.assertTrue;
4 |
5 | import org.junit.jupiter.api.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class MyTests {
10 | @SuppressWarnings("unused")
11 | private static final Logger LOGGER = LoggerFactory.getLogger(MyTests.class);
12 |
13 | @Test
14 | void testSomething() throws Exception {
15 | LOGGER.info("Started tests.");
16 | assertTrue(false);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------