Return-Path: Delivered-To: apmail-jakarta-tomcat-user-archive@apache.org Received: (qmail 74990 invoked from network); 7 Jan 2003 18:03:28 -0000 Received: from exchange.sun.com (192.18.33.10) by daedalus.apache.org with SMTP; 7 Jan 2003 18:03:28 -0000 Received: (qmail 16341 invoked by uid 97); 7 Jan 2003 18:03:47 -0000 Delivered-To: qmlist-jakarta-archive-tomcat-user@jakarta.apache.org Received: (qmail 16293 invoked by uid 97); 7 Jan 2003 18:03:46 -0000 Mailing-List: contact tomcat-user-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Tomcat Users List" Reply-To: "Tomcat Users List" Delivered-To: mailing list tomcat-user@jakarta.apache.org Received: (qmail 16250 invoked by uid 98); 7 Jan 2003 18:03:46 -0000 X-Antivirus: nagoya (v4218 created Aug 14 2002) Message-ID: <053f01c2b677$4eb16fd0$01000001@Will> From: "Will Hartung" To: "Tomcat Users List" References: <391B37A07F3AA843B445A454C6DB483414F3DA@dimail01.remtec.fi> Subject: Re: How to organize your software in proper version control structure? Date: Tue, 7 Jan 2003 10:05:05 -0800 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.50.4807.1700 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 X-OriginalArrivalTime: 07 Jan 2003 18:00:46.0562 (UTC) FILETIME=[B435DC20:01C2B676] X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N > From: "Timo Riikonen" > Sent: Tuesday, January 07, 2003 3:46 AM > Subject: How to organize your software in proper version control structure? > Hello, > > Here ia a question that may not have only one correct answer, > but I hope you will try to give me your answer still. > > How to organize your software in proper version control structure? There are certainly a gazillion answers, but I'll throw in my 2 cents. One thing to consider is that your end product should simply be a single WAR file, with all of the assorted bits and pieces assembled within. The web.xml file has a lot of flexibility on how the various portions of the WAR are exposed to the client, and this is where most of your high level configurations should go. This also helps eliminate, as you mentioned, the potential conflicts between related, yet distinct, WAR applications on the same server. It also helps maintain container portability, as its the least common denominator of all the webapps (in theory). With this in mind, then the task of creating a client application and tracking it falls into a task of creating and managing the appropriate sub-components and assembling a final, cohesive WAR representing the whole thing. This leads to a configuration where you have a single directory for each client application, and this essentially manages the build and integration process. From the root of this directory is where it would be appropriate to have the client specific build.xml file. When you build your WAR, the build.xml would be tasked with pulling the appropriate core code, classes and beans by simply copying jar files into your WEB-INF/lib directory. If you have common jsps and content, you can copy those as well into their appropriate places. Another thing you can do is have a "shared" content directory between the core and client application. With this shared directory, you have the build.xml copy down the files from the core code area, and then copy over that with the client code. This gives you a crude form of inheritance where you only specialize the appropriate content. For example, in your core directory you might have logo.gif, left-arrow.gif, right-arrow.gif. In your client directory, you only have logo.gif. When copied to their final destination, you end up having the client logo with the stock arrow gifs. Don't do this with Java classes, though, you can use Javas inheritance for that. In the end, what you end up with is several "stand alone" application fragments that can be readily merged and customized for your clients. And certainly, you don't rebuild a WAR for every trivial JSP change during development. You simply make those changes in place. The key though is that everything ends up in this kind of structure. In the end, when you want to build a WAR for you client, you get the appropriate version of the core application tree, get your clients application tree, go into the client directory and then: ant build-war, as it goes through and builds your final app. What's nice about this is it helps keep you core generic code seperated. If you end up building other "generic" modules, they can easily be integrated into the final WAR in the same ways. So, just because a WAR is one big single rooted tree does not mean you really need to have all of your source code organized the same way. Only the final result needs to be in the WAR structure. It's not perfect, but it helps isolate your client specific stuff from your generic stuff. It gives you some ability to continue to develop your generic code while snapshotting your clients if necessary, yet still able to bring them "up to date" later if appropriate. Making custom changes for clients is always a mess for source code. Use your source code controls branching and versioning tools to help keep the pieces together. Regards, Will Hartung (willh@msoft.com) Here's a sample: /CoreClasses -> creates core.jar build.xml /com /company /pkg1 class1.java /pkg2 class2.java /GenericApp build.xml /content x.jsp y.html /images logo.gif left-arrow.gif right-arrow.gif /WEB-INF web.xml /code -- these classes end up in WEB-INF/classes /com /company /GenericAppPkg localClass.java /OptionalFeature build.xml -- builds a webapp with GenericApp and OptionalFeature /content /optionalFeature feature.jsp /images /optionalFeature feature.gif /WEB-INF web.xml -- feature specific bits /code /com /company /OptionalFeaturePkg feature.java /ClientABC build.xml -- builds a webapp with GenericApp, OptionalFeature, and ClientABC /content x.jsp z.jsp /images logo.gif /WEB-INF web.xml - essentially a copy of GenericApps web.xml and edited appropriately to include ClientABC and OptionalFeature /code -- these classes end up in WEB-INF/classes /com /company /ClientABCPkg clientSpecificClass.java Now, you "simply" merge these trees together to build the final webapp. Ending up looking like this: x.jsp -- (from ClientABC) y.html -- (from GenericApp) z.jsp -- (from ClientABC) /optionalFeature feature.jsp /images logo.gif -- (from ClientABC) left-arrow.gif right-arrow.gif /optionalFeature feature.gif /WEB-INF web.xml -- (from ClientABC) /classes /com /company /ClientABCPkg clientSpecificClass.class /GenericAppPkg localClass.class /OptionalFeaturePkg feature.class /lib core.jar -- To unsubscribe, e-mail: For additional commands, e-mail: