- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
lib.web 0.3: welcome to try!
Sun, 2010-01-24, 23:49
Hello everyone!
I am proud to announce version 0.3 of lib.web (thin, stateless, strictly
typed Scala web framework). I believe it has finally grown to something
useful, at least for simple tasks. So I'm starting public ride as
maintainer. I don't expect significant API changes or changes I cannot
handle with @deprecated (well, they maybe but few).
Take it at http://github.com/dimgel/lib.web/
NOTE: Please don't take master branch, it's empty. Take branch
0.3-SNAPSHOT or latest tag.
Also my archive is still available: http://dimgel.ru/lib.web/files/
Now I'll try to join scala-tools community and install lib.web into
scala-tools.org maven repository. When it's done I'll update to mailing
list.
I encourage everyone to try it and will appreciate any feedback,
including bug reports, suggestions about API improvements (particularly,
I love words 'private' and 'final', and you may find I love them more
than needed =)), new ideas and so on.
--------------------
New features in this version are: headers, file uploads, sessions,
stabilized core API, documented pluggability.
Previous announces:
version 0.1: http://thread.gmane.org/gmane.comp.lang.scala/16636
version 0.2: http://thread.gmane.org/gmane.comp.lang.scala.tools/3426
HEADERS
Initially I didn't want to manually parse header values to extract, for
example, charset parameter from Content-Type. Finally, this is how it
looks in lib.web:
val charset /* : String*/ = request.headers(ContentType).charset.get
Or, more safely:
val ctOpt /* : Option[ContentType] */ = request.headers.get(ContentType)
val charset =
if (ctOpt.isEmpty) null
else ctOpt.get.charset.getOrElse(null)
So, there are two basic ideas here:
1. Each header type has corresponding class which is a _semantic_
representation of header's data. Strict static typizatioin is honored.
2. Constructing header class instances from raw header values uses Scala
Combinator Parsers, and literally follows BNF described in RFC 2616
(HTTP 1.1) and others.
Please see examples: e06header (using headers), e07headercustom
(creating your own header classes).
FILE UPLOADS
There is nothing special here, but this functionality was missing in
previous versions. I use Apache Commons FileUpload. Also I took a look
at Servlet 3 spec draft and found there interface
javax.servlet.http.Part which looked to me pretty much like Apache's
FileItem. So I tried to mirror upcoming Servlet 3 in lib.web API.
Please see example: e11fileupload.
SESSIONS
Sessions are strictly typed too. Instead of attributes which can store
arbitrary data by string keys, lib.web sessions are generic classes
parametrized with single data type they store. Also, there're two
session implementations:
- HttpSessionWrapper just delegates to container-maintained sessions.
- CustomSession is completely independent: it deals with session cookie
on its own and can use any StateStorage strategy. I introduced it
because container looses session data when application is undeployed,
and this behaviour is often unacceptable. On the other hand,
CustomSession cannot be automatically replicated by container.
Please see examples: e08session (for HttpSessionWrapper),
e09sessioncustom (for CustomSession).
STABILIZED CORE API
I finally combed core package interfaces (Request and Response
hierarchies, etc.). I was once surprised to realize that core lib.web
architecture tends to ideologically mirror Servlet API, to certain
degree. Since that moment, I often looked at Servlet API and tried not
to go too far away from it.
DOCUMENTED PLUGGABILITY
ArtemGr gave me an idea (
http://article.gmane.org/gmane.comp.lang.scala.tools/3436 ) that I
should allow using lib.web parts, not only completely wrap over and
replace Servlet API. I made some effort in this direction, and this
arrived to be another reason to keep close to Servlet API structure.
Please see example: e17pluggability
--------------------
Unless Nibiru hits the Earth or some other cataclysm happens, my plans are:
0. Fix bugs as quick as possible.
1. Format all comments with scaladoc tags and add scaladoc pages
generation to project maven file.
2. Study ScalaQL announced by Miguel Garcia not so long ago, and finally
try to use this shit in a real project. Until now, it all was just
"academic" interest. Real project (e.g. forum) would be a good knock to
further library development.
3. I'm working on forms module. New version will be much more powerful:
nested forms (forms as reusable components of other forms), dynamic ajax
fields with no restrictions on dependency graph, full-blown client-side
validation (each atomic validator has its javascript counterpart) and so
on. This work is driven by my current job tasks, so it goes with good
quality but bad speed.
So. Thank you for reading (or skipping) so many words. =)
Cheers,
Mon, 2010-01-25, 18:07
#2
Re: damn, what a shame...
> 2. Study ScalaQL announced by Miguel Garcia not so long ago, and finally
> try to use this shit in a real project. Until now, it all was just
> "academic" interest.
Told me my mother never to say dirty words. :) That was about my
homegrown masterpiece, not about ScalaQL I've been waiting for a long
time to come. Sorry. :)
Mon, 2010-01-25, 19:17
#3
Re: lib.web 0.3: welcome to try!
Hi Dmitry,
I'm always happy to see more web tools (or libraries in general)
available for Scala.
Thank you for creating one :-). Just out of curiosity - is lightweight the
major goal of lib.web? By mixing HTML with code, you can reduce the number of
files in a project and make the project structure simpler but it's
generally believed
that this makes creating and debugging view code more challenging. What's
your experience with lib.web in this regard?
Thanks,
Jack
On Sun, Jan 24, 2010 at 2:49 PM, Dmitry Grigoriev wrote:
> Hello everyone!
>
> I am proud to announce version 0.3 of lib.web (thin, stateless, strictly
> typed Scala web framework). I believe it has finally grown to something
> useful, at least for simple tasks. So I'm starting public ride as
> maintainer. I don't expect significant API changes or changes I cannot
> handle with @deprecated (well, they maybe but few).
>
>
> Take it at http://github.com/dimgel/lib.web/
> NOTE: Please don't take master branch, it's empty. Take branch
> 0.3-SNAPSHOT or latest tag.
>
> Also my archive is still available: http://dimgel.ru/lib.web/files/
>
> Now I'll try to join scala-tools community and install lib.web into
> scala-tools.org maven repository. When it's done I'll update to mailing
> list.
>
>
> I encourage everyone to try it and will appreciate any feedback,
> including bug reports, suggestions about API improvements (particularly,
> I love words 'private' and 'final', and you may find I love them more
> than needed =)), new ideas and so on.
>
> --------------------
>
> New features in this version are: headers, file uploads, sessions,
> stabilized core API, documented pluggability.
>
> Previous announces:
> version 0.1: http://thread.gmane.org/gmane.comp.lang.scala/16636
> version 0.2: http://thread.gmane.org/gmane.comp.lang.scala.tools/3426
>
>
> HEADERS
>
> Initially I didn't want to manually parse header values to extract, for
> example, charset parameter from Content-Type. Finally, this is how it
> looks in lib.web:
>
> val charset /* : String*/ = request.headers(ContentType).charset.get
>
> Or, more safely:
>
> val ctOpt /* : Option[ContentType] */ = request.headers.get(ContentType)
> val charset =
> if (ctOpt.isEmpty) null
> else ctOpt.get.charset.getOrElse(null)
>
> So, there are two basic ideas here:
>
> 1. Each header type has corresponding class which is a _semantic_
> representation of header's data. Strict static typizatioin is honored.
>
> 2. Constructing header class instances from raw header values uses Scala
> Combinator Parsers, and literally follows BNF described in RFC 2616
> (HTTP 1.1) and others.
>
> Please see examples: e06header (using headers), e07headercustom
> (creating your own header classes).
>
>
> FILE UPLOADS
>
> There is nothing special here, but this functionality was missing in
> previous versions. I use Apache Commons FileUpload. Also I took a look
> at Servlet 3 spec draft and found there interface
> javax.servlet.http.Part which looked to me pretty much like Apache's
> FileItem. So I tried to mirror upcoming Servlet 3 in lib.web API.
>
> Please see example: e11fileupload.
>
>
> SESSIONS
>
> Sessions are strictly typed too. Instead of attributes which can store
> arbitrary data by string keys, lib.web sessions are generic classes
> parametrized with single data type they store. Also, there're two
> session implementations:
>
> - HttpSessionWrapper just delegates to container-maintained sessions.
>
> - CustomSession is completely independent: it deals with session cookie
> on its own and can use any StateStorage strategy. I introduced it
> because container looses session data when application is undeployed,
> and this behaviour is often unacceptable. On the other hand,
> CustomSession cannot be automatically replicated by container.
>
> Please see examples: e08session (for HttpSessionWrapper),
> e09sessioncustom (for CustomSession).
>
>
> STABILIZED CORE API
>
> I finally combed core package interfaces (Request and Response
> hierarchies, etc.). I was once surprised to realize that core lib.web
> architecture tends to ideologically mirror Servlet API, to certain
> degree. Since that moment, I often looked at Servlet API and tried not
> to go too far away from it.
>
>
> DOCUMENTED PLUGGABILITY
>
> ArtemGr gave me an idea (
> http://article.gmane.org/gmane.comp.lang.scala.tools/3436 ) that I
> should allow using lib.web parts, not only completely wrap over and
> replace Servlet API. I made some effort in this direction, and this
> arrived to be another reason to keep close to Servlet API structure.
>
> Please see example: e17pluggability
>
> --------------------
>
> Unless Nibiru hits the Earth or some other cataclysm happens, my plans are:
>
> 0. Fix bugs as quick as possible.
>
> 1. Format all comments with scaladoc tags and add scaladoc pages
> generation to project maven file.
>
> 2. Study ScalaQL announced by Miguel Garcia not so long ago, and finally
> try to use this shit in a real project. Until now, it all was just
> "academic" interest. Real project (e.g. forum) would be a good knock to
> further library development.
>
> 3. I'm working on forms module. New version will be much more powerful:
> nested forms (forms as reusable components of other forms), dynamic ajax
> fields with no restrictions on dependency graph, full-blown client-side
> validation (each atomic validator has its javascript counterpart) and so
> on. This work is driven by my current job tasks, so it goes with good
> quality but bad speed.
>
>
>
> So. Thank you for reading (or skipping) so many words. =)
>
> Cheers,
Tue, 2010-01-26, 08:07
#4
Re: lib.web 0.3: welcome to try!
Hello Jack,
> Just out of curiosity - is lightweight the major goal of lib.web? By
mixing HTML with code, you can reduce the number of files in a project
and make the project structure simpler but it's generally believed that
this makes creating and debugging view code more challenging. What's
your experience with lib.web in this regard?
Well, the major goal is to make something useful, convenient and
beautiful. :) And the main point is to keep the whole thing conceptually
clear. Lightweight is just a consequence. When I'll start, for example,
forum written in lib.web, all related reusable stuff would fit into
lib.cms package or so.
My experience with lib.web is currently limited with writing examples
for it. %) As I said in announce, a shift to real project (forum) is one
of my current priorities.
Concerning logic and view separation.
Technically, I don't think that external HTML templates are easier to
debug than language-supported (and thus IDE-supported) stuff. Besides,
external template engine introduces extra indirection level, which is no
good in any case.
Ideologically, I'm pretty sure and ready to repeat on and on that it's
just a matter of programmer's discipline. Whether you define templates
as separate methods or separate files, the essence does not change.
Every second or third template I've ever seen heavily mixes logic and
presentation. I think this is just because the task itself is complex,
and the distinction between view and logic must be considered
individually in every particular case. Take even Lift's templates: they
are really exiting, but they don't forbid you to generate markup in code
and pass it to template. If they did, be sure they'd immediately be
claimed for being too limited. :/
The only advantage of external template files I see is that they can be
edited by "Designers with Dreamweavers" (c). My point is:
- First, anyone can use any template engine with lib.web. Just like with
pure servlets. Here is conceptual clearness and lightweightness. _Maybe_
someday I (or somebody else) will add some "default" template engine to
lib.web.
- Second, me personally will never leave markup for designer. After
years of freelancing, I cannot recall a single project where I could use
designers' markup without fixing or (more often) completely rewriting it
to work with dynamic content. I finally came to taking just designer's
images (cut into pieces and optimized) and making markup myself.
Tue, 2010-01-26, 14:57
#5
Re: Re: lib.web 0.3: welcome to try!
I agree with you on this one : the so called "separation of concern"
brings more complexity that it helps, it has been way over hyped.
UI interface design is not just a matter of esthetics that are
best left to graphical designers (that part is only the icing on the cake ;),
it is complex enough to be a discipline in itself. I would say
that it is much more like API design that like brochure design...
I haven't had time to look at your project, but if it doesn't fall into
the seperation of concern trap, it's a good start.
Don't get me wrong, MVC is a good pattern, it's just that the I prefer
to have the V (View) as plain old code, rather than markup that gets
little or no compile time validation. Which is why I like GWT so much,
unfortunately it is not (yet) available in Scala.
Cheers !
On Tue, Jan 26, 2010 at 2:02 AM, Dmitry Grigoriev wrote:
> Hello Jack,
>
>> Just out of curiosity - is lightweight the major goal of lib.web? By
> mixing HTML with code, you can reduce the number of files in a project
> and make the project structure simpler but it's generally believed that
> this makes creating and debugging view code more challenging. What's
> your experience with lib.web in this regard?
>
> Well, the major goal is to make something useful, convenient and
> beautiful. :) And the main point is to keep the whole thing conceptually
> clear. Lightweight is just a consequence. When I'll start, for example,
> forum written in lib.web, all related reusable stuff would fit into
> lib.cms package or so.
>
> My experience with lib.web is currently limited with writing examples
> for it. %) As I said in announce, a shift to real project (forum) is one
> of my current priorities.
>
>
> Concerning logic and view separation.
>
> Technically, I don't think that external HTML templates are easier to
> debug than language-supported (and thus IDE-supported) stuff. Besides,
> external template engine introduces extra indirection level, which is no
> good in any case.
>
> Ideologically, I'm pretty sure and ready to repeat on and on that it's
> just a matter of programmer's discipline. Whether you define templates
> as separate methods or separate files, the essence does not change.
> Every second or third template I've ever seen heavily mixes logic and
> presentation. I think this is just because the task itself is complex,
> and the distinction between view and logic must be considered
> individually in every particular case. Take even Lift's templates: they
> are really exiting, but they don't forbid you to generate markup in code
> and pass it to template. If they did, be sure they'd immediately be
> claimed for being too limited. :/
>
> The only advantage of external template files I see is that they can be
> edited by "Designers with Dreamweavers" (c). My point is:
>
> - First, anyone can use any template engine with lib.web. Just like with
> pure servlets. Here is conceptual clearness and lightweightness. _Maybe_
> someday I (or somebody else) will add some "default" template engine to
> lib.web.
>
> - Second, me personally will never leave markup for designer. After
> years of freelancing, I cannot recall a single project where I could use
> designers' markup without fixing or (more often) completely rewriting it
> to work with dynamic content. I finally came to taking just designer's
> images (cut into pieces and optimized) and making markup myself.
>
> --
> Cheers,
> dimgel
>
> http://github.com/dimgel/lib.web — thin, stateless, strictly typed Scala
> web framework.
>
>
Tue, 2010-01-26, 16:17
#6
Re: lib.web 0.3: welcome to try!
Hello Maxime,
> Don't get me wrong, MVC is a good pattern, it's just that the I prefer to have the V (View) as plain old code, rather than markup that gets little or no compile time validation.
Yeah, that's exactly what I'm advocating for: templates as just Scala
functions (anything) => scala.xml.NodeSeq. For example, surrounding
template is:
def template(..., content: => NodeSeq): NodeSeq =
...
...
{content}
...
> Which is why I like GWT so much, unfortunately it is not (yet) available in Scala.
I have already heard many good words about GWT and plan to look at it in
the nearest future.
Why not
val optCharset = request.headers.get(ContentType).map (_.charset)
Dmitry Grigoriev-2 wrote:
>
> Initially I didn't want to manually parse header values to extract, for
> example, charset parameter from Content-Type. Finally, this is how it
> looks in lib.web:
>
> val charset /* : String*/ = request.headers(ContentType).charset.get
>
> Or, more safely:
>
> val ctOpt /* : Option[ContentType] */ = request.headers.get(ContentType)
> val charset =
> if (ctOpt.isEmpty) null
> else ctOpt.get.charset.getOrElse(null)
>
-----
Razvan Cojocaru,
Work: http://www.sigma-systems.com
Me: http://feeds.razie.com/RazvanTech
Playground: http://wiki.homecloud.ca