Skip to content
Print

So Long WTP, Embedded Jetty for Me

5
Nov
2007

As some of you may know, I’ve been doing some work for Teachscape (think Eelco Hillenius) on their Wicket-based application.  It’s been a learning experience for me as much as a working position in that I’ve got to experiment with a lot of technologies and techniques I haven’t tried before.  For example, Teachscape is based on Hibernate and Spring, so I’ve been getting some really in-depth exposure to both technologies (I still dislike them both).  More interesting to me though is the way the application is run in a developer environment. 

It uses Jetty, not Tomcat or Glassfish.  There’s a main class within the application which sets up the Jetty instance, configures it to use the Wicket servlet and starts the server.  This means that running the web application is as simple as “Run As…” -> “Java Application”.  It starts fast, is more responsive than a straight-up Tomcat instance, and best of all, hot code replace works properly in debug mode.  Now having used this approach at Teachscape for some time, I’m starting to really miss it when I jump back to my own, WTP-based Wicket projects.

So after much wrestling with pros and cons, I decided to switch one of my more substantial projects over to using embedded Jetty.  I did this partially for the experience, partially because Jetty makes development so much easier, and partially because it lets me do cool things like package the app up in a single JAR and easily run it from any Java-equipped computer.

Step One: Dependencies

Dependencies are always an issue.  Modern web applications have in excess of 20-30 JAR files which are either packaged into the WAR, or thrown into the app server’s lib/ directory.  Some applications (like the one I was working with) have many more.  As you can imagine, this poses a more-than-minor inconvenience.

WTP makes dependency management (comparatively) easy, since everything is just thrown indiscriminately into the WebContent/WEB-INF/lib/ directory.  Since the JARs just sit there in a centralized spot, deploying is easy, the Eclipse classpath configuration is trivial and I don’t need to work all that hard to upgrade a certain library (such as wicket-1.3-beta3 to beta4). 

Of course, I can keep this approach when I switch to Jetty, but it’s not the cleanest thing to do.  What’s best is to configure the Eclipse classpath to reference the JAR files in their unzipped directories in my system somewhere (preferably through the use of classpath variables).  After all, that’s what I would do for a standard Java project, and with Jetty, a web application is no different from any other Java app.  With this rosy-eyed decision having been made, I deleted the lib/ directory and began reconfiguring the classpath.

Eclipse wasn’t too bad, since I already had half the libraries set as variables to begin with, but the Ant build was another story.  Two hours of typing into a build.properties file and several cups of strong coffee later, I was just about at the end of my rope.  The dependencies were all set, and the project was building, but it was a nightmare.  I can only imagine what’s going to happen if I have a significant influx of libraries and dependencies…

Lesson learned: use Maven.  Actually, don’t use Maven, since it’s just more headache than it’s worth.  What I should have done (had I really thought things through), is take advantage of the now-incubating Apache project, Buildr.  It’s basically a Maven-like build system with scripts based on Ruby and Rake.  Instead of writing an epic-length POM file, you write a 10-20 line buildfile (which is actually a Ruby script with some DSL syntax) and Buildr figures out the rest.  Unfortunately, by the time I bethought myself of this option, I was almost finished with the Ant configuration, and I’m too stubborn to give up half-way through something.

Step Two: The Launcher

The next step in my evil plan was to create a main class somewhere in the project which could configure Jetty and start the server.  Unfortunately, this is a bit harder than it sounds on paper.

The problem is not that Jetty has a tricky API, or any sort of gotchas in its configuration.  The problem is there’s very little useful documentation which shows how to turn the trick.  So, for the record, here’s the source for the main class I wrote:

public class StartApplication {
    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        Context context = new Context(server, "/", Context.SESSIONS);
 
        ServletHolder servletHolder = new ServletHolder(new WicketServlet());
        servletHolder.setInitParameter("applicationClassName",
                "com.myapp.wicket.Application");
        servletHolder.setInitOrder(1);
        context.addServlet(servletHolder, "/*");
 
        server.start();
        server.join();
    }
}

Not really too much there once you see it all laid out for you, but it took me way longer than it should have to figure out that it needed to be done that way.  Executing this class starts a new Jetty instance serving my application at http://localhost:8080.  I can start the app in debug mode, getting proper hot code replace (something WTP never got right) and every debug feature Eclipse offers for Java apps.  To stop the server, all I need to do is hit that cryptically labeled button in the Console view which kill the running application.  Oh, and there’s no need to maintain a web.xml file, Jetty doesn’t need it.

Surprisingly, that’s all that’s different between WTP and embedded Jetty from a code standpoint.  I had expected to have to make significant changes elsewhere in my code base, but that was the extent of my fiddling.  Pretty slick!

Evaluation

Once the Jetty environment was up and running, it was time to decide whether or not it was worth it.  After all, I could always do an svn revert if I really didn’t like the results.

Feature WTP/Tomcat Jetty
Rough startup time 10 sec 2 sec
Page responsiveness Decent (a bit sluggish) Excellent (pages generate insanely fast)
Server errors Cryptic and well formatted Cryptic and ugly
Debugging Passable, no hot code replace Perfect, just as good as Java apps
Ease of setup Very good Harder than it should be
Setup time 10 minutes 3 hours

Overall, I’ll take Jetty any day, but I definitely need to use something like Buildr the next time I do this.  That would have pretty much dropped the setup time from 3 hours down to maybe 30 min (if that).  Oh well, live and learn.

So the moral of the story is that I’m done messing around with Eclipse WTP, trying to beat it into submission and putting up with all its oddities and extreme slowness.  I’m keeping it installed, if only for the HTML editor, but no more will I attempt to use it as a runtime controller.

Comments

  1. In fact if you’d use maven instead of going with your allergy and trying the ‘not in my backyard’ approach, I’d say you would have been ready in about 5, maybe 10 minutes.

    Though buildr does look nice (don’t look surprised when the Wicket build switches to buildr some time in the future), I am not too convinced my dev team is up to speed with ruby on their windows systems.

    Martijn Dashorst Monday, November 5, 2007 at 2:59 am
  2. I hate the way WTP assumes my project is going to be just one neat webapp. It makes it useless for any complicated project with a couple of webapps and configurations in it.
    I don’t understand why you went to all that trouble with your classpath. Why not just throw all your jars into a lib folder in your project?

    Asd Monday, November 5, 2007 at 3:57 am
  3. The main reason to mess with the classpath like that was to avoid the “nice clean” lib/ directory. It’s really bad practice to checkin the dependencies to the repository. So many people do it because it’s easier, but that doesn’t make it a good idea.

    The problem with maven as I see it is it wants to take over the *whole* build system. It’s not as fine-grained as Ant (as far as I can tell), and as such I wouldn’t be able to completely do away with my build.xml file. I’d love to use Maven *just* for managing dependencies, but it seems to make it inordinately hard to do that and still keep a working Ant build (since you still have to manually manage dependencies for the Ant build to work). Maybe I’ll experiment a bit with Buildr, see how things go. I’ve heard it’s got some nice Ant interop, as well as being extremely powerfully procedural (being based on Rake).

    Daniel Spiewak Monday, November 5, 2007 at 6:40 am
  4. I’ve been switching projects to embedded that build in Maven or Buildr (or both). With Buildr I wrote an embed_server method that sets up a :run task, and also :start and :stop tasks that detach to run live servers. (It took me a lot longer than 30 minutes though!) Here is the slightly clunky include I’m using across projects, in case it’s any help: http://databinder.net/wsvn/Databinder/databinder/trunk/tasks/databinder.rake?op=file

    n8han Monday, November 5, 2007 at 8:49 am
  5. Excellent post Daniel, thanks!

    I am using jetty from the maven plugin, to start my war build with maven, from maven, inside jetty. I have not given much thought on writing a main, and simply launch it as an app inside idea. It is a nice idea, which I might try out some time.

    Per Olesen Monday, November 5, 2007 at 12:46 pm
  6. Nice article, I use embedded Jetty too as often as possible and I really like the advantages of running a plain old java app (new acronym anyone? :-) ). About dependency management, I can’t refrain from mentioning Ivy, which is now a subproject of Ant. It can be a very good choice for those who just want dependency management for Ant.

    Xavier Hanin Monday, November 5, 2007 at 2:33 pm
  7. Sorry to deviate a bit from the topic,

    @Daniel Spiewak what is it about check in dependencies into repository that makes it not a good practice?

    Seems easier and more manageable to me. I’m a bit curious about the downside of the practice.

    Fadzlan Tuesday, November 6, 2007 at 6:47 pm
  8. Well, for open source projects with alternatively licensed dependencies, it may be downright prohibitive. However, the more common case is for a commercial project to just throw all of its dependencies into the SVN. Problems I see with it:

    1. Lots (sometimes hundreds of MB) of binary files in your repository. This is especially a problem for CVS, though SVN doesn’t do too well either. Your source code repository is designed for *source code*, not random build artifacts.
    2. Sticking a lone JAR in your repository divorces it from its documentation, and perhaps more importantly, its source code. Auto-complete in most IDEs (such as Eclipse) only works to its fullest potential if you link the JAR to its source code and/or javadoc within the IDE. This is much harder to do if the JAR is sitting all by its lonesome alongside 20 or 30 others.

    The main reason is the binary files in the repository. As I said, CVS really starts croaking if you try to stick binaries into it. While SVN is significantly better suited to such a task, it’s still not a very good solution.

    Oh, all this isn’t even including the fact that developers may already have many (if not all) of the dependencies locally. Irregardless of whether this is the case or not, the libraries-in-the-SVN approach forces developers to download large volumes of data that they might already have.

    Daniel Spiewak Tuesday, November 6, 2007 at 7:52 pm
  9. IMHO your two arguments for not putting jars in source control can be discussed:
    - If you don’t update your dependencies often, #1 isn’t that much a problem
    - if you have a good performing source control with a lot of space, you don’t care about #1
    - if you have good practice you can check in source code and javadoc together with jars, along with the proper configuration for your IDE. It’s even more space in your SCM, but some don’t care or are fine with that. Ok considering how simple it is to setup basic dependency management you often lose more time setting this things up than introducing a dependency management tool, so #2 is still a good argument.

    IMO there is at least one other argument for using a tool for dependency management: the problem of maintenance of transitive dependencies.
    With a flat library directory, you often lose information about why a particular jar is there: is it because you use it directly, or because a library you use need it? Or even maybe because several libraries need it? So if you want to update a dependency which comes with a lot of different dependencies than previously, you may be lost in what you really need to update. OK this can also be documented without using a tool, but it can quickly become tedious.
    And the dependency management tool really shines when you develop your system in modules, each having their own dependencies (maybe developed by separate teams). When you need to integrate all this modules frequently, integrating their dependencies and transitive dependencies is cumbersome. Even with a good documentation, you quickly lose a lot of time, where a tool could really help solve all the related problems more quickly and efficiently.

    Xavier Hanin Wednesday, November 7, 2007 at 12:36 am
  10. 1. I avoid putting dependencies in SCM. But in order to do that, you have to have a good alternative dependencies management process or system. I use maven for that.

    2. I agree that using Embedded Jetty beats the pants off WTP any time of the day. I don’t agree with the commenter who stated that using maven instead would be a better solution (I suspect he was referring to the jetty:run mojo). Eclipse’s debugger is one of its best features, and it’s simply not that easy to run maven-launched processes under it.
    I don’t see it as a Embedded Jetty vs Maven issue. I use Embedded Jetty to debug within the IDE as well as often for production, but I use maven’s jetty:run for build-time testing. Both have their uses…

    Denis Robert Wednesday, December 12, 2007 at 7:45 am
  11. Here is an article where I show how to build from mvn source and run/debug it in eclipse embedded jetty mode:

    http://www.zkoss.org/smalltalks/foodtogo/zkfoodtogo.dsp

    Just setup building with maven and running with maven as standalone executable as per the screenshots in that article. Then you just hit the debug button and it works. All of the dependencies are managed for you.

    In my day job guys at work have even configured JProbe to debug standalone maven+jetty+app based on the approach outlined above. It is just quicker, easier and faster once you have your project pom.xml setup and you know the settings for the stand-alone launch.

    Simon Massey Saturday, December 22, 2007 at 11:18 am
  12. I actually just this afternoon setup a new project from scratch to be debuggable in Eclipse running in embedded Jetty running in Maven. It took about 20 minutes from kick starting the project with:

    mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp

    then I just cut and paste the jetty plug-in section from a working project into the created pom.xml to get “mvn jetty:run” up. Then I configured eclipse to build, run and debug the code as per the ZkFoodToGo article that I mentioned in my last post. It would have taken me 10 minutes but I had forgotten how to add a java source folder correctly to get a HelloWorld servlet into a location that maven would pick it up and run with it. The answer to that one is to right click on the imported eclipse project and create a source folder called src/main/java which will create your new package there.

    Simon Massey Saturday, December 22, 2007 at 11:31 am
  13. Hi,

    This is a great post! I am curious how you solve the problem of resolving css style file references with Jetty/Wicket. For example, in my HTML file I have:

    The ’style/boilerplate/screen.css’ is relative to the “webapp” directory that I currently have outside the jar file location, which is bogus. If I include the style files inside the jar file, how do I tell Wicket/Jetty to find them there?

    Thanks for any insight you can provide.

    Philip

    Philip Johnson Monday, April 21, 2008 at 8:00 pm
  14. http://cwiki.apache.org/WICKET/javascript-and-css-support.html

    Specifically:

    // …
    add(new StyleSheetReference(“pageCSS”, getClass(), “css/page.css”));

    There’s an easier way too, but I can’t remember what it is right now. In any case, this should work just fine. :-)

    Daniel Spiewak Monday, April 21, 2008 at 9:32 pm
  15. Philip,

    If you have maven setup the project as per the mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp mentioned below then run the app with “mvn jetty:run” then jetty will load the webapp resources out of the src folder. Which is to say “mvn install” creates the exploded resources and war under /target but running with jetty:run on either the commandline or inside eclipse as per the link against my name then jetty is running out of the src folder. So you can edit .jsp or .zul files (if you have discovered ZK yet) and jetty picks them up immediately from the src folder which can be the working copy of your code under source control.

    rgds

    Simon

    Simon Massey Tuesday, April 22, 2008 at 3:44 am
  16. Thanks for your post.
    I used it to build my own maven eclipse wtp jetty integration process, I described here : http://www.jroller.com/francoisledroff/entry/quickly_create_run_and_test

    Francois Friday, April 25, 2008 at 9:02 am
  17. Has anyone figured out how to run an embedded server and still use the j2ee module dependencies feature in eclipse wtp? thanks amigos!

    robert mcguinness Wednesday, August 20, 2008 at 10:36 am
  18. I am using jetty server. I want to replace the .jar files but once I restart the service, this new jar file is not getting loaded? Any solution for this?

    Rajesh kumar Tuesday, March 9, 2010 at 3:18 am
  19. I use jetty everyday, I made a jettyRunner, writing a .config file where I put all jars (and classpath folders) I want, it work really fast. My question is that jetty 6 asks for “core-3.1.1.jar”, I put the “runJettyRun” core.jar file and it works BUT, why does it need it? I can’t find this file in maven2 repos… any ideas?

    Alfonso Thursday, March 18, 2010 at 12:14 pm
  20. Thank you so much. Saved me probably days.

    Mle Tuesday, September 14, 2010 at 3:05 pm
  21. This was a good tip. We already had Jetty itself working and integrating Wicket was less than 5 minutes work.

    So far Wicket+Jetty is looking like the holy grail of XML-free Java web development.

    Trejkaz Thursday, January 19, 2012 at 5:32 pm

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*