Discussions

News: A Stateless Web experience with continuation server

  1. Common Web development is a sometimes sweet but often bitter experience. Java Web developers go to great lengths to provide a stateless model, but the resulting performance and ease of deployment make the efforts worthwhile.

    This article explores a radically different approach to Web development called the continuation server. By offering a stateful programming model without giving up the scalability inherent in statelessness, continuation servers make Web application development much easier.

    Threaded Messages (62)

  2. Minor clarification for RIFE[ Go to top ]

    I just wanted to chime in to say that RIFE supports both the native Java web continuations and the state machine continuations (thus both the 'Implement continuations' as the 'Simulate continuations' approach). I never really accentuated the 'flow continuations', but since SWF does, we might as well come out for those capabilities of our flow engine too.

    For those that want to know some more about continuations, I uploaded the presentation I did at TheServerSide Java Symposium last week:
    http://uwyn.com/resources/flow_with_continuations_tssjs_2006.pdf
    http://uwyn.com/resources/flow_with_continuations_tssjs_2006.mov

    Additionally, last time I checked, Jetty 6 (when it announced its continuations support), it also simulated continuations by putting threads into a wait state and didn't implement the feature fully. Maybe that has changed in the meantime though and I have missed it. If someone knows more about this, please tell me.
  3. Minor clarification for Jetty[ Go to top ]

    Jetty 6 (when it announced its continuations support), it also simulated continuations by putting threads into a wait state and didn't implement the feature fully. Maybe that has changed in the meantime though and I have missed it. If someone knows more about this, please tell me.

    The wait state implementation is just the fall back Continuation in Jetty, used for non-NIO connectors (which
    cannot release the thread) and if the webapp is deployed in
    another servlet container.

    The main implementation in Jetty used a Throwable to extract the thread from the current servlet/filter and arranges for the HTTP request to be retried (within the container) when the continuation is resumed.

    I know that Geert takes exception at the use of the name "continuation" for this mechanism. While the Jetty mechanism is indeed not a general purpose continuation for application logic, it certainly meets the definition of a continuation within the context of HTTP request handling, where the state that is suspended and resumed is the HTTP request itself.

    The code clarity, features and performance that Jetty obtains by using the continuation paradigm is a validation of the abstraction and supports the assertion that continuations can be more generally applicable to application logic that can avoid decompostion into request/response handlers.

    I would hope that Jetty continuations would be a useful mechanism used within the implementation of more generic application continuations.
  4. Without the hyperbolic claims in the original article. Storing your state on the client in querystrings, hidden forms etc. is as old as web development and if you claim it as some kind of unique benefit of continuation servers then you should expect to get flamed.
  5. Without the hyperbolic claims in the original article. Storing your state on the client in querystrings, hidden forms etc. is as old as web development and if you claim it as some kind of unique benefit of continuation servers then you should expect to get flamed.



    CONTINUATION SERVERS ARE NOT MORE SCALABLE THAN WEB APPLICATION SERVERS.
    CONTINUATION SERVERS ARE NOT MORE SCALABLE THAN WEB APPLICATION SERVERS.
    CONTINUATION SERVERS ARE NOT MORE SCALABLE THAN WEB APPLICATION SERVERS.
    CONTINUATION SERVERS ARE NOT MORE SCALABLE THAN WEB APPLICATION SERVERS.
    CONTINUATION SERVERS ARE NOT MORE SCALABLE THAN WEB APPLICATION SERVERS.
    CONTINUATION SERVERS ARE NOT MORE SCALABLE THAN WEB APPLICATION SERVERS.


    That's not what I've said.


    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.
    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.
    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.
    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.
    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.
    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.



    This is the meat of the scalability claims. Old client/server models, and database servers, and many other types of application servers bind resources to a user request. Web servers with AJAX will too, if you're not careful. (Ironically, Jetty 6 is looking to continuations to solve this problem.)

    No hyperbolic claims were made, except that continuation servers make programming web applications much easier!!!

    Re. scalability, for the last time, I'm not claiming that continuations are much more scalable than WebLogic or WebSphere or Tomcat or any other web server. Those all run on a stateless protocol by default, and the programmer has to enable your application to support the statefullness. Thus, you have to code stateful apps using a stateless model, and you do so because it's more scalable. You don't have to bind resources to an individual application beyond the time that it takes to service the request. (Session storage is a community resource that may be expired at need.)

    Continuation servers maintain that scalability advantage by automating your state management through putting a continuation in your session for you, but give you the ability to code your application as if you were on a stateful (e.g. client/server) model. It's a tremendous advantage, from a programming perspective. I've spoken directly with Patrick Lightbody, Keith Donald, Howard Lewis Ship, Geert Bevin, and many others about this approach, or closely related approaches. All agree that the model is a big win.

    Some disagree about the implementation of the state snapshot. People like Patrick and Geert come down on the side of coding Java continuations (Java doesn't support them, but Geert has built his own custom continuations, and WebWork uses them), with few coding restrictions (e.g. no forced API for a state machine) make the programming experience much nicer. Some, like Keith Donald, like the state machine approach, and WebFlow effectively extends the state machine approach to blur the lines between continuations and state machines somewhat.

    But the idea that I'm making exagerated claims about scalability is way out in left field...it reflects a lack of understanding based on the three early kneejerk flames in this thread. And this article, combined with the referenced seaside article, makes all of this clear.
  6. Actually you are quite right. Sorry about that. Funny how reading comments changes your memory of the original article :(.

    Though I think it should be:
    CONTINUATION SERVERS CAN BE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.

    The fact that it is a continuation server doesn't imply that the state is necessarily stored on the client.
  7. Funny how reading comments changes your memory of the original article :(.

    :)

    no problems...I've been guilty of the same.
  8. Kneejerk? Alternatives exist.[ Go to top ]

    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.

    I just re-read that article, and the 'kneejerk reaction' stays for a few items in there.

    One scentence after
    a user experience with stateless performance
    there is
    The framework can identify individual continuations within a URL and store that continuation in the session.
    . So you have 'stateless performance' as you don't 'bind resources to the server' yet you are storing continuations in the session.

    Ok, as an alternative, you can store them on the client. Which saves you from binding resources to the server, but cost you extra in terms of bandwith and CPU - you have to serialize/ deserialize that continuation somehow, and you have to rebuild your state first when a request comes in. This *might* even be more expensive in than storing the continuation in the session and cluster it, totally depending on how you do that, what your usage statistics look like, etc. Now the part that I missed was partial continuations. That's a nice optimization, though it probably limits your 'stateful way of programming' somewhat.

    Whether you store state in the session or on the client, there are alternatives to continuations that give you a similar stateful programming experiences. All the component based frameworks do that, and they support the backbutton etc too, and some support communicating state via clients. Both your article and your answers in this thread completely fail to mention that, while you bring continuations forward as the novel solution for all us coders out there that doing our state management by hand.

    As a final note: it might not be clear from my responses in this thread, but I think continuations *are* a nice alternative to have in our programmer's toolbox. I think they are nice fit for wizard like applications, and with the proper server support like Jetty is building in, they might lead to good optimizations for e.g. ajax functionality.

    What I like less about continuations is that using continuations in the way it is usually promoted is flow oriented. I don't agree with what seems to be a prevalent idea nowadays that you have to design your web applications with flow in mind. IMVHO, this is a suboptimal, non-intuitive way of building GUIs and I am glad that idea never got popular in - say - GUI development with Swing. I find the concept of having a screen with a stack of nested components where sometimes you replace one of them - e.g. a panel - and other times you replace the whole screen - a page - more powerful and a better fit for object oriented programming. For frameworks that are setup to support that, like Wicket, *I think* continuations are not a good match as they don't have the granularity needed when working with an component tree. After our first contacts with Geert we seriously considered it, but we never found enough reason to step away from the memento-like pattern we are using today, as this seems to be a more effictive, tunable way to keep state snapshots for our case.

    Your article was a smooth read, but imo it could have been more objective and precise.
  9. Kneejerk? Alternatives exist.[ Go to top ]

    CONTINUATION SERVERS ARE MORE SCALABLE THAN STATEFULL APPLICATION SERVERS.
    I just re-read that article, and the 'kneejerk reaction' stays for a few items in there.One scentence after
    a user experience with stateless performance
    there is
    The framework can identify individual continuations within a URL and store that continuation in the session.
    . So you have 'stateless performance' as you don't 'bind resources to the server' yet you are storing continuations in the session.Ok, as an alternative, you can store them on the client. Which saves you from binding resources to the server, but cost you extra in terms of bandwith and CPU - you have to serialize/ deserialize that continuation somehow, and you have to rebuild your state first when a request comes in. This *might* even be more expensive in than storing the continuation in the session and cluster it, totally depending on how you do that, what your usage statistics look like, etc. Now the part that I missed was partial continuations. That's a nice optimization, though it probably limits your 'stateful way of programming' somewhat.

    A fair and balanced criticism. It's not really that expensive, though. You really want to snapshot everything over, say, servlet. Many frameworks can go even higher. The rest can be captured exactly once.

    The real danger to scalability is that you make it too easy to add things to the session, but that's a philosophical decision: should you give your users sharp tools that are potentially dangerous? I say yes.

    Re. the cost of serializing state, take your pick. Automate it and save some time, or manually do everything, and save performance. I'd submit that we choose automation often, to make things more convenient and correct: persistence frameworks over straight JDBC, higher-level programming languages, etc. The question is are we ready for a higher abstraction? I submit that many of us are.
    Whether you store state in the session or on the client, there are alternatives to continuations that give you a similar stateful programming experiences. All the component based frameworks do that, and they support the backbutton etc too, and some support communicating state via clients.
    All component-based frameworks don't do that, at least, not in equal measure. Most, in fact, make it easy for YOU to do it. Most don't seek to invert control at all. Rife, Coccoon, soon WebWork, Seam and WebFlow are the major players doing it now...and probably some others I'm not familiar with.

    Howard Lewis Ship and I have had extensive conversations on this topic. The continuation isn't the silver bullet, but the programming model is much nicer if you choose to go that route, if you're seeking to represent your inter and intra page flows in Java. But the approach is at least more interesting than you're making it out to be here. We're talking about a much more transparent programming model, that can encapsulate component flow as easy as page flow. It's inversion of control for the web server.
    Both your article and your answers in this thread completely fail to mention that, while you bring continuations forward as the novel solution for all us coders out there that doing our state management by hand.
    At this point in your response, i'm about ready to check out. It's a one-day, 2000 word introductory article. I could not possibly hope to cover all of the nuances of continuation servers, even if I were qualified to do so. I still think that we could all go a long way by seeking to understand before seeking to flame. That's the foundation of a good on line community.

    And *you know* that the majority of Java programmers *do* manage state by hand. You know because you're working on a framework that provides an alternative approach. Most of us still use Struts. I never deny that there are other approaches, not even once. I even show some of the more closely related ones in the article.
    As a final note: it might not be clear from my responses in this thread, but I think continuations *are* a nice alternative to have in our programmer's toolbox. I think they are nice fit for wizard like applications, and with the proper server support like Jetty is building in, they might lead to good optimizations for e.g. ajax functionality.

    What I like less about continuations is that using continuations in the way it is usually promoted is flow oriented. I don't agree with what seems to be a prevalent idea nowadays that you have to design your web applications with flow in mind. IMVHO, this is a suboptimal, non-intuitive way of building GUIs and I am glad that idea never got popular in - say - GUI development with Swing. I find the concept of having a screen with a stack of nested components where sometimes you replace one of them - e.g. a panel - and other times you replace the whole screen - a page - more powerful and a better fit for object oriented programming. For frameworks that are setup to support that, like Wicket, *I think* continuations are not a good match as they don't have the granularity needed when working with an component tree. After our first contacts with Geert we seriously considered it, but we never found enough reason to step away from the memento-like pattern we are using today, as this seems to be a more effictive, tunable way to keep state snapshots for our case.Your article was a smooth read, but imo it could have been more objective and precise.

    Fair enough. It's actually not clear that you think continuations are useful, because you never stated it. You were too busy piling on. I've long been a fan of Wicket, and I would have liked to talk about on this thread, rather than the crap that we had to wade through to get here.

    Would like to do so over a beer some time. Are you going to be at JavaZone? (Don't know if I'll be at JavaPolis or not.)
  10. Kneejerk? Alternatives exist.[ Go to top ]

    It's actually not clear that you think continuations are useful, because you never stated it. You were too busy piling on.

    Yeah, I'm a bit hot headed at times... sorry.
    rather than the crap that we had to wade through to get here. Would like to do so over a beer some time. Are you going to be at JavaZone? (Don't know if I'll be at JavaPolis or not.)

    I think we got invited for JavaZone, but I'm not sure about the current status. We're also invited for TSSS Europe.

    Sure, if we're at the same conference somewhere let's have a beer. Or if you ever stop by Seattle (I'm currently relocating, and it's also where Wicket's founder, Jonathan Locke lives) you're more than welcome too.
  11. I think continuations will be useful to Wicket (under the covers) for implementing our RFE for AjaxPushBehavior, but I would prefer an alternative that allows me to avoid throwing an exception to unwind the stack since I can definitely return from my user code normally. Exceptions can be very expensive on certain operating systems and processor architectures.

    For Wicket, I think all we really need is access to an interface like this from our Servlet (maybe through a standard extension mechanism?):

    public interface RequestContinuation
    {
        public void setRequestContinued(boolean);
        public boolean getRequestContinued();
    }

    This would just turn on or off whether the socket for a given request is closed or stays open and gets reused by the next request instead... I guess you could set an expiration timeout too... or maybe I missed something...
  12. Ignoring the "framework" aspect (that continuations may or may not make web-programming easier), I don't see how continuations make a (web)server more scalable: There doesn't seem to be much of a difference to save the "state" via continuation or together with an "enclosing" session object - provided that no "should-be-shared" "state" (cache?) is saved, but that applies in either case.
    Can someone explain what I'm missing?

    regards,

    Messi
  13. Scalability[ Go to top ]

    In the Jetty 6 model, the scalability comes from the fact that the sockets are freed up when longer running tasks are waiting for an event that indicates their completion. By using continuations, you can free up the sockets and with real continuations event the threads and only reactivate them when the result is actually available.
  14. Stateless makes the app server more scalable. Continuation servers make them scale like stateless servers, but program like stateful servers.

    But you don't use continuation servers for scalability...you use them to be more productive and a statefull programming model. Very big win. We'll all be using them soon.
  15. By offering a stateful programming model without giving up the scalability inherent in statelessness

    That's just nonsense. Those continuations are either stored on the server, having an impact on scalability viewed from a memory and network (clustering) perspective, or they will be carried on by the client, having an impact on the bandwidth and CPU utilization (encoding/ decoding). The latter having some pretty serious security implications too btw.

    What seems to me as a big drawback compared to e.g. how Wicket implements state handling (it keeps track of a number of state changes akin to memento), is that using continuations doesn't leave you with much opportunities to optimize. It's just the whole current state/ stack. You can't single out the elements you don't need, and you can't provide your own optimized translation of this state.
    We'll all be using them soon.

    And witness the start of yet another hyped term.

    I don't agree with that statement. Reentrant continuations might be a nice construct to have in Java - for some exceptional cases. Maybe. Though there are a number of drawbacks too, as you are basicially reintroducing jump/ GOTO again. It seems that it was a deliberate choice to leave that out of Java and only support exceptions (the escape variant).
  16. That's just nonsense. Those continuations are either stored on the server, having an impact on scalability viewed from a memory and network (clustering) perspective, or they will be carried on by the client, having an impact on the bandwidth and CPU utilization (encoding/ decoding).

    Surely a couple of query parameters or hidden form parameters aren't any noticeable impact on bandwidth or CPU usage, in the case simulated continuations are used, or the state storage or implemented continuations is implemented with a client-side store?
    It's just the whole current state/ stack. You can't single out the elements you don't need, and you can't provide your own optimized translation of this state.
    See, that's where you're seeing it wrongly, you actually can. In a web environment you only capture partial continuations. This is the path from when the web request is handled by an action/component/element execution until the moment you decide to pause the execution. In practice this is very often only one or two calls deep, and is very lightweight. Also, anything you do inside separate methods that are called priorly to executing the pausing is not captured in the local variable state. This is a very easy and intuitive way to 'isolate' expensive state elements and only worry about the results. Additionally, in RIFE's pure Java implementation, you're actually able to tailor the cloning behavior of each continuation step as you do with regular Java object cloning. This allows you to decide that some variables shouldn't actually be cloned and only be copied by reference value, in case you need to have some parts that behave as stateful across requests and are shared across continuations.
  17. See, that's where you're seeing it wrongly, you actually can. In a web environment you only capture partial continuations. This is the path from when the web request is handled by an action/component/element execution until the moment you decide to pause the execution.

    Ok, I see where you're getting at. That must make a big difference indeed. I had serializing - encoding - decoding - deserializing in mind in a comparable way in which it would work for a component tree.
    In practice this is very often only one or two calls deep, and is very lightweight. Also, anything you do inside separate methods that are called priorly to executing the pausing is not captured in the local variable state. This is a very easy and intuitive way to 'isolate' expensive state elements and only worry about the results.

    Not exactly my idea of encouraging good code practices, but ok, it's a nice and simple to understand optimization.
    Additionally, in RIFE's pure Java implementation, you're actually able to tailor the cloning behavior of each continuation step as you do with regular Java object cloning. This allows you to decide that some variables shouldn't actually be cloned and only be copied by reference value, in case you need to have some parts that behave as stateful across requests and are shared across continuations.

    Sounds pretty cool! Any pointers on how that looks, or is it just rtfm?

    I understand how it works now and I do think it can be a relatively cheap way to get a semi stateful programming experience. It's not exactly the kind of stateful object oriented programming I had in mind however, but that again seems to be matter of taste.

    I'm sorry about putting it too strong with 'That's just nonse'.
  18. Sounds pretty cool! Any pointers on how that looks, or is it just rtfm?I understand how it works now and I do think it can be a relatively cheap way to get a semi stateful programming experience. It's not exactly the kind of stateful object oriented programming I had in mind however, but that again seems to be matter of taste.I'm sorry about putting it too strong with 'That's just nonse'.

    This is a quick example for this, continuations are used to handle the intermediate steps during an order checkout process. By providing a custom clone() implementation, the individual steps are prefilled with earlier submitted data if the user has pressed the back button.

    http://rifers.org/08_advanced_continuations

    source code here:
    http://rifers.org/08_advanced_continuations/src/implementations/tutorial/advancedcontinuations/Order.java.html
  19. geert, how does this cluster if continuations are so scalable?
  20. geert, how does this cluster if continuations are so scalable?
    Hi Jacob, note that I have nowhere expressed myself about the scalability of continuations, and hence not about clustering. I have not used continuations in a clustered environment yet. Obviously, though, if you put the continuations state in the client side (with the simulated flow continuations), you get clustering for free with a simple round robin approach. The native approach is more complicated though, and the current released version isn't usable in a cluster yet. However, we're working on two solutions for this:
    1. making continuations serializable and thus storable in any possible backend like for example a distributed cache
    2. adding a second identifier that is tied to one particular continuation tree (conversation). This id typically stays the same for each user (though a user can have multiple) and spans the continuations that are a logic sequence and an "island of functionality". You can then simply use this id to always direct the same treeid to the same server, and still use a round robin for the initial step.
  21. geert, how does this cluster if continuations are so scalable?
    Hi Jacob, note that I have nowhere expressed myself about the scalability of continuations, and hence not about clustering.

    Just wondering man :-) It looks fun, I just worry about how it would affect 'traditional' clustering in app server farms.
  22. geert, how does this cluster if continuations are so scalable?
    The stateless scalability comment is against other stateful programming models, like client/server, where resources (database connections, threads, server connections, etc) are bound to a user.

    The stateful programming model is against other stateless programming models, like the web, with manual state management.

    So it's not inherently more scalable than other approaches. If you want to cluster, you need to sticky-bit, meaning serve returning clients from the same box, or distribute your session cache. I favor sticky-bit approach.

    -bt
  23. Stateless makes the app server more scalable. Continuation servers make them scale like stateless servers, but program like stateful servers.But you don't use continuation servers for scalability...you use them to be more productive and a statefull programming model. Very big win. We'll all be using them soon.

    How?

    From the article:
    Continuations can be expensive. Making it easier to put data into a session means more people will put more data into a session. A framework designer can lessen the expense by using an approach called partial continuations, where the framework saves only the application-specific portion of the continuation.

    and
    It assures statelessness between requests. The framework can identify individual continuations within a URL and store that continuation in the session.

    and
    It gives you a stateful programming model. The framework can restore any continuation at any time. If the user submits a form a second time, the continuation can pick up processing at an earlier point in time.

    and
    But the state machine is a nice approach to continuations. A state machine is a program with well-defined transitions from state to state. By far, the most popular Java framework with a heavy continuation-server influence is Spring's Web Flow. Web Flow models the navigation between the pages of a user interface as a state machine.

    So you can do stateful programming to a stateless statemachine that scales like a stateless server but gets bogged down when too much state gets put into session?

    Next thing you're going to be telling me is that it offers transient persistence of the stateless state.

    It sounds to me like both the scalibility and productivity increase come from is hiding something programmers do poorly (i.e. deciding what to put into session scope) in a framework that makes smarter decisions, and can do black distributed cache magic in the background, so continuation-based applications scale almost as well as stateless applications. Of course, the framework is still being ruled by the same programmer, who can manage to block the framework from working it's magic.

    In other words, continuation servers don't always make applications more scalable, and probably rarely make them as scalable as pure stateless applications, but maybe almost as scalable.

    I'm not arguing that continuation servers are a bad idea. The claims being made just sound like hyperbole. I would love to be proven wrong.
  24. Stateless???[ Go to top ]

    There isn't anything stateless about this, a couple of problems I see:

    1) My memory footprint is substantiallly bigger with continuations (to store each state), how is this more scalable?

    2) Un-placing an order when I hit the back button is NOT expected behavior, using this approach will take some user education and can't be done wholesale.

    3) If we're talking about retail / e-commerce sites, appending a transaction id to every URL is a great way to get your site deep sixed in search engine rankings.
  25. Stateless???[ Go to top ]

    Stateless in that you do not bind server resources to a user. ie. why the web is stateless in the first place...it's not to make YOUR life easier.

    Stateful in that you don't have to manage it yourself. Of course there is a cost.

    If you need to scale at all costs, you probably shouldn't use them...then again, if that were the only consideration, we'd all be using c++, or c, or assembler.

    In practice, continuations, especially partial continuations, don't cost much. Do a little research before you slam the idea. Read a little seaside code. Try a little WebWork or Rife and see how much easier it makes your programming.
  26. Stateless???[ Go to top ]

    Stateless in that you do not bind server resources to a user. ie. why the web is stateless in the first place...it's not to make YOUR life easier.

    Just to help making it clearer, Bruce is talking about the user *experience* here as far as I can tell, not about the technical implementation being stateful or stateless. The title of this thread is just badly chosen, in his article it is quite clear.
  27. Stateless???[ Go to top ]

    1) My memory footprint is substantiallly bigger with continuations (to store each state), how is this more scalable?
    It's more scalable than stateless approaches because you don't bind the session to server side resources.
    2) Un-placing an order when I hit the back button is NOT expected behavior, using this approach will take some user education and can't be done wholesale.
    So don't. Invalidate past sessions. Very easy to do.
    3) If we're talking about retail / e-commerce sites, appending a transaction id to every URL is a great way to get your site deep sixed in search engine rankings.
    Check Amazon urls...they seem to be ok. Seaside urls are very similar.

    Really...you need to do a little research before slamming an introductory article out of hand. WebWork, Rife, Spring, and JBoss are all getting some milage out of this technique or similar techniques.
  28. Stateless???[ Go to top ]

    Really...you need to do a little research before slamming an introductory article out of hand. WebWork, Rife, Spring, and JBoss are all getting some milage out of this technique or similar techniques.

    A while back on Java.net, I asked you how you thought this compared to JBoss Seam-- is this what you are referring to?
  29. Research???[ Go to top ]

    How am I not binding session to server side resources? Where, prey tell, are these continuations stored?

    And as far as amazon URL's, they use mod_rewrite to pass parameters, not URL arguments. Seems maybe you ought to take your own advice and do some research of your own.
  30. Research???[ Go to top ]

    How am I not binding session to server side resources? Where, prey tell, are these continuations stored?And as far as amazon URL's, they use mod_rewrite to pass parameters, not URL arguments. Seems maybe you ought to take your own advice and do some research of your own.
    Hi Adam, nothing mandates you to store them on the server. The simulate flow continuations model in RIFE actually stores them on the client by default. We're working on similar support for the storage of the pure Java continuations. The storage of the location and the state is unrelated to the concept of continuations.
  31. Research???[ Go to top ]

    How does this cluster?
  32. Research???[ Go to top ]

    The whole scalability model of the web is based on statelessness. We use a stateless model because with so many potential clients, we can't bind each one to his own server connection, database connection, etc. We use the session to mitigate that stateless model within a conversational app by storing data that you're likely to need again in a session...can be in url, db, server, http session, stateful session bean, etc. All conversational systems must hold state.

    Continuations automate that conversational data storage. As the article states, there are some limitations.

    1) It's slightly more expensive than doing everything manually (but only slightly...see partial continuations), but adds a much cleaner user experience, and a fraction of the lines of code for session management. In short, it's a programming model with a higher level of abstraction...you pay some, and get a lot.

    2) You need to add data to the URL. But this style of URL (style, not purpose) is very similar to the Amazon URL that's half pretty to enable book marking and search engine support, and half ugly. Seems to work ok for them.

    3) You must map any returning user to the same session.

    This programming model is now becoming very popular in the Java side. Rife, Struts (through WebWork), Spring, JBoss are all using continuations, or the closely related approach of a state machine, to provide a richer programming experience, and to mitigate complexity around things like back button support, and the support for some types of AJAX applications.

    The approach has been used for years outside of Java, most notably in the ViaWeb application (became yahoo stores, was rewritten in C++), and in a bunch of Seaside applications, and in a few other Lisp, Python, Perl and Ruby frameworks...but the best of all is Seaside.

    The idea is promoted as one of the top 5 technologies to watch (Sam Ruby), powered the development of DabbleDB (won the best-in-show at a recent conference...forget the name,) and is widely recognized as an important advancement in web programming.

    This thread is becoming a little too contentious for my taste...I'm out. If you're interested in exchanging ideas, drop me a note.
  33. Bruce,

    Actually people have done research on this topic and the value add proposition here is coroutines -- not continuations. Continuations are one way to implement coroutines. And I will agree that concurrency programming models are going to become more visible in the future for all applications.

    The problem with this whole continuations "epiphany" is that book writing grandstanders are promoting it as a "radically new thing" as you state in your article -- but they've been around for decades. Coroutines have nothing to do with scalability, it's about coordination of cooperating tasks, in addition to others. And they are not as simple as you portray especially when multiple actors are involved. They can be quite complicated so I don't think your "they're so easy" argument holds on this front either. You are still limited to the coordinator for scalability metrics and as other's have put it, resource managment and locking becomes somewhat of a black art to do properly.

    And on final note, you're known for writing contentious articles to so to run away at this point because people may not agree is a little cowardly , don't you think?
  34. Actually, for me the value add is in the continuations. I don't need coroutines. I need continuations (or a technology similar to it) for virtually every web app I write. In fact, I prefer the "continuations for dummies" approach that Seam uses. I do hardly anything and it does all the ugly work.

    As I think more about this I have no idea where you get the idea that the real benefit is in coroutines. How many people need that functionality? I'm trying to think of the last time I was sitting at my computer and thinking, "gee, if I only had coroutines life would be so much better!" but I can't think of any time like that because IT'S NEVER HAPPENED. Perhaps I'm too simple-minded to realise I need them but guess what...so are 90+% of the developers in this world.

    As for Tate...yeah, I can see why you have a beef with him. Hell, I'm tired of all the Ruby Happy Juice he keeps drinking but you should restrict your attacks to when he says stupid things and not something that's actually useful. And he's right about continuations...soon everyone will be using them.
  35. cowardly...[ Go to top ]

    And on final note, you're known for writing contentious articles to so to run away at this point because people may not agree is a little cowardly , don't you think?

    Guess I'm getting baited back into this one. Since this is addressed directly to me.

    I like to talk about ideas that advance the state of the art. When people invest too much of their identity into a technology or project, they feel insulted. When this happens, at some point, meaningful exchange of ideas ends, and idea exchange ends, degenerating into flame baiting. I don't have the time for that kind of dialogue, I don't think it is productive, and I don't think that's cowardly.

    I just would rather be part of a conversation where ideas are being exchanged without attacking the person, like cowardly, nonsense, etc. They add nothing to the flow of the technical ideas in play.
  36. nonsense[ Go to top ]

    like cowardly, nonsense, etc.

    I - again - appologize for using 'nonsense'. BUT, look at what you wrote:
    Stateless makes the app server more scalable. Continuation servers make them scale like stateless servers, but program like stateful servers.

    If you put it that binary, without even the slightest hint of how/ why that might be, you can expect some flak. They don't scale like stateless servers (you mean like static files from Apache?), though they might scale better then...
    Very big win. We'll all be using them soon.
    and
    blockquote>When people invest too much of their identity into a technology or project, they feel insulted.
    As if that isn't asking for contentiousness.
  37. etc[ Go to top ]

    like cowardly, nonsense, etc.
    I - again - appologize for using 'nonsense'. BUT, look at what you wrote:
    Stateless makes the app server more scalable. Continuation servers make them scale like stateless servers, but program like stateful servers.
    If you put it that binary, without even the slightest hint of how/ why that might be, you can expect some flak. They don't scale like stateless servers (you mean like static files from Apache?), though they might scale better then...

    Are you confusing stateless with static? If so, I see the disconnect. I'm using stateless in the sense of most web application servers. Web servers are by definition stateless...you have to work within the framework of the web server to maintain context for any stateful conversation. We have to trade simplicity for scalability...and that's the point. Coding stateful programs with a stateless programming model is time consuming, and frustrating, and error prone and hard.

    If you can leave behind that state management, (e.g. stateful programming model), and at the same time keep the benefits of stateless web servers (e.g. stateless performance and scalability), it's a big win.
    When people invest too much of their identity into a technology or project, they feel insulted.
    As if that isn't asking for contentiousness.

    Don't see why that statement has to be 'asking for it'. Is true of any good professionals with passion. Java's a great language...has come a long way in 10 years. But is it the ends or the means? That's the question, no? Why can't you criticize it, or say there are better ways of doing things that we can learn from? If Java is the means for getting something done, you should invest no more passion in it than a nice hammer. Someone comes out with a nail gun, says it's great, no big deal. Go buy a nail gun if it helps you do your job better (like driving in 10,000 nails while framing) or don't if it doesn't (like replacing the hammer you're keeping one for handy jobs around the house.)

    But there are things you can't say in this community (and most others). Because to some, Java has become the end. As in, it feeds my family. Or has fed me for 10 years. Or I can really make Java sing, and much better than anything else I've tried. Up until this last year, I was in that camp, so I understand. There are still some technologies and creations I hold a little too closely, and get a little too insulted when people talk bad about them. I understand, I just don't want to be part of the constant bickering that these topics have become.

    As a result, I pulled a talk from tssjs, pulled my Java blog, and am slowly working out of this community. I still think I could do some good, but when fairly benign articles like this one get receptions like these, I think it's time to move on. This kind of discussion is simply not productive for me.
  38. etc[ Go to top ]

    Are you confusing stateless with static? If so, I see the disconnect. I'm using stateless in the sense of most web application servers. Web servers are by definition stateless...you have to work within the framework of the web server to maintain context for any stateful conversation. We have to trade simplicity for scalability...and that's the point. Coding stateful programs with a stateless programming model is time consuming, and frustrating, and error prone and hard. If you can leave behind that state management, (e.g. stateful programming model), and at the same time keep the benefits of stateless web servers (e.g. stateless performance and scalability), it's a big win.

    It sure is. That the whole idea why I am being involved in one of those initiatives. My whole point is - as you pointed out in a later reply yourself - that there are always trade-offs. It looks like Rife found a good way to minimalize this trade off. And that's great. It's great for it's users and it's great for the competitors who even have to try harder to compete on this field.
    When people invest too much of their identity into a technology or project, they feel insulted.
    As if that isn't asking for contentiousness.
    Don't see why that statement has to be 'asking for it'. Is true of any good professionals with passion. Java's a great language...has come a long way in 10 years. But is it the ends or the means? That's the question, no? Why can't you criticize it, or say there are better ways of doing things that we can learn from? If Java is the means for getting something done, you should invest no more passion in it than a nice hammer. Someone comes out with a nail gun, says it's great, no big deal. Go buy a nail gun if it helps you do your job better (like driving in 10,000 nails while framing) or don't if it doesn't (like replacing the hammer you're keeping one for handy jobs around the house.)But there are things you can't say in this community (and most others). Because to some, Java has become the end.
    It's natural to move on after a while. I might have misinterpreted it, but I took it as a pinch towards me and Jacob being two framework writers 'having invested too much of their personality'. I think there is a big difference between wanting to get technical merrits communicated honestly and promoting our bloated egos. Speaking for myself, I really don't care that much about any certain technology for personal reasons. What I do care about is the sorry state web app development is in, and I'm ready to speak up for and contribute to the things I believe in.

    I'm sorry how threads like this end up sour too. I guess it's the medium, and the talk would have been entertaining with a good beer within reach.
  39. And on final note, you're known for writing contentious articles to so to run away at this point because people may not agree is a little cowardly , don't you think?

    In other words, you're bitter that Bruce won't participate in being the whipping boy for your Ruby rage.
  40. You get Back button support thrown in for free. Because you literally have the execution state at any point in time, the framework can simply restore the appropriate continuation if the user ever hits the Back button.
    Do I understand this correctly, that instead of keeping one current state the continuation-based system keeps series of states for every request? So when a user clicks "back", the system moves one step back and pulls out previous state?

    * How keeping a series of states is better than keeping one current state?
    * How many states are kept in the continuation state queue? Infinite? If there is a limit, than what's the point?
    * How does database fit in this system? What if data has been committed to database? Should it be "uncommitted" when a user goes back?
    * Does this model consider synchronizing server with application as better approach than synchronizing browser with server?
    * Is it true that for a webapp, the flow of pages is still fixed and a user cannot break away, because state is identified by URL or a query parameter or a hidden field?

    I think that continuation-based systems are not a good fit for webapps, especially for those that use databases. I think that keeping one current state is simpler and less memory-intensive than keeping series of states. Passing current state in a _viewstate-like hidden field is no worse than having a continuation system. Keeping current state on server is better navigation-wise since a user can break out of the flow and navigate to an arbitrary resource, its current state is preserved on server. The current state does not have to be serialized/deserialized. One can pass a reference to it instead of passing a whole new continuation.
  41. Do I understand this correctly, that instead of keeping one current state the continuation-based system keeps series of states for every request? So when a user clicks "back", the system moves one step back and pulls out previous state?

    Correct, in general it does, unless you explicitly invalidate the previous state(s).

    About all your other questions, these problems are exactly the same ones you have when developing any kind of conversation or multi-page flow with associated state. Instead of however having to worry of keeping the state in sync with your location, this is handled implicitly and you only need to pay attention to the state that due to your business requirements has to span multiple requests. You are able to externalize this or with some implementations indicate that certain references should not be cloned and just copied by reference value.
  42. Do I understand this correctly, that instead of keeping one current state the continuation-based system keeps series of states for every request? So when a user clicks "back", the system moves one step back and pulls out previous state?
    Correct, in general it does, unless you explicitly invalidate the previous state(s).

    About all your other questions, these problems are exactly the same ones you have when developing any kind of conversation or multi-page flow with associated state. Instead of however having to worry of keeping the state in sync with your location, this is handled implicitly and you only need to pay attention to the state that due to your business requirements has to span multiple requests. You are able to externalize this or with some implementations indicate that certain references should not be cloned and just copied by reference value.
    I don't think the problems are the same. With one current state I have objects in memory that correspond to data committed to database. With continuations i can rollback memory objects, but I cannot rollback committed database transaction. How is this going to work? Or you are saying that a continuation works only within one database transaction or when database is not used at all?

    Also, why do you think that keeping state in sync with location is better than keeping view in sync with state? Continuations as a means to grab application state is a nice concept, but going back on continuation queue when a user clicks Back seems backwards to me.

    About the length of continuation. If it is limited, than it does not make much sense. The whole thing transfers to a state-machine system (at best) where each state is a continuation. Why not using a state machine right from the start?
  43. I don't think the problems are the same. With one current state I have objects in memory that correspond to data committed to database. With continuations i can rollback memory objects, but I cannot rollback committed database transaction. How is this going to work?

    You'd invalidate past continuations. Most useful in multipage wizards...like shopping cart, or the insurance forms with dozens of pages, and things like that.
  44. I don't think the problems are the same. With one current state I have objects in memory that correspond to data committed to database. With continuations i can rollback memory objects, but I cannot rollback committed database transaction. How is this going to work?
    You'd invalidate past continuations. Most useful in multipage wizards...like shopping cart, or the insurance forms with dozens of pages, and things like that.
    Multpage wizard... Hmm... Sounds like something I worked on. (Follows is a shameless plug I could not help inserting) How would you like a wizard implemented with boring old Struts:

    WizardInputAction (dispatch-style)
    ----------------------------------

    public ActionForward cancelled(...) {
      ((WizForm) form).setWizard(null);
      return mapping.findForward("cancel");
    }

    public ActionForward back(...) {
      WizForm wizForm = (WizForm) form;
      wizForm.getMyWizard().back();
      return mapping.findForward("render");
    }

    public ActionForward next(...) {
      WizForm wizForm = (WizForm) form;
      MyWizard wiz = wizForm.getMyWizard();
      if (wiz.isCompleted()) {
        wizForm.setWizard(null);
        return mapping.findForward("done");
      } else {
        wiz.forward();
        return mapping.findForward("render");
      }
    }

    WizardRenderAction
    ------------------

    public ActionForward execute(...) {
      WizForm wizForm = (WizForm) form;
      MyWizard MyWizard = wizForm.getMyWizard();

      // Show page appropriate to wizard state
      String strMapping =
        wizForm.getMyWizard().getCurrentStepName();
      return mapping.findForward(strMapping);
    }

    WizardForm
    ----------

    public class WizForm extends ActionForm {
      private MyWizard wizard;
      public MyWizard getMyWizard () {return wizard;}
      public void setWizard(MyWizard wizard) {this.wizard = wizard;}

      public void reset(...) {
        if (wizard == null) {
          wizard = new MyWizard ();
        }
      }
    }

    Notice, that you do not navigate pages here, you send a command: "give me next step" or "give me previous step". The wizard keeps its state on server, if a user clicks Back button this is OK, since when he clicks "Next" button, the wizard will get next step using *current server state*. It does not care what page is displayed to the user. After server returns, it renders a proper page corresponding to current server state.

    Looks something like this
    or like this when running. Of course, the real meat is in the wizard object that holds states and transitions. The difference from other state machines is that wizard object basically does not have its own state, it calculates state based on Model state. Therefore you don't have problems synchronizing state machine states with domain model states.

    [Download the sample]
    [Read Easy Wizard docs]
  45. But wouldn't it be nice to generalize that behavior, and not have to build in a custom wizard for it? Something like

    if (logonPage()==success) {
      mainPage();
    } else {
      unauthorizedPage();
    }

    pervasively, without having to concern yourself with specialized wizards, or session state, or the back button, or the other problems inherent in stateless programming?

    And isn't that where Struts (or at least WebWork) is going anyway, (and through Rife continuations, I might add)?
  46. But wouldn't it be nice to generalize that behavior, and not have to build in a custom wizard for it? Something likeif (logonPage()==success) {  mainPage();} else {  unauthorizedPage();}pervasively, without having to concern yourself with specialized wizards, or session state, or the back button, or the other problems inherent in stateless programming?And isn't that where Struts (or at least WebWork) is going anyway, (and through Rife continuations, I might add)?

    It is better than doing it yourself as you would have to do with model 2 frameworks.

    However, automated state handling is not something only continuations based frameworks inhibit. Wicket, Tapestry, JSF, they all have that too. For instance:
    if (logonPage()==success) {
      setResponsePage(new MainPage());
    } else {
      setResponsePage(new UnauthorizedPage());
    }

    would be a variant on the theme, having the same effect for the framework's end users.
  47. I agree w/ Eelco-- especially the bit about AJAX in the article (???). The usefulness of AJAX resides in being able to partially process/apply state as part of a greater transaction as Wicket/JSF/Tapestry do-- how does continuations of a process support this partial processing from the client? Are we now talking about allowing the client to interact with multiple threads to support the partiality of AJAX within the UI?
  48. But wouldn't it be nice to generalize that behavior, and not have to build in a custom wizard for it? Something likeif (logonPage()==success) {  mainPage();} else {  unauthorizedPage();}pervasively, without having to concern yourself with specialized wizards, or session state, or the back button, or the other problems inherent in stateless programming?And isn't that where Struts (or at least WebWork) is going anyway, (and through Rife continuations, I might add)?
    But wouldn't it be nice to generalize that behavior, and not have to build in a custom wizard for it? Something like

    if (logonPage()==success) {
      mainPage();
    } else {
      unauthorizedPage();
    }

    pervasively, without having to concern yourself with specialized wizards, or session state, or the back button, or the other problems inherent in stateless programming?

    First, the notion of "logonPage()==success" has a page-driven smell to me. It should be "isLoggedIn()" instead. Second, this kind of login filters have been implemented long ago, even before Struts, and Struts is ooold. This is a simple two-state switchyard that either allows access to a resource or prohibits it. This is not a wizard. I would say that a wizard has to have at least three states and logic built into transitions.
    And isn't that where Struts (or at least WebWork) is going anyway, (and through Rife continuations, I might add)?
    Struts is going where exactly? It is going there through Rife continuatins? I don't think so.
  49. Struts is going where exactly? It is going there through Rife continuatins? I don't think so.

    Euhm, since RIFE/Continuations are used by the Webwork version that will become Struts Action 2, one might argument this way.
  50. But wouldn't it be nice to generalize that behavior, and not have to build in a custom wizard for it? Something likeif (logonPage()==success) {  mainPage();} else {  unauthorizedPage();}pervasively, without having to concern yourself with specialized wizards, or session state, or the back button, or the other problems inherent in stateless programming?And isn't that where Struts (or at least WebWork) is going anyway, (and through Rife continuations, I might add)?
    But wouldn't it be nice to generalize that behavior, and not have to build in a custom wizard for it? Something likeif (logonPage()==success) {  mainPage();} else {  unauthorizedPage();}pervasively, without having to concern yourself with specialized wizards, or session state, or the back button, or the other problems inherent in stateless programming?
    First, the notion of "logonPage()==success" has a page-driven smell to me. It should be "isLoggedIn()" instead. Second, this kind of login filters have been implemented long ago, even before Struts, and Struts is ooold. This is a simple two-state switchyard that either allows access to a resource or prohibits it. This is not a wizard. I would say that a wizard has to have at least three states and logic built into transitions.
    And isn't that where Struts (or at least WebWork) is going anyway, (and through Rife continuations, I might add)?
    Struts is going where exactly? It is going there through Rife continuatins? I don't think so.

    I think you're just being argumentative. But if you're really interested in exchanging ideas rather than pushing an agenda, check out Seaside's online store as an example of a wizard with continuations. It's a classic shopping cart. The code:

    go
      | shipping billing creditCard |
      cart _ WAStoreCart new.
      self isolate:
         [[self fillCart.
        self confirmContentsOfCart]
          whileFalse].

      self isolate:
         [shipping <- self getShippingAddress.
          billing <- (self useAsBillingAddress: shipping)
                        ifFalse: [self getBillingAddress]
                        ifTrue: [shipping].
        creditCard <- self getPaymentInfo.
        self shipTo: shipping billTo: billing payWith: creditCard].

      self displayConfirmation.
  51. I think you're just being argumentative. But if you're really interested in exchanging ideas rather than pushing an agenda, check out Seaside's online store as an example of a wizard with continuations.
    Well, maybe I am. Please, accept my apologies. The Seaside's code sure is not Java, I need to get the syntax first :)

    I still think that continuation is not a state machine. With continuations you have a series of state snapshots, with state machine you have states and rules to change from state to state (transitions). In state machine you change to a new state based on current state and a command, so you can change A->B, then B->C and then you can legally change C->A if there is a transition defined for that. With continuations there are no rules or transitions, just a stack of state snapshots. These seem like different but complimentary concepts, state machine is a database, continuation is a backup file. Backup file cannot exist without database anyway.
    You need to add data to the URL. But this style of URL (style, not purpose) is very similar to the Amazon URL that's half pretty to enable book marking and search engine support, and half ugly. Seems to work ok for them.
    Amazon's URLs are independent, I can jump in or break out. They may seem ugly but they are not linked. With continuations I have either a hidden field or a mangled URL. If I type address manually, I am out of the sequence and my continuation is gone. I can see how continuations work to detach threads in a web server, but I don't see how this is a better concept for a webapp developement than, say, _viewstate. I guess, strict page flow is just not my cup of java. For those rare cases when I need several pages of strict state transitions, I have my state machine.
  52. Jetty and continuations[ Go to top ]

    Greg Wilkins gives some good examples on his belog.

    http://www.mortbay.com/MB/log/gregw/
  53. Greg Wilkins gives some good examples on his belog.http://www.mortbay.com/MB/log/gregw/

    What Greg Wilkins explains is a very specialized optimization for AJAX polling, which though usefull and interesting in itself, does imo does not apply to the general problem of building stateful web applications.

    Btw, I wonder why that should be part of any servlet spec without having continuation support in the language itself. Frameworks depending on hacks, ok. Specs depending on hacks, not so ok.
  54. Greg Wilkins gives some good examples on his belog.http://www.mortbay.com/MB/log/gregw/
    But AJAX based web applications have very different traffic profiles to traditional webapps. ... An AJAX application needs a connection to the server almost continuously.
    Depends on Ajax flavor. Not true for simple in-place update technique (AHAH).
    [Continuations is a] new feature introduced in Jetty 6. A java Filter or Servlet that is handling an AJAX request, may now request a Continuation object that can be used to effectively suspend the request and free the current thread.
    This seems like a proper application for continuations. Just grab the state and release the thread, no funky state rollback, no issues with domain model and database.
  55. Jetty and continuations[ Go to top ]

    Greg Wilkins gives some good examples on his blog.

    http://www.mortbay.com/MB/log/gregw/

    Thanks! From a servlet container standpoint, I see this as extremely beneficial, but I still see that while it does make client/server communication more efficient (as with Sun's Grizzly implementation), I don't necessarily agree that it helps at higher levels of abstraction within your application code (as in the examples provided).
  56. Jetty and continuations[ Go to top ]

    The Jetty 6 Continuation mechanism is certainly not a general purpose continuation that is going to allow application logic to be written without docomposition into a request/response paradigm.

    It is, however, a continuation mechanism that can suspend and restore state (the HttpRequest) within the handling of a specific request. Resources are freed while the request is suspended.

    This is exceedingly useful as the processing of a request that may need to deal with other request/response APIs or asynchronous event sources. Using continuations in http request handling allows asynchronous events to be delivered from the server to the client without consuming VM and network resources.

    I see jetty continuations as a demonstration that contiuations are a very powerful abstraction that can be applied at many levels.

    I would expect that frameworks that provide application logic with a general continuation mechanism would be able to use the jetty continuation mechanism as part of their implementation if there are to be run within a servlet container.
  57. Javaflow[ Go to top ]

    FWIW, Apache have a project in the sandbox (JavaFlow)for enhancing java classes to support continuations.

    Regards
    Kit
  58. Java JdonFramework supports Stateless and Stateful, Jdon Framework = Ioc(pico) + AOP( simple ) + CRUD + Cache

    https://jdon.dev.java.net/
  59. I don't see the connection. A continuation is not a state machine.
    The cocoon example is nice but again I don't see the continuation. What I see there is an argument for better thread handling from the JVM.

    Dealing with limitations in the number of threads you can reasonably use by saving the scope and then bunging it into another thread when you want to resume it is something the JVM should do if it needs to.
    It is not something that developers should be doing.

    I see continuations as you see them in Lisp etc. as basically a (p)reinvention of objects with state for functional programming. For example an OO version of the Ruby example:

    class IntPrinter{
       int step;
       int current = 1;

       public IntPrinter(int step){ this.step = step;}
       private IntPrinter(int step, int current){ this.step = step; this.current = current;}
       public IntPrinter go(){
           for(int i=current; i <= Math.min(10, current + step); i++){
              out.println("Value of i: " + i);
           }
           if (current + step > 10) { return null; }
           return new IntPrinter(step, current + step);
       }

       public static void main(String[] args)
       {
            IntPrinter p = new IntPrinter(5);
            while(p != null) {
                out.println("call go:");
                p = p.go();
            }
            
            p = new IntPrinter(8);
            while(p != null) {
                out.println("call go:");
                p = p.go();
            }
        }
    }

    Output:
    call go:
    Value of i: 1
    Value of i: 2
    Value of i: 3
    Value of i: 4
    Value of i: 5
    call go:
    Value of i: 6
    Value of i: 7
    Value of i: 8
    Value of i: 9
    Value of i: 10

    call go:
    Value of i: 1
    Value of i: 2
    Value of i: 3
    Value of i: 4
    Value of i: 5
    Value of i: 6
    Value of i: 7
    Value of i: 8
    call go:
    Value of i: 9
    Value of i: 10

    call go:
    Value of i: 1
    Value of i: 2
    Value of i: 3
    Value of i: 4
    Value of i: 5
    Value of i: 6
    Value of i: 7
    Value of i: 8
    Value of i: 9
    call go:
    Value of i: 9
    Value of i: 10

    I don't see the advantage of continuations for this kind of use and I really don't see the advantage for Web apps.
  60. Doh[ Go to top ]

    Ignore that extra bit of output in my previous message
  61. Hi Cormac, I suggest you look over my TSSJS presentation wrt the usefulness of continuations for web application development (and more specifically partial continuations). You can find the links in the first comment on this thread.
  62. I don't see the connection. A continuation is not a state machine. The cocoon example is nice but again I don't see the continuation.

    The continuation approach and state machine approach are actually quite similar in concept. Both allow you to snapshot the system at each user interaction, and store that snapshot so that:

    1) The user experience is smooth and consistent should he use browser history or the back button;
    2) the programming experience is quite similar to stateful programming; and
    3) the system scalability and performance are enhanced, as they are with web application servers, because you don't have to bind each new user with his own set of system resources.

    The concepts are identical in that you snapshot system state, including control flow and instance variables, before each user request, and you restore system state after the user interaction. It's effectively an inversion of control for web frameworks, and one that makes sense.

    The primary difference is that native continuations (in our case, partial continuations...from, say, servlet on up) let you express flow in pure Java rather than XML or some hybrid. Rife, in fact, implements both approaches.

    But to be clear, this has nothing to do with Ruby, except that there are 2 frameworks on the Ruby side that do continuations; Rails doesn't. The article talks more about Seaside on Smalltalk.

    Hope this helps.
  63. Hype[ Go to top ]

    The primary difference is that native continuations (in our case, partial continuations...from, say, servlet on up) let you express flow in pure Java rather than XML or some hybrid.
    Why would you not be able to represent state machine transitions in plain Java?

    printTemplate(template);
    return new CheckAnswerState(0); // next state

    CheckAnswerState process method:

    if (answer < mGuess) {
      template.setBlock("indication", "lower");
      printTemplate(template);
      return new CheckAnswerState(guess++);
    }

    This may not be a good way of doing states, but it clearly shows it is possible.

    I see two very distinct uses of continuations here:
    1. Jetty style limiting the number of threads you need by suspending them and storing the state. This is interesting and could be very useful but I think it is something that should be tranparent to the client developer. And it is solving a problem that could theoretically go away with better machines/OSs/JVMs
    2. Partial continuations as state machines, except your different states are all in the one method. I don't see how such a hard to understand concept as continuations is an improvement over a simple and commonly used pattern.
    And there is no way option 2 could possibly use less resources than your own state machine. Your own state object versus all the locals automatically grabbed?
    because you don't have to bind each new user with his own set of system resources.
    WTF? Gibberish.

    Continuations as a way of allowing me not to worry about threads? Excellent. Just as long as I don't have to do anything weird. If I can go:
    printPage()
    command = getCommand()
    And the framework or app server hides the fact that the thread got supended and resumed then its great!

    I don't buy using continuations in the second way though. Though then again I think they are mostly a functional programmer's bizarre way of doing something that could be easily done with objects (for example teach yourself scheme in fixnum days' tree matching example teach yourself scheme in fixnum days' tree matching example Think how easy that is with iterators)