|
View:
New views
6 Messages
—
Rating Filter:
Alert me
|
|
|
[scala-tools] [lib.web] v.0.2: validators rewritten, state management, formsHello everyone!
I'd like to announce version 0.2 of my stateless web framework lib.web. New features briefly described below are: - rewritten request parameter validators; - generalized state management; - forms and multipage forms module. It can be downloaded from http://dimgel.ru/lib.web/files/ Examples can be tried at http://dimgel.ru:8080/lib.web/example/ I don't yet consider existing API stable and worth using in real projects, so I haven't yet bothered with git and github. Forms took more time than I expected. In 1-3 months I hope to finish some stuff (like file uploads), cleanup, publish v.0.3 and start a public ride with issue tracking, etc. For now I'd just appreciate any feedback. I also need help with maven configuration (please see readme, section "how to run examples"). ***** VALIDATORS REWRITTEN ***** With validators framework presented in v.0.1, I could create VRangeInt(min: Int, max: Int) and write something like this: param(VRequired & VInt & VRangeInt, CInt) Not only one had to clone VRange validators for param(VRequired & VDouble & VRangeDouble, CDouble) or for param(VRequired & VIntTrim & VRangeIntTrim, CIntTrim), it also brings a significant overhead because VInt, VRangeInt and CInt all perform integer parsing. So the problem is that validators are separate from converters and don't exchange validated data among themselves. In v.0.2, there are no separate converters. Validators are also converters; they return validated/converted data along with validation error list. The root Validator trait is declared like this: package ru.dimgel.lib.web.param trait Validator[In,Out] { def validate(in: In): Param.Result[Out] } So VInt, for example, takes String input and returns Integer result; now VRange maybe declared as generic VRange[T <% Ordered[T]] which performs only test without conversion (its In and Out types are equal). This also makes unnecessary to clone trimming and non-trimming validators; only first validator must trim and pass that trimmed data forth. The other problem solved is necessity of different parameter emptiness semantics for different validation scenarios. I removed method Param.isEmpty() and made it very easy to define custom Required and Optional validators which implement emptiness tests. Finally, because validators can be now chained based on their input and output types compatibility, there's no need for my old weird Tags anymore. Examples e03param and e04paramcustom are rewritten and now demonstrate all new stuff. ***** STATE MANAGEMENT ***** When working on multipage forms, I had to track form context (data submitted on previous form pages). For small forms with small total data size, I planned next solution: serialize all data into base64-encoded string and pass that string through a single hidden form field. Generalization of this idea is next interface: package ru.dimgel.lib.web.state trait StateHandler { def put(obj: AnyRef): String def get(key: String): AnyRef def remove(key: String) } This looks like collection, but implementations may be 100% stateless (put() serializes, get() deserializes, remove() does nothing), 100% stateful (HashMap which returns GUID keys), or anything in the middle. Very flexible. Do you want stateful or stateless site? Just choose/create appropriate state handler implementation. Currently StateSerializer used in multipage form example (http://dimgel.ru:8080/lib.web/example/en/e26formmultipage/) uses java serialization which produces rather heavy strings. I was thinking about JSONSserializer which could return shorter strings without all that Java metadata. But I've put it off for now: there were questions about simple ways of mapping possibly complex objects. This flesh is not urgent. See example e05state. ***** FORMS ***** Forms look like this: @serializable class LoginDTO { var email: String = _ var password: String = _ var remember: Boolean = _ } object LoginForm extends Form[LoginDTO] (Map("method" -> "post")) { // short form for common use case: val email: FText(VRequired & VEmail) // full form for flexibility: val password: Field(WPassword, CString, VRequired) val remember: FCheckBox() override protected def htmlImp(errors:Form.ErrorList): NodeSeq = { def err(f: Field.Generic) = if (errors.ok(f)) "" else "err" {<table> <tr class={err(email)}> <th>Email</th><td>{email.w}</td></tr> <tr class={err(password)}> <th>Password</th><td>{password.w}</td></tr> <tr><th/> <td><label>{remember.w} Remember me</label></td></tr> <tr><th/> <td><input type="submit" value="Submit"/></td></tr> </table>} } override def submit(param: ParamMap, default: LoginDTO) = { //... } } Here you can see that I rely on reflection quite a lot. I tried many various ways but finally had to choose between concise source code and total strict typization. I've chosen conciseness. See examples e20widgets, e22form, e23formfields, e26formmultipage. -- Cheers, dimgel |
|
|
[scala-tools] Re: [lib.web] v.0.2: validators rewritten, state management, formsDmitry Grigoriev <mail@...> writes:
> In 1-3 months I hope to finish some stuff (like > file uploads), cleanup, publish v.0.3 and start a public ride with issue > tracking, etc. For now I'd just appreciate any feedback. Stateless form stuff looks interesting, but I do not like the idea of working under framework, I like the idea of useful libraries more, so that I could use the neat stuff where I want, not where I must. |
|
|
[scala-tools] Re: [lib.web] v.0.2: validators rewritten, state management, formsArtemGr wrote:
> Stateless form stuff looks interesting, > but I do not like the idea of working under framework, > I like the idea of useful libraries more, > so that I could use the neat stuff where I want, not where I must. Yeah, I agree: whatever framework you take, you face its limits very soon. So my point about forms module was: 1. It must suit my own needs as far as I can recall my own experience. Of course I tried to generalize it but in some situations I've chosen simplicity over flexibility. 2. It's independent from lib.web core so those who don't like it may forget it. More, if anyone would share some another cute forms stuff I can add it as form2 package or so. =) 3) At last, while working on forms I could create really good validators framework which can be easily extended to fit exactly to one's needs. Request parameter validation is usually asspain, too. One of my primary goals was to create validators flexible enough to be used in different contexts - particularly, with and without forms. Unfortunately, I could not create forms exactly as I dreemed them. I claimed lib.web to be thin strictly typed wrapper over thick and powerful things like Scala, Java codebase and servlets. My slogan here is "write IN language, not USING language" (c) anti-McConnell. But forms arrived to be neither thin nor strictly typed. I only hope that time will show they're not completely useless. :) -- Cheers, dimgel |
|
|
[scala-tools] Re: [lib.web] v.0.2: validators rewritten, state management, formsArtemGr wrote:
> Stateless form stuff looks interesting, > but I do not like the idea of working under framework, > I like the idea of useful libraries more, > so that I could use the neat stuff where I want, not where I must. BTW, you gave me good idea: in readme I noted that validators maybe used on their own, but I'll probably add ability to create Param and ParamMap classes directly from HttpServletRequest. It would make validators really useful independently of lib.web core. P.S. In my previous answer, I occasionally deleted "forms are always asspain" after "yeah I agree". Overproofreading. %) -- Cheers, dimgel |
|
|
[scala-tools] Re: [lib.web] v.0.2: validators rewritten, state management, formsDmitry Grigoriev <mail@...> writes:
> BTW, you gave me good idea: in readme I noted that validators maybe used > on their own, but I'll probably add ability to create Param and ParamMap > classes directly from HttpServletRequest. It would make validators > really useful independently of lib.web core. That was the first thing I looked for in the code. "Where do I put my HttpServletRequest in?" I saw you have your own generalizations around request and response, but without standard ServletRequest support it looks at least like Scala would look without JCL. |
|
|
[scala-tools] Re: [lib.web] v.0.2: validators rewritten, state management, formsArtemGr wrote:
> I saw you have your own generalizations around request and response, > but without standard ServletRequest support it looks at least like > Scala would look without JCL. OK, I'll do that. Thanks for feedback. :) -- Cheers, dimgel |
| Free embeddable forum powered by Nabble | Forum Help |