|
HowToCreateMavenArchetypeFromProject
How to Create a Maven Archetype From an Existing Project.
Phase-Support IntroductionMaven archetype provides you the capability to create a new project using ONE maven command. For example, the following Maven command will create a Tellurium JUnit Test project for you. mvn archetype:create -DgroupId=example -DartifactId=myproject -DarchetypeArtifactId=tellurium-junit-archetype -DarchetypeGroupId=tellurium -DarchetypeVersion=1.0-SNAPSHOT \
-DarchetypeRepository=http://kungfuters.org/nexus/content/repositories/snapshotsIf you check the created the project, you will see the new project includes all the code skeleton you need to write Tellurium tests. [jfang@localhost myproject]$ tree .
.
|-- README
|-- TelluriumConfig.groovy
|-- pom.xml
`-- src
|-- main
| |-- groovy
| `-- resources
`-- test
|-- groovy
| |-- module
| | `-- GoogleSearchModule.groovy
| `-- test
| `-- GoogleSearchTestCase.java
`-- resources
9 directories, 5 filesHow to Create a Maven Archetype From an Existing ProjectYou can create a Maven archetype from scratch, for example, Tellurium Maven Archetypes are created in this way. But in some cases, your project may be pretty complicated and you want to create the Maven archetype from a template project. Here, we use the app-template project project, which is a Spring project with iBatis, as a template to create a Maven archetype for it. Skeletonize the Template ProjectMake a copy of the app-template project project and remove all unnecessary code. Usually, Maven archetype will include some sample code for you to follow. Hence, I create a sample app "hello", which includes an entry in the job registry, processor, coordinator, and down to DAO as well as all the XML wiring files. In this way, users can simply follow the sample code to create new business functions. Create the Maven ArchetypeAfter cleanup code in the template project, run the following Maven command to create a Maven archetype [jfang@localhost app-templateproject]$ mvn archetype:create-from-project [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] org.apache.maven.plugins: checking for updates from mycompany-thirdparty-repo [INFO] ------------------------------------------------------------------------ [INFO] Building app Server [INFO] task-segment: [archetype:create-from-project] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] Preparing archetype:create-from-project [INFO] ------------------------------------------------------------------------ [INFO] Building app Server for Security Check [INFO] ------------------------------------------------------------------------ [INFO] No goals needed for project - skipping [INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'. [INFO] Setting property: velocimacro.messages.on => 'false'. [INFO] Setting property: resource.loader => 'classpath'. [INFO] Setting property: resource.manager.logwhenfound => 'false'. [INFO] [archetype:create-from-project] [INFO] Setting default groupId: mycompany.app.web [INFO] Setting default artifactId: app-templateproject [INFO] Setting default version: 1.0.0.0 [INFO] Setting default package: com.mycompany.app [INFO] Archetype created in target/generated-sources/archetype [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6 seconds [INFO] Finished at: Mon May 18 10:27:51 GMT-05:00 2009 [INFO] Final Memory: 19M/315M [INFO] ----------------------------------------------------------------- As shown in the above message, the generated archetype code stays under target/generated-sources/archetype. You may like to create a new project and copy all files under target/generated-sources/archetype to the new project. Take a look at the code structure [jfang@localhost app-server-archetype]$ tree . . |-- pom.xml |-- src | `-- main | `-- resources | |-- META-INF | | `-- maven | | |-- archetype-metadata.xml | | `-- archetype.xml | `-- archetype-resources | |-- WebContent | | |-- META-INF | | | `-- MANIFEST.MF | | |-- WEB-INF | | | |-- jax-ws-catalog.xml | | | |-- sun-jaxws.xml | | | `-- web.xml | | `-- index.jsp | |-- archetype-resources.iml | |-- pom.xml | `-- src | |-- main | | |-- java | | | `-- com | | | `-- mycompany | | | `-- app | | | |-- converter | | | | |-- iface | | | | `-- impl | | | | `-- spring | | | |-- data | | | | |-- coordinator | | | | | |-- iface | | | | | | `-- hello | | | | | | `-- HelloCoordinator.java | | | | | `-- impl | | | | | `-- spring | | | | | `-- hello | | | | | `-- HelloCoordinatorImpl.java | | | | `-- dao | | | | |-- iface | | | | | `-- hello | | | | | `-- HelloDAO.java | | | | `-- impl | | | | `-- spring | | | | `-- ibatis | | | | `-- hello | | | | `-- HelloDAOImpl.java | | | |-- job | | | | `-- impl | | | | `-- spring | | | | `-- HelloappJobImpl.java | | | `-- processor | | | |-- iface | | | | `-- hello | | | | `-- HelloProcessor.java | | | `-- impl | | | `-- spring | | | `-- hello | | | `-- HelloProcessorImpl.java | | `-- resources | | |-- com | | | `-- mycompany | | | `-- app | | | `-- config | | | |-- data | | | | `-- fsom | | | | `-- FsoMapConfig.xml | | | |-- messages | | | |-- persistence | | | | `-- ibatis | | | | |-- SqlHello.xml | | | | `-- SqlMapConfig.xml | | | `-- wiring | | | |-- __artifactId__.xml | | | |-- connector | | | | `-- connector.xml | | | |-- converter | | | | `-- converter.xml | | | |-- coordinator | | | | |-- coordinator.xml | | | | `-- hello-coordinator.xml | | | |-- web_app_server.properties | | | |-- job | | | | |-- hello-job.xml | | | | `-- job.xml | | | |-- persistence | | | | |-- datasource.xml | | | | |-- hello-dao.xml | | | | `-- persistence.xml | | | |-- processor | | | | |-- hello-processor.xml | | | | `-- processor.xml | | | `-- server | | | `-- app-job-registry.xml | | `-- log4j.xml | `-- test | |-- java | | `-- com | | `-- mycompany | | `-- app | | |-- config | | | `-- wiring | | | `-- Wiring_FuncTest.java | | |-- data | | | `-- dao | | | `-- impl | | | `-- spring | | | `-- ibatis | | | `-- hello | | | `-- HelloDAOImpl_DataTest.java | | |-- job | | | `-- impl | | | `-- spring | | | `-- HelloappJobImpl_DataTest.java | | `-- processor | | `-- impl | | `-- spring | | `-- hello | | `-- HelloProcessorImpl_FuncTest.java | `-- resources | `-- com | `-- mycompany | `-- app | |-- config | | `-- wiring | | |-- Wiring_FuncTest.xml | | `-- test-__artifactId__.xml | |-- data | | `-- dao | | `-- impl | | `-- spring | | `-- ibatis | | `-- hello | | `-- HelloDAOImpl_DataTest.xml | |-- job | | `-- impl | | `-- spring | | `-- HelloappJobImpl_DataTest.xml | `-- processor | `-- impl | `-- spring | `-- hello | `-- HelloProcessorImpl_FuncTest.xml As you can see, all templates for the new project are under src/main/resources/archetype-resources/. There are two files you need to pay attention to. archetype.xmlThis file lists all source, test source, resource, and test resource you want to include in the new project. <?xml version="1.0" encoding="UTF-8"?><archetype>
<id>web-app-server</id>
<sources>
<source>src/main/java/com/mycompany/app/processor/iface/hello/HelloProcessor.java</source>
<source>src/main/java/com/mycompany/app/processor/impl/spring/hello/HelloProcessorImpl.java</source>
<source>src/main/java/com/mycompany/app/job/impl/spring/HelloappJobImpl.java</source>
<source>src/main/java/com/mycompany/app/data/coordinator/iface/hello/HelloCoordinator.java</source>
<source>src/main/java/com/mycompany/app/data/coordinator/impl/spring/hello/HelloCoordinatorImpl.java</source>
<source>src/main/java/com/mycompany/app/data/dao/iface/hello/HelloDAO.java</source>
<source>src/main/java/com/mycompany/app/data/dao/impl/spring/ibatis/hello/HelloDAOImpl.java</source>
</sources>
<testSources>
<source>src/test/java/com/mycompany/app/config/wiring/Wiring_FuncTest.java</source>
<source>src/test/java/com/mycompany/app/processor/impl/spring/hello/HelloProcessorImpl_FuncTest.java</source>
<source>src/test/java/com/mycompany/app/job/impl/spring/HelloappJobImpl_DataTest.java</source>
<source>src/test/java/com/mycompany/app/data/dao/impl/spring/ibatis/hello/HelloDAOImpl_DataTest.java</source>
</testSources>
<resources>
<resource>src/main/resources/log4j.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/messages</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/processor/hello-processor.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/processor/processor.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/converter/converter.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/server/app-job-registry.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/job/hello-job.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/job/job.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/__artifactId__.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/coordinator/hello-coordinator.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/coordinator/coordinator.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/connector/connector.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/persistence/persistence.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/persistence/datasource.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/persistence/hello-dao.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/wiring/web_app_server.properties</resource>
<resource>src/main/resources/com/mycompany/app/config/data/fsom/FsoMapConfig.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/persistence/ibatis/SqlHello.xml</resource>
<resource>src/main/resources/com/mycompany/app/config/persistence/ibatis/SqlMapConfig.xml</resource>
<resource>WebContent/META-INF/MANIFEST.MF</resource>
<resource>WebContent/WEB-INF/jax-ws-catalog.xml</resource>
<resource>WebContent/WEB-INF/sun-jaxws.xml</resource>
<resource>WebContent/WEB-INF/web.xml</resource>
<resource>WebContent/index.jsp</resource>
</resources>
<testResources>
<resource>src/test/resources/com/mycompany/app/config/wiring/test-__artifactId__.xml</resource>
<resource>src/test/resources/com/mycompany/app/config/wiring/Wiring_FuncTest.xml</resource>
<resource>src/test/resources/com/mycompany/app/processor/impl/spring/hello/HelloProcessorImpl_FuncTest.xml</resource>
<resource>src/test/resources/com/mycompany/app/job/impl/spring/HelloJobImpl_DataTest.xml</resource>
<resource>src/test/resources/com/mycompany/app/data/dao/impl/spring/ibatis/hello/HelloDAOImpl_DataTest.xml</resource>
</testResources>
</archetype>Sometimes, you may want a file name matching your new project name. The trick is the portion __artifactId__ in a filename will be replaced with the artifactId you specify when create a new project from this Maven archetype, as a result you can achieve your goal to include __artifactId__ as part of your file name. For example, the file src/test/resources/com/mycompany/app/config/wiring/test-__artifactId__.xml will be replaced with src/test/resources/com/mycompany/app/config/wiring/test-app-new.xml if we specify the artifactId as app-new. archetype-metadata.xmlThis file is used to control how to process the template files. Maven archetype plugin uses velocity as a template engine to process the template files. For example, the Wiring_FuncTest.xml is shown as follows, #set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
<import resource="classpath:/com/mycompany/app/config/wiring/${artifactId}.xml" />
</beans>The ${artifactId} will be replaced with the artifactId you specify when you create a new project. The archetype-metadata.xml file specifies the filter rules for different file sets. <?xml version="1.0" encoding="UTF-8"?><archetype-descriptor name="app-server">
<fileSets>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</fileSet>
<fileSet filtered="false" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/test/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/test/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>WebContent</directory>
<includes>
<include>**/*.jsp</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>WebContent/WEB-INF</directory>
<includes>
<include>**/*.xml</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>WebContent/META-INF</directory>
<includes>
<include>**/*.MF</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>The filtered option controls whether to process the file set and another option packaged determines whether to change your project package name. For a company project, most likely you do not want to change the package name. As a result, you may need to removed all the packaged options. After all this, you have to cleanup the code and replace ${package} in the template files with your fixed package name. Test the Maven ArchetypeSince the sample project code includes velocity templates, you cannot test directly in the Maven archetype project. You need to install the Maven archetype to your local repository and create a new project from it to test your code. To install the Maven archetype to your local repository, run mvn clean install To create a new project from the installed Maven archetype, you can use the following Maven command, [jfang@localhost archetype]$ mvn archetype:generate -DarchetypeCatalog=local [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Default Project [INFO] task-segment: [archetype:generate] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] Preparing archetype:generate [INFO] No goals needed for project - skipping [INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'. [INFO] Setting property: velocimacro.messages.on => 'false'. [INFO] Setting property: resource.loader => 'classpath'. [INFO] Setting property: resource.manager.logwhenfound => 'false'. [INFO] [archetype:generate] [INFO] Generating project in Interactive mode [INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0) Choose archetype: 1: local -> app-server-archetype (app-server-archetype) Choose a number: (1): 1 Define value for groupId: : mycompany.app Define value for artifactId: : app-warranty Define value for version: 1.0-SNAPSHOT: : Define value for package: mycompany.app: : Confirm properties configuration: groupId: mycompany.app artifactId: app-new version: 1.0-SNAPSHOT package: mycompany.app Y: : Y [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 19 seconds [INFO] Finished at: Wed May 20 10:22:33 GMT-05:00 2009 [INFO] Final Memory: 14M/325M [INFO] ------------------------------------------------------------------------ Look at what we got for the new app-new project [jfang@localhost app-new]$ tree .
.
|-- WebContent
| |-- META-INF
| | `-- MANIFEST.MF
| |-- WEB-INF
| | |-- jax-ws-catalog.xml
| | |-- sun-jaxws.xml
| | `-- web.xml
| `-- index.jsp
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | |-- data
| | | |-- coordinator
| | | | |-- iface
| | | | | `-- hello
| | | | | `-- HelloCoordinator.java
| | | | `-- impl
| | | | `-- spring
| | | | `-- hello
| | | | `-- HelloCoordinatorImpl.java
| | | `-- dao
| | | |-- iface
| | | | `-- hello
| | | | `-- HelloDAO.java
| | | `-- impl
| | | `-- spring
| | | `-- ibatis
| | | `-- hello
| | | `-- HelloDAOImpl.java
| | |-- job
| | | `-- impl
| | | `-- spring
| | | `-- HelloappJobImpl.java
| | `-- processor
| | |-- iface
| | | `-- hello
| | | `-- HelloProcessor.java
| | `-- impl
| | `-- spring
| | `-- hello
| | `-- HelloProcessorImpl.java
| `-- resources
| |-- com
| | `-- mycompany
| | `-- app
| | `-- config
| | |-- data
| | | `-- fsom
| | | `-- FsoMapConfig.xml
| | |-- messages
| | |-- persistence
| | | `-- ibatis
| | | |-- SqlHello.xml
| | | `-- SqlMapConfig.xml
| | `-- wiring
| | |-- app-new.xml
| | |-- connector
| | | `-- connector.xml
| | |-- converter
| | | `-- converter.xml
| | |-- coordinator
| | | |-- coordinator.xml
| | | `-- hello-coordinator.xml
| | |-- web_app_server.properties
| | |-- job
| | | |-- hello-job.xml
| | | `-- job.xml
| | |-- persistence
| | | |-- datasource.xml
| | | |-- hello-dao.xml
| | | `-- persistence.xml
| | |-- processor
| | | |-- hello-processor.xml
| | | `-- processor.xml
| | `-- server
| | `-- app-job-registry.xml
| `-- log4j.xml
`-- test
|-- java
| `-- com
| `-- mycompany
| `-- app
| |-- config
| | `-- wiring
| | `-- Wiring_FuncTest.java
| |-- data
| | `-- dao
| | `-- impl
| | `-- spring
| | `-- ibatis
| | `-- hello
| | `-- HelloDAOImpl_DataTest.java
| |-- job
| | `-- impl
| | `-- spring
| | `-- HelloappJobImpl_DataTest.java
| `-- processor
| `-- impl
| `-- spring
| `-- hello
| `-- HelloProcessorImpl_FuncTest.java
`-- resources
`-- com
`-- mycompany
`-- app
|-- config
| `-- wiring
| |-- Wiring_FuncTest.xml
| `-- test-app-new.xml
|-- data
| `-- dao
| `-- impl
| `-- spring
| `-- ibatis
| `-- hello
| `-- HelloDAOImpl_DataTest.xml
|-- job
| `-- impl
| `-- spring
| `-- HelloappJobImpl_DataTest.xml
`-- processor
`-- impl
`-- spring
`-- hello
`-- HelloProcessorImpl_FuncTest.xml
91 directories, 59 filesThe new project includes everything you need for a Spring web application. You can load this project up to an IDE, or run the tests using Maven directly, mvn test Deploy the Maven ArchetypeRun the following maven command to deploy the artifacts. mvn clean install deploy How to Use the Maven ArchetypeOnce the app server Maven archetype is deployed to either your local repository or a public repository, you can run the following Maven command to create a new project mvn archetype:generate -DarchetypeGroupId=mycompany.app.web -DarchetypeArtifactId=app-server-archetype -DarchetypeVersion=1.0.0.0 \ -DgroupId=mycompany.app.web -Dpackage=mycompany.app -DartifactId=Your_project_name -Dversion=Your_project_version For example, the following command will create a new project "app-new", mvn archetype:generate -DarchetypeGroupId=mycompany.app.web -DarchetypeArtifactId=app-server-archetype -DarchetypeVersion=1.0.0.0 \
-DgroupId=mycompany.app.web -Dpackage=mycompany.app -DartifactId=app-new -Dversion=1.0-SNAPSHOTBe aware that you need to specify the package to be "mycompany.app" to keep the package name consistent with the template project and DO NOT use the following Maven command to create a new project mvn archetype:create The reason is that the "archetype:create" command cannot replace __artifactId__ in filenames. After the new project is created, go to the project directory and run tests to check if everything is fine. mvn test Resources |