Matt RaibleMatt Raible is a Web Architecture Consultant specializing in open source frameworks.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Comparing Web Frameworks Presentation

Since Kris let the cat out of the bag, I might as well give you the link to my comparing web frameworks presentation (PDF, 280KB). I also created a page on the Equinox site for this presentation and related materials. In addition to the presentation, this page also has links to the various framework implementation demos. Here they are for your convenience:

Kris notes that I would still choose Struts. I think it should be noted that I would only choose it in combination with AppFuse (which generates ActionForms). Same goes for Spring and WebWork. I've added interceptors and convenience methods that simply make developing with these frameworks faster and easier. I would've chosen WebWork for my current project, but I'd like to see better client-side validation. Spring needs better tag libraries.

I think the choice of what framework to use is a very personal thing. I think the "best" framework for one person might be very different for someone else. For me, I typically do short-term projects with clients - get them up and running with an application, and then head off to the next project. It makes sense for me to create applications that use a popular framework like Struts that they can easily find developers to maintain it. However, the one thing I'm starting to find is that as long as I use AppFuse - there's good documentation on how to do things. So I've already written the "how to develop and extend this app" for future developers of a client's application. This will (hopefully) open the door for me to use any web framework that AppFuse supports.

I think WebWork rocks, but it's similar to JSF in that it doesn't come with everything your need. The good news is it's easy to write interceptors, but IMO there's a few that should be part of the framework. After working with Tapestry and JSF, I can see how component-based frameworks will be the wave of the future. I think as you develop more and more components, the code you write becomes less and less. It's funny that this is one of the goals of AppFuse - incorporate a bunch of tips and tricks for various frameworks to make development easier. By adding support for Tapestry and JSF, hopefully AppFuse will someday become a repository of useful components. Documentation is good - code is better.

I'd probably be more enthusiastic about Tapestry and JSF if I knew more about them. I still have a lot to learn. I've bought the books (Tapestry in Action and Core JSF), I just haven't had time to read them. I think after incorporating these frameworks in AppFuse (hopefully this year), I'll get a better feel for them and how they make development faster and more efficient. My major problem with JSF is that it's being written for the tools vendors and not for the developers. Make it easy for everyone, not just folks that want to use their hammer-like IDE to develop webapps. The major problem I have with the JSF Tools is 1) none of them are free and 2) most of them are tied to a proprietary app server.

Posted in Java at Nov 04 2004, 09:50:21 AM MST 22 Comments
Comments:

Matt you are right on when you say choosing a framework is a personal thing. If you like the framework you are working with (and you hopefully know it well too) you will fly with it. However for the inexperieced web developer it does go beyond personal desires because they have no experience to fall back on so presentations like the one you gave is VERY valuable. Keep up the great work Matt!

Posted by Kris Thompson on November 04, 2004 at 12:18 PM MST #

Rafe (rc3.org) really likes Spring, for the fact "I found some instructions online and gave it a shot, and lo and behold, everything just worked. The first time."

Personally, I haven't had a chance to start using it; maybe on the next gig.

Cheers,
Bryan

Posted by Bryan on November 04, 2004 at 12:32 PM MST #

Matt, if you could record your presentation and offer it as an mp3 on your site along with the slides, that would be great. The Hibernate group did that, and I found it very helpful when evaluating it.

Posted by Ted on November 04, 2004 at 05:18 PM MST #

What is Webwork missing that you need?

Posted by Eric Hauser on November 05, 2004 at 08:20 AM MST #

Hey Matt - I was pondering your Spring MVC point: "nice, but are people using it?" I think a far more telling question is, "Are people considering using it for new projects?", or "Are people switching to Spring MVC because they're already familiar with core Spring and can get synergy from a common configuration format?" As we know Spring in general is still a relatively new project, certainly new compared to Struts. The first 1.0 production release was April 04--just about 6 months. It would unlikely for tons of projects to be using Spring MVC in this very short period of time. Or do see job postings for Spring MVC "maintenance" developers. But what about new projects? You're exactly right, though, if it ain't broke, don't fix it (if an organization is already productive with Struts, it likely bodes well to keep using it.) But I'm curious how many starting out organizations, or those with productivity problems, are considering moving to Spring MVC--perhaps because they've standardized on the core Spring Framework for the underpinning of their application architecture, and can get some synergy/cost savings there.

Posted by Keith on November 05, 2004 at 08:37 AM MST #

Matt, Very cool as always. Thanks for posting this now and not making us wait until after ApacheCon. I did find a little snafu in the Struts version of Equinox. http://mraible.kattare.com/equinox-struts. Edit a record and then cancel the edit. The grid is brought back up with no data. None of the other implementations have this problem.

Posted by Jeff Carlson on November 05, 2004 at 12:01 PM MST #

Sorry to bug you about this, but it's distracting to some readers that you misuse "i.e." so frequently in your writing (for example on slide 14 of this presentation, which is otherwise great, by the way). This also shows up a lot in the AppFuse tutorial on your Wiki. A brief explanation is here: http://dictionary.reference.com/help/faq/language/i/ie-eg.html.

Posted by 64.28.86.59 on November 05, 2004 at 03:48 PM MST #

Ted - sounds like a lot of work, I'm gonna have to pass. Sorry.

Eric - WebWork needs some more work on its client-side validation. More most, this is a non-issue, but I've worked with some usability experts that believe it is important. If you do choose to use WW's client-side validation, you can't cancel it (w/o using location.href on a button) and it shows each validation error individually rather than collected in one alert box. I know it's minor - but I had to crack on it <em>someway</em> since I've been bashed by WW guys for being a Struts developer for so many years. ;-)

Keith - good point. I think if Spring MVC was released when Rod first invented it (before Struts I believe), it would be widely used today. Most of the frameworks, except for Spring and JSF, have enjoyed quite a bit of user feedback over the years. I'm actually starting a couple small projects next week - one using WebWork and one using Spring MVC.

Jeff - thanks - I've entered it as a bug.

Anonymous - yeah, I have a problem with that. The copy editor for Spring Live is always changing my i.e.'s to "for example" and "that is" - maybe I should get her to edit this presentation...

Posted by Matt Raible on November 05, 2004 at 04:01 PM MST #

A Very Good Presentation, and a very good one which shows comparison of all the leading frameworks :)

Posted by Muhammad Mansoor on November 05, 2004 at 11:11 PM MST #

why can i see others talking??

Posted by jsf on November 06, 2004 at 08:19 PM MST #

Mike: I would be interested in knowing if anyone has solved the design issues (piece-meal coding) when dynamic javascript is needed and the population data is coming from a database? I use Struts and my own custom tags along with DynaActionForms but things are getting very messy when I need elaborate dynamic javascript that requires managed data in Oracle. The design of my large application was very solid when I started, and I've been migrating legacy systems into this design one client at a time. And also I've added new clients to the same application. Anyhow, the javascript business rule compliance was used because javascript already existed in legacy systems (clients). Here's an article I wrote about this system. My issues are now in the complexity of the jsp pages. http://www.fawcette.com/javapro/2003_11/online/jsp_dwhitehurst_11_18_03/ Let me know your thoughts. Thanks, David Whitehurst aka Piratepete (irc.freenode.net #javapro) David Whitehurst

Posted by David Whitehurst on November 14, 2004 at 07:15 PM MST #

Sorry Matt (Mike)

Posted by David Whitehurst on November 14, 2004 at 07:17 PM MST #

Hi Matt, did not want to join the mailing list, so I will post Equinox-Struts bug here. Add user, say John Doe. Save, it will show the list. Go back, save again. It will add another John Doe to the list. And again, and again.

Now, select one of the Johns, my has ID==36. Delete him. Go back, try delete him once more: "Data Access Failure, Object of class [org.appfuse.model.User] with identifier [36]: not found". Go back using browser Back button, click either Save, Delete or Cancel. You will get the same error. Now go back using "<<Back" link provided on error page, and click any button again: the same error. You are stuck. Just for kicks, reload error page. You will see nasty "Do you want to resend POSTDATA?" window. Click OK and you will get the same error.

Do you want to check out another version of Struts CRUD application? See my Redirect-after-Post sample. Feel free to reload any page, go back or forward (if you use Firefox, do not use prerelease versions, they do not honor "no-store" response header). You can even open the same item in two windows, one for viewing, another for editing, and see how the viewed version is updated when you save edited version.

And by the way, the phrase "JSF does POST for everything" from your comparison is not truthful, I thought the same and I was wrong. I tried redirect directive in the navigation rule, works great, loads success page using GET.

Posted by Michael Jouravlev on January 20, 2005 at 04:55 PM MST #

Hmm, Spring version as bad as Struts, and JSF is much worse. After I added new user, the user list is shown as response to POST. Now refresh the list, get "Do you want to resend POSTDATA?", say "yes", and you get an empty(!) form to create a new user. Enter a new user, submit, get the list, click Back, reload. Again, the "Do you want to resend POSTDATA?" window, but this time the data is kept in the fields. Click Save, get another user.

Select user by ID, delete him, get user list, refresh the list, get "Do you want to resend POSTDATA?", click "yes", and get... an empty new user form! Reload user form, get the user data in the fields. WTF? Or, select user by ID, delete him, get user list, go back, delete the user again and get an empty new user form. Reload user form, get the user data in the fields. Yuck.

Tapestry version blows up on "delete/get list/go back and delete again" with "An exception has occurred. You may continue by restarting the session. org.apache.tapestry.ApplicationRuntimeException Unable to invoke method delete on org.appfuse.web.UserForm$Enhance_18@4764a1[userForm]: Object of class [org.appfuse.model.User] with identifier [41]: not found org.springframework.orm.ObjectRetrievalFailureException Object of class [org.appfuse.model.User] with identifier [41]: not found" and a stacktrace.

Go back from the error and save the user. Now you get a different error: "An exception has occurred. You may continue by restarting the session. org.apache.tapestry.ApplicationRuntimeException Unable to invoke method save on org.appfuse.web.UserForm$Enhance_18@4764a1[userForm]: SQL insert, update or delete failed (row not found); nested exception is net.sf.hibernate.HibernateException: SQL insert, update or delete failed (row not found) org.springframework.orm.hibernate.HibernateSystemException SQL insert, update or delete failed (row not found); nested exception is net.sf.hibernate.HibernateException: SQL insert, update or delete failed (row not found) net.sf.hibernate.HibernateException SQL insert, update or delete failed (row not found)" But Cancel works, what a relief.

Webwork version allowed me to add from the same form again and again, where is this POST interceptor which Jason was talking about? After I performed my "delete/get list/go back and delete again" move, Webwork just hung up on me, or so it seemed. After about a minute Firefox shown me a completely empty screen. When I tried one more time, Tomcat returned with exception: "type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception javax.servlet.ServletException: Servlet execution threw an exception org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:93) com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118) com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52) org.appfuse.web.MessageFilter.doFilter(MessageFilter.java:36) root cause java.lang.OutOfMemoryError note The full stack trace of the root cause is available in the Apache Tomcat/5.0.28 logs." But Cancel worked, whoa.

Posted by Michael Jouravlev on January 20, 2005 at 05:29 PM MST #

Michael - Thanks for the detailed analysis of Equinox. I'm not too concerned about the "Back button, then delete again" problem because you're the first to complain about it. I agree that I should fix it, but I'm also trying to keep Equinox as simple as possible. IMO, most folks won't try this - but programmers will. Patches welcome. ;-)

For the JSF version, I've added a <redirect/> as suggested and it works quite well - thanks! I agree that it's strange that subsequent POSTs cause different behavior.

The OOM issue happens periodically on this server because I'm running so many demos and the box seems to be *very* slow. I'm considering moving it back to my local server as I hardly had any issues when it was hosted here.

Posted by Matt Raible on January 23, 2005 at 11:40 AM MST #

Matt, in the <code>readme.txt</code> to Equinox you wrote that you were inspired to create it while "...looking at the struts-blank and webapp-minimal applications that ship with Struts and Spring, respectively. These "starter" apps were not robust enough for me..." Well, your starter apps do not look robust enough for me. Are you saying that they are ok only because no one tried to use them "incorrectly"?

Posted by Michael Jouravlev on February 16, 2005 at 08:44 PM MST #

Michael - I'm saying that Equinox is more robust than the "starter" apps for Struts and Spring. The Struts/Spring starter apps are not much more than a build file, directory structure and JARs. At least Equinox can be built, tested and deployed.

If Equinox is not robust enough for you (because of your stated bugs) - it's an open source project, so patches are always welcome. ;-)

Posted by Matt Raible on February 22, 2005 at 02:44 PM MST #

I'll try to use MSSQL db instead of HSQL. I modify dataSource in applicationContext as follows.

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <description>Conference Call Web DataSource</description>
    <property name="driverClassName">
      <value>net.sourceforge.jtds.jdbc.Driver</value>
    </property>
    <property name="url">
      <value>jdbc:jtds:sqlserver://PHSQLDEV1:1433/bfstats;TDS=8.0;USER=xxx;PASSWORD=xxx</value>
    </property>
  </bean>

As I add a new User exception below is being thrown.

javax.servlet.ServletException: SQL insert, update or delete failed (row not found); nested exception is net.sf.hibernate.HibernateException: SQL insert, update or delete failed (row not found)

Can you figure where did I go wrong?

Thanks,

Edison

Posted by Edison Ormichigos on March 22, 2005 at 01:29 AM MST #

Edison - you might look at this post. Another user has managed to get Equinox running with SQL Server.

Posted by Matt Raible on March 23, 2005 at 12:21 PM MST #

Matt,

Im using the Spring version not the JSF. The only difference is that I use MSSQL 2000 instead of HSQLDB. As I run UserDAOTest testcase I got this following error.

ERROR - SessionImpl.execute(2400) | Could not synchronize database state with session

org.springframework.orm.hibernate.HibernateSystemException: SQL insert, update or delete failed (row
not found); nested exception is net.sf.hibernate.HibernateException: SQL insert, update or delete failed 
(row not found)

Also, please edit my last post. Remove the username and password please. :)

Posted by Edison Ormichigos on March 28, 2005 at 03:55 AM MST #

Edison - you're probably better off asking these questions on the Equinox mailing list (users@equinox.dev.java.net). Someone else using Equinox might be able to help you there. I'm not quite sure what the issue is - but it sounds like a caching issue, where you see something on your page that doesn't exist in the database.

Posted by Matt Raible on March 28, 2005 at 03:43 PM MST #

Matt, Nice job on the comparison presentation. That was a while ago - have you had a chance to explore JSF further? I think you'll find that it's possible to get the same level of reuse as with Tapestry by implementing your own UI components for Enterprise applications. Throwing exceptions in order to perform redirects just seems plain old wrong. Nigel

Posted by Nigel DeFreitas on April 22, 2005 at 11:07 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed