JavaScript webflow for Spring

Home

News: JavaScript webflow for Spring

  1. JavaScript webflow for Spring (18 messages)

    A new Apache-licensed open-source project, Rhino in Spring aims to integrate the Mozilla Foundation's Rhino JavaScript interpreter for Java with the Spring Framework. The current release includes a controller component for the Spring Web MVC that allows you to express complex multipage flows in your web applications as server-side JavaScript programs. You can use all the amenities of a full-blown imperative programming language while designing flows. You can write libraries of reusable code encapsulated into functions (i.e. validators), you can use the familiar for(), if(), while(), switch/case etc. statements to express the control flow, and so on. Rhino in Spring uses the Rhino's support for continuations to achieve high scalability - when a script is suspended between a response and the next request in the flow, its state is stored in a continuation (think of it as a snapshot of its stack), taking up no scarce system resources (i.e. no physical threads), allowing for any number of concurrently active flows. Even more so, "old" states are preserved (with configurable expiration policies), so the users can go back and forward using the browser's back and forward buttons, or even split the flow in two using the browser's "New Window" menu, and the framework will take care of resuming the server-side script on each request originating from a backed or split response page at the correct point, with correct values of all variables automatically - no need to disable the back button or use custom navigation links on your pages to keep server and browser state in sync. In addition to in-memory and JDBC server-side storage of states it even provides a facility for embedding an encoded textual representation of the continuation in the generated webpage, thus moving it to the client and completely eliminating any server-side state storage for the ultimate in scalability. Compression, encryption and digital signing can be enabled to protect the client-side stored continuations from tampering. As an added bonus, you also get generic Spring bean factories for Java Cryptography Architecture public and private keys as well as Java Cryptography Extension secret keys, that you can also reuse elsewhere. The party guilty for Rhino in Spring is myself, Attila Szegedi. My other Open Source hats include being a project co-admin and principal developer of FreeMarker, as well as a committer on the Rhino project itself.

    Threaded Messages (18)

  2. This seems to be very similar to what Spring Web Flow (SWF) offers, except that it uses its own state machine which is (mostly) configured via XML. It would be cool to see if Rhino could be used to back a SWF flow execution.
  3. Although the crux of what I see in Rhino in Spring involves reinventing Spring WebFlow using JavaScript to define the flows, the project hints at other future integrations between Rhino and Spring. In that context, it should be noted that Spring 2.0 will include support for wiring dynamic scripting into Spring as Spring-managed "beans". As of right now, the nightly builds for 2.0RC1 include support for scripting beans in Groovy, JRuby, and BeanShell. But for you Rhino fans out there, my friend and colleague James Tikalsky has implemented Spring scripting in Rhino and has submitted it to the Spring project in http://opensource.atlassian.com/projects/spring/browse/SPR-1933. The code that is attached to that issue works (I've verified it). However I've pointed out a few things for James to do to clean it up a bit (add unit-tests, removing some debugging code, repackage it under org.springframework.scripting.javascript, etc). He's working on it now and will resubmit it soon.
  4. Although the crux of what I see in Rhino in Spring involves reinventing Spring WebFlow using JavaScript to define the flows,... That's right. I just happen to prefer writing programs to either editing XML files or drawing boxes and connecting them with arrows, so I felt like giving the freedom of choice to all the other web application developers out there.
    ... the project hints at other future integrations between Rhino and Spring.
    I intentionally wasn't being any more specific there, as I wanted to avoid limiting people's imagination. One wild idea I have floating around is seeing whether it would be easy to get TrimPath Junction (a port of Ruby-on-Rails to JavaScript) to work within this environment. That's not to say that I have it on my agenda to provide a RoR-like environment on top of Spring, although I have no problem providing an enabler technology for it. Another wild idea is to engineer an intuitive ORM mapping in JavaScript, possibly building on top of Spring's ORM abstractions.


    In that context, it should be noted that Spring 2.0 will include support for wiring dynamic scripting into Spring as Spring-managed "beans". As of right now, the nightly builds for 2.0RC1 include support for scripting beans in Groovy, JRuby, and BeanShell.

    But for you Rhino fans out there, my friend and colleague James Tikalsky has implemented Spring scripting in Rhino and has submitted it to the Spring project in http://opensource.atlassian.com/projects/spring/browse/SPR-1933. The code that is attached to that issue works (I've verified it). However I've pointed out a few things for James to do to clean it up a bit (add unit-tests, removing some debugging code, repackage it under org.springframework.scripting.javascript, etc). He's working on it now and will resubmit it soon.
    Heh - I knew I can't be the only one who realized it'd be worth integrating the two, even if Google stubbornly refused to turn up relevant hits whenever I searched for "Rhino Spring" and "JavaScript Spring" :-) I'm sure James' work will be a nice addition to Spring, but I believe that what I provide in "Rhino in Spring" is at the moment a bit orthogonal to that. For one thing, this is specifically a webflow controller, and it addresses questions of state storage and retrieval (continuations) and persistence of said state - something you could have troubles generalizing in a scripting interface since not all languages support it. Sure, you could come up with a Spring controller implementation that takes a generic script factory, but I believe it'd probably be limited to single-request actions (although of course, I'd be hardly sad or very surprised if someone proved me wrong, as we know nothing is possible). This controller integration, as well as other integrations that may follow (JavaScript ORM or whatever else people who come in the contact with the project might come up with) are intended to be quite sophisticated and I believe they point beyond simple representation of scripts as factory managed objects that's currently implemented by Spring 2.0 (although that has its own rightful usage and deserved place as well).
  5. Sorry, reposting as I botched the markup on the first one - don't you wish ServerSide had a preview button in posts?
    Although the crux of what I see in Rhino in Spring involves reinventing Spring WebFlow using JavaScript to define the flows,...
    That's right. I just happen to prefer writing programs to either editing XML files or drawing boxes and connecting them with arrows, so I felt like giving the freedom of choice to all the other web application developers out there.
    ... the project hints at other future integrations between Rhino and Spring.
    I intentionally wasn't being any more specific there, as I wanted to avoid limiting people's imagination. One wild idea I have floating around is seeing whether it would be easy to get TrimPath Junction (a port of Ruby-on-Rails to JavaScript) to work within this environment. That's not to say that I have it on my agenda to provide a RoR-like environment on top of Spring, although I have no problem providing an enabler technology for it. Another wild idea is to engineer an intuitive ORM mapping in JavaScript, possibly building on top of Spring's ORM abstractions.


    In that context, it should be noted that Spring 2.0 will include support for wiring dynamic scripting into Spring as Spring-managed "beans". As of right now, the nightly builds for 2.0RC1 include support for scripting beans in Groovy, JRuby, and BeanShell.

    But for you Rhino fans out there, my friend and colleague James Tikalsky has implemented Spring scripting in Rhino and has submitted it to the Spring project in http://opensource.atlassian.com/projects/spring/browse/SPR-1933. The code that is attached to that issue works (I've verified it). However I've pointed out a few things for James to do to clean it up a bit (add unit-tests, removing some debugging code, repackage it under org.springframework.scripting.javascript, etc). He's working on it now and will resubmit it soon.
    Heh - I knew I can't be the only one who realized it'd be worth integrating the two, even if Google stubbornly refused to turn up relevant hits whenever I searched for "Rhino Spring" and "JavaScript Spring" :-) I'm sure James' work will be a nice addition to Spring, but I believe that what I provide in "Rhino in Spring" is at the moment a bit orthogonal to that. For one thing, this is specifically a webflow controller, and it addresses questions of state storage and retrieval (continuations) and persistence of said state - something you could have troubles generalizing in a scripting interface since not all languages support it. Sure, you could come up with a Spring controller implementation that takes a generic script factory, but I believe it'd probably be limited to single-request actions (although of course, I'd be hardly sad or very surprised if someone proved me wrong, as we know nothing is possible). This controller integration, as well as other integrations that may follow (JavaScript ORM or whatever else people who come in the contact with the project might come up with) are intended to be quite sophisticated and I believe they point beyond simple representation of scripts as factory managed objects that's currently implemented by Spring 2.0 (although that has its own rightful usage and deserved place as well). Plus, it works with Spring 1.x :-)
  6. That's right. I just happen to prefer writing programs to either editing XML files or drawing boxes and connecting them with arrows, so I felt like giving the freedom of choice to all the other web application developers out there.
    Nothing wrong with that. I'm in favor of options and JavaScript is a fine option (I'd have preferred Ruby, but that's just me). But it'd be great if you were to leverage as much of Spring WebFlow as possible so that it wouldn't be a completely different web flow framework. Just provide an option for defining the flow, but use the rest of SWF as-is. (Note: I've not had the time to really dig into Rhino in Spring, so if it does leverage SWF, then bravo!)
    I'm sure James' work will be a nice addition to Spring, but I believe that what I provide in "Rhino in Spring" is at the moment a bit orthogonal to that.
    I agree that it's orthogonal, but you did leave it open for future expansion. Before someone goes off and builds support for scripting beans in JavaScript in Spring, I thought I'd point out that James has already done some work in this area.
  7. I'm in favor of options and JavaScript is a fine option (I'd have preferred Ruby, but that's just me).
    As far as I know, JRuby doesn't support continuations, so that unfortunately makes it unfeasible for implementing a scripted web controller in a scalable way. The goal is to not have a physical thread blocked between a response and the next request. you need continuations for that.
    But it'd be great if you were to leverage as much of Spring WebFlow as possible so that it wouldn't be a completely different web flow framework. Just provide an option for defining the flow, but use the rest of SWF as-is. (Note: I've not had the time to really dig into Rhino in Spring, so if it does leverage SWF, then bravo!)
    No, it does not leverage SWF, although that's not a principal decision, rather a consequence of circumstances, and might as well change in the future. As strange as it may sound, I wrote the core of the code last August. It sat on my hard drive ever since because I didn't feel comfortable releasing it without proper testing, examples, and documentation. Various factors such as paid work and family preempted the testing and documentation efforts, and it was only few weeks ago that I got enough time again to give it momentum -- create an example webapp, test the hell out of it, write API docs, write a tutorial, pin up a website, set up a SourceForge project up, etc. Last August, Spring Web Flow was not really crystallized yet, it was quite a moving terrain. That's why I didn't bind my implementation to it. My first priority now was to push what I have written so far in a stable, usable state out to the public. Now that's done, I'll certainly revisit it to see whether it makes sense to provide adapters that'll make it also work as a SWF component. I'll need to reevaluate SWF to see how far did it go since last August - i.e. if it has all the state persistence options I built into Rhino in Spring, or those persistence options are easy to add to it, then it's a viable near-term future implementation path.
    I agree that it's orthogonal, but you did leave it open for future expansion. Before someone goes off and builds support for scripting beans in JavaScript in Spring, I thought I'd point out that James has already done some work in this area.
    And again, it is much appreciated - as I said, I was occasionally digging for technologies that bring together Rhino and Spring via Google and didn't find anything, so thanks for pointing it out. As for future expansions - if we're aware of each other's work, we can certainly either figure out along the way how to integrate them in helpful ways. I always use the theoretical "JavaScript ORM on Spring" as an example of a possible expansion of Rhino in Spring -- it could hopefully be implemented so that it's independent of usage context and therefore reusable from scripts managed through org.springframework.scripting.javascript and from scripts managed by my webflow controller. I'm hardly a "lone wolf" who's bent on doing things in his own project at all costs - I just love to be nonintrusive, and I believe that showing your work in independently created project is less intrusive than going to the Spring development community and asking for my stuff to be included there. If at any point in time Spring developers like what they see here, and want to merge Rhino in Spring to some mainline Spring effort, I don't think I'd pose obstacles. (That's actually pretty much how my initial involvement with FreeMarker went - I developed a 3rd-party add-on that existed on its own for few years, then got merged). We'll see what does the future bring :-)
  8. A few remarks
    That's right. I just happen to prefer writing programs to either editing XML files or drawing boxes and connecting them with arrows, so I felt like giving the freedom of choice to all the other web application developers out there.
    The reason why we went with XML configuration of a state machine in SWF is that it maps much more naturally to state transition diagrams than a programming language. If you try to 'implement' a state transition diagram using something like Java or JavaScript you end up wanting to use 'goto' a lot.
    I'll need to reevaluate SWF to see how far did it go since last August - i.e. if it has all the state persistence options I built into Rhino in Spring, or those persistence options are easy to add to it, then it's a viable near-term future implementation path.
    SWF has full support for the web-continuation features that Rhino also provides. Furthermore, persistence of flow executions if fully pluggable. Erwin
  9. The reason why we went with XML configuration of a state machine in SWF is that it maps much more naturally to state transition diagrams than a programming language. If you try to 'implement' a state transition diagram using something like Java or JavaScript you end up wanting to use 'goto' a lot.
    Not if your language supports continuations. It's true that ECMAScript proper doesn't define continuations, but Rhino has them as a proprietary feature since the 1.6 release. It's not a problem as the flowscripts themselves don't directly use continuations, so they're fully standard JavaScript - all continuation juggling is hidden behind helper functions, so your script just needs to do a ... nextRequest = respondAndWait(viewName, dataModel); ... to have the script respond to a request and have the execution suspended until the next one (that's when respondAndWait() will return).
  10. The reason why we went with XML configuration of a state machine in SWF is that it maps much more naturally to state transition diagrams than a programming language. If you try to 'implement' a state transition diagram using something like Java or JavaScript you end up wanting to use 'goto' a lot.
    Not if your language supports continuations. It's true that ECMAScript proper doesn't define continuations, but Rhino has them as a proprietary feature since the 1.6 release. It's not a problem as the flowscripts themselves don't directly use continuations, so they're fully standard JavaScript - all continuation juggling is hidden behind helper functions, so your script just needs to do a ... nextRequest = respondAndWait(viewName, dataModel); ... to have the script respond to a request and have the execution suspended until the next one (that's when respondAndWait() will return).
  11. The reason why we went with XML configuration of a state machine in SWF is that it maps much more naturally to state transition diagrams than a programming language. If you try to 'implement' a state transition diagram using something like Java or JavaScript you end up wanting to use 'goto' a lot.
    Look. that's the whole point of Rhino-in-Spring: that you need not wrap your mind around thinking in terms of state machines. You can keep thinking in terms of a normal structured/object-oriented programming with for() and while() loops and if() and switch() statements, as well as function declarations and then multiple invocations for code reuse. In this system, for example, a page validation becomes a for(;;) loop that keeps returning to the same page in the loop while validation succeeds and breaks out of it and moves on when the validation succeeds. When your script invokes the respondAndWait(viewName, dataModel) function, what happens behind the scenes is that the current state of your script - nested in as many for() loops, if() branches, or function invocations as you wish - is captured as a continuation. A continuation is a full snapshot of the call stack, complete with local variable values and return addresses from functions for each stack frame. It is then stashed somewhere (session, JDBC database, or a hidden form field in the response HTML page), the ViewAndModel is returned to Spring, and when Spring is done rendering the view the physical Java thread is free to take upon another task. When the next request comes in, the stack and local variables are resurrected from the stashed state and the script is resumed from where it was suspended, returning from the respondAndWait(), with the next HttpServletRequest object as its return value. This is completely transparent to the script and its programmer, of course. The "state machine" is on the call stack - in the variable values, and return addresses associated with each call frame on the stack, and you as the script writer are never exposed to it. Just as with normal programming :-) (you usually don't have to worry about stuff like your program returning into the correct iteration of a loop after a function call from the loop body executed :-) ) The whole point was to not force people accustomed to programming in structured and OOP languages back into the world of state machines. I hope I was able to enlighten :-)
  12. I think you misunderstood my remark. I fully understand how the Rhino flow JavaScripts work and what's happening with the web continuations since I originally wrote the continuations support in SWF.
    Look. that's the whole point of Rhino-in-Spring: that you need not wrap your mind around thinking in terms of state machines.
    What I was hinting at when I said that you end up wanting to use 'goto' a lot is that normal structured/oo programming constructs like if/for/while/... are not ideal to implement a page flow, which is basically a state transition diagram whatever way you look at it (explain a page flow to an end user and see if you come up with program using if/for/while or a picture displaying a state transition diagram)! Consider for example a simple wizard flow with 4 steps. there are next/previous buttons on each page, but on the third page there's also a link to go back to the first page. In my experience people find it much more natural to capture this kind of page flow in a declarative XML definition of a state machine than in a programming language using if/for/while/... Granted, there are examples like the 'numberguess' app that are more elegantly modeled in a JavaScript program. Howemer, IMHO most real-world page flows are more naturally described using something like XML. Erwin

  13. What I was hinting at when I said that you end up wanting to use 'goto' a lot is that normal structured/oo programming constructs like if/for/while/... are not ideal to implement a page flow, which is basically a state transition diagram whatever way you look at it (explain a page flow to an end user and see if you come up with program using if/for/while or a picture displaying a state transition diagram)!
    It all depends on who that end user is. I know that for myself, I prefer writing programs. I don't question it that lots of webapp interactions are modeled on paper initially and that for some people it makes sense implementing them preserving the original graph (by the way, turning flowcharts or block diagrams into programs used to be taught as The Right Way of writing software on many universities not so far in the past, so even if you start with a flow diagram on pen-and-paper, you needn't end up with a flow diagram in computer implementation, but I digress). Also consider that you can rather naturally roll together (by including a function library) into the controller script those things that are commonly implemented as separate filters/interceptors: data validation, authentication, etc. So, as usual, it boils down to who's comfortable with what. I don't question your approach, and I believe you did produce a great quality work with SWF. I'm just saying that some people are mentally wired so that they're more productive writing code, while others get along better with state diagrams. It boils down to right tools for right task in hands of people. Whatever works for whoever has to do the work. An interesting analogy lies in the land of business process management software: jBPM vs. BPMScript. Last year I attended the JAOO conference and there was a JBoss jBPM presentation where the presenter claimed how their "graph oriented programming" is downright superior to object oriented programming, since "object oriented programming doesn't provide support for suspending execution at particular state and later continuing from there", essentially rendering it unfeasible for long-running business processes. I nearly fell off the chair when I heard that. I talked with the presenter after his presentation and tried to explain to him the concept of continuations and how they're really completely independent from the object-oriented nature of the language and that he shouldn't market writing state machines as a new kind of programming paradigm ("graph-oriented") that's in any way superior to OOP. His final argument was that end-users tend to prefer drawing circles and connecting them with arrows. Which is something I couldn't argue with, really - if that's what works for them, more power to them. Then yesterday I accidentally found BPMScript, which is a BPM software that uses - you guessed - Rhino with continuations to implement business process flows! So in BPM world too, there are people who prefer to work with state diagrams ("graph-oriented programming" in JBoss market speak), and there are us (old fashioned?) programmers who'd rather keep writing code in a traditional general-purpose programming language. So, in my humble opinion both approaches have their place under the sun, as some people find working with one and other people find working with the other to be easier.
  14. So, in my humble opinion both approaches have their place under the sun, as some people find working with one and other people find working with the other to be easier.
    I fully agree. In that respect your 'top-down' integration approach might even make sense, although it wouldn't really leverage much of the current SWF approach, it would give the user 2 options: graph based or script based flows all under the same SWF umbrella. Erwin
  15. But it'd be great if you were to leverage as much of Spring WebFlow as possible so that it wouldn't be a completely different web flow framework. Just provide an option for defining the flow, but use the rest of SWF as-is. (Note: I've not had the time to really dig into Rhino in Spring, so if it does leverage SWF, then bravo!)
    I donwloaded the SWF 1.0RC1 release and set out to investigate whether it is possible to integrate Rhino in Spring (RiS) into SWF somehow. Well, it looks like it's a tough call, and let me explain why. SWF (architecturally) has its top level (entry point) and bottom level (leaf functionality) interfaces/classes, with naturally few others in between. The integration problem can be attacked from two directions: from top and from bottom. Let's see the top-level approach... It'd be rather easy to implement a high level adapter by implementing a top level entry-pont interface (namely, FlowExecutor). That's not too beneficial though, as then it's not leveraging any of the under-the-hood machinery already present within SWF, but again just providing a full replacement to SWF, only disguised in SWF's top-level interface. Now, if I created this hypothetical RhinoFlowExecutor, there's not too much benefit in being able to plug it into SWF's FlowController as compared to the current situation where RiS simply provides its own controller implementation. Although ResponseInstruction seems like a nice control to have, so maybe it'd make sense as a marginal benefit. Now for the bottom-up approach... I could try it other way round, implementing low-level leaf functionalities and thus allow reuse of all the layers above them. However, and this is a big however, SWF at the moment isn't really engineered for alternative flow specifications as far as I could determine. Sure, you have an abstract concept of a "flow builder", but it builds a "flow" object (concrete class, not interface) that is assumed to be a state machine, with explicit declaration of states, transitions, subflows, variables, exception handlers, whatnot. Again, referencing back to my "Forget the state machine..." comment, the beauty of using a continuations-capable programming language is that states are not really explicit. A "state" emerges whenever the JavaScript code decides to send back a response and wait for the next request. Heck, given JavaScript's Turing-completeness as well as dynamic nature, you could come up with programs where the state machine is not even finite, or calculating all the states and transitions up front is equal to the halting problem! (You could of course argue that majority of webapp developers out there won't write this complex flows and thus don't need this many degrees of freedom, but I think it's a valid concern if people start building a bit more complex stuff - like, you can bundle data-validation loops, authentication subroutines (i.e. a set of page that logs in the user or allows him to complete a few pages of a sign-up process before returning to the task at hand), etc. into functions, bundle those functions into libraries that are then included from main flowscripts, and it can quickly surpass a certain level of complexity where it all starts to matter). Therefore, smuggling JavaScript into SWF from bottom up quickly encounters obstacles like how to deal with the rest of the framework expecting a Flow to be composed of explicitly defined State and Transition objects - and these just don't manifest themselves explicitly from a JavaScript program's source code. I.e. there's no need for different "events" in requests when you want to move on with the next request and choose the right Transition to the next State based on the Event - the program can just do an if/elseif/else or a switch() on an arbitrary request parameter itself, simple as that. There's also quite a lot of other stuff in the Flow class that is simply not applicable as soon as you leave the state machine paradigm behind. Actually, the more I look at the SWF source code, the more it looks to me that the bulk of it is there to deal with the explicit management of states and transitions. Don't get me wrong - people who wrote SWF apparently did a terrific job at making a good system for running a state machine, but to me - and this is my very personal opinion - a program expressed as an explicit state machine is to a program written in a modern high level programming language (JavaScript) what machine code is to C, at least, both in clarity and long-term maintainability. I believe that if JVM specification supported the notion of continuations, SWF as it is now would have probably never been invented, along with the ecosystem of graphical editor and other tools that are meant to address the inherent complexity of working with state machine definitions directly. People would just write their flow algorithms in Java. With RiS they can do the next best thing - write them in JavaScript :-) Therefore: since the bulk of SWF is about dealing with the state machine *and* JavaScript continuations make it completely unnecessary, I don't really think there's much RiS could benefit from being shoehorned into the SWF shape... RiS does flows by running JavaScript programs; SWF does flows by running state machines. It unfortunately really isn't more general than that so as to easily accomodate a flow engine following a different paradigm. If SWF could be reengineered so that it has a generic persistence/execution services that are completely independent of the fact that the underlying flows are defined as state machines, then maybe... Well, that's how far I got from initial analysis of the SWF source code - if you wish to continue the discussion, you're more than welcome. Everything I said - it is not my final verdict, I'll keep looking for possibilities, and if anyone wants to point my attention in direction of something I overlooked, they're more than welcome to do so.
  16. Therefore, smuggling JavaScript into SWF from bottom up quickly encounters obstacles like how to deal with the rest of the framework expecting a Flow to be composed of explicitly defined State and Transition objects - and these just don't manifest themselves explicitly from a JavaScript program's source code. I.e. there's no need for different "events" in requests when you want to move on with the next request and choose the right Transition to the next State based on the Event - the program can just do an if/elseif/else or a switch() on an arbitrary request parameter itself, simple as that.
    This kind of switching code can get contorted pretty quick. We decided to build a domain specific language targetted at page flows (FSM based) to make it much more natural to translate your paper page flow design into a working web flow. Erwin
  17. Now with Javascript being promoted heavily on the server (i.e. Rhino in Spring, Phobos, BPMScript, Cocoon, Helma etc.), we now find Google promoting Java heavily on the browser. Is this just trading places? http://www.manageability.org/blog/stuff/trading-places/view
  18. Why?[ Go to top ]

    I have been experimenting with Spring Webflow for several months. I like the current flow of development using plain Java and XML, why would you want to use JavaScript? What could a developer gain from this?
  19. Re: Why?[ Go to top ]

    I agree, there's no interest at all in developing with javascript