2008-06-21

Software Dev: Archive: - 0 (Favorite Java Build Process: Ant + Maven Dependency Management) (2007.12)

(This article is still under editing because it's kinda hard to post here this style of docs which is much better to use attachments. Interested guys please leave your comments and contact info, I will send you those attachments.)


Ant + Maven Dependency Management

Ant: http://ant.apache.org/

Release used: 1.7.0

Maven dependency management within Ant: http://maven.apache.org/ant-tasks.html

Release used: 2.0.7

Build script configuration guide:

Common Ant with Maven


Artifactory (Best internal Maven Repository Management tool):

http://www.jfrog.org/sites/artifactory/latest/
Release used: 1.2.5-rc6

Configuration of Artifactory with SQL-Server

How to Deploy Artifact file(s) into Internal Maven Repo under Artifactory


How to Utilize Common Ant With Maven for Easy Ant Build-- To utilize Maven dependency management feature within Ant build process

To take the advantage of Maven dependency library management (focus on your project direct dependencies only, let Maven Dependency Management to manage / download the dependencies of dependencies of dependency for you automatically) without the learning curve and pain of building entire pure Maven build process. And to ease/simplify the ant build script for classpath and get libraries for IDE.
A working copy:




build.xml:


<?xml version="1.0"?>
<project name="rms-core" default="jar" basedir=".">
<property name="common-ant.script.dir" value="../../common-ant" />
<import file="${common-ant.script.dir}/common-maven-in-ant.xml" />

<target name="jar" depends="compile">
<jar destfile="${sjs-artifact}">
<fileset dir="${classes.dir}">
<exclude name="**/test/**" />
</fileset>
</jar>

<antcall target="share-local" />
<!-- This call is important if this target jar is a dependency of your other project components -->
</target>

......

<!--
This post-compile target won't work for you by default.
I list it here just as an example to show that you could do anything in post-??? targets..
-->
<property name="config.dir" value="conf" />
<property name="DEPLOY_TARGET" value="Tomcat" /> <!-- Overwrite it in ant command line -->
<target name="post-compile">
<condition property="DTARGET" value="${DEPLOY_TARGET}" else="default">
<available file="${config.dir}/META-INF/persistence-${DEPLOY_TARGET}.xml" />
</condition>
<echo message="Deploy target is ${DTARGET}" level="info" />
<copy file="${config.dir}/META-INF/persistence-${DTARGET}.xml" tofile="${classes.dir}/META-INF/persistence.xml" overwrite="true" />
</target>
</project>

The most relevant line to this topic is:




<import file="${common-ant.script.dir}/common-maven-in-ant.xml" />


The common-maven-in-ant.xml does the dependency magic.





common-maven-in-ant.xml:


<?xml version="1.0"?>
<project name="Maven-in-Ant"
xmlns:maven="urn:maven-artifact-ant">
<!-- Internal maven repo (artifactory) url property -->
<property name="repo-syscon-url" value="http://build01:8081/artifactory/repo/" />
<!-- IMPORTANT: change this value to your internal repo url, no matter it's artifactory or not. -->

<property name="shared.lib.dir" value="//syscon.ca/repo" />
<path id="maven-ant-tasks.classpath" path="${shared.lib.dir}/maven/maven-ant-tasks-2.0.7.jar" />
<typedef uri="urn:maven-artifact-ant" resource="org/apache/maven/artifact/ant/antlib.xml" classpathref="maven-ant-tasks.classpath" />
<maven:remoteRepository id="repo.syscon.url" url="${repo-syscon-url}" layout="default" />
<maven:pom id="maven.pom" file="${basedir}/pom.xml" />

<property name="shared.build.dir" value="../../BUILD" />
<property name="build.dir" value="${shared.build.dir}/${maven.pom.artifactId}" />
<property name="lib.dir" value="${build.dir}/lib" />
<property name="classes.dir" value="${build.dir}/classes" />
<property name="deploy.dir" value="${build.dir}/deploy" />
<property name="sjs-artifact" value="${deploy.dir}/${maven.pom.artifactId}-${maven.pom.version}.jar" />

<target name="clean">
<delete dir="${build.dir}" />
<antcall target="post-clean" />
</target>
<target name="post-clean" description="Hook into local build for post clean processing." />

<target name="init" depends="clean">
<mkdir dir="${classes.dir}" />
<mkdir dir="${lib.dir}" />
<mkdir dir="${deploy.dir}" />
<antcall target="post-init" />
</target>
<target name="post-init" description="Hook into local build for post init processing." />

<!-- Dependencies definition common to every project build component:
To compile and to add correct CLASSPATH into run-time scripts
-->
<dirname property="common-ant-script.basedir" file="${ant.file.common-maven-in-ant}" />
<target name="dependencies" depends="init">
<copy file="${common-ant-script.basedir}/settings-m2-syscon-common.xml"
   tofile="${shared.build.dir}/.m2/settings.xml">
<filterset>
 <filter token="shared.build.dir" value="${shared.build.dir}"/>
</filterset>
</copy>

<maven:dependencies   pathId="dependency.classpath"
                   filesetId="dependency.fileset"
    settingsFile="${shared.build.dir}/.m2/settings.xml" >
<pom refid="maven.pom" />
<remoteRepository refid="repo.syscon.url" />
</maven:dependencies>
</target>

<!-- This definition includes all the dependencies in pom.xml already.
Overwrite "classpath" definition ONLY when necessary.
NOTE: any target referring to this "classpath" must depend on "dependencies" target
-->
<path id="classpath">
<path refid="dependency.classpath" />
<pathelement path="${classes.dir}"/>
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
<fileset dir="${deploy.dir}">
<include name="**/*.jar"/>
</fileset>
</path>

<target name="get-lib-by-maven" depends="dependencies">
<copy todir="${lib.dir}" flatten="true">
<fileset refid="dependency.fileset" />
</copy>
</target>

<!--
Compiles local src directory to classes directory in shared build.
Then call a target that hooks into your local post compile process.
-->
<property name="src.dir" value="src" />
<target name="compile" depends="init, get-lib-by-maven">
<javac destdir="${classes.dir}" classpathref="classpath">
<src path="${src.dir}" />
</javac>
<antcall target="post-compile" />
</target>
<target name="post-compile" description="Hook into local build for post compile processing." />

<!-- Target for sharing the artifact locally to other project components as dependency -->
<target name="share-local">
<maven:install file="${sjs-artifact}"
   settingsFile="${shared.build.dir}/.m2/settings.xml">
<pom refid="maven.pom"/>
</maven:install>
</target>
</project>

Simple steps to utilize above common scripts:

1. Create a pom.xml file for your project to define your direct dependencies:
Following are key format & elements of a pom. (a working copy pom.xml)
pom.xml

4.0.0
RMS Core Module


syscon.rms
sjs-rms-core
1.0







org.hibernate
hibernate-entitymanager
3.3.1.ga
compile



javax.mail
mail
1.4
compile



junit
junit
4.3.1
test



com.oracle
ojdbc14
10.2.0.2.0
runtime



log4j
log4j
1.2.14
runtime






syscon.common
sjs-common-util
1.0
compile







Note:



  • the pom.xml file
    must be in the same directory as the build.xml file.


  • Additional settings in build.xml if
    your project used sjs internal dependencies such as, a. sjs-common-util
    Make your "post-init" target depends on "compile-common-util".


  • ...



b. sjs-common-action Make your "post-init" target depends on
"compile-common-action".


...


Please refer
to http://maven.apache.org/maven-v4_0_0.xsd
for more details.

2. Run ant
build task as usual. e.g.

ant jar

One extra
benefit is to get library jars easier by one command:

ant get-lib-by-maven



Bottom of Form

Artifactory
use Derby as database by default. Syscon has SQL-Server production
database already and the most important is that the backup machenism is
there
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalready.

Quick two
steps to get it work from original zip file:

1. Replace the
content of repo.xml (inside
webapps\artifactory.war\WEB-INF\lib\artifactory-core-1.2.5-rc6.jar\jcr\repo.xml
inside artifactory-1.2.5-rc6.zip) with the content of attached http://info/download/attachments/7962830/repo.xml.sql-server(note: change all "???" to real password)

2. Include a
SQL-Server JDBC driver file into webapps\artifactory.war\WEB-INF\lib

Following are
related information.

A. Artifactory


A1. JCR API


A2. JCR Implementation


A3. Default DB: Derby

This is the
part to be replaced by SQL-Server.

A4. Switch to SQL-Server



  • Configuring
    Jackrabbit
    use SimpleDbPersistenceManager to replace DerbyPersistenceManager


  • Tricky is all in repo.xml
    ( plus a jdbc driver for sqlserver)

core/src/main/resources/jcr/repo.xml
inside svn source or webapps\artifactory.war\WEB-INF\lib\artifactory-core-1.2.5-rc6.jar\jcr\repo.xml
inside artifactory-1.2.5-rc6.zip or it could be /jcr/repo.xml under WEB-INF/classes or any classpath
preceeding WEB/INF/lib

A5. Issues TBD:



  • How to pass
    variables value into the repo.xml config file? db.server.name,
    db.server.port, db.name, db.user, db.password option 1. Hard code in
    the source code. option 2. Write a script to update at build / deploy
    time.



  • Move Web UI users data to
    sqlserver too? Requires more research effort related to: org.springframework.jdbc.datasource.DriverManagerDataSource



  • The link for deploy is available
    to Reader/Search only user, the permission check is done after the user
    uploaded the jar file and then get error message: Not enough permissions to deploy
    artifact 'org.jfrog:artifactory:zip:1.2.5-rc6'.

B. SQL-SERVER


B1. DB Info:



  • Server: sqlsrv01


  • User: artifactory


  • Database: repo (set owner to
    "artifactory" user so that the db schema could be created
    automatically) (Note: SQL-Server default installation disabled TCP/IP
    protocal, use SQLServer Configuration Manager to enable it.)

B2. JTDS JDBC Driver

C.
Artifactory database switch architect diagram



Bottom of Form


Step 0.
Do a search first to see if the jar is already in Syscon internal repo.

Login as
"search" Username: search Password: password

Click "Search
for Artifacts" in the left side Enter the name of the jar and click the
"Go!" button

Step 1.
Prepare to deploy a 3rd party jar into the repo Pre-condition: the 3rd
party jar file has been downloaded and verified. (e.g. to deploy
'icefaces-1.7.0.DR2.jar' )

Login as
"admin" Username: admin Password: xxxxxxxxx (set by the administrator)

Click "Deploy
an Artifact"

Step 2.
Upload and deploy the pom file (optional if the 3rd party jar has no
dependency itself) (e.g. 'icefaces-1.7.0.DR2.pom') Note: Verify to make
sure: a. the value of "GroupId" is same as defined in the pom. b. the
value of "Packaging" is "pom". c. the checkbox "Use Jar POM/Generate
default POM" is UNCHECKED. Tip: Copy the value of the "GroupId". It will
be used in the next step. Click "Deploy" button.

Step 3.
Upload and deploy the jar file (e.g. 'icefaces-1.7.0.DR2.jar' )

Note&Tip: paste the value of "GroupId" from step 2. Verify and/or
correct the values of "ArtifactId", "Version" to make sure it's proper.
IMPORTANT: Leave the "Use Jar POM/Generate default POM" check-box as is.
Do NOT change it. Click "Deploy" button.

Step 4.
Last but not least, verify the jar is in the repo and the pom is
correct. Click "Browsing" ==> "Repositories Tree" and navigate to the
jar file through package names

Right click on
the pom file and select "View" from the popup menu.

Verify the pom
file content is correct. (the values of "groupId", "artifactId",
"version", etc.. and dependencies reference included.)

没有评论:

发表评论