开发者

Help setting up a Java build environment

I'm at my wit's end. I'm spending more time working on getting my build to work rather than actually developing software. I'm currently working on large-scale Java web application based on Tomcat 6.

Currently the code-base is about 25k LOC (although that's not quite representative because some of that is autogenerated for web services -- but the take away is that it's big) and I've been working exclusively with eclipse to do everything from debugging, to build path management to building. In the past, eclipse has always been more than enough, but I've never worked on a project this large before.

The first problem I had was when I started adding GWT content. It worked ok, but the build process was a bit hacky: I had to manually compile and then copy the js output into the appropriate directory and debugging was a nightmare (I realize some of those problems are just GWT and the way it works...). Now, the issue I'm running into is attempting to work on the project on a Windows machine (I had been working on a Mac, and will continue to work from a Mac from time to time). Eclipse a开发者_如何学编程dded the Mac OS JVM libraries to the build path which, of course, Windows can't find.

I asked a question about working in two different environments and most of the answers pertained to using a build tool like Ant+Ivy or Maven. I've started investigating Maven and attempting to get my project to use it, but it's just been one headache after another and I haven't even begun to try to actually execute/debug my application in Tomcat through eclipse. The most frustrating part of all of this is it, to me, seems like these build tools are exceptionally complex (and to be fair, incredibly flexible) but, at least initially, make life even more difficult while you try to figure out how to simply compile a Java file.

So all of that to say, does anybody have suggestions for how to simplify this scenario? Dependency management would be nice, but I don't mind hunting down the JARs myself. The biggest thing I need is something that will just get out of my way and let me work on what I'm actually trying to work on, not spend hours debugging my typos in an xml file used by the build system.

Thanks in advance


I agree. You don't need Maven; you don't need Ivy. Start with Ant.

Here's a relatively generic Ant build.xml. Customize it as you wish.

<?xml version="1.0" encoding="UTF-8"?>
<project name="xslt-converter" basedir="." default="package">

    <property name="version" value="1.6"/>
    <property name="haltonfailure" value="no"/>

    <property name="out" value="out"/>

    <property name="production.src" value="src"/>
    <property name="production.lib" value="lib"/>
    <property name="production.resources" value="config"/>
    <property name="production.classes" value="${out}/production/${ant.project.name}"/>

    <property name="test.src" value="test"/>
    <property name="test.lib" value="lib"/>
    <property name="test.resources" value="config"/>
    <property name="test.classes" value="${out}/test/${ant.project.name}"/>

    <property name="exploded" value="out/exploded/${ant.project.name}"/>
    <property name="exploded.classes" value="${exploded}/WEB-INF/classes"/>
    <property name="exploded.lib" value="${exploded}/WEB-INF/lib"/>

    <property name="reports.out" value="${out}/reports"/>
    <property name="junit.out" value="${reports.out}/junit"/>
    <property name="testng.out" value="${reports.out}/testng"/>

    <path id="production.class.path">
        <pathelement location="${production.classes}"/>
        <pathelement location="${production.resources}"/>
        <fileset dir="${production.lib}">
            <include name="**/*.jar"/>
            <exclude name="**/junit*.jar"/>
            <exclude name="**/*test*.jar"/>
        </fileset>
    </path>

    <path id="test.class.path">                            
        <path refid="production.class.path"/>
        <pathelement location="${test.classes}"/>
        <pathelement location="${test.resources}"/>
        <fileset dir="${test.lib}">
            <include name="**/junit*.jar"/>
            <include name="**/*test*.jar"/>
        </fileset>
    </path>

    <path id="testng.class.path">
        <fileset dir="${test.lib}">
            <include name="**/testng*.jar"/>
        </fileset>
    </path>

    <available file="${out}" property="outputExists"/>

    <target name="clean" description="remove all generated artifacts" if="outputExists">
        <delete dir="${out}" includeEmptyDirs="true"/>
        <delete dir="${reports.out}" includeEmptyDirs="true"/>
    </target>

    <target name="create" description="create the output directories" unless="outputExists">
        <mkdir dir="${production.classes}"/>
        <mkdir dir="${test.classes}"/>
        <mkdir dir="${reports.out}"/>
        <mkdir dir="${junit.out}"/>
        <mkdir dir="${testng.out}"/>
        <mkdir dir="${exploded.classes}"/>
        <mkdir dir="${exploded.lib}"/>
    </target>

    <target name="compile" description="compile all .java source files" depends="create">
        <!-- Debug output
                <property name="production.class.path" refid="production.class.path"/>
                <echo message="${production.class.path}"/>
        -->
        <javac srcdir="src" destdir="${out}/production/${ant.project.name}" debug="on" source="${version}">
            <classpath refid="production.class.path"/>
            <include name="**/*.java"/>
            <exclude name="**/*Test.java"/>
        </javac>
        <javac srcdir="${test.src}" destdir="${out}/test/${ant.project.name}" debug="on" source="${version}">
            <classpath refid="test.class.path"/>
            <include name="**/*Test.java"/>
        </javac>
    </target>

    <target name="junit-test" description="run all junit tests" depends="compile">
        <!-- Debug output
                <property name="test.class.path" refid="test.class.path"/>
                <echo message="${test.class.path}"/>
        -->
        <junit printsummary="yes" haltonfailure="${haltonfailure}">
            <classpath refid="test.class.path"/>
            <formatter type="xml"/>
            <batchtest fork="yes" todir="${junit.out}">
                <fileset dir="${test.src}">
                    <include name="**/*Test.java"/>
                </fileset>
            </batchtest>
        </junit>
        <junitreport todir="${junit.out}">
            <fileset dir="${junit.out}">
                <include name="TEST-*.xml"/>
            </fileset>
            <report todir="${junit.out}" format="frames"/>
        </junitreport>
    </target>

    <taskdef resource="testngtasks" classpathref="testng.class.path"/>
    <target name="testng-test" description="run all testng tests" depends="compile">
        <!-- Debug output
                <property name="test.class.path" refid="test.class.path"/>
                <echo message="${test.class.path}"/>
        -->
        <testng classpathref="test.class.path" outputDir="${testng.out}" haltOnFailure="${haltonfailure}" verbose="2" parallel="methods" threadcount="50">
            <classfileset dir="${out}/test/${ant.project.name}" includes="**/*.class"/>
        </testng>
    </target>

    <target name="exploded" description="create exploded deployment" depends="testng-test">
        <copy todir="${exploded.classes}">
            <fileset dir="${production.classes}"/>
        </copy>
        <copy todir="${exploded.lib}">
            <fileset dir="${production.lib}"/>
        </copy>
    </target>

    <target name="package" description="create package file" depends="exploded">
        <jar destfile="${out}/${ant.project.name}.jar" basedir="${production.classes}" includes="**/*.class"/>
    </target>

</project>


while maven may be a bit daunting at first glance, i think it really is a pretty nice tool. yes, it does have it's warts, but all in all i think it's one of the best choices for java. the "thing" you really need to get about maven is that everything is based on convention. if you do everything the conventional maven way, then your maven pom is generally very small and everything "just works". and there is plenty of getting started info out there to show you what the "maven convention" is. (and yes, you usually can do things your own way, but it's usually not worth it unless you are stuck w/ an existing project which would be difficult to re-organize).


There are alternatives to Ant/Ivy or Maven XML that might be worth a gander. They use a real programming language instead of an XML DSL.

  • http://buildr.apache.org/ (Ruby based)
  • http://www.gradle.org/index.php (Groovy based)


One simplification you can use when working solely in Eclipse is to let Eclipse take care of the compilation. A given project can have its own simple Ant script, which packages up whatever is need from bin into a jar.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜