[racket] Stateless servlets and formlets error

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Wed Feb 6 09:28:14 EST 2013

On Wed, Feb 6, 2013 at 12:13 AM, Lorenz Köhl <rainbowtwigs at gmail.com> wrote:
> The following servlet show an input field from a formlet and then tries to use formlet-process on the resulting request. I don't understand why this fails when, like below, the send/suspend and formlet-process is in a function but works when inlined, like the #; commented code in handle-html-form.
>
> The error is
>
> stuff-url: Cannot stuff (kont #<procedure:...abort-resume.rkt:154:25>) into a URL because it contains non-serializable pieces. Convert #<procedure:...formlets/lib.rkt:17:2> to a serializable struct
>
> Why does the extra lambda lead to this error message?

The answer to the "WHY" is this:

1. send/form2 is generalized over 'f', so the particular binding for
'f' must be part of its closure, which must be serialized.

2. If you inline it, or replace the f is send/form2 with
'main-input-formlet', then you are now referring to a global variable,
which is never part of closures, because it is always available.

3. The value that you are giving to 'main-input-formlet' is not
serializable, because it is a normal function. This is documented on
the contract for formlets:

http://docs.racket-lang.org/web-server/formlets.html#%28def._%28%28lib._web-server%2Fformlets%2Flib..rkt%29._formlet%2Fc%29%29

Now, the question you didn't ask, does it have to be this way? (1) and
(2) have to work the way that they do. (3) is a little bit harder to
decide if it has to be that way. Serializability is an infectious
property where you can't just rely on your local code to do something,
but you need global changes across the system. The Web server does not
generally promise that its data structures are serializable (for
example, requests are not because they contain promises, which would
be very expensive to make serializable across the system.) The only
"easy" way to make formlets serializable would be to write that file
in the "#lang web-server" language. But down that path is writing
every module in Racket in this language. (For example, objects and
classes aren't generally serializable so the second you start using
them in a Web app you want to be serializable, you're in for a world
of hurt.)

I don't think the benefits are worth it to justify things in the case
of formlets, but I'm open to arguments.

What should you do instead in this and similar situations? This is the
reason for serial->native, etc. You could also change your program so
that the set of valid formlets were always top-level, if that were the
case, and name them by symbol.

Jay



--
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.