📜 ⬆️ ⬇️

Creating your own archetypes and directories in Maven

For quite a long time (I’ll come running for about a year) I actively use the Apache Maven build system and I am completely satisfied with it. Despite its obvious and not very flaws, an indisputable advantage is the automatic dependency management, good structuring of projects and the absence of build scripts as such, and therefore problems with them.

Many people may not like that mavens really take away from the developer the freedom to choose the structure of the project and directly dictate it, but is this freedom really important enough to make a bold argument against it? I do not think. There are other, more serious, in my opinion, flaws, in the first place - the difficulty of diagnosing problems during assembly and insufficient documentation of maven and plug-ins.

There was a case on the project when a new member of the team was unable to build the build, having received the unintelligible conclusion that even after two hours of digging it turned out that the fifth version of Java as the main version was nailed into the pome and it was not installed.

Searching for plugins and setting them up is also agonizing circles of hell, but compared to xml programming on ant, this is still nothing.
')
However, with the right approach and full of skill, maven is almost not felt in the work, which I really like.

Actually, this article is not about torments, but about archetypes, their catalogs and creating your own archetypes and directories.
With the help of these simple concepts, you can significantly simplify your life when creating a new project.

Create a local directory



The archetype in mavena is a template for a new project, with the structure and presets of the source and configuration files.

Anyone who has created a project on mavena at least once has come across archetypes. For example, a typical method of creating a project that hovers on the Internet:

	 mvn archetype: create \
	   -DarchetypeGroupId = <archetype-groupId> \
	   -DarchetypeArtifactId = <archetype-artifactId> \
	   -DarchetypeVersion = <archetype-version> \
	   -DgroupId = <my-groupid> \
	   -DartifactId = <my-artifactId>
	


The question of where to get the necessary parameters always worried me, usually I politely ask Google and he usually answers me :)

If we, for example, want to create a simple application, then we use an archetype called maven-archetype-quickstart, for example like this:

	 mvn archetype: create \
	   -DarchetypeGroupId = org.apache.maven.archetypes \
	   -DarchetypeArtifactId = maven-archetype-quickstart \
	   -DarchetypeVersion = 1.0 \
	   -DgroupId = org.example \
	   -DartifactId = simpleapp
	

There is a more convenient way to create a project using the archetype: generate target. When you call, in the interactive mode you will be prompted to enter the parameters of the new project.

  mvn archetype: generate 


But there is a problem. Maven offers to choose the type of new project from the list of ready-made templates, and the list consists of more than 300 options. Finding the right template there is quite a non-trivial task, usually I drop the output to a file and then I search for what I need with a grep.

Googling a bit, I found a solution to this problem for myself, not quite as final for me, but quite to myself with a hint of elegance. Archetypes can be combined into catalogs! But how can this help?

The directory is determined by the URL, where it is located, besides there are three predefined directories in the mavena, or, if you wish, the alias: internal , remote and local .

internalcontains archetypes embedded in maven, there are not many of them and they already de facto go with the distribution itself
remoteThe maven central directory is located at http://repo1.maven.org/maven2/archetype-catalog.xml , its location depends on the current settings of the maven, for example, it is possible to redefine this URL to one of the repository mirrors
localdirectory from local repository, usually located in ~ / .m2 / archetype-catalog.xml


The archetype: generate target has an archetypeCatalog parameter with which you can specify a list of directories where you can search for possible archetypes. The default value of the 'remote, local' parameter. But if you remove the remote from there, you get almost what you need.

For example, like this:

	 grim @ blackbox: ~ / projects $ mvn archetype: generate -DarchetypeCatalog = local

	 [... bulshit ...]

	 Choose archetype:
	 1: local -> maven-archetype-quickstart (quickstart)
	 2: local -> maven-archetype-archetype (archetype)
	 3: local -> maven-archetype-webapp (webapp)
	 Choose a number: 1:
	


You can look at the file structure from the remote directory. For example, to get the list above, the file should look like

<?xml version="1.0" encoding="UTF-8"?> <archetype-catalog xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0 http://maven.apache.org/xsd/archetype-catalog-1.0.0.xsd" xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <archetypes> <archetype> <groupId>org.apache.maven.archetypes</groupId> <artifactId>maven-archetype-quickstart</artifactId> <version>1.1</version> <description>quickstart</description> </archetype> <archetype> <groupId>org.apache.maven.archetypes</groupId> <artifactId>maven-archetype-archetype</artifactId> <version>1.0</version> <description>archetype</description> </archetype> <archetype> <groupId>org.apache.maven.archetypes</groupId> <artifactId>maven-archetype-webapp</artifactId> <version>1.0</version> <description>webapp</description> </archetype> </archetypes> </archetype-catalog> 


After a little conjuring with the configuration of mavena, you can make this situation permanent, you need to create a profile in which to set the value of the variable archetypeCatalog. To do this, you need to add to your settings.xml file

  <profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <archetypeCatalog>local</archetypeCatalog> </properties> </profile> </profiles> 


Use! Now, when called, the goal of archetype: generate instead of tons of garbage will output what you say.

By the way, the archetype plugin has a curious crawl target, which scans your local repository for the presence of archetypes and generates a directory from all found. Unfortunately, the documentation is a bit untrue and by default the file is generated not at all where it expects to see its maven. You need to cook like this:

	 grim @ blackbox: ~ / projects $ mvn archetype: crawl -Dcatalog = ~ / .m2 / archetype-catalog.xml
	

Contrary to official documentation, the parameter is called not catalogFile, but catalog.

Create your own archetype



The second problem that we will consider is the creation of our own archetype. Why do you need it? It is necessary for the simple reason that for all the seeming abundance of archetypes, among them was not suitable for simple web development. There are a few congenial ones, for example the same maven-archetype-webapp, but the descriptors in it are outdated, there is no log4j and the normal jsp template. In total, after creating an empty project, you need to go to the file mode, and use Google to redo everything as it should. In the end, for the tenth time I got tired of it, and I decided to create my own archetype, the best and the most correct one. More specifically, we will create a workpiece for a simple application on spring-mvc using Servlet 2.5 / JSP 2.1 / JSTL 1.2 with logging ready for operation.

Attention, in the next paragraph it is possible to freeze on the number of references to the word archetype.

First you need to create a project for our archetype using the maven-archetype-archetype archetype, for example, using the same archetype: create.

	 grim @ blackbox: ~ / projects $ mvn archetype: create \
	    -DarchetypeArtifactId = maven-archetype-archetype \
	    -DartifactId = baremvc \
	    -DgroupId = example
	

In order not to suffer in the console, let's move to the eclipse, although of course everything that is written below can be done with the help of vim or something else like that.

	 grim @ blackbox: ~ / projects $ cd baremvc && mvn eclipe: eclipse
	

Then we import and look at the structure in more detail.



The project consists of one resources folder, which contains two subfolders: archetype-resources and META-INF. The first one contains the backbone of future outstanding projects that will be created by generations of programmers after our death, the second one contains the file META-INF / maven / archetype.xml. This is the handle of the archetype. A description of what is included in the archetype will be stored in it.

Let's add the skeleton, with everything you need: add a simple jsp page, a more or less tolerable web.xml, a simple controller and the config log4j.properties. All this you will find in the archive, which can be downloaded . Of the interesting points that are worth paying attention to, these are the replacements that the maven makes when creating a project. The archetype implements the mechanism of templates based on Velocity, which is practically not documented, if someone is sure of the opposite, share, I will be grateful.

In particular, in the controller, through the templates, the substitution of the package name is implemented.

  // HomeController.java package $package; import org.apache.commons.logging.Log; @Controller public class HomeController { ... 

The same move is used in the Spring MVC configuration and in generating the target pom.xml. So far, the list of variables known to me is rather poor: $ groupId , $ artifactId , $ version and $ package . I think everyone understands what each means, all this is indicated when creating a project from the archetype.

In general, the theme of the templates is interesting and unrevealed, I think a little later I will dig it deeper, but for now the fact that there is, is quite enough for our modest needs.

When the process of preparing templates is completed, you need to prepare the file descriptor of the archetype, the same archetype.xml.

  <archetype xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype/1.0.0 http://maven.apache.org/xsd/archetype-1.0.0.xsd"> <id>baremvc</id> <sources> <source>src/main/java/HomeController.java</source> </sources> <resources> <resource>src/main/resources/log4j.properties</resource> <resource>src/main/webapp/home.jsp</resource> <resource>src/main/webapp/WEB-INF/applicationContext.xml</resource> <resource>src/main/webapp/WEB-INF/web.xml</resource> </resources> <testSources /> </archetype> 

The tag must match the artifactId of our archetype. The <sources> and <resources> tags are intended for templates of different parts of the archetype. In particular, resources from the webapp folder should be specified in the <resources> tag. There are a few more valid sections. The following lists the valid sections and folders where the templates specified in them will go.

<sources>src / main / java
<resources>src / main / resources
<testSources>src / test / java
<testResources>src / test / resources
<siteResources>src / site


Once everything is ready, you can install our archetype into the repository using

	 grim @ blackbox: ~ / projects / baremvc $ mvn clean install
	

and now it is ready for use.

	 grim @ blackbox: ~ / projects / baremvc $ cd ..
	 grim @ blackbox: ~ / projects $ mvn archetype: create \
	   -DarchetypeGroupId = org.example \
	   -DarchetypeArtifactId = baremvc \
	   -DarchetypeVersion = 1.0 \
	   -DgroupId = org.example \
	   -DartifactId = baremvcapp
	

Our little project is ready to launch.

	 grim @ blackbox: ~ / projects / baremvcapp $ cd baremvcapp
	 grim @ blackbox: ~ / projects / baremvcapp $ mvn tomcat: run
	


After that, the link http: // localhost: 8080 / baremvcapp can see this creation.

Now the archetype, it can be said prepared, add it to the local directory by hand or by using the target archetype: crawl.

	 grim @ blackbox: ~ / projects $ mvn archetype: crawl -Dcatalog = / home / grim / .m2 / archetype-catalog.xml
	

Now, when you call archetype: generate, a line should appear in the list

	 1: local -> baremvc (baremvc)
	

with which I congratulate us.

In conclusion, it remains to add that the method described above is outdated (alas), and marked as deprecated, but still works, but about the right way of the documentation, like a cat, wept. All that I know so far is that the handle has been changed, now it is called archetype-metadata.xml and has a more powerful syntax. Hopefully enough for another ten years to write articles ahead.

Downloadable archive

Sources that can be viewed

Resources used


  1. Guide to Creating Archetypes - http://maven.apache.org/plugins/maven-archetype-plugin-1.0-alpha-7/examples/archetype.html
  2. Maven Archetype Plugin - http://maven.apache.org/archetype/maven-archetype-plugin/
  3. Maven - reflections after two years of use - http://habrahabr.ru/blogs/personal/102181/


UPD: There is also an archetype: create-from-project target that will generate a template from your project. The template is generated in the target / generated-sources / archetype folder. That is, from virtually any of your projects, you can generate an archetype and then use it as a starting point. Thanks 1nd1go

Source: https://habr.com/ru/post/111408/


All Articles