ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Drew Davidson <d...@eblox.com>
Subject Re: J2EE config/build best practices
Date Fri, 12 Apr 2002 22:14:21 GMT
Dave Smith wrote:

> Can anyone point me to a guide on the best way to layout source and package
> structure for building a J2EE project? Sort of an "Ant in Anger"
> (http://jakarta.apache.org/ant/ant_in_anger.html) for EJBs? I'm struggling
> to find the best place to put things so that it's easy to build and deploy.
> Should each EJB have its own subfolder in the project tree? Where should I
> put library code used by multiple EJBs and that may run outside a managed
> environment? I'm sure there are best practices that answer these questions
> and include sample build files, but I can't find a good guide. I don't want
> the Java Pet Store to serve as the model for my project...

This brings up an interesting point.  Ant is a good tool for doing your builds
but doesn't dictate practice; obviously the correct approach.  Look to Erik
Hatcher and his new book on Ant to provide true insight into this matter.

In the mean time...

It would be nice to have reusable ant "code" in the form of xml files that you
could include.  I've done this (partially) with my code in what I feel is a
rational way to lay things out.  I'm still not completely happy with it, but it
solves certain problems well and allows me to hand-edit my build.xml file
easily by just adding a single target that calls my specific project-type task
with the root of the directory I'm building:

<!-- ognl is a library -->
<target name="ognl">
    <ant target="library">
        <property name="srcdir" value="${workarea.src}/ognl"/>
    </ant>
</target>

<!-- ognl-test is a code that test the ognl library -->
<target name="ognl-test" depends="ognl">
    <ant target="compile-and-copy">
        <property name="srcdir" value="${workarea.src}/ognl/test"/>
    </ant>
</target>

The basis of all of this are several abstract targets that work using
parameters (the srcdir in the previous example) and implicitly assume a
structure to the "srcdir" directory.

For example, a web application would be layed out like the following:

<root>                          # root of my workarea
    lib                         # third-party libraries needed by all projects
(junit, struts, etc.)
    build_lib                   # third-party libraries needed by all projects
for building only (ant tasks, etc.)
    projects                    # top-level projects directory
        mylibrary               # library project that produces a jar file
            java                # source to the library
            meta                # resources to be put in the META-INF
(taglib.tld for example)
            test                # sub-project with testing code
                java            # Java source for test sub-project
        mywebapp                # root of the "mywebapp" web application
project
            java                # Java source that is independant of
presentation
            ui                  # Java source that is presentation-specific to
web application (Struts actions, etc.)
            meta                # web.xml, struts-config.xml, etc. that goes in
META-INF and WEB-INF directories
            global_resources    # .html, .jsp that are copied to the root
            jsp                 # similar to jsp except separate for
organizational purposes
            lib                 # webapp-required jars and zips that are copied
to WEB-INF/lib
            build_lib           # build-time libraries required by this build
but not installed with the web app (ant tasks, etc.)
            properties          # properties files that are used for project
configuration
            test                # test sub-project code for the webapp
(httpunit and cactus tests, junit tests, etc)
                java            # Java source for test sub-project

As you see from above, each project is listed in the build.xml and calls the
target for the type of project that you are building.  The above project is a
library so it calls the "library" target to build the library.  The ognl-test
is just code so it calls "compile-and-copy" to build.

I generally like the idea that the builds will go to a staging area (like
/tmp/builds/<projectname>) before being assembled into a deployable component.

In the case of my webapps and other EJB-based apps I like to have .ejb files
separate from one another and have them assembled at build-time.  I've had
several good replies to use XSLT to merge various .ejb files into one; I'm
working on this portion right now.

Related to the above is the problem with developing and deploying a Struts and
EJB-based application.  The number of files that you have to deal with gets
large quickly; these files are all related conceptually but you are forced to
have one file for things like the EJB deployment descriptor (which requires
that one file contain entity definitions for EJBs that have relations to one
another) and the struts-config.xml.  These files grow huge as your project
grows and they become virtually unmanageable.  Hence I've been trying to get a
way to specify on the relavent pieces that will coexist in the same directory.
For example, a fictional webapp called "mywebapp" from org.foo that has two
EJBs and a struts UI for editing them:

mywebapp
   ejbs            # EJB Java files and partial deployment descriptors
      org
         foo
            image
                Image.java         # Image interface
                ImageBean.java     # ImageBean implementation
                ImageHome.java     # ImageHome interface
                Image.ejb          # <entity> for Image
            user
                User.java          # User interface
                UserBean.java      # UserBean implementation
                UserHome.java      # UserHome interface
                User.ejb           # <entity> for User
                User-Image.ejb     # <relationship> between User and Image
    ui
        org
            foo
                image
                    ImageEditAction.java       # Struts Action that initiates
editing an Image (i.e. from a listing)
                    ImageEdit.jsp              # edit Image info
                    ImageListing.jsp           # lists all images available,
allows for clicking to edit
                    ImageUpdateAction.java     # Struts Action that updates an
Image from an ImageForm
                    ImageForm.java             # Struts ActionForm with Image
info
                    Image-struts-config.xml    # Actions and forms related to
Image
                user
                    UserEditAction.java        # Struts Action that initiates
editing a User (i.e. from a listing)
                    UserEdit.jsp               # edit User info; links to Image

                    UserListing.jsp            # lists all Users available,
allows for clicking to edit
                    UserUpdateAction.java      # Struts Action that updates an
User from an UserForm
                    UserForm.java              # Struts ActionForm with User
info
                    User-struts-config.xml     # Actions and forms related to
User
    global_resources           # global resources
        images                 # context images
            logo.gif           # a logo picture
            Drew.gif           # my picture, which should be included in any
webapp!
            spacer.gif
    jsp                        # global JSP copied into context root of webapp
        index.jsp              # index page
        wrapper.jsp            # page wrapper for all pages on the site
        footer.jsp             # footer for all pages on the site
    meta
        web.xml                # Application deployment descriptor
    properties
        testing.properties     # testing parameters (i.e. database url, login)
        deployment.properties  # deployment parameters

Building the above application would do the following:
    1) compile all code under ejbs and ui into WEB-INF/classes
    2) combine all .ejb files into mywebapp.ejb and put this under WEB-INF (see
note below)
    3) combine all *-struts-config.xml files into struts-config.xml under
WEB-INF
    4) copy all files under jsp to context root (preserving sub-directory
structure)
    5) copy all files under global_resources to context root (preserving
sub-directory structure)
    6) copy web.xml to WEB-INF (see note below)

note: web.xml and ejbs are filtered through properties stored at the top level
"properties" directory.  This allows you to store variant deployment options
and munge your web.xml and ejb files to fit the deployment database
configurations and servlet parameters.

The final webapp would be built to the staging area and result in the following
structure:

/tmp/builds/mywebapp
    images
        logo.gif
        Drew.gif
        spacer.gif
    wrapper.jsp
    footer.jsp
    image
        ImageEdit.jsp
        ImageListing.jsp
    user
        UserListing.jsp
        UserEdit.jsp
    WEB-INF
        classes
            org
                foo
                    image
                        ImageEditAction.class
                        ImageForm.class
                        ImageUpdateAction.class
                    user
                        UserEditAction.class
                        UserForm.class
                        UserUpdateAction.class
        web.xml                     # copied from meta
        struts-config.xml           # combines all *-struts-config.xml files
from source directories
        mywebapp.ejb                # combines all *.ejb files from source
directories

Having your applications organized like this reduces the amount of flailing
around you do trying to find related files.  It also keeps things functionally
structured so that you have model code (EJBs) and UI code (Struts, .jsps)
separate.

Anyway that's just my opinion.  I could be wrong.

- Drew



Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message