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