Introduction
Let's say that after a lot of research, trial and errors, you set up a base maven project with a combination of frameworks and a bunch of tricky configurations. Your project works now, it prints
Wouldn't be easier if you could incorporate this customized project to a maven catalog so you can instantiate it from the terminal with a
Maven can take a project folder and generate the maven archetype file (a jar) that can be later installed on a maven proxy/repository to be available for all the people that have access to it. This is what this tutorial is about.
"Hello World!" in the browser window, text file or terminal, and you feel proud of yourself for being able to set up the whole thing. Now that you have this small code base, you can make a copy of the project folder and rename it as template-xyzw-project so if you (or any other programmer) wish to start a new project, you copy this template-xyzw-project folder, rename it and apply the appropiated tweaks. Lot of work, right?
mvn archetype:generate command instead of copy/paste/adjust everything?
Example Project
pom.xml that lists all the dependencies, you can also use a project of your own if you prefer.
Generate the base-archetype
cd into the project directory (or, in the case of a multi-module project, cd into the parent/aggregator project) and run the following command:
$ mvn archetype:create-from-project
This will generate a bulk of files and folders under the target/generated-sources/archetype directory:
.
├── src
│ ├── main
│ │ └── resources
│ │ ├── archetype-resources
│ │ │ └── src
│ │ │ └── main
│ │ │ ├── java
│ │ │ │ ├── portlets
│ │ │ │ └── services
│ │ │ │ └── impl
│ │ │ └── webapp
│ │ │ ├── VAADIN
│ │ │ │ ├── themes
│ │ │ │ │ └── test-portlet
│ │ │ │ └── widgetsets
│ │ │ └── WEB-INF
│ │ │ └── spring-conf
│ │ └── META-INF
│ │ └── maven
│ └── test
│ └── resources
│ └── projects
│ └── basic
└── target
├── classes
│ ├── archetype-resources
│ │ └── src
│ │ └── main
│ │ ├── java
│ │ │ ├── portlets
│ │ │ └── services
│ │ │ └── impl
│ │ └── webapp
│ │ ├── VAADIN
│ │ │ ├── themes
│ │ │ │ └── test-portlet
│ │ │ └── widgetsets
│ │ └── WEB-INF
│ │ └── spring-conf
│ └── META-INF
│ └── maven
└── test-classes
└── projects
└── basic
From this folder structure you can discard the target directory sub-tree (the red one), just mvn clean it.
com.test.portlets to com.organization.application.portlets and adjust all the package references (updating all the xml, properties, etc files). That's the next step.
Adjusting the archetype
cd target/resources/archetype) or you can make a copy in another directory of the archetype folder and cd into it, the second option is preferred as if you screw some configuration file, you can start over making another copy from the original archetype folder, it's up to you.
pom.xml in the archetype directory, it describes the project as a maven archetype (yes, the archetype folder is indeed a maven project), you can change the groupId, artifactId and version properties used to address the project in the GAV way, modify these properties to change the archetype name.
archetype-metadata.xml located under the src/main/resources/META-INF/maven directory. This file groups the resources as file sets (fileSets) that are going to be filtered by the archetype during the generation process, every file set is of the form:
-
filtered="true"indicates that the resource files of the file set should be parsed. Maven will use Apache Velocity templating framework to substitute/replace/conditional replace values in your files. -
packaged="true"From the documentation: "flags maven that the resource files have to be packaged, which means the selected files will be generated/copied in a directory structure that is prepended by the package property. They can be non-packaged, which means that the selected files will be generated/copied without that prepend." -
encoding="UTF-8"indicates that your files are in the specified encoding.
archetype-metadata.xml should look something like this:
You have to manually add the file sets that aren't listed in the above xml, normally you wouldn't have to do that, but this project employs some files that maven thinks shouldn't be fitlered and it groups them in a non-filtered file set. Sometimes you have to delete some of this maven generated file sets, like those that group IDE files (e.g,. .settings, .project, etc) that you forgot to manually delete from the project folder prior to running mvn archetype:create-from-project.
.scss located inside the folder VAADIN/themes/test-portlet.
-
For README and README.md, you only have to change the lines 27-34 in the above
archetype-metadata.xmlto: Open those README files and add the following lines at the beginning of the file (if they are not already there):#set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' )
Every file that you want to be filtered by maven has to start with those lines, even the.javafiles, but don't worry, maven archetype plugin have done this for you with all the file-sets that are initially listed in thearchetype-metadata.xmlfile, so you only add those that doesn't appear in a filtered file set (or in any file set at all). Then add the value${rootArtifactId}whenever you want the supplied user project name to appear.#set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) README for module ${artifactId} =============================== This module belongs to the project ${rootArtifactId} -
For the
.scssfiles, first remove the.scssinclude from the unfiltered file set: Now include the.scssfiles in a new file set: As done above, open the.scssfiles and add the#setlines, then replace those values that contains the project name (test-portlet) with${rootArtifactId}, for example, open the filestyles.scss: Then replacetest-portletwith${rootArtifactId}: Remember to check the java source files, and adjust those variables, methods, commets, etc that depends on the supplied project name, substitute them with${rootArtifactId}. Note that you can even tweak the code comments to reflect the user application name. Repeat the process with all the files you want to include and filter.You can also replace package strings likecom.test.portletswith the user supplied package name using the${package}variable. There are another variables you can use:Variable Meaning ${rootArtifactId}Already explained above, it holds the value entered by the user as the project name (the value that maven ask as the artifactId:in the prompt when the user runs the archetype)${artifactId}If your project is composed by one module, this variable will have the same value as ${rootArtifactId}, but if the project contains several modules, this variable will be replaced by the module name inside every module folder, for example: given a module namedportlet-domaininside a project namedportlet, all the files inside this module folder that are to be filtered will have the value of the variable${artifactId}replaced byportlet-domainwhereas the${rootArtifactId}variable will be replaced byportlet${package}The user provided package for the project, also prompted by maven when the user runs the archetype ${packageInPathFormat}The same value as ${package}variable but replacing'.'with the character'/', e.g:, for the packagecom.foo.barthis variable iscom/foo/bar${groupId}The user supplied groupIdfor the project, prompted by maven when the user runs the archetype${version}The user supplied versionfor the project, prompted by maven when the user runs the archetype
__rootArtifactId__. For example, rename the VAADIN/themes/test-portlet/test-portlet.scss to VAADIN/themes/test-portlet/__rootArtifactId__.scss, so it will be renamed as the user supplied project name with the extension .scss. Again, repeat this process with all those files and/or folders that you want to rename to reflect the user's project name.
Further tweaking
com/your-company/your-application-name?
Wouldn't be even nicer if some of the web.xml values reference your application name instead of the test-portlet inherated from the template?
package in the file set, it will copy the src folder content and paste it under a folder that represents the user provided project package name.
Creating the archetype (again)
cd in the parent archetype and run:
$ mvn install
This will re-generate the target folder and the test-vaadin7-portlet-archetype-1.0.0-SNAPSHOT jar file, if you want to change the archetype project (thus, change the name of the jar name), remember to edit the archetype pom.xml file groupId and artifactId properties.
Test your archetype locally
mvn install line executed in the previous section will generate a file archetype-catalog.xml in your ~/.m2 directory with the following content:
Then, type:
$ mvn archetype:generate
Your newly deployed archetype will be listed as the last one of a list that will appear in your terminal, choose the archetype, fill in the parameters and hit enter, open up your file browser and check that all the generated files accomodates to the supplied parameters.
Uploading your archetype to your local maven proxy
maven-archetype for Packaging. Upload the archetype jar generated in the target folder and click the button "Upload Artifact(s)", after this, the archetype should be available for all the user that have access the the proxy.
Multi-module projects
application-persist subproject, the web application that serves as the application front-end can be in a application-webapp subproject, and so on. All these submodules would be controlled by an Aggregator Project.
The project layout should be in hierarchical form, the parent/aggregator project must contain the module subprojects directories inside it. If you start from a flat layout structure and run mvn archetype:create-from-project, maven will generate the module archetype rosource folders in the directory /src/main/resources, then in the archetype creation (mvn install) it will complain that it can't find the archetype resource files inside the folder /src/main/resources/archetype-resources and will exit the execution with an error message. To solve this problem you have to manually move the module archetype resources to the /src/main/resources/archetype-resources directory or rearrange your project structure to the hierarchical form.
Is usually the case that the project modules are named <project-name>-module-name and reside inside the parent folder named <project-name>. For example, given a project named nextgeo with the modules persist, web-services and web-app, a common project folder names for this modules would be: nextgeo-persist, nextgeo-web-services and nextgeo-web-app all inside the nextgeo folder. To process a project layout such as this, run mvn archetype:create-from-project inside the project parent folder, then rename the subfolders nextgeo-persist, nextgeo-web-services and nextgeo-web-app (inside the src/main/resources/archetype-resources folder) to: __rootArtifactId__-persist, __rootArtifactId__-web-services and __rootArtifactId__-web-app, also in the archetype-metadata.xml you would see that the file-sets are grouped together by a <modules> tag:
Change the base project name (nextgeo) with the variable ${rootArtifactId}, except for the dir attribute that points to a folder name (this must remain equal to the phisycal folder name or maven won't be able to copy/filter the folder and its content), like this:
Everything else in the process stays the same, after you finish editing your files, run mvn install and it should work as well as before, now your user can make an instance of the archetype by running mvn archetype:generate. It the user provides, for example, the project name wumpus (rootArtifactId = wumpus), the generated folders should be: wumpus-persist, wumpus-web-services and wumpus-web-app, all inside the wumpus parent folder.
Summarized process
cdin the project folder.- Run
mvn archetype:create-from-project. cdin the<project-folder>/target/generated-sources/archetype.- Make a copy of the archetype folder (Optional).
- Delete the
targetsubfolder (Optional). - Change the archetype
groupId,artifactId,versionanddescriptionfor your archetype in thepom.xml. - Edit the file
<archetype-folder>/src/main/resources/META-INF/maven/archetype-metadata.xml, add the file-sets you consider neccesary, edit the existing ones, remember that the attributefiltered="true"will filter the files in the file-set replacing variables like${rootArtifactId}with the project name given by the user in the form of theartifactIdthat maven ask him/her during generation (that moment when the users uses your archetype). Also remember thatpackaged="true"will copy the files in the file-set in a destination folder that matches the package given by the user during generation. - Edit the files you want to be specially processed, remember whenever you see the project name (your project name) replace it with the
${rootArtifactId}variable. - Rename those files/folders that you want reflect the user provided project name during generation with
__rootArtifactId__. - If your project is a multi-module project, then rename the modules folders using
__rootArtifactId__inside the name (only if the module folder name contains a reference to the project name), and update thearchetype-metadata.xmlmoduletags accordingly. Remember that${rootArtifactId}will contain the project name whereas${artifactId}will contain the module name. - Run
mvn installfrom the archetype folder. - Test it using
mvn archetype:generate, search for the last entry in the list.

After step 11, you should run mvn archetype:update-local-catalog in folder where your archetype resides. Archetype plugin reads archetype catalogs. Google about it.
ReplyDeleteThanks for the suggestion and sorry for the late reply.
DeleteVery useful article!!!
ReplyDeleteThank you very much!!!
You're welcome, glad it was of help! And sorry for taking so long to answer the comment.
DeleteThank you for this simple and straightforward overview of the archetype creation process.
ReplyDeleteYou're welcome :)
DeleteSorry for the late reply.
+1 Thank you for this tutorial.
ReplyDeleteYou're welcome, glad it helped, sorry for the late reply.
DeleteI have a xml file it's path is src/main/resources/archetype-resources/src/main/resources/sql/myapp/DemoUser.xml.when execute mvn archetype:generate I specify artifactId is foo.bar and package is com.foo.bar(-DartifactId=foo.bar -Dpackage=com.foo.bar) but I want to DemoUser.xml in folder sql/bar/DemoUser.xml, how to implement this? That is replace myapp to bar.
ReplyDeleteWhat about renaming your folder to `src/main/resources/archetype-resources/src/main/resources/sql/__artifactId__/DemoUser.xml` and then specify the artifactId as bar and the groupId as com.foo?
DeleteHope it helps.
Thanks! I resolved it by this way: in `archetype-resources/pom.xml` I resolved app name from artifactId. #set ($artifactId = "${artifactId}")
Delete#set ($index = $artifactId.indexOf('.'))
#set ($index = $index + 1)
#set ($appName = $artifactId.substring($index)). Then in archetype-metadata.xml I add appName property and default value:
${appName}
. It seems you must put velocity syntax in pom.xml, if you put in archetype-metadata.xml it cannot be resolved.
Thanks!
ReplyDeleteSorry for the late reply.
hi I have a question of how to specify a default package value so user do not need specify a package parameter explicitly? please see http://stackoverflow.com/questions/38419903/when-execute-maven-archetype-generate-how-to-specify-a-default-package-value-cor
ReplyDeleteHello , I have a question, what if you want a json file to be filtered? because if you add the lines
ReplyDelete#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
then it will become an invalid json file. Thank you!
why when put the command mvn archetype:generate and then put the number of an archetype give this error:
ReplyDelete[ERROR] ResourceManager : unable to find resource 'archetype-resources/pom.xml' in any resource loader. ????
Hi
ReplyDeleteAm trying to create the new archetype as per your tutorial , but i do not want the .java files to include , in my instance of the module structure created based on the new archetype , can you please help me how to do this
This comment has been removed by the author.
ReplyDeleteHello, I got a question:
ReplyDeleteHow can I control that generate or not a file by a required property?
e.g:
if (prop.use.redis == true) {
generateFile("src/main/resources/redis.xml");
}
else {
System.out.println("do not need generate redis.xml");
}
This comment has been removed by the author.
ReplyDeleteThis is my first time visit to your blog and I am very interested in the articles that you serve. Provide enough knowledge for me. Thank you for sharing useful and don't forget, keep sharing useful info: Visit Office Rental Singapore
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteFrom your discussion I have understood that which will be better for me and which is easy to use. Really, I have liked your brilliant discussion. I will comThis is great helping material for every one visitor. You have done a great responsible person. i want to say thanks owner of this blog.
ReplyDeletePython Online certification training
python Training institute in Chennai
Python training institute in Bangalore
Very interesting to read thanks
ReplyDeleteBest salesforce training in chennai
Very Clear Explanation. Thank you to share this
ReplyDeleteCCNA Course in Chennai
CCNA Training in chennai
I am obliged to you for sharing this piece of information here and updating us with your resourceful guidance. Hope this might benefit many learners. Keep sharing this gainful articles and continue updating for us.
ReplyDeleteoneplus mobile service centre in chennai
oneplus mobile service centre
oneplus service center near me
Your very own commitment to getting the message throughout came to be rather powerful and have consistently enabled employees just like me to arrive at their desired goals.
ReplyDeleteAnd indeed, I’m just always astounded concerning the remarkable things served by you. Some four facts on this page are undeniably the most effective I’ve had.
MATLAB TRAINING IN CHENNAI | Best MATLAB TRAINING Institute IN CHENNAI
EMBEDDED SYSTEMS TRAINING IN CHENNAI |Best EMBEDDED TRAINING Institute IN CHENNAI
MCSA / MCSE TRAINING IN CHENNAI |Best MCSE TRAINING Institute IN CHENNAI
CCNA TRAINING IN CHENNAI | Best CCNA TRAINING Institute IN CHENNAI
ANDROID TRAINING IN CHENNAI |Best ANDROID TRAINING Institute IN CHENNAI
Excellent Blogs,Appreciating for this intense work and keep doing more...Learn Python to get a enormous impact in your life
ReplyDeletepython training in chennai | python training in annanagar | python training in omr | python training in porur | python training in tambaram | python training in velachery
Excellent Blogs,Appreciating for this intense work and keep doing more...Learn Python to get a enormous impact in your life
ReplyDeleteAWS training in Chennai
AWS Online Training in Chennai
AWS training in Bangalore
AWS training in Hyderabad
AWS training in Coimbatore
AWS training
very interesting stuff.thanks for sharing.Angular training in Chennai
ReplyDeleteperde modelleri
ReplyDeletesms onay
MOBİL ÖDEME BOZDURMA
Nft Nasıl Alınır
Ankara Evden Eve Nakliyat
trafik sigortası
dedektör
web sitesi kurma
aşk kitapları
Good content. You write beautiful things.
ReplyDeletemrbahis
vbet
sportsbet
mrbahis
vbet
sportsbet
hacklink
taksi
hacklink
Good text Write good content success. Thank you
ReplyDeletetipobet
kralbet
betpark
kibris bahis siteleri
slot siteleri
poker siteleri
bonus veren siteler
mobil ödeme bahis
salt likit
ReplyDeletesalt likit
dr mood likit
big boss likit
dl likit
dark likit
T7DJ
salt likit
ReplyDeletesalt likit
L8RİM