... and I can have that man executed for treason.
I can't remember where this quote comes from, but the gist is that if you set out to prove someone guilty, and your system has no proper checks and balances (fifth amendment, habeas corpus, etc.) then it's quite easy. We saw this happen with the Starr investigation of Clinton: every roadblock that indicated a lack of wrongdoing was interpreted as an ever greater conspiracy and ever greater guilt.
Remember that amenesty international was started around a case of two men simply toasting "to freedom"; they were imprisoned for treason.
Yes, that's what I got out of this too, that CC is looking for emergent behavior, and expecting the player to "fill in the gaps" between all those Verbs and Reactions and generate a real story in their head.
However, at some level, I'm pretty dubious. A tool such as Inform 7 (or TADs, or the other heavy hitters) makes it reasonable to build a narrative that feels spontaneous even if it is not. My gut reaction is that Storytron will have a cursory kind of believability, but when you pressure it a little, it that suspension of disbelief will break down.
By contrast, when I show people what can be done in just a couple of minutes using Inform (and the Inform library, which models the "player world" quite nicely), people immediately think its doing much, much more than it really is, or that I code more than I really do. People want to see storys, which is good for Storyworld, but I think better for Inform.
I make 100% of my income off two open source projects: Tapestry and HiveMind. Apache owns the copyright, but the license is free (ASL 2.0). I make my living doing training and project work. This has paid my bills for over two years now.
It's not for the faint hearted; my job window is always just a couple of months out but doesn't seem to be drying up either. And you need to be a triple threat: able to code, and to teach and mentor... and to market! There's no way to tell if you can pull this off without trying.
Even so, my wife has to work (mostly to get health insurance for us).
I love the freedom, especially from PHBs... but there are also occasions where I feel trapped by my choice. I'll need to come up with something else, someday, but in the meantime I'm loving life. You mileage may vary.
If you assume that all Tapestry is doing is routing requests and outputting HTML, you are missing the forrest for the trees. To be honest, I think most web application development is primarily about state management (transient state used for one request, persistent state used across requests, stored on the server or on the client). These are more areas where developers are used to slaving away, but a real framework is quite capable of handling it, and handling it better than the developer can (at a certain scale of complexity). So, as long as you are happy to try and manage everything in terms of HttpServletRequest and HttpSession attributes, and endless code to pick apart query parameters, and a bunch of other limitations, you can get by with something simple. I tend to think of Tapestry, not as more complex, but as more complete.
Second, there is an inherent and invalid assumption in your statement that Tapestry is not scalable, when in fact, it is very scalable not just in terms of concurrent users, but scalable in many dimensions: scalable in terms of number of pages, of number (and type) of developers, in the complexity of pages. What's important is that as your application does grow more complicated, your approach never has to change... in effect, Tapestry is built for the worst case: highly dynamic pages, complex forms, multiple forms per page, complex client-side JavaScript, etc. A major portion of what Tapestry does is fundamentally about naming things, particularily form control element ids, and JavaScript functions and fields, to avoid naming conflicts. But even in terms of basic scalability, Tapestry uses a pooling mechanism around its page objects to support effecient, concurrent access by restricting non-threadsafe objects (the pages) to individual requests (and, thus, individual threads).
So, what you get is an object oriented programming model (hey! look! objects with methods and properties!) in a highly multithreaded environment without having any concerns about multiple threads. The pooling and typesafety is baked into the framework, not the code you write. Further, you get to build a servlet application without ever seeing the servlet API (unless you really want to).
So, yes, there's a lot of moving parts in Tapestry, but they are all there for a purpose. I personally find Tapestry useful even for a single-page application... and I wouldn't want to use anything else when I'm working on an application with dozens or hundreds (even thousands) of pages and components.
Just different. People trying to find Struts++ get confused because Tapestry is a completely different beast.
2. Does not support unit testing.
Wrong. This was doeable in 3.0 with an add-on; an improved version of the add-on is part of Tapestry 4.0.
3. The "Model" component of MVC is closely tight to "View"; you cannot have many views of the same page (for instance: web page, web page for printing, WAP page).
Ultimately, your model is really DTO, not your page or component class. Tapestry components don't care where data comes from, thanks to OGNL. So, there's no reason you can't have multiple pages for different formats. However, Tapestry does not address the myth of one page / multiple views. A desktop HTML application and a WAP application are completely different beasts and should be treated as such. You should not be coding applications inside a big case statement.
4. Adding your own JavaScripts suxx. You have to map component names etc.
Because HTML output is componentized, JavaScript generation for that HTML must be
componentized. This is an annoyance for simple cases, but means that complex cases just work. You can have as many DatePickers or Palettes or validating fields and forms per page as you like and it all just works with everything wired together properly, and all client-side elements (JavaScript variables and function names) generated free of naming collisions. Tapestry was born to do Ajax.
5. If you want to validate form field, you have to use special components (ValidField). Some components do not have their validated counterparts. Client-side validation is very basic (e.g. cannot check if entered date is in the future).
You haven't looked at Tapestry 4.0. Paul Ferarro did a complete rewrite of the validation subsystem to make it more powerful and more flexible; all the form control components now support input validation, ValidField has been deprecated.
6. Changing one line of code/template requires you to redeploy whole application; that is, pack it into.war archive, send to web server, perform refresh. When used with Apache Tomcat, leads to memory leaks.
So you're blaming Tapestry for your bad development model? I deploy into Tomcat, but do all my development inside my IDE using Jetty. No redeploy, and I can bounce the Jetty instance in a few seconds.
7. The page pool model is said to scale well, but can be very error-prone. For instance: if you forget to reset some variable, it can be displayed by some other user when he happens to pull it from the page pool.
This I find an amazing observation; Even Tapestry 3.0 supports transient and persistent properties for you... meaning you write an abstract class and let Tapestry provide the code to implement the property along with the compliance code to work well with the page pool. Management of transient and persistent page state is an application concern that you should be delegating to Tapestry. Just define abstract getters and/or setters, rather than instance variables (and getters and setters). Tapestry writes the code for you (at runtime).
If the Simple container is a valid Servlet container, then Tapestry will work fine within it. Tapestry's footprint is rather large, however. About 2 MB for the framework and its dependencies. That may compromise its use for embedded.
Although I freely being influenced as a user of WebObjects back in the day (circa 1998 and 1999), that's about as far as the lineage goes. I certainly built Tapestry with a different set of expectations and compromises than WebObjects, and that has evolved further of the years.
However, I will stand by declaring myself "the original author of Tapestry". That clearly describes Tapestry design and implementation; the flavor might inlcude a little WebObjects spice, but the meat is pure Java + Servlets + Howard Lewis Ship's insights and contributions (and mistakes).
Now look what you made me do... refer to myself in the third person!
Rails has a lot going for it, and the entire Ruby concept of focusing on code has influenced many frameworks, including Tapestry. Tapestry uses abstract properties combined with annotations (or auxillary XML files) to do the kind of meta programming that is done using class methods in Ruby, but nonetheless.
In terms of dependencies, being an Apache project causes some distribution problems w.r.t depenencies, especially when you use non-Apache projects like OGNL and Javassist. The next major release of Tapestry will build using Maven, which will make nearly all of part 1 of this article irrelevant (or at least, standard). I'm looking forward to part 2 myself, which should identify why Tapestry is so special.
Finally, within the Java community, Tapestry is fairly well known, though a regrettably small percentage have used it. The majority of the targetted readers of this article would have objected to wasting too much space describing Tapestry and its goals, just as others in this thread have objected to the lack of that introductory material. You can't please everyone (exception on Slashdot, where you can't please anyone).
As the original author of Tapestry (but not the article on DeveloperWorks, which caught me by surprise) I can say that IBM doesn't have any secret agenda on this. In fact, given that IBM is selling a commercial product that competes head-to-head with Tapestry (their JavaServer Faces, built on top of their WebSphere proprietary Eclipse IDE) it is enlightened of them to cover Tapestry.
Of course, what's going on there is two fold. First, IBM is big enough that different areas of the organization will have different and occasionally competing goals. Primarily, all on-line magazines are constantly hunting for new material to keep the eyeballs looking (and the click rates clicking). IBM doesn't solicit authors to write on particular subjects, they accept existing authors efforts, with the authors pursuing their own interests. Here, Brett happened to be into Tapestry and did a great job providing additional documentation in the form of this article.
I make my living off of Tapestry, so I'm happy to see this kind of coverage, but the framework itself is open source and free, with a very, very liberal license (ASL 2.0). I make money by providing Tapestry support and training. There's your ad.
Objective-C was my first object-oriented language (this was back in 93 - 95). I loved the syntax and the integrated vision of the tools and frameworks... but I hated memory management. The whole retain/release/autorelease thing was always a bug waiting to happen, and I spent many wasted hours tracking those down (basically, retain/release works great for trees but flops around like a dying fish for graphs).
Anyway, I simply can't go back to a non-memory managed environment again.
I have seen that, as I've matured as an OO developer, and as I've distanced myself from Objective-C, my style has changed. The Objective-C libraries are heavily based on inheritance, but I've learned that "composition trumps inheritance"... meaning that its better to combine many small focused objects. In Objective-C, you have a layer-cake approach, where each layer of inheritance mixes in a particular concern. This makes sense when you want to minimize the number of objects allocated, but in a GC language (Java, Ruby, etc.) you end up with better, more testable code when you let the GC do its thing.
You can see this in Tapestry, where currently (through the 4.0 release) you extend base classes. I'm starting to gear up to break this limitation for 4.1 (where you will use simple objects and have framework dependencies injected into your classes).
ProjectBuilder was great in its time, but compared to Eclipse, it's hopeless. IB still rocks, and I wish Sun had demostrated some intelligence when first designing Swing by investigating IB. That is, Swing treats UIs as a coding problem, IB treats it as a configuration problem.
This is interesting to me, because I worked at WebCT before I left to become an independent consultant.
What's more interesting is that WebCT's Vista was out pacing Blackboard's product in terms of features (at least when I left in October 2003). Blackboard was, I believe, an ASP.NET product, WebCT's Vista is J2EE (and written in Struts and JSP, not Tapestry, alas).
My guess is that one of the two product lines will be phased out. This could become an interesting competative case for.Net and J2EE.
Sorry, JEE. Cause Sun can't stand to stick with just one name for anything.
Switching from Burnout 3 to Burnout Revenge was, well, interesting. They've changed a few things that were broke, introduced a few new things that are partially broken, and created a different but not better game.
The revamp of crash mode is fun but also broken. First off, the launch is stupid... you quickly master this and you won't get gold unless you get a perfect start. Games should be rewarding, not frustrating and missing a perfect start (and then having to reset) is just frustrating. Likewise, the rapid-tap of the B button to provoke a crashbreaker is nasty, and penalizes my wife who can't hit the button as quickly.
The new environments for crash mode partially upset this, as well as the wider selection of vehicles. The fun part of crash mode now is finding both the right path and the right vehicle... Burnout 3 crash mode was just about the one, single path.
What's dissapointing is that there's no longer a crash replay! That makes it harder to determine how to "improve" your rating since you see just the aftermath of your run, rather than the run itself. And the target car is silly, since it is almost guaranteed to be involved in any reasonably sized crash. Additionally, it would be nice if two vital statistics were displayed at the end of the crash in addition to dollar damage: number of cars wrecked and explosion multiplier. These can be dug out with a few button presees, but they are critical to levelling up and should simply be displayed.
A side note: you can see the hand of the developers clearly in crash mode; not only do cars NOT try to avoid crashes, but you can see cars hit a "radius of control" at which point they accelerate into the crash. Despite this, the physics of crash mode is improved in many subtle ways. Cars tend to twist and roll in a much more realistic manner.
In terms of new things that are broke, being able to rear-end cars is a total mistake. It randomizes the races, since you just plow through traffic, with your vision obscured by the vehicles you've slammed ahead of you, until eventually you hit a bus or wall. It's very common, because of this (and shortcuts) to see you position shift constantly between first and last. When I first heard about this feature, I assumed you'd be able to side-check, not rear-end, vehicles... and I think that would have been a more tactical, more controlled, less random approach.
Opponents do not avoid you as well during aftertouch; it's much easier to score an aftertouch takedown in Burnout Revenge than in Burnout 3, but it's much harder to score an ordinary takedown. "Psyche-out" takedown are even more rare.
The new race crashbreakers (the ability to explode when taken out) are generally a good idea; you have to be tactical about them, since detonating without taking out an opponent leaves you with no boost at all. However, your opponents do NOT have this ability... only you! This is an example of how they've made the game easier, but not necessarily better.
The "stars" system is another broken change. Despite the fun feedback you get during a race for reaching new levels ("OK", "Good", "Awesome")... you are unlikely to finish the race before getting the maximum of four stars and I can't see you ever getting gold without earning four stars. So the stars are just window dressing on top of the ordinary medals you receive anyway. If stars were harder to earn, so that you could finish with a Gold but only two stars, for example, it would be a different story.
The 10 levels of unlocking progression is more confusing and less satisfying than Burnout 3's approach of unlocking classes of cars. You unlock a huge number of cars, sometimes it feels like one per race. The cars are all fast (many blindingly fast) but run together as well, the names are less memorable than Burnout 3's, and all seem to handle the same. The differentiation between cars (outside of top speed) is even less in Burnout Rev
I remember reading about how Steve Jobs motivated the original Mac team to speed up the boot. "Millions of people will boot their Macs every day; if you can shave 30 seconds off that boot time, it's the equivalent of three human lives every day".
If that concept is true (debatable, but stick with me) then spammers, in the aggregate, are killing dozens or even hundreds of people a day... a few seconds here and a few seconds there. So, in this respect, what goes around comes around.
I wouldn't hold my breath. The serious NeXTHeads (myself included) moved on to Java and have tried to recreate that environment in J2EE land. I've built Tapestry, Andrus has built Cayenne, etc.
However, I do suspect that the NeXT crew is on its way to Ruby land at some point. I think it would be a blast to build an even better framework than Tapestry in Ruby. But that's not on my current TODO list... in fact, what is, is to build technology that better differentiates Tapestry from JSF (and Tapestry from WOF).
I can't believe what a scam the Diebold's of the world have pulled on this issue. Touch Screens easier than paper ballots?
Where touch screens were used, people had to wait in line hours and hours. Many gave up.
The lack of a paper trail is completely wrong. WE all know how fallable hardware and software can be.
My voting experience for the last few elections has been based on 30 year old technology and works great.
Quincy uses paper ballots; you use a felt marker to connect a line on an arrow pointing towards your candidate.
The paper is legal size (larger than 8.5 x 11) so there's plenty of room. No butterfly ballot needed.
They ask for your name/address (but no id) before giving you the ballot. A second check, different people, before giving the ballot to the machine.
The machine reads the ballot (presumably) and displays a satisfying ballot count (I was number 138 at 8am yesterday).
No hanging chads. Simple, proven optical technology. Recounts just a matter of refeeding in the ballots.
I can't see how touch screens would be any faster, even in an ideal world. Imagine what it'll be like in a couple of years, after those touch screens have gotten bounced around a few times... I hate touch screens on ATMs and banks have the money to keep them properly repaired.
I think this country needs voting reform even before it needs true campaign reform. No voting, short of a face-to-face visible show of hands, will ever be secure or perfect... but paper ballots and simple technology is much more confidence inspiring than these touch screens. America should standardize on simple, effective, confidence inspiring methods.
Broadband is presumably required
to download the DVD content
This will likely be broadband over cable in most areas
My provider, Comcast, offers a competing on-demand service
Comcast is known to terminate service
for anyone who actually uses their unlimited broadband
Sign up, start downloading... then go begging to get your Internet restored?
I suspect that other large cable/broadband providers will do the same (terminate, interrupt, or otherwise impede service), perhaps regardless of whether they provide on-demand services that directly compete with this Tivo/Netflicks offering.
I think you tarnish the name of everything the geniuses at Apple pioneered with WebObjects by even comparing it to Struts.
Fundamentally, Struts is a refactoring of the basic servlet API, but is still intrinsically operation-based (as are pure servlets).
WebObjects, and it's thematic successor Tapestry are component based approaches, an entirely different mindset. I created Tapestry and I have about two years of Struts experience... Struts is a straight-jacket. Component frameworks offer incredible advantages in terms of clarity and developer productivity. Struts offers very, very little except a slew of books that have the daunting task of explaining in detail something that should be (was intended to be) very simple.
Used to drink lots of Coke and Jolt in college (alas, my main vices!). Somewhere around 2 liters a day.
Went cold turkey. Headaches, miserable, sick to my stomache. Relapsed.
Went cold turkey again. Was a man. Suffered through. First day: bad! Second day: worse! Third day: just bad again. Fourth day: getting better.
Just choose a four day stretch where you don't have a lot of responsibilities!
Even after ruling out collectible games (such as Magic), the number of card games out there using specialized or modified card decks is virtually endless. Reference: Board Game Geek.
Although I love Whist and Hearts, one of my favoriate card games is Mu, a trick-taking game (like Whist or Bridge) which uses a modified deck:
5 suites
Numbered 0 - 9
Cards are worth 0 - 2 points
Two trumps per round, decided by bidding
Variable (each round) teams
Plays best with five
It looks like a kitchen sink game, but in reality every aspect of it is wonderfully balanced and there's room for devious bidding and strategy.
Re:Business Object Persistance and Caching
on
Struts Kick Start
·
· Score: 1
Happy developers use Tapestry (not Struts) for presentation, and Cayanne or Turbine for persistance. Cayanne is inspired by Apple's Enterprise Objects Framework (EOF) in much the way that Tapestry is inspired by Apple's WebObjects.
First off, I probably shouldn't have even brought up Tapestry, I'm generating a bad reputation for trying to monopolize discussions and steer them towards Tapestry.
Struts rounds off the rough edges of servlet/JSP development. It does a little streamlining, such as creating an abstraction between actions and JSPs. Actions are subclasses of a struts-provided class and are very, very similar to servlets... in fact, they must be stateless, just like a servlet.
JSPs are called "forwards" and, in fact, the plumbing doesn't require that the output be JSPs, you can plug in other templating systems such as Velocity.
There's standard taglibs that help with creating URLs that reference actions, help with building forms, and there's a system, called form beans, where query parameters are picked up and dumped in as properties of a bean, which is then passed to an action for processing.
That's really about it.
Tapestry is simply a different kind of beast. It's goals are different... it doesn't round out the edges of the servlet API... it makes the servlet API irrlevant to the developer. You create Tapestry applications without thinking about URLs, query parameters or any of that jazz. It's all "objects, methods and properties".
Let's take a simple form example. In Struts you would have to
Create a JSP
Register the JSP in the struts_config.xml
Create a html:form tag and identify the action it submits into
Create html:textfield and etc. tags. These pull properties from domain objects and create HTML form elements from them.
Define a form bean class to receive the submitted values
Register the form bean in struts_config.xml
Create an action to receive the form submission (and register it in struts_config.xml)
Put code in your action to extract properties from the form bean and apply them to your business objects
Struts doesn't have any kind of namespace management, so if you are on a a big team, you have to be careful to name things uniquely.
In Tapestry, you would
Create a new page template
Create a page specification for that template
Add a Form component to the template
Add various form components to the template
Define a listener method for the Form component
Create a page subclass
Create the listener method for the form
Although this looks similar, its much easier in Tapestry. Everything you need to do is localized in the three resources of the page (the specification, the template or the class). You write very, very little code... instead, you declare what you want the framework to do inside the page specification (an XML document), or even inside the HTML template (more like taglibs, and a 2.4 feature in progress right now).
These page specification entries are pretty short, for example:
This says "use a TextField component, bind its value parameter to the name property of the employee property of the page". This assumes that your page class provides a JavaBeans property, "employee". The accessor method knows how to obtain this object from a backend database or EJB.
You and the other developers aren't conflicting on access to struts_config.xml. No change that another developer makes to thier page will break yours. Name conflicts simply can't happen... each page is like a little application unto itself.
In both frameworks you have to provide the business object to the form. In Struts, an action has to store a bean as a HttpServletRequest. In Tapestry, the page provides an accessor method that exposes the business objects to the components on the page.
Tapestry does much more work for you when the form is submitted. Notice that you don't specify a URL, action, page or anything with a Form component, you simply tell the Form component what method to invoke when the form is submitted.
The form components will pull request parameters, convert the parameters to correct Java types, and apply changes to the properties of the business object. If you are using the validating text field component, then more conversions and validations occur, automatically (and properties are only updated if the input is valid).
Once all the properties have been set, the Form will invoke the listener method which carries things forward from there, including selecting which page will render the response.
On something like a login page (i.e., user name and password), you don't need a seperate business object; your form components can simply update corresponding properties of the page object itself.
Right there is one of the big differences; the objects Tapestry users work on are stateful, not stateless. You don't have to deal with that problematic indirection (storing everything as request or session attributes). Tapestry does the shuffling of data to and from the session for you, invisibly. It uses object pooling so that you code naturally (objects with methods and properties) without worrying about multi-threading issues.
Now, that's just off the top of my head and doesn't scratch the surface of what Tapestry can do. The important thing is that its all about components, and creating new components (and even packaging them into libraries of components) is a snap, in fact its often a necessary and natural part of creating an application.
Unlike taglibs, Tapestry components can (and usually do), have their own templates and often are constructed from other components. Very natural, much more like a Swing GUI in terms of composition.
Because all of the request dispatching is performed by the framework (both during render, when the framework creates URLs, and in subsequent requests, when the framework interprets those same URLs), components can have thier own private listeners and behaviors.
Thus you can have things like MindBridge's Table component, that has sortable column headings. The links for the headings are components embedded within the Table component, and the Table component provides the listeners for those links. You can have ten Table components on ten different pages, or ten on the same page and everything just works, no questions asked.
Everything in Tapestry is designed to assist the developer... wringing more functionality out of less effort. When things go wrong, it has incredible exception reporting.
Right now we're working on release 2.4 which includes significant improvements that will make Tapestry the easiest (and still, most powerful) web app framework available.
There's reams of documentation at the Tapestry Home Page and you might just want to check it out (if you want something more coherent).
Re:What the big deal with Struts...
on
Struts Kick Start
·
· Score: 1
I just can't resist plugging Tapestry, which follows the concepts of WebObjects but runs with it... and is open source.
Tapestry has a great plugin for Eclipse called "Spindle".
The learning curve can be a bit steep, but not as steep as Struts in many ways (I use Struts at my current job, and it was a massive pain for me to shift gears and work within the limitations of Struts).
Meanwhile we're changing the framework and improving the documentation to make Tapestry the easiest to use web framework out there.
Struts is light years behind WebObjects.
Tapestry is "inspired" by WebObjects... they are kissing cousins. Each has its own set of strengths and weaknesses. Tapestry does a little less magic for you and thus is a lot more scalable.
Check it out
Found the quote:
x _lines_written_by_the_hand_of/188939.html
http://thinkexist.com/quotation/if_you_give_me_si
... and I can have that man executed for treason. I can't remember where this quote comes from, but the gist is that if you set out to prove someone guilty, and your system has no proper checks and balances (fifth amendment, habeas corpus, etc.) then it's quite easy. We saw this happen with the Starr investigation of Clinton: every roadblock that indicated a lack of wrongdoing was interpreted as an ever greater conspiracy and ever greater guilt. Remember that amenesty international was started around a case of two men simply toasting "to freedom"; they were imprisoned for treason.
However, at some level, I'm pretty dubious. A tool such as Inform 7 (or TADs, or the other heavy hitters) makes it reasonable to build a narrative that feels spontaneous even if it is not. My gut reaction is that Storytron will have a cursory kind of believability, but when you pressure it a little, it that suspension of disbelief will break down.
By contrast, when I show people what can be done in just a couple of minutes using Inform (and the Inform library, which models the "player world" quite nicely), people immediately think its doing much, much more than it really is, or that I code more than I really do. People want to see storys, which is good for Storyworld, but I think better for Inform.
I make 100% of my income off two open source projects: Tapestry and HiveMind. Apache owns the copyright, but the license is free (ASL 2.0). I make my living doing training and project work. This has paid my bills for over two years now.
... and to market! There's no way to tell if you can pull this off without trying.
... but there are also occasions where I feel trapped by my choice. I'll need to come up with something else, someday, but in the meantime I'm loving life. You mileage may vary.
It's not for the faint hearted; my job window is always just a couple of months out but doesn't seem to be drying up either. And you need to be a triple threat: able to code, and to teach and mentor
Even so, my wife has to work (mostly to get health insurance for us).
I love the freedom, especially from PHBs
Two comments on your post:
If you assume that all Tapestry is doing is routing requests and outputting HTML, you are missing the forrest for the trees. To be honest, I think most web application development is primarily about state management (transient state used for one request, persistent state used across requests, stored on the server or on the client). These are more areas where developers are used to slaving away, but a real framework is quite capable of handling it, and handling it better than the developer can (at a certain scale of complexity). So, as long as you are happy to try and manage everything in terms of HttpServletRequest and HttpSession attributes, and endless code to pick apart query parameters, and a bunch of other limitations, you can get by with something simple. I tend to think of Tapestry, not as more complex, but as more complete.
Second, there is an inherent and invalid assumption in your statement that Tapestry is not scalable, when in fact, it is very scalable not just in terms of concurrent users, but scalable in many dimensions: scalable in terms of number of pages, of number (and type) of developers, in the complexity of pages. What's important is that as your application does grow more complicated, your approach never has to change ... in effect, Tapestry is built for the worst case: highly dynamic pages, complex forms, multiple forms per page, complex client-side JavaScript, etc. A major portion of what Tapestry does is fundamentally about naming things, particularily form control element ids, and JavaScript functions and fields, to avoid naming conflicts. But even in terms of basic scalability, Tapestry uses a pooling mechanism around its page objects to support effecient, concurrent access by restricting non-threadsafe objects (the pages) to individual requests (and, thus, individual threads).
So, what you get is an object oriented programming model (hey! look! objects with methods and properties!) in a highly multithreaded environment without having any concerns about multiple threads. The pooling and typesafety is baked into the framework, not the code you write. Further, you get to build a servlet application without ever seeing the servlet API (unless you really want to).
So, yes, there's a lot of moving parts in Tapestry, but they are all there for a purpose. I personally find Tapestry useful even for a single-page application ... and I wouldn't want to use anything else when I'm working on an application with dozens or hundreds (even thousands) of pages and components.
1. Complicated. Uneasy to learn.
Just different. People trying to find Struts++ get confused because Tapestry is a completely different beast.
2. Does not support unit testing.
Wrong. This was doeable in 3.0 with an add-on; an improved version of the add-on is part of Tapestry 4.0.
3. The "Model" component of MVC is closely tight to "View"; you cannot have many views of the same page (for instance: web page, web page for printing, WAP page).
Ultimately, your model is really DTO, not your page or component class. Tapestry components don't care where data comes from, thanks to OGNL. So, there's no reason you can't have multiple pages for different formats. However, Tapestry does not address the myth of one page / multiple views. A desktop HTML application and a WAP application are completely different beasts and should be treated as such. You should not be coding applications inside a big case statement.
4. Adding your own JavaScripts suxx. You have to map component names etc.
Because HTML output is componentized, JavaScript generation for that HTML must be componentized. This is an annoyance for simple cases, but means that complex cases just work. You can have as many DatePickers or Palettes or validating fields and forms per page as you like and it all just works with everything wired together properly, and all client-side elements (JavaScript variables and function names) generated free of naming collisions. Tapestry was born to do Ajax.
5. If you want to validate form field, you have to use special components (ValidField). Some components do not have their validated counterparts. Client-side validation is very basic (e.g. cannot check if entered date is in the future).
You haven't looked at Tapestry 4.0. Paul Ferarro did a complete rewrite of the validation subsystem to make it more powerful and more flexible; all the form control components now support input validation, ValidField has been deprecated.
6. Changing one line of code/template requires you to redeploy whole application; that is, pack it into .war archive, send to web server, perform refresh. When used with Apache Tomcat, leads to memory leaks.
So you're blaming Tapestry for your bad development model? I deploy into Tomcat, but do all my development inside my IDE using Jetty. No redeploy, and I can bounce the Jetty instance in a few seconds.
7. The page pool model is said to scale well, but can be very error-prone. For instance: if you forget to reset some variable, it can be displayed by some other user when he happens to pull it from the page pool.
This I find an amazing observation; Even Tapestry 3.0 supports transient and persistent properties for you ... meaning you write an abstract class and let Tapestry provide the code to implement the property along with the compliance code to work well with the page pool. Management of transient and persistent page state is an application concern that you should be delegating to Tapestry. Just define abstract getters and/or setters, rather than instance variables (and getters and setters). Tapestry writes the code for you (at runtime).
If the Simple container is a valid Servlet container, then Tapestry will work fine within it. Tapestry's footprint is rather large, however. About 2 MB for the framework and its dependencies. That may compromise its use for embedded.
Although I freely being influenced as a user of WebObjects back in the day (circa 1998 and 1999), that's about as far as the lineage goes. I certainly built Tapestry with a different set of expectations and compromises than WebObjects, and that has evolved further of the years.
However, I will stand by declaring myself "the original author of Tapestry". That clearly describes Tapestry design and implementation; the flavor might inlcude a little WebObjects spice, but the meat is pure Java + Servlets + Howard Lewis Ship's insights and contributions (and mistakes).
Now look what you made me do ... refer to myself in the third person!
Rails has a lot going for it, and the entire Ruby concept of focusing on code has influenced many frameworks, including Tapestry. Tapestry uses abstract properties combined with annotations (or auxillary XML files) to do the kind of meta programming that is done using class methods in Ruby, but nonetheless.
In terms of dependencies, being an Apache project causes some distribution problems w.r.t depenencies, especially when you use non-Apache projects like OGNL and Javassist. The next major release of Tapestry will build using Maven, which will make nearly all of part 1 of this article irrelevant (or at least, standard). I'm looking forward to part 2 myself, which should identify why Tapestry is so special.
Finally, within the Java community, Tapestry is fairly well known, though a regrettably small percentage have used it. The majority of the targetted readers of this article would have objected to wasting too much space describing Tapestry and its goals, just as others in this thread have objected to the lack of that introductory material. You can't please everyone (exception on Slashdot, where you can't please anyone).
As the original author of Tapestry (but not the article on DeveloperWorks, which caught me by surprise) I can say that IBM doesn't have any secret agenda on this. In fact, given that IBM is selling a commercial product that competes head-to-head with Tapestry (their JavaServer Faces, built on top of their WebSphere proprietary Eclipse IDE) it is enlightened of them to cover Tapestry.
Of course, what's going on there is two fold. First, IBM is big enough that different areas of the organization will have different and occasionally competing goals. Primarily, all on-line magazines are constantly hunting for new material to keep the eyeballs looking (and the click rates clicking). IBM doesn't solicit authors to write on particular subjects, they accept existing authors efforts, with the authors pursuing their own interests. Here, Brett happened to be into Tapestry and did a great job providing additional documentation in the form of this article.
I make my living off of Tapestry, so I'm happy to see this kind of coverage, but the framework itself is open source and free, with a very, very liberal license (ASL 2.0). I make money by providing Tapestry support and training. There's your ad.
In even newer news, Tapestry 4.0 final release is now available.
Objective-C was my first object-oriented language (this was back in 93 - 95). I loved the syntax and the integrated vision of the tools and frameworks ... but I hated memory management. The whole retain/release/autorelease thing was always a bug waiting to happen, and I spent many wasted hours tracking those down (basically, retain/release works great for trees but flops around like a dying fish for graphs).
... meaning that its better to combine many small focused objects. In Objective-C, you have a layer-cake approach, where each layer of inheritance mixes in a particular concern. This makes sense when you want to minimize the number of objects allocated, but in a GC language (Java, Ruby, etc.) you end up with better, more testable code when you let the GC do its thing.
Anyway, I simply can't go back to a non-memory managed environment again.
I have seen that, as I've matured as an OO developer, and as I've distanced myself from Objective-C, my style has changed. The Objective-C libraries are heavily based on inheritance, but I've learned that "composition trumps inheritance"
You can see this in Tapestry, where currently (through the 4.0 release) you extend base classes. I'm starting to gear up to break this limitation for 4.1 (where you will use simple objects and have framework dependencies injected into your classes).
ProjectBuilder was great in its time, but compared to Eclipse, it's hopeless. IB still rocks, and I wish Sun had demostrated some intelligence when first designing Swing by investigating IB. That is, Swing treats UIs as a coding problem, IB treats it as a configuration problem.
But, as I said, you can't go home again.
What's more interesting is that WebCT's Vista was out pacing Blackboard's product in terms of features (at least when I left in October 2003). Blackboard was, I believe, an ASP.NET product, WebCT's Vista is J2EE (and written in Struts and JSP, not Tapestry, alas).
My guess is that one of the two product lines will be phased out. This could become an interesting competative case for .Net and J2EE.
Sorry, JEE. Cause Sun can't stand to stick with just one name for anything.
Switching from Burnout 3 to Burnout Revenge was, well, interesting. They've changed a few things that were broke, introduced a few new things that are partially broken, and created a different but not better game.
... you quickly master this and you won't get gold unless you get a perfect start. Games should be rewarding, not frustrating and missing a perfect start (and then having to reset) is just frustrating. Likewise, the rapid-tap of the B button to provoke a crashbreaker is nasty, and penalizes my wife who can't hit the button as quickly.
... Burnout 3 crash mode was just about the one, single path.
... and I think that would have been a more tactical, more controlled, less random approach.
... only you! This is an example of how they've made the game easier, but not necessarily better.
... you are unlikely to finish the race before getting the maximum of four stars and I can't see you ever getting gold without earning four stars. So the stars are just window dressing on top of the ordinary medals you receive anyway. If stars were harder to earn, so that you could finish with a Gold but only two stars, for example, it would be a different story.
The revamp of crash mode is fun but also broken. First off, the launch is stupid
The new environments for crash mode partially upset this, as well as the wider selection of vehicles. The fun part of crash mode now is finding both the right path and the right vehicle
What's dissapointing is that there's no longer a crash replay! That makes it harder to determine how to "improve" your rating since you see just the aftermath of your run, rather than the run itself. And the target car is silly, since it is almost guaranteed to be involved in any reasonably sized crash. Additionally, it would be nice if two vital statistics were displayed at the end of the crash in addition to dollar damage: number of cars wrecked and explosion multiplier. These can be dug out with a few button presees, but they are critical to levelling up and should simply be displayed.
A side note: you can see the hand of the developers clearly in crash mode; not only do cars NOT try to avoid crashes, but you can see cars hit a "radius of control" at which point they accelerate into the crash. Despite this, the physics of crash mode is improved in many subtle ways. Cars tend to twist and roll in a much more realistic manner.
In terms of new things that are broke, being able to rear-end cars is a total mistake. It randomizes the races, since you just plow through traffic, with your vision obscured by the vehicles you've slammed ahead of you, until eventually you hit a bus or wall. It's very common, because of this (and shortcuts) to see you position shift constantly between first and last. When I first heard about this feature, I assumed you'd be able to side-check, not rear-end, vehicles
Opponents do not avoid you as well during aftertouch; it's much easier to score an aftertouch takedown in Burnout Revenge than in Burnout 3, but it's much harder to score an ordinary takedown. "Psyche-out" takedown are even more rare.
The new race crashbreakers (the ability to explode when taken out) are generally a good idea; you have to be tactical about them, since detonating without taking out an opponent leaves you with no boost at all. However, your opponents do NOT have this ability
The "stars" system is another broken change. Despite the fun feedback you get during a race for reaching new levels ("OK", "Good", "Awesome")
The 10 levels of unlocking progression is more confusing and less satisfying than Burnout 3's approach of unlocking classes of cars. You unlock a huge number of cars, sometimes it feels like one per race. The cars are all fast (many blindingly fast) but run together as well, the names are less memorable than Burnout 3's, and all seem to handle the same. The differentiation between cars (outside of top speed) is even less in Burnout Rev
This was Steve Jobs in 1982 - 83, so it doesn't reflect how computers are used today ... and he was motivating people (by fudging the numbers a bit).
I remember reading about how Steve Jobs motivated the original Mac team to speed up the boot. "Millions of people will boot their Macs every day; if you can shave 30 seconds off that boot time, it's the equivalent of three human lives every day". If that concept is true (debatable, but stick with me) then spammers, in the aggregate, are killing dozens or even hundreds of people a day ... a few seconds here and a few seconds there. So, in this respect, what goes around comes around.
However, I do suspect that the NeXT crew is on its way to Ruby land at some point. I think it would be a blast to build an even better framework than Tapestry in Ruby. But that's not on my current TODO list ... in fact, what is, is to build technology that better differentiates Tapestry from JSF (and Tapestry from WOF).
Where touch screens were used, people had to wait in line hours and hours. Many gave up.
The lack of a paper trail is completely wrong. WE all know how fallable hardware and software can be.
My voting experience for the last few elections has been based on 30 year old technology and works great.
Quincy uses paper ballots; you use a felt marker to connect a line on an arrow pointing towards your candidate.
The paper is legal size (larger than 8.5 x 11) so there's plenty of room. No butterfly ballot needed.
They ask for your name/address (but no id) before giving you the ballot. A second check, different people, before giving the ballot to the machine.
The machine reads the ballot (presumably) and displays a satisfying ballot count (I was number 138 at 8am yesterday).
No hanging chads. Simple, proven optical technology. Recounts just a matter of refeeding in the ballots.
I can't see how touch screens would be any faster, even in an ideal world. Imagine what it'll be like in a couple of years, after those touch screens have gotten bounced around a few times ... I hate touch screens on ATMs and banks have the money to keep them properly repaired.
I think this country needs voting reform even before it needs true campaign reform. No voting, short of a face-to-face visible show of hands, will ever be secure or perfect ... but paper ballots and simple technology is much more confidence inspiring than these touch screens. America should standardize on simple, effective, confidence inspiring methods.
- Broadband is presumably required
to download the DVD content
- This will likely be broadband over cable in most areas
- My provider, Comcast, offers a competing on-demand service
- Comcast is known to terminate service
for anyone who actually uses their unlimited broadband
- Sign up, start downloading
... then go begging to get your Internet restored?
I suspect that other large cable/broadband providers will do the same (terminate, interrupt, or otherwise impede service), perhaps regardless of whether they provide on-demand services that directly compete with this Tivo/Netflicks offering.Fundamentally, Struts is a refactoring of the basic servlet API, but is still intrinsically operation-based (as are pure servlets).
WebObjects, and it's thematic successor Tapestry are component based approaches, an entirely different mindset. I created Tapestry and I have about two years of Struts experience ... Struts is a straight-jacket. Component frameworks offer incredible advantages in terms of clarity and developer productivity. Struts offers very, very little except a slew of books that have the daunting task of explaining in detail something that should be (was intended to be) very simple.
Used to drink lots of Coke and Jolt in college (alas, my main vices!). Somewhere around 2 liters a day. Went cold turkey. Headaches, miserable, sick to my stomache. Relapsed. Went cold turkey again. Was a man. Suffered through. First day: bad! Second day: worse! Third day: just bad again. Fourth day: getting better. Just choose a four day stretch where you don't have a lot of responsibilities!
Although I love Whist and Hearts, one of my favoriate card games is Mu, a trick-taking game (like Whist or Bridge) which uses a modified deck:
It looks like a kitchen sink game, but in reality every aspect of it is wonderfully balanced and there's room for devious bidding and strategy.
Happy developers use Tapestry (not Struts) for presentation, and Cayanne or Turbine for persistance. Cayanne is inspired by Apple's Enterprise Objects Framework (EOF) in much the way that Tapestry is inspired by Apple's WebObjects.
First off, I probably shouldn't have even brought up Tapestry, I'm generating a bad reputation for trying to monopolize discussions and steer them towards Tapestry.
Struts rounds off the rough edges of servlet/JSP development. It does a little streamlining, such as creating an abstraction between actions and JSPs. Actions are subclasses of a struts-provided class and are very, very similar to servlets ... in fact, they must be stateless, just like a servlet.
JSPs are called "forwards" and, in fact, the plumbing doesn't require that the output be JSPs, you can plug in other templating systems such as Velocity.
There's standard taglibs that help with creating URLs that reference actions, help with building forms, and there's a system, called form beans, where query parameters are picked up and dumped in as properties of a bean, which is then passed to an action for processing.
That's really about it.
Tapestry is simply a different kind of beast. It's goals are different ... it doesn't round out the edges of the servlet API ... it makes the servlet API irrlevant to the developer. You create Tapestry applications without thinking about URLs, query parameters or any of that jazz. It's all "objects, methods and properties".
Let's take a simple form example. In Struts you would have to
Struts doesn't have any kind of namespace management, so if you are on a a big team, you have to be careful to name things uniquely.
In Tapestry, you would
Although this looks similar, its much easier in Tapestry. Everything you need to do is localized in the three resources of the page (the specification, the template or the class). You write very, very little code ... instead, you declare what you want the framework to do inside the page specification (an XML document), or even inside the HTML template (more like taglibs, and a 2.4 feature in progress right now).
These page specification entries are pretty short, for example:
This says "use a TextField component, bind its value parameter to the name property of the employee property of the page". This assumes that your page class provides a JavaBeans property, "employee". The accessor method knows how to obtain this object from a backend database or EJB.
You and the other developers aren't conflicting on access to struts_config.xml. No change that another developer makes to thier page will break yours. Name conflicts simply can't happen ... each page is like a little application unto itself.
In both frameworks you have to provide the business object to the form. In Struts, an action has to store a bean as a HttpServletRequest. In Tapestry, the page provides an accessor method that exposes the business objects to the components on the page.
Tapestry does much more work for you when the form is submitted. Notice that you don't specify a URL, action, page or anything with a Form component, you simply tell the Form component what method to invoke when the form is submitted.
The form components will pull request parameters, convert the parameters to correct Java types, and apply changes to the properties of the business object. If you are using the validating text field component, then more conversions and validations occur, automatically (and properties are only updated if the input is valid).
Once all the properties have been set, the Form will invoke the listener method which carries things forward from there, including selecting which page will render the response.
On something like a login page (i.e., user name and password), you don't need a seperate business object; your form components can simply update corresponding properties of the page object itself.
Right there is one of the big differences; the objects Tapestry users work on are stateful, not stateless. You don't have to deal with that problematic indirection (storing everything as request or session attributes). Tapestry does the shuffling of data to and from the session for you, invisibly. It uses object pooling so that you code naturally (objects with methods and properties) without worrying about multi-threading issues.
Now, that's just off the top of my head and doesn't scratch the surface of what Tapestry can do. The important thing is that its all about components, and creating new components (and even packaging them into libraries of components) is a snap, in fact its often a necessary and natural part of creating an application.
Unlike taglibs, Tapestry components can (and usually do), have their own templates and often are constructed from other components. Very natural, much more like a Swing GUI in terms of composition.
Because all of the request dispatching is performed by the framework (both during render, when the framework creates URLs, and in subsequent requests, when the framework interprets those same URLs), components can have thier own private listeners and behaviors.
Thus you can have things like MindBridge's Table component, that has sortable column headings. The links for the headings are components embedded within the Table component, and the Table component provides the listeners for those links. You can have ten Table components on ten different pages, or ten on the same page and everything just works, no questions asked.
Everything in Tapestry is designed to assist the developer ... wringing more functionality out of less effort. When things go wrong, it has incredible exception reporting.
Right now we're working on release 2.4 which includes significant improvements that will make Tapestry the easiest (and still, most powerful) web app framework available.
There's reams of documentation at the Tapestry Home Page and you might just want to check it out (if you want something more coherent).
Tapestry has a great plugin for Eclipse called "Spindle".
The learning curve can be a bit steep, but not as steep as Struts in many ways (I use Struts at my current job, and it was a massive pain for me to shift gears and work within the limitations of Struts).
Meanwhile we're changing the framework and improving the documentation to make Tapestry the easiest to use web framework out there.
Struts is light years behind WebObjects. Tapestry is "inspired" by WebObjects ... they are kissing cousins. Each has its own set of strengths and weaknesses. Tapestry does a little less magic for you and thus is a lot more scalable.
Check it out