<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://commons.oreilly.com/wiki/skins/common/feed.css?97"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>Beyond Java/Continuation Servers - Revision history</title>
		<link>http://commons.oreilly.com/wiki/index.php?title=Beyond_Java/Continuation_Servers&amp;action=history</link>
		<description>Revision history for this page on the wiki</description>
		<language>en</language>
		<generator>MediaWiki 1.11.0</generator>
		<lastBuildDate>Wed, 22 May 2013 21:11:14 GMT</lastBuildDate>
		<item>
			<title>Docbook2Wiki: Initial conversion from Docbook</title>
			<link>http://commons.oreilly.com/wiki/index.php?title=Beyond_Java/Continuation_Servers&amp;diff=9906&amp;oldid=prev</link>
			<description>&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 17:12, 17 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;</description>
			<pubDate>Mon, 17 Mar 2008 17:12:09 GMT</pubDate>			<dc:creator>Docbook2Wiki</dc:creator>			<comments>http://commons.oreilly.com/wiki/index.php/Talk:Beyond_Java/Continuation_Servers</comments>		</item>
		<item>
			<title>Docbook2Wiki: Initial conversion from Docbook</title>
			<link>http://commons.oreilly.com/wiki/index.php?title=Beyond_Java/Continuation_Servers&amp;diff=9832&amp;oldid=prev</link>
			<description>&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 23:57, 11 March 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 182:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 182:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Author of ''Maximum Java 1.1''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Author of ''Maximum Java 1.1''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;[[Image:Beyond Java_I_8_tt135.png&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;|&lt;/del&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;[[Image:Beyond Java_I_8_tt135.png]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;''Glenn Vanderburg, a consultant from Dallas, has been writing Java programs since before it was called Java, and was the author of one of the first advanced Java books. Glenn has 19 years of software development experience, encompassing a wide variety of languages, platforms, industries, and domains''.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;''Glenn Vanderburg, a consultant from Dallas, has been writing Java programs since before it was called Java, and was the author of one of the first advanced Java books. Glenn has 19 years of software development experience, encompassing a wide variety of languages, platforms, industries, and domains''.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key wikicontent:diff:version:1.11a:oldid:8917:newid:9832 --&gt;
&lt;/table&gt;</description>
			<pubDate>Tue, 11 Mar 2008 23:57:29 GMT</pubDate>			<dc:creator>Docbook2Wiki</dc:creator>			<comments>http://commons.oreilly.com/wiki/index.php/Talk:Beyond_Java/Continuation_Servers</comments>		</item>
		<item>
			<title>Docbook2Wiki: Initial conversion from Docbook</title>
			<link>http://commons.oreilly.com/wiki/index.php?title=Beyond_Java/Continuation_Servers&amp;diff=8917&amp;oldid=prev</link>
			<description>&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Beyond Java/TOC}}&lt;br /&gt;
I rarely run rapids on blind faith. If there's any danger, I like to know exactly what the water and rocks could do to me, and I need a plan to deal with any potential trouble. On this day, though the consequences for failure were high, the move was easy. I still don't know exactly how it worked, but I watched boater after boater thrust, brace, and arrive in the turbulent boil below ''The Elbow'', a slotted 20-foot drop that guidebooks describe as a deadly entrapment motel. Sure, I could tell you that the move was called a slot move, and I'd need to apply my brace with perfect timing and angle to avoid hitting the wall on the way down. I knew the timing, because I'd been told. It's just the &amp;quot;why&amp;quot; of it that was a mystery. The experts tried to tell me why it worked. Most really didn't know. No one could really tell me with any kind of certainty how the rocks were configured at the bottom. They just knew that at this river level, the move worked. And so it did.&lt;br /&gt;
&lt;br /&gt;
At different points in my programming life, a few tricks held the same kind of mystery for me: recursion as a college student, my first glimpse at reflection shortly thereafter, and now, continuation servers . In this chapter, you'll see continuations, and how they're used in a new class of application servers.&lt;br /&gt;
&lt;br /&gt;
== The Problem ==&lt;br /&gt;
&lt;br /&gt;
Web development, for all its usefulness, often happens with a curious inelegance. It's kind of like making sausage. I like the result, but I don't want to see how it's made. Web programming in Java was better than web programming in alternative languages. It gave you more structure with easier maintenance and, often, better scalability than Visual Basic or Perl-based approaches, and an easier programming model than C++. But for all the benefits, certain problems make it seem clunky and awkward.&lt;br /&gt;
&lt;br /&gt;
=== What You Want ===&lt;br /&gt;
&lt;br /&gt;
Current web application servers might be powerful, but they're not convenient or natural. So, what is convenient and natural? It shouldn't take too much effort to figure that out. What if your controllers looked like this:&lt;br /&gt;
&lt;br /&gt;
     if (logon.show() =  = true) {&lt;br /&gt;
       mainPage.show();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
or this:&lt;br /&gt;
&lt;br /&gt;
     if (shoppingCart.verify()) checkout.show();&lt;br /&gt;
&lt;br /&gt;
That's better. What you really want to do is encapsulate the presentation of one or more web screens in a method. Then, more sophisticated page flows would not be a problem. You could simply roll up more and more pages into higher-level components. For example, you could take this code:&lt;br /&gt;
&lt;br /&gt;
     checkoutAddress.showForm();&lt;br /&gt;
     if(checkoutAddress.getSeparateBilling) checkoutBilling.showForm();&lt;br /&gt;
     creditCardNumber.showForm();&lt;br /&gt;
&lt;br /&gt;
and roll it up onto a method:&lt;br /&gt;
&lt;br /&gt;
     public static void showCheckoutWizard() {&lt;br /&gt;
       checkoutAddress.showForm();&lt;br /&gt;
       if(checkoutAddress.getSeparateBilling) checkoutBilling.showForm();&lt;br /&gt;
       creditCardNumber.showForm();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
so the usage becomes:&lt;br /&gt;
&lt;br /&gt;
     cart.showCheckoutWizard();&lt;br /&gt;
&lt;br /&gt;
in its cleaner, refactored form. But you can't code that way, because your web server won't let you. Creators of most web application servers will sell their soul to keep things stateless and scalable.&lt;br /&gt;
&lt;br /&gt;
=== Statelessness ===&lt;br /&gt;
&lt;br /&gt;
Think of living without any short-term memory. Normal conversations in day-to-day life would be nearly impossible. Think of the logistics:&lt;br /&gt;
&lt;br /&gt;
* You'd have to write down every important phrase of every conversation as it occurred.&lt;br /&gt;
* Then, when someone asked you a question, you'd have to look up the history of your conversation with that person before you could answer.&lt;br /&gt;
* To optimize things, you'd have to decide how much information you should keep close by—say, in your briefcase—versus at home, in your filing cabinets.&lt;br /&gt;
* When information got too old, you'd need to throw it out.&lt;br /&gt;
* You'd have to maintain this whole system and revisit it when it didn't meet your needs.&lt;br /&gt;
&lt;br /&gt;
That's the status quo for web developers. Your briefcase is the HTTP session, and your file cabinet at home is the relational database. It's an insane proposition, but we deal with the tedium because the Web is so important, and stateless solutions scale better. So, you willingly take a pretty large stride away from the ideal solution. Still, each time you struggle with the awkward little edge cases, you ask yourself if there's a better way, some kind of abstraction that fits the problem more neatly.&lt;br /&gt;
&lt;br /&gt;
=== The Back Button ===&lt;br /&gt;
&lt;br /&gt;
Saving state within simple conversations does not cover the whole problem. On the Web, conversations are not linear. Users can and do change their minds, pressing the Back button. Some assumptions that you've made as you continue to accumulate data may no longer apply.&lt;br /&gt;
&lt;br /&gt;
Sometimes, you'll want to keep the user from going back, such as when she's made a purchase, or done something to force a committed change in a relational database. In these cases, you can simply punt and disable the Back button. Most often, you need to build special support for the Back button. You may even have to remove data from a database that a user would not have seen yet. Worse, many web designers simply don't solve the problem, and tell the user to expect unintuitive behavior. You've taken one more step back, away from the ideal. Once again, this awkward Back button forces you to deal with things on a case-by-case basis, and it just doesn't feel right.&lt;br /&gt;
&lt;br /&gt;
=== Navigation ===&lt;br /&gt;
&lt;br /&gt;
Web development in Java focuses an incredible amount of brain power around navigation and flow . You'd think controlling flow from the server side would be natural, but servers can't update clients—they can only respond to requests. This simple little truism forces servers to handle hundreds of little requests rather than a couple dozen application flows. It's also hard to synchronize the user interface with the model. You'd like to use a simple method call that controls the user interface and model, but you can't. The web server just doesn't work that way. And you're stepping back again, and you've got that sinking suspicion that there's a cliff behind you somewhere.&lt;br /&gt;
&lt;br /&gt;
=== Continuation Servers to the Rescue ===&lt;br /&gt;
&lt;br /&gt;
A new class of web servers called continuation servers is starting to make some real noise. A continuation server uses a programming construct called the ''continuation'' to keep enough information about a request to be able to completely reconstruct the context. In technical terms, a continuation saves the execution environment, including the call stack. In practical terms, using continuations in a web server lets the server maintain context for you, freeing you to program in a more natural way.&lt;br /&gt;
&lt;br /&gt;
== Continuations ==&lt;br /&gt;
&lt;br /&gt;
You've probably played video games. Think of a continuation as a ''save game'' feature. As you're playing your game, you save your current game. You can feel free to take your chances with the monster control center. If you die, you simply restore the game. Said another way, a continuation is a snapshot of a point in time. Continuations let you save the system's state (in the form of an execution stack) in one place, and then return to that state on command.&lt;br /&gt;
&lt;br /&gt;
Since I've already introduced Ruby's syntax, I'll first show you continuations in Ruby, where continuation syntax is clean and precise. Then, I'll show you Seaside, the most popular continuation-based server, in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
In Ruby, a code block defines the universe for the continuation. You'll use a continuation object to hold the execution state, consisting of the execution stack. You'll later invoke a call method on the continuation object to restore the system state, replacing the current execution state, including the call stack, with the one in the continuation object. The call returns execution to the point immediately after the code block. From Ruby's perspective, you're conceptually letting your execution state jump back in time.&lt;br /&gt;
&lt;br /&gt;
=== The Syntax ===&lt;br /&gt;
&lt;br /&gt;
In Ruby, you get a continuation by calling the &amp;lt;tt&amp;gt;callcc&amp;lt;/tt&amp;gt; method on &amp;lt;tt&amp;gt;Kernel&amp;lt;/tt&amp;gt; and passing it a code block. This block does nothing with the continuation but print its object identifier:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    irb(main):001:0&amp;gt; callcc {|continuation| puts continuation}&lt;br /&gt;
    #&amp;lt;Continuation:0x28c2dd8&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This passive little program does more than you think it does. The argument called &amp;lt;tt&amp;gt;continuation&amp;lt;/tt&amp;gt; is a powerful little gem that has the whole execution context, with variable values and the entire call stack, at the time that you called &amp;lt;tt&amp;gt;callcc&amp;lt;/tt&amp;gt;. Look at it as a saved game, or a frozen moment in time. You can return to that moment in time. Specifically, Ruby will return to execute the statement immediately after the continuation block by calling the continuation. Here's a trickier continuation example:&lt;br /&gt;
&lt;br /&gt;
     callcc do |continuation|&lt;br /&gt;
       for i in 1..10 do&lt;br /&gt;
         continuation.call if (i =  = 7)&lt;br /&gt;
         puts i&lt;br /&gt;
       end&lt;br /&gt;
       puts 'This never happens.'&lt;br /&gt;
     end&lt;br /&gt;
     puts 'Good bye.'&lt;br /&gt;
&lt;br /&gt;
And the output:&lt;br /&gt;
&lt;br /&gt;
     &amp;gt;'''ruby forloop.rb'''&lt;br /&gt;
     1&lt;br /&gt;
     2&lt;br /&gt;
     3&lt;br /&gt;
     4&lt;br /&gt;
     5&lt;br /&gt;
     6&lt;br /&gt;
     Good bye.&lt;br /&gt;
     &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, the whole &amp;lt;tt&amp;gt;callcc&amp;lt;/tt&amp;gt; statement is a point in time. When &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;7&amp;lt;/tt&amp;gt;, Ruby executes &amp;lt;tt&amp;gt;continuation.call&amp;lt;/tt&amp;gt;. That takes control to the point right after the continuation code block, so the last two numbers don't get printed, and the &amp;lt;tt&amp;gt;puts 'This never happens.'&amp;lt;/tt&amp;gt; in fact doesn't happen. The &amp;lt;tt&amp;gt;callcc&amp;lt;/tt&amp;gt; method loads the application stack in the continuation, abruptly sending execution to the line of code immediately after the continuation code block, or &amp;lt;tt&amp;gt;puts 'Good bye.'&amp;lt;/tt&amp;gt;. It moves execution around a little bit like a &amp;lt;tt&amp;gt;goto&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Of course, you'd not usually use continuations to break out of a &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; loop. Continuations take on a little more power when you pass them out of the code block, such as with a method call.&lt;br /&gt;
&lt;br /&gt;
=== A More Powerful Example ===&lt;br /&gt;
&lt;br /&gt;
Keep in mind that the continuation will return the call stack and local variables in the block to the way they were when you made the continuation call. So, this program:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    1  def loop&lt;br /&gt;
    2    for i in 1..5 do&lt;br /&gt;
    3      puts i&lt;br /&gt;
    4      callcc {|continuation| return continuation} if i=  =2&lt;br /&gt;
    5    end           # cont.call returns here&lt;br /&gt;
    6    return nil&lt;br /&gt;
    7  end&lt;br /&gt;
    8&lt;br /&gt;
    9  puts &amp;quot;Before loop call&amp;quot;&lt;br /&gt;
    10 cont=loop()&lt;br /&gt;
    11 puts &amp;quot;After loop call&amp;quot;&lt;br /&gt;
    12 cont.call if cont&lt;br /&gt;
    13 puts &amp;quot;After continuation call&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
gives you this result:&lt;br /&gt;
&lt;br /&gt;
     &amp;gt;ruby continuation.rb&lt;br /&gt;
     Before loop call&lt;br /&gt;
     1&lt;br /&gt;
     2&lt;br /&gt;
     After loop call&lt;br /&gt;
     3&lt;br /&gt;
     4&lt;br /&gt;
     5&lt;br /&gt;
     After loop call&lt;br /&gt;
     After continuation call&lt;br /&gt;
&lt;br /&gt;
So, we were able to exit the loop when something happened and return to the loop on command. Since continuations are so alien, let's look at this example in a little more detail. It's not too bad to read, once you know what's happening. Line 4 saves the game, putting it into a container. Line 12 restores the game. Let's break it down a little further, thinking like a Ruby interpreter:&lt;br /&gt;
&lt;br /&gt;
* Start on line 9, after the method declaration.&lt;br /&gt;
* Execute line 9, printing the string &amp;lt;tt&amp;gt;Before loop call&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Execute line 10, calling the method called &amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;. Put line 10 on the call stack, so you'll remember where to return after the method call.&lt;br /&gt;
* Enter the method &amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;, specified in line 1.&lt;br /&gt;
* Do the first pass through the &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; loop in lines 2–5. &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; has a value of &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;. You'll print &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Start the second pass through the &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; loop. &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; now has a value of &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;. You'll print &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* At line 4, &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;, so make the &amp;lt;tt&amp;gt;callcc&amp;lt;/tt&amp;gt; call in three steps. First, make a copy of the call stack. Second, make a copy of the instance variables (&amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;). Third, push the line after the continuation block (line 5) onto the ''copy'' of the call stack, so now the continuation's copy of the stack has (line 5, line 10). The call stack simply has (line 10).&lt;br /&gt;
* At line 4, execute the &amp;lt;tt&amp;gt;return&amp;lt;/tt&amp;gt; statement. You'll return the value of &amp;lt;tt&amp;gt;continuation&amp;lt;/tt&amp;gt; to the line on the top of the call stack. The call stack has line 10, so you'll return the value of &amp;lt;tt&amp;gt;continuation&amp;lt;/tt&amp;gt; to line 10. Set &amp;lt;tt&amp;gt;cont&amp;lt;/tt&amp;gt; to the returned continuation. Recall the continuation has the current execution context—the call stack has (line 5, line 10), and variable &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; has a value of &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Execute line 11, printing the screen &amp;lt;tt&amp;gt;After call loop&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Execute line 12. Calling the continuation restores the execution state. Set the value of &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;. Go to the line number on the top of the call stack so that you'll remove it from the call stack. Now the call stack has only line 10.&lt;br /&gt;
* Execute the rest of the &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; loop, for &amp;lt;tt&amp;gt;i=3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* You'll return &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt;. The call stack has 10 on it, so you'll return to line 10, and assign &amp;lt;tt&amp;gt;cont&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Execute lines 13 and 15. Skip line 14 because &amp;lt;tt&amp;gt;cont&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This continuation example shows you a few nice capabilities. You can take a snapshot of execution state at some point in time, like we did within the &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; loop. You can save that execution state in an object, as we did in the &amp;lt;tt&amp;gt;cont&amp;lt;/tt&amp;gt; object. You can then return to the execution state stored in a continuation object at any point.&lt;br /&gt;
&lt;br /&gt;
=== Why Would You Use Them? ===&lt;br /&gt;
&lt;br /&gt;
You might first think that continuations are the most useful when you want to break logical control structures, as in implementing a break for our &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; loop, or processing exceptions. For the most part, though, you want to think &amp;quot;suspend and resume.&amp;quot; Continuations are marvelous in these kinds of scenarios. Cooperative multitasking lets one program voluntarily relinquish control to another application, and resume at a later date. This problem is remarkably easy to solve using continuations. A subtler use involves communication. When you've got an application that spans multiple computers with synchronous request/response communication, you often want to suspend control until the remote system responds. When you need to scale this solution, suspending control while you wait frees the system to handle other requests. The system can conveniently resume your application without disruption when the remote system responds, simply by calling a continuation.&lt;br /&gt;
&lt;br /&gt;
== Continuation Servers ==&lt;br /&gt;
&lt;br /&gt;
You can probably begin to see why continuations might be interesting for web servers. If you want to look at a web application as one continuous application with suspend/resume breaks in between to communicate with the user, it makes more sense. While waiting for user input in the form of an HTTP request, the web server could simply store a state, stash the continuation object away in the HTTP session, and instantly return to that frozen point in time when it's time to process another request. Notice in [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-1|Figure 8-1]] that I've conveniently inverted the control. Instead of thinking of a web app as a series of request/response pairs initiated by the user, I can think of a web app as a series of response/request pairs controlled by the server. My server code gets much simpler.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;beyondjava-CHP-8-FIG-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 8-1. Continuation servers invert control from client to server, simplifying the world view, and the code, of the server'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt134.png|Continuation servers invert control from client to server, simplifying the world view, and the code, of the server]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your web application server is no longer composed of many different independent requests. The server can conveniently look at the world as a bunch of simple end-to-end applications. It processes individual requests by loading the state of each user when it's time to process another request, and suspending the user's application when it's time to communicate with the user again. ''Voilá''! Your application can maintain state, and use it to seamlessly control application flow.&lt;br /&gt;
&lt;br /&gt;
At a lower level, the continuation server becomes a collection of web applications with states frozen at a point in time, in the form of continuations. Each user has a session. The continuation server assigns an ID to each session, and organizes the continuations per session. After each request, the continuation server takes a snapshot of the execution state with a continuation object, and associates that continuation with the session. So, a server has multiple sessions, and each session has one or more continuations representing frozen points in time, as shown in [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-2|Figure 8-2]]. You can no longer see individual HTTP requests, because they're buried in the application flow. As they should be!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sidebar&amp;quot;&amp;gt;&lt;br /&gt;
'''Glenn Vanderburg: Continuation Servers'''&lt;br /&gt;
&lt;br /&gt;
Author of ''Maximum Java 1.1''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt135.png|]]&lt;br /&gt;
&lt;br /&gt;
''Glenn Vanderburg, a consultant from Dallas, has been writing Java programs since before it was called Java, and was the author of one of the first advanced Java books. Glenn has 19 years of software development experience, encompassing a wide variety of languages, platforms, industries, and domains''.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''What's wrong with current web development models, like the Servlet model?''&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''GV:'' There are two big problems. I'll start with the most obvious. When I did mainframe programming, I would build a screen of information mixed with form fields, and push it out to a 3270 terminal. The program wouldn't hear from the terminal again until the user hit Enter. Sound familiar?In the mainframe days, the program got to pause and wait on the user's submission. Web programming is actually worse, because in the interest of scaling to thousands of users (as opposed to hundreds), the program is asked to forget as much as possible between each interaction so that each submission can stand alone. The stateless nature of the web programming model forces programmers to manually manipulate, store, and retrieve the program state at every stage. Web frameworks help some, but programmers still have to consider carefully how to deal with each piece of state. One mistake and we get web applications that are (at best) very confusing to use.The other big deficiency of the web development model is that our programs are held together with strings. The navigational structure is defined by URLs we stick in links, and those URLs have to also go in configuration files to tie them to pieces of code that get invoked. User input comes to us in form fields that are named with strings. State that we store in the session is usually referenced by a key that is a string. We have all of these strongly typed programming languages and IDEs to go with them to make sure we don't make silly errors like misspelling variable names, but that all goes out the window with web apps, because the tools don't help us to validate all of our uses of URL fragments, form fields, etc. Also, those strings provide ways for crackers to attack our applications. Here again, some frameworks help us manage the tangled ball of strings, but most of them just reduce the problem, they don't solve it.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''But those fundamental problems come straight from HTTP and HTML, not Java, right?''&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''GV:'' True, but we shouldn't discount how much they hurt our productivity. Those two things together make web applications significantly more complex than more traditional counterparts. And complexity costs us—in time and in quality. Managing the complexity of our systems is the fundamental problem of software development.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''What is a continuation server?''&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''GV:'' First, I really don't like the term continuation server, for two reasons. First, it obscures what these servers and frameworks are all about. They serve web applications. Frameworks like Seaside and Iowa employ continuations as a way of hiding the stateless, back-and-forth nature of web applications from the programmer. Continuations are used deep inside the framework; developers don't deal with them directly. The second reason I don't really like the term is that continuations are just one of the techniques that frameworks like Seaside use to provide a better web development experience.What these servers do is to use continuations (as well as closures stored as callbacks, plus automatic tracking of session state and caching of backtracking information) to build high-level abstractions for web development, transparently handling many of the messy details that web developers are constantly wrestling with. Continuations, closures, and the common features of dynamic languages provide much more powerful tools for abstraction than Java does.&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''What do they bring to the table?''&lt;br /&gt;
| align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot; | ''GV:'' They simplify web development. And it's a radical simplification: many of the most difficult issues of web development, things that nearly all applications punt on because they're too difficult, are handled automatically and transparently so that they're built into your applications by default. Seaside, for example, makes it easy to develop web applications that work the way users expect: proper handling of the Back button, proper session forking if the user opens multiple windows or tabs, and no &amp;quot;accidental double purchase&amp;quot; when backing up to a form result page.In Seaside, web application code looks like the code you'd write for a desktop application. Need to ask the user a question? Call a dialog, wait for it to return, and act on the result. Of course, within the scope of that dialog call, a lot of things happen: a continuation is saved, a dialog page is sent to the browser, the user considers the question (possibly for a long time) and answers, and when Seaside receives the response it looks up the saved continuation, calls it—and the dialog call returns, just as if the thread had been waiting on the response the whole time. And, in a very lightweight sense, it actually was.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;beyondjava-CHP-8-FIG-2&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 8-2. A continuation server stores snapshots that have the state of web applications in progress'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt136.png|A continuation server stores snapshots that have the state of web applications in progress]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Advantages and Disadvantages ===&lt;br /&gt;
&lt;br /&gt;
You've seen the primary benefit: you can look at a web application as one big piece, instead of coordinating lots of little requests. That's incredibly powerful. Continuation servers have some other capabilities as well. The Back button problem becomes much easier to solve, because if the Back button is not disabled, you can just revert the application state to the last continuation, ''or any previous continuation''. To disable the Back button, you simply tell the browser and delete past continuations. Threading also becomes trivial, because each thread can work on a private continuation, each with an application's own resources. You don't have to worry about serializing access to a shared session.&lt;br /&gt;
&lt;br /&gt;
Continuation servers work best for applications that have complex state management issues and sophisticated control flows between pages. The continuation server simplifies navigation dramatically by letting you maintain application state between pages.&lt;br /&gt;
&lt;br /&gt;
Continuation servers do have a few problems:&lt;br /&gt;
&lt;br /&gt;
* The servers typically attach identifiers to URLs, and some don't like ugly URLs (though web sites like ''Amazon.com'' use them).&lt;br /&gt;
* You must guarantee ''session affinity'' , meaning that after an initial request in a user's session, the same machine must serve the user for every subsequent request. You could overcome this problem with a distributed continuation cache, but just as distributed HTTP sessions are a problem, distributing a continuation cache may not be completely practical.&lt;br /&gt;
* Continuations are more expensive than other session management techniques. I've seen little practical evidence that this has been a problem in production deployments. Still, some believe this approach will not scale as well as traditional web apps. Research on partial continuations will probably solve this problem eventually.&lt;br /&gt;
&lt;br /&gt;
To me, the powerful advantages dwarf the potential disadvantages. It's possible, even likely, that a continuation server in some language will garner enough popularity to serve as a catalyst. Respected programmers Dave Thomas, Glenn Vanderburg, and David Heinemeier Hansson have all pointed to the continuation server as an important technology to watch. ''Hackers and Painters'' author, Paul Graham, used continuations in web applications with devastating effect at Viaweb, on an application that eventually became Yahoo! Store. He's also a proponent of continuation servers. Let's see an example of the most popular web framework supporting continuations.&lt;br /&gt;
&lt;br /&gt;
== Seaside ==&lt;br /&gt;
&lt;br /&gt;
Seaside is a highly productive web development framework written in Smalltalk. Avi Bryant initially developed Seaside in Ruby, in a framework called Iowa. Early Ruby continuations had a few problems, so the original author of Seaside moved to Smalltalk. Since then, he's been improving the framework and using it to deliver commercial applications. Seaside has a few defining characteristics:&lt;br /&gt;
&lt;br /&gt;
* Seaside renders HTML programmatically. Most Java frameworks render HTML with templates. I don't know enough to advocate one method over another, but it's certainly different, and it works well in Seaside's model.&lt;br /&gt;
* Seaside has a model for components. A Seaside component manages user interface state and renders itself in HTML. Seaside components are highly reusable, and they let you think in increments smaller than a page.&lt;br /&gt;
* Seaside makes it easy to manage a link. You can specify a link with a code block, so links don't get out of sync. The framework manages them for you.&lt;br /&gt;
* Seaside is modal. This is the author's word for a continuation server approach. Seaside lets you express one web page, or multipage web flows, in a single method.&lt;br /&gt;
* Seaside's debugging is the best I've ever seen. From within the browser, you can open a web-based Smalltalk browser, complete with code. You can also inspect the values of all the objects in the application.&lt;br /&gt;
&lt;br /&gt;
Of course, you also get the advantages of using a highly dynamic language. You get a rapid feedback loop, interactive interpretation as needed, and full access to Smalltalk's excellent environments. I used the Squeak IDE for examples in this chapter. Squeak is a dialect of Smalltalk popularized by Disney.&lt;br /&gt;
&lt;br /&gt;
=== A Little Smalltalk Syntax ===&lt;br /&gt;
&lt;br /&gt;
Before we get too far, you should know a little Smalltalk syntax. Don't worry. I'm not saying that Smalltalk is the next great language; I just want you to see the power of the best continuations-based server. If you want to follow along, download the Squeak IDE from ''http://www.squeak.org/download/index.html''. Start Squeak, click on Tools, and drag a workspace and transcript window onto your desktop. Use your workspace window for input, and look to the transcript window for output.&lt;br /&gt;
&lt;br /&gt;
Smalltalk syntax is quite simple. Type an object name first, the method second, and any parameters third. Let's evaluate a few statements. In your workspace, type:&lt;br /&gt;
&lt;br /&gt;
     Transcript show: 'Hello'&lt;br /&gt;
&lt;br /&gt;
Highlight it, right-click, and then select &amp;lt;tt&amp;gt;do it&amp;lt;/tt&amp;gt; from the menu. (You can also use Alt-D before you press Enter, to evaluate the line.) You should see the word ''Hello'' in your Transcript window. &amp;lt;tt&amp;gt;Transcript&amp;lt;/tt&amp;gt; is the object, &amp;lt;tt&amp;gt;show:&amp;lt;/tt&amp;gt; is the method (Smalltalk calls methods ''messages''), and &amp;lt;tt&amp;gt;'Hello'&amp;lt;/tt&amp;gt; is a parameter.&lt;br /&gt;
&lt;br /&gt;
Like Ruby, Smalltalk supports code blocks, though the syntax is a little different. Evaluate this:&lt;br /&gt;
&lt;br /&gt;
     1 to: 5 do: [:i | Transcript show: i]&lt;br /&gt;
&lt;br /&gt;
First, you see that &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;]&amp;lt;/tt&amp;gt; mark the beginning and end of the code block. &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; is a parameter for the code block. In the declaration, you'll precede it with a colon.&lt;br /&gt;
&lt;br /&gt;
Let's try multiple statements. Smalltalk terminates statements with a period. Logic uses messages and code blocks :&lt;br /&gt;
&lt;br /&gt;
     age := 4.&lt;br /&gt;
     (age &amp;gt; 16)&lt;br /&gt;
        ifFalse: [Transcript show: 'Youngster.']&lt;br /&gt;
        ifTrue: [Transcript show: 'Old timer.']&lt;br /&gt;
&lt;br /&gt;
This bit of code sets &amp;lt;tt&amp;gt;age&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; with the &amp;lt;tt&amp;gt;:=&amp;lt;/tt&amp;gt; message. Then, it sends the &amp;lt;tt&amp;gt;ifFalse:&amp;lt;/tt&amp;gt; method to the &amp;lt;tt&amp;gt;(age &amp;gt; 16)&amp;lt;/tt&amp;gt; expression. The first code block is a parameter for &amp;lt;tt&amp;gt;ifFalse&amp;lt;/tt&amp;gt;, and gets called if the expression evaluates to &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can see the influence of the elegance of Smalltalk in Java, and other languages, too. Java's garbage collection, design patterns, and collections all share Smalltalk's influence. Consider Hibernate's use of message chaining . If a method doesn't have a return value, it simply returns itself, enabling tighter code like this:&lt;br /&gt;
&lt;br /&gt;
     cfg.add(&amp;quot;pet.hbm&amp;quot;)&lt;br /&gt;
         .add(&amp;quot;vet.hbm&amp;quot;)&lt;br /&gt;
         .add(&amp;quot;pet.hbm&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Many ideas from Eclipse have roots in IBM's VisualAge for Java , which first shared IDE code and a virtual machine with a Smalltalk product. Smalltalk syntax is wonderfully consistent.&lt;br /&gt;
&lt;br /&gt;
=== A Seaside Overview ===&lt;br /&gt;
&lt;br /&gt;
Seaside is a Smalltalk framework and a server. Remember, a continuation server is different from other web servers, so Seaside must run in its own environment. In Squeak, you'll left-click on the desktop to give you a menu (called the ''world menu''). Then, you'll select Open... → SqueakMap Package Loader. Use it to install four packages: DynamicBindings, KomServices, KomHttpServer, and Seaside, in that order. Now, your Smalltalk image has Seaside. To see it, fire up the server. In Squeak, you'll open a workspace and evaluate:&lt;br /&gt;
&lt;br /&gt;
     WAKom startOn: 9090&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;WAKom&amp;lt;/tt&amp;gt; is the name of the server. &amp;lt;tt&amp;gt;starton:&amp;lt;/tt&amp;gt; is a method that tells the server to start on a supplied port, 9090 in this case. In some ways, &amp;lt;tt&amp;gt;WAKom&amp;lt;/tt&amp;gt; is like Tomcat, or any other web application server. You can configure it by pointing your browser to:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    http://localhost:9090/seaside/config&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll see Seaside's configuration screen. Some of the items should look familiar to you. You'll see a list of registered applications, and some configuration options. Later, it will become clear that Seaside is more than Tomcat in Java.&lt;br /&gt;
&lt;br /&gt;
== A Seaside Example ==&lt;br /&gt;
&lt;br /&gt;
Under the &amp;lt;tt&amp;gt;/seaside&amp;lt;/tt&amp;gt; heading, notice the list of apps. One of the examples that you see in the configuration screen is store. Click on it. You'll see SushiNet , one of the more bizarre examples for web frameworks. In the search window, type the word &amp;lt;tt&amp;gt;Tuna&amp;lt;/tt&amp;gt;. Click on two different tunas to add them to your cart. Now click the Back button and notice that you go back to a previous page, just the way it was. Add another tuna to your cart, and you'll notice that the old tuna item is still in your cart. So, you can override the Back button behavior, as needed.&lt;br /&gt;
&lt;br /&gt;
=== Components ===&lt;br /&gt;
&lt;br /&gt;
Notice the three boxes across the top of the screen, in [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-3|Figure 8-3]]. Seaside is a component-based architecture . Each component has independent rendering, and each has a model behind it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;beyondjava-CHP-8-FIG-3&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 8-3. This Seaside application has three major components, each with independent rendering and business logic'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt143.png|This Seaside application has three major components, each with independent rendering and business logic]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This component-oriented approach often makes it much easier to design and refactor complex web screens. For example, here's the rendering for the shopping cart:&lt;br /&gt;
&lt;br /&gt;
       html divNamed: 'cart' with: [&lt;br /&gt;
         html small: [html bold: 'Your cart:'].&lt;br /&gt;
         ''html table: [''&lt;br /&gt;
 ''          cart countsAndItems do'':&lt;br /&gt;
            ''[:assoc | self renderRowForCount'':&lt;br /&gt;
                      ''assoc key of: assoc value on: html ]''.&lt;br /&gt;
           ''html spacerRow''.&lt;br /&gt;
           ''html''&lt;br /&gt;
 ''            tableRowWith:''&amp;lt;nowiki&amp;gt; ''&lt;br /&gt;
            &amp;lt;/nowiki&amp;gt;''with:''&amp;lt;nowiki&amp;gt; ''&lt;br /&gt;
            &amp;lt;/nowiki&amp;gt;''with: [html bold: cart totalPrice printStringAsCents]''.&lt;br /&gt;
         '']''&lt;br /&gt;
             &lt;br /&gt;
&lt;br /&gt;
Notice that Seaside components have code that generates HTML. Java people don't tend to like this approach either, but it's very productive in Seaside. The code in bold generates the table. First, you see the &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt; message passed to the &amp;lt;tt&amp;gt;html&amp;lt;/tt&amp;gt; object. This will generate &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt; tags around the code block. Next, you'll see a loop that processes the items in the cart, a spacer row, and a row with the totals.&lt;br /&gt;
&lt;br /&gt;
=== Complex Control Flows ===&lt;br /&gt;
&lt;br /&gt;
For this application, the most complex series of windows is the checkout. Think of how a traditional stateful application would manage the flow of control. Try out the checkout in the application and see how it works. Add a few pieces of sushi to your cart and click on Checkout. This piece of SushiNet will walk you through a few major steps:&lt;br /&gt;
&lt;br /&gt;
* You'll verify the contents of your cart. If you like your order, you can click &amp;quot;Proceed with checkout.&amp;quot; Otherwise, you'll click &amp;quot;Modify my order.&amp;quot; So the user makes a decision, and flow changes based on the user's input.&lt;br /&gt;
* You'll specify a shipping address. You can then choose whether to use this address for your billing address. Again, this decision impacts the flow of the application. If you don't want to use the same address for shipping and billing, SushiNet will reuse the component that renders the shipping address for the billing addresses. Nice.&lt;br /&gt;
* You'll enter your credit card information. If it doesn't verify, you'll go back to the same screen. If it does verify, you'll get a success screen.&lt;br /&gt;
* Users can click the Back button at any time. If the user hits the Back button after his order is submitted, he'll get a message that the page has expired.&lt;br /&gt;
&lt;br /&gt;
So, the flow looks something like [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-4|Figure 8-4]]. It's not that complicated. You've got four decisions, and based on the decisions, you route the user to the appropriate place.&lt;br /&gt;
&lt;br /&gt;
If you implemented this flow with Java servlets, you'd need to process four or more independent requests, as in [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-5|Figure 8-5]]. Each one would have to first load the current state at the beginning of a request, and store the current state at the end of the request. The web flow would be based on the user's&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;beyondjava-CHP-8-FIG-4&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 8-4. This flow has three different user decisions, and would complicate traditional web apps'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt145.png|This flow has three different user decisions, and would complicate traditional web apps]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
decisions, so you'd have several forwards. Changes in flow would lead to potentially major refactoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;beyondjava-CHP-8-FIG-5&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 8-5. Java servlets view the checkout problem as four or more independent requests'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt146.png|Java servlets view the checkout problem as four or more independent requests]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With a continuations approach, the logic becomes almost trivial, as you see in [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-6|Figure 8-6]]. You can simply look at the flow as one simple component, called &amp;lt;tt&amp;gt;Checkout&amp;lt;/tt&amp;gt;. That component can handle flows involving more than one component, or more than one page! The code looks seductively simple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;beyondjava-CHP-8-FIG-6&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 8-6. With Seaside and other continuation servers, the flow becomes a single, integrated method'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Beyond Java_I_8_tt147.png|With Seaside and other continuation servers, the flow becomes a single, integrated method]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Debugging and browsing ====&lt;br /&gt;
&lt;br /&gt;
Since you have a frozen continuation, it's easy for Seaside to provide a complete snapshot of the execution state. Seaside goes a step further and gives you access to a web-enabled browser. At the bottom of the screen, you should see a few links. Seaside creates them by default for all the applications. Notice that you can do profiling or check memory usage, but I've got something else in mind. Click on the link called Toggle Halos.&lt;br /&gt;
&lt;br /&gt;
You should see a frame with three icons appear around each component. These icons give you a full code browser, an inspector, and a cascading style sheet editor. Click on the browser icon (the first one). Notice that you can see exactly where the execution state is frozen. Next, click on (from left to right) Seaside-Examples-Store, WAStoreTask, and Go. You see the code for the store task.&lt;br /&gt;
&lt;br /&gt;
You'll see the code that implements the cart in [[Beyond Java/Continuation Servers#beyondjava-CHP-8-FIG-4|Figure 8-4]]:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
    go&lt;br /&gt;
      | shipping billing creditCard |&lt;br /&gt;
      cart _ WAStoreCart new.&lt;br /&gt;
      self isolate:&lt;br /&gt;
         [[self fillCart.&lt;br /&gt;
        self confirmContentsOfCart]&lt;br /&gt;
          whileFalse].&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;/nowiki&amp;gt;''self isolate'':&lt;br /&gt;
          ''[shipping &amp;lt;- self getShippingAddress''.&lt;br /&gt;
           ''billing &amp;lt;- (self useAsBillingAddress: shipping)''&lt;br /&gt;
 ''                        ifFalse: [self getBillingAddress]''&lt;br /&gt;
 ''                        ifTrue: [shipping]''.&lt;br /&gt;
         ''creditCard &amp;lt;- self getPaymentInfo''.&lt;br /&gt;
         ''self shipTo: shipping billTo: billing payWith: creditCard]''.&lt;br /&gt;
 &lt;br /&gt;
     self displayConfirmation.&lt;br /&gt;
&lt;br /&gt;
==== Tasks ====&lt;br /&gt;
&lt;br /&gt;
In Seaside, tasks handle business logic. Let's zero in on the code in bold. It handles everything after the cart verification. The &amp;lt;tt&amp;gt;self isolate&amp;lt;/tt&amp;gt; method takes a code block and makes sure everything in the block is an atomic operation, or a transaction. The next line of code is interesting:&lt;br /&gt;
&lt;br /&gt;
                   &lt;br /&gt;
 ''    [shipping &amp;lt;- self getShippingAddress''.&lt;br /&gt;
&lt;br /&gt;
This statement actually presents the &amp;lt;tt&amp;gt;getShippingAddress&amp;lt;/tt&amp;gt; web page to the user, and puts the resulting address into the shipping address. You can see how the framework inverts control. Now, instead of the browser being in control, Seaside lets you direct traffic from the server. The next three lines show a decision:&lt;br /&gt;
&lt;br /&gt;
                   &lt;br /&gt;
 ''    billing &amp;lt;- (self useAsBillingAddress: shipping)''&lt;br /&gt;
 ''                  ifFalse: [self getBillingAddress]''&lt;br /&gt;
 ''                  ifTrue: [shipping]''.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;useAsBillingAddress&amp;lt;/tt&amp;gt; method presents the decision screen. The expression &amp;lt;tt&amp;gt;(self useAsBillingAddress: shipping)&amp;lt;/tt&amp;gt; returns a Boolean, and will trigger either the &amp;lt;tt&amp;gt;ifFalse:&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ifTrue:&amp;lt;/tt&amp;gt; methods. &amp;lt;tt&amp;gt;ifFalse:&amp;lt;/tt&amp;gt; will actually trigger the code block &amp;lt;tt&amp;gt;[self getBillingAddress]&amp;lt;/tt&amp;gt;, which sends yet another web page to the user.&lt;br /&gt;
&lt;br /&gt;
Though the Smalltalk syntax may seem awkward, if you're a Struts or Servlet developer, you're probably smiling right now. This approach frees you to work at higher abstractions. You can roll up several components, or pages, into a single task, and the continuation server keeps the management simple. State and navigation issues just melt away.&lt;br /&gt;
&lt;br /&gt;
== So What? ==&lt;br /&gt;
&lt;br /&gt;
I'm pretty sure that continuation servers will prove to be important. I'm equally sure that Seaside is not a killer app that will suddenly spring Smalltalk into the mainstream. Smalltalk has 30 years of reputation to overcome. In this time, Smalltalk has rarely been more than an academic language with small forays into commercial development. The Smalltalk community is smart and has technical vision, but I've not yet seen the marketing leadership that will break Smalltalk into the mainstream. After 30 years, that's not likely to change.&lt;br /&gt;
&lt;br /&gt;
Continuation servers do have some minor hurdles to overcome:&lt;br /&gt;
&lt;br /&gt;
* So far, the servers require ugly, temporary URLs, because each continuation must have a unique identifier. Users don't like uglier URLs. Like Amazon, Seaside works around this limitation by providing a meaningful piece of the URL, followed by the continuation ID.&lt;br /&gt;
* Continuation servers will not scale as well, because saving continuations is stateful and expensive, though if you think about it, the problem is not quite as bad as it could be. Most of the continuations in a server will have common code for the framework. Only the last part of the call stack should be different from one continuation to the next. Partial continuations should provide a good performance boost.&lt;br /&gt;
* So far, the best servers are on academic languages. Lisp, Smalltalk, and Ruby may be holding them back. And of course, continuation servers may help break one of those languages closer to the mainstream.&lt;br /&gt;
&lt;br /&gt;
Still, in the end, continuation servers will play a role, because they're a much more natural and powerful abstraction, and they represent a much more natural way to program. Systems continually get more processing power, and both short-term and long-term storage get cheaper. Productivity eventually trumps all else. In the end, continuation servers are fast enough. Higher abstractions make us more productive. If you held a gun to my head and forced me to make a prediction, I'd guess that continuation servers will evolve and break into the mainstream, but not on Java, or a derivative like C#. Such a language would have to simulate continuations. The concept is cleanest and purest when it is implemented on a more dynamic, higher-level language. I'd guess that continuation servers, in a language like Python or Ruby, may well prove to provide the foundation for all web application servers, in some not-too-distant future.&lt;/div&gt;</description>
			<pubDate>Tue, 11 Mar 2008 21:49:32 GMT</pubDate>			<dc:creator>Docbook2Wiki</dc:creator>			<comments>http://commons.oreilly.com/wiki/index.php/Talk:Beyond_Java/Continuation_Servers</comments>		</item>
	</channel>
</rss>