views:

241

answers:

6

Hi all I'm trying to figure out the optimum way to develop and release a fairly simple web application, and I'm running into several problems. I'll outline the decisions I've made, because somewhere I've clearly gone off the rails.. Hugely grateful for any help!

I have what I think is a fairly simple web application. It contains a couple of jsps that reference a couple of java beans, and the usual static html, js, css and images.

Decision 1) I wanted to have a clear and clean release procedure, such that I could develop on my local machine and then release reliably to a production machine. I therefore made the decision to package the application into a war file (including all the static resources), to minimize the separate bits and pieces I would need to release. So far so good?

Decision 2) I wanted things on my local machine to be as similar as possible to the production environment. So in my html, for example, I may have a reference to a static file such as http://static.foo.com/file . To keep this code working seamlessly on dev and prod, I decided to put static.foo.com in my /etc/hosts when developing locally, so that all the urls work correctly without changing anything.

Decision 3) I decided to use eclipse and maven to give me a best practice environment for administering and building my project.

So I have a nice tight set up now, except that:

Every time I want to change anything in development, like one line in an html file, I have to rebuild the entire project and then wait for tomcat to load the war before I can see if it's what I wanted. So my questions are:

1) Is there a way to connect up eclipse and tomcat so that I don't have to rebuild the war each time? ie tomcat is looking straight at my actual workspace to serve up the static files?

2)I think I'm maybe making things harder by using /etc/hosts to reflect production urls - is there a better way that doesn't involve manually changing over urls (relative urls are fine of course, but where you have many subdomains, say one for static files and one for dynamic, you have to write out the full path, surely?)

3) Is this really best practice?? How do people set things up so that they balance the requirement for an automated, all-encompassing build process on the one hand, and the speed and flexibility to be able to develop javascript and html and css quickly, as quickly as if one just pointed apache at the directory and developed live? What do people find works?

Many thanks!

Edit: Thanks all for your great responses! If I could mark them all right, I would.. This has really helped me out. What I'm hearing is that best practice is to conserve the structure of the webapp in development, and run it in as close an environment to production as possible. Seems like the differences between people are the extent to which people are prepared to hot deploy resources into the servlet container, circumventing the build process for a little extra speed or convenience. That makes sense. Thanks again.

+2  A: 

To answer #1, I would suggest the following:

  1. Spend some time learning maven to build your .war without eclipse. It's not that hard with the proper archetype. See here for more details: http://maven.apache.org/guides/mini/guide-webapp.html
  2. Maven can generate eclipse projects either through mvn eclipse:eclipse or by using the m2 plugin
  3. For deployment to your local machine and to production, use the maven cargo plugin. http://cargo.codehaus.org/Maven2+plugin and http://blank.jasonwhaley.com/2010/03/automated-deployment-with-cargo-drive.html

To answer question #2, there's nothing wrong with modifying your /etc/hosts file to mimic production. Just have a quick script that lets you add/remove those entries and flushes your dns cache. I do exactly that all of the time. (be sure to make your browser clear its cache frequently also through its relevant setting).

To answer question #3) yes this is how you should be doing things. Each build should result in a single deployable artifact that you can deploy to any of your environments in one step. You need to make sure you can do this without your IDE and use the IDE only as a tool to help you during the development phase.

whaley
Thanks Whaley. So I'm clear - are you confirming that even if I want to, say, put a quick alert in a line of javascript, or correct a typo in some text in an html file, I'll need to wait for the war to rebuild and then get deployed (even if automatically) to my development servlet container, and only then I can see the result of my change? If so, that feels very stilted compared to the efficiency of just having something pointed right at the project files. Have I understood correctly, or am I missing something?
Jeremy
That's precisely what I'm suggesting. If your production deployment consists of .war drops, that is what your development deployment should look like too. Java webapps are meant to be bundled and deployed as war's - I find life is always much easier when you don't try to work around that convention.
whaley
+4  A: 

Is there a way to connect up eclipse and tomcat so that I don't have to rebuild the war each time?

1) I think you're relying too much on your IDE. Usually I have an Ant build.xml that has a couple of tasks: one is "build war" the other is "update jsps." Building the war compiles all the code, packages it, deploys it to Tomcat and restarts everything. Updating the jsps doesn't restart the server, it's just a straight copy from my local files to Tomcat's deployed instance. No restart necessary since they're JSPs. Takes about half a second.

where you have many subdomains, say one for static files and one for dynamic, you have to write out the full path, surely?

2) No way, Jose. So you mean any time the server name changes, you have to recompile your code? If you need to support dynamic URLs you might just want to bite the bullet and take a look at a framework to do the heavy lifting for you. I'm partial to Stripes (which supports dynamic URL rewriting out-of-the-box)... there are others.

Matt Brock
Sorry, I wasn't very explicit about the subdomain urls point. What I mean is that if you only have relative urls in your code like href=file.html, then those work equally on dev and prod. But if you have a file f.html located at www.foo.com, whose html references a file f2.html located at STATIC.foo.com, eg href=http://STATIC.foo.com/f2.html , then you can make those urls still work OK in dev and prod by putting entries in your /etc/hosts file like so:127.0.0.1 www.foo.com STATIC.foo.comNow in dev, those urls all resolve to your local machine, which is what you want, WITHOUT changing code.
Jeremy
If you absolutely must specify the full URL, I think your current method is probably best. I would definitely take whaley's advice re:automating that part of the process.
Matt Brock
+3  A: 

This is much like what I have to do at work, although we use ant (for now?). Also, while I use an IDE (or two), I refuse to have one as part of my build process, EVER. Somebody needs to be able to understand and tune your build.

Roboprog
Disclaimer: I would break the "no IDE build" for a toy / throwaway project. But not for something released into a production work environment.
Roboprog
+1  A: 

Others have already answered you, I'll just comment on this (this too long for a comment btw so I make it an answer):

Every time I want to change anything in development, like one line in an html file, I have to rebuild the entire project and then wait for tomcat to load the war before I can see if it's what I wanted.

If you change one line in an html file, there's no need to rebuild the entire project.

Note that I always rebuild the full .war and redeploy my .war but this takes less than two seconds (less than one second to rezip the .war [that's really what a .war is, a zipped file] and less than one second to redeploy it) because:

  • you don't need to recompile your entire project when you simply change one line in an html file

Same when you change one .java file: you can simply recompile that one file and re-war.

I wrote my own Ant build file from scratch (no Maven here) and I've got several targets. I can force a "clean build", that shall re-compile everything but typically I'm simply repackaging and redeploying the .war

You can check it for yourself: build a .war, unzip it in, say, directory dir1, then modify one .html (or one .java/.class file) and build a new .war and unzip that new .war in, say, dir2.

Then compare dir1 and dir2: now fix your build process so that you can create that second .war without needing to recompile everything.

Changing one .html, .java, .jsp, .css, .js / whatever file and redeploying a new .war should be a matter of seconds (less than two seconds if you didn't throw the kitchen sink in your Webapp).

Note that on the very same project, another developer here prefers to "hot deploy" / replace the files directly in the exploded webapp (I prefer to redeploy a .war everytime and because my complete repackage/redeploy takes less than two seconds I'm fine with it that way).

Webinator
oops, forgot to precise: I've got a *really* fast Linux workstation with a sh!tload of memory so things tend to be faster then on my co-worker systems (who're on OS X MacBook Pro, fine machines, but nowhere near as fast as my system) :) But still, everything should be a matter of a few seconds. [btw I've got a MBP too for when I'm on the run: this is not a cheap shot at Apple]
Webinator
+1  A: 

You don't need to reconstruct war file if your project is an Dynamic Web App in Eclipse and configured Tomcat server properly. Follow the below instructions:

1) Check out the below of how to configure tomcat server with eclipse: http://greatwebguy.com/programming/eclipse/make-eclipse-and-tomcat-play-nice-together/

2) Use relative paths for your application but not absolute paths.

3) If you follow the above 2 steps properly then you have a best environment for development.

Phani
A: 

during development, you should configure eclipse and tomcat so that no rebuild/redeloy is required. just modify html/css/jsp etc, save, and refresh browser to see the result.

but before deploying to production site, you should do a clean full build and test it carefully.

domains: they should be in a config file; dev and prod should have different config files.

irreputable