Top Screenshot Manual Download Wiki Chat
1 Abstract 2 Getting started 3 Download 4 License 5 Contact 6 Postscript Appendix
I have been looking for a framework to make Web application easily, but I was not satisfied the existing ones. I think that the idea of scriptlet of JSP is a good way to ease of development.
Therefore, using the JSP cocept, I developed the Web framework with the following features:
The previous versions of Web flavor 0.1 can use with Rhino (JavaScript) or JRuby (Ruby), however, this version is only for Scala in order to utilize features of Scala.
"Better CGI, Better PHP!"
The environment without strong constraint but which enable to develop easily as CGI or PHP, the loose but enough for Web application development --- that is my goal.
The features of Web Flavor version 0.3 are:
Web Flavor requires:
Java | Java 5 Runtime Environment or later |
---|---|
Java Servlet | Java Servlet 2.3 or later |
Java Servletコンテナ | Apache Tomcat 6 or later (Tomcat 5 might be compatible but it has not be confirmed. Other containers such as Jetty are not tested.) |
Scala | 2.7.1.final (included) |
Because we have not tested every combination of the above environment, some might not work well.
Deploy ${WEB_FLAVOR_HOME}/webflavor.war on the servlet container.
Add ${WEB_FLAVOR_HOME}/lib/scala-library.jar to the CLASSPATH of the servlet container, or it might not work on some servlet containers.
Flavor is a script for Web application, and is written by Scala language.
In Web Flavor, a web application is developed by writing Flavors.
Details of Flavor are shown in "A3 Flavor".
A Flavor source is to be deployed in the directory WEB-INF/src/, and the relative path of the source is mapped to its access path in the same way.
作成したFlavorソースは、WEB-INF/src/下に置かれ、その相対パスがそのままアクセスパスにマッピングされます。
For example:
Flavorソース | URL |
---|---|
WEB-INF/src/examples/Foo.scala | http://localhost:8080/webflavor/examples/Foo.scala |
Details are shown in "A4 Deployment of Flavor source" and "A5 Mapping Rules of Access Path".
Java Servlet API are provided with wrapping of Scala to be easily used in Flavors.
Details are shown in "A2 API Reference".
Flavor programming is explained with examples as follows:
As a first example, let us make a Flavor which displays "Hello, world!."
// HelloWorld.scala // Title val TITLE = "Hello, world!" // An XML element to be returned to // Web Flavor engine as response. <html><body><h1>{TITLE}</h1></body></html>
Save the Flavor (Scala script) as HelloWorld.scala in WEB-INF/src/. The character set of the file should be UTF-8.
Though it looks like a mere HTML template, actually, it is a Scala code. It might be hard to understand because the return value of the code is not explicitly expressed.
The last line is equivalent to the statement
return <html><body><h1>{TITLE}</h1></body></html>
(In Scala, return keyword is omitted usually.)
In this sample code, it returns an XML element, but returning String or null is possible.
リクエストしたパラメータなどを表示するFlavorを作ります。
// Echo.scala // Title val TITLE = "Echo" // An XML element to be returned to // Web Flavor engine as response. <html> <head> <title>{TITLE}</title> </head> <body> <h1>{TITLE}</h1> <h2>Headers:</h2> {for ((name, value) <- request.headers) yield <p>{name}: {value}</p>} <h2>Parameters:</h2> {for ((name, value) <- request.params) yield <p>{name}: {value}</p>} </body> </html>
Save the Flavor as Echo.scala in the directory WEB-INF/src/.
The "request" in the code is an instance equivalent of HttpServetRequest. The header and parameter information are provided as request.headers and request.params respectively with type of Map[String,String].
As both are Seq[String,String], they are iterable in for-loops to obtain the contained information.
The version 0.2.7 or later allows HTML page generation using POHP (Plain Old HTML Page).
This feature enables sepalation of View as HTML template, and pure HTML template allows collabolation with web designer.
To write "Hello, world!" Flavor with POHP, make the following HTML template as src/POHPHelloWorld.html . The character set should be UTF-8.
<html> <head> <title><span flavor:id="title">title</span></title> </head> <body> <h1><span flavor:id="title"/></h1> <span flavor:id="message">Hello</span> </body> </html>
The element <span flavor:id="resourceName"/>...</span> is the resource to be embedded.
Next, save the following Flavor as src/POHPHelloWorld.scala with character encoding of UTF-8.
Template("", "title" -> Text("Hello, world!"), "message" -> <p>Hello, POHP world!</p> )
Template("pageName", (String,Seq[scala.xml.Node])*) is a method to generate template object.
"title" -> Text(...) describes the resource to be inserted. The resource is an object with type of Seq[scala.xml.Node], and an XML element such as an XML-literal is available as a resource. The text has to be converted to an XML element by Text(...) method.
The template file and the flavor source file have to be in the same directory and the same filename with suffixes of ".html" and ".scala" respectively.
By doing above, HTML page with substitution of resource can be displayed.
<html> <head> <title>Hello, world!</title> </head> <body> <h1>Hello, world!</h1> <p>Hello, POHP world!</p> </body> </html>
The Flavor of the same URL can respond different pages. If "src/POHPHelloWorld.scala" is as following,
Template("Foo", "title" -> Text("Hello, world!"), "message" -> <p>Hello, POHP world!</p> )
とした場合、対象となるテンプレートは"src/POHP_HelloWorld_Foo.html"となり、ページ名と名前の組み合わせにより、複数ページを返すことが可能になります。
the targeted HTML template changes to "src/POHP_HelloWorld_Foo.html". Combinations of page name and name(名前って何のこと?) enable different pages. Default page name is "" (empty string). Details of POHP template are shown in "A9 POHP Template".
If the type of the object which is persistent, such as Context#attributes or Session, is defined in a Flavor source, updating the flavor souce may cause ClassCastException.
It is caused by the difference of the class space (ClassLoader) between the persistent object and the newly created class. It cause the exception continuously until restart of the servlet container or deployment.
To solve this problem,
Dynamic library is the library used in Flavors, is compiled with Flavors, and is executed on the same ClassLoader.
Dymanic library enables to share codes used in Flavors.
It also allows try-and-error development because it is compiled dynamically. Details are shown in "A10 Dymanic Library".
Version 0.25 or later allows to compile Flavors in advance to package as web application.
It's merit is:
It is suited for operating the developed programs as package.
The development process is
flavorcコマンドやflavorc Antタスクについては、「A8 Flavor Compiler」をご覧ください。
"flavorc" command and flavorc Ant task are described in "A8 Flavor Compiler".
To deploy on a servlet container, the web.xml should be modified as follows:
<filter> <filter-name>WebFlabor</filter-name> <filter-class> jp.ne.cappuccino.keisuken.servlet.flavor.WebFlavorFilter </filter-class> ... <init-param> <param-name>staticMode</param-name> <param-value>true</param-value> </init-param>
By setting staticMode to true, Flavor is excuted statically and is not compiled dynamically.
In WEB-INF/src directory, there are sample sources.
Version 0.2.0a3 or later has an administrator menu, which administrates Web Flavor. Current version allows
This feature enables editing and executing Web Flavors from web brouser, which means easy and rapid development of web applications. Administrator manu is also written in Flavor.
Details are shown in "A7 Administrator menu".
Download WebFlavor-samples-x.x.x.zip and expand it. Set an environment variable JAVA_HOME or JRE_HOME to the Java runtime home directory (such as C:¥Program Files¥java¥jre¥1.6.0_07). Execute startup.bat (WINDOWS) or start.sh (UNIX) in WebFlavor-samples directory.
By accessing http://localhost:8080/, sample applications are executed.
As Administrator menu requires BASIC authentication, login with username: webflavor and password: webflavor.
以下のページからダウンロードできます.
https://sourceforge.net/project/showfiles.php?group_id=242794
アーカイブ | 詳細 |
---|---|
WebFlavor-#.#.#.zip | ソースとWARファイルパッケージ |
WebFlavor-samples-#.#.#.zip | サンプルアプリケーション(Apache Tomcat込) |
以下のページからダウンロードできます.
ライセンスファイルを参照してください.
なお,このソフトウェアを使って生じた損害などについては,作者である西本 圭佑は一切責任をとりませんのでご了承ください.
また,Scalaなどのランタイムについても,各ライセンスファイルをご覧下さい.
質問や要望などがありましたら keisuken atmark cappuccino.ne.jp あるいは Twitterの @keisuke_n まで内容を書いてお送りください.
Administrator menuでソースの生成から編集までできるようになり、ちょっとしたCGIぽいものをServletコンテナ上で試すことができ、Scalaの記述性も助けて、便利に使えるものになったと思います。
パフォーマンスも、コンパイルに時間がかかることに目をつぶれば、生のJava Servletと同じくらいのパフォーマンスが出ると思います。
JSPのScriptletでも短いものは同様に軽快に書けていけますが、JSPの記述ルールをある程度覚えなくてはいけなかったり、XMLのタグの中にコードが埋もれてしまって、読みにくく書きにくいものになっています。
Web FlavorではScalaのコードのみ許すことによって、読みやすさや書きやすさを追求できますし、XMLリテラルがあるために、Viewをかなり簡単に記述できます。XSS(クロスサイトスクリプティング)が生じにくくなる良い副作用もあります。
通常ViewとControllerを混ぜて記述するのは推奨されせんが、Web FlavorではViewとController、場合によってはModelまで1つのソースファイルに書いてしまいます。しかし「それでもいい」と思わせてしまう魅力を持っていると思います。
しかしまだ未完成です.APIなどの仕様が大幅に変更される可能性がありますし,バグもたくさんあります、ドキュメントもまだまだ十分とはいえませんが、これからも改良していきたいと思います。応援してください。
Web Flavor requires:
Java 5 Runtime Environment以上 | |
Java Servlet | Java Servlet 2.3以上 |
Java Servletコンテナ | Apache Tomcat 6以上(Tomcat 5以降でも動作すると思われる, Jettyなど他のコンテナは未確認) |
Scala | 2.7.1.final (標準添付) |
Flavor API is for handling resources and configuration to write Flavor.
Flavor GUI API is a kind of framework to write FORM in Flavor.
GUI component (which displays input element and holds inputed values) and validator (which validates inputed values) are provided.
A Flavor is a script for web application written in Scala.
Flavors shall be written with the following rules:
Character code os Flavor source is UTF-8 (fixed.)
Flavor source is a closure (class) which inherits,
and variables such as context, request, response, and sessions are passed as arguments of closure.
As Web Flavor engines adds closure (class) declarations shown below automatically, only content of closures are required to write.
import jp.ne.cappuccino.keisuken.servlet.flavor.{Context,Request,Response,FlavorUtils} import jp.ne.cappuccino.keisuken.servlet.flavor.HTMLUtils._ import java.io._ class {名前} extends (Context,Request,Response,Session) => AnyRef { def apply( context: Context, request: Request, response: Response, session: Session): AnyRef = { val __flavor_util__ = new FlavorUtils(context, request, response, session) import __flavor_util__._ // A Flavor source is inserted here } }
Returned values are handled as Servlet response and displayed as
返り値 | 出力 |
---|---|
null | No output |
String | String |
scala.xml.Node(XML literal) | XML/(X)HTML |
Template(POHP Template) | XML/(X)HTML |
Book(null/String/scala.xml.Node/Temlate etc.) | No output/String/XML/(X)HTML |
Output can be configured with
For example,
response.contentType = "text/plain; charset=Windows-31J"
makes output as text format with Windows-31J encoding.
Basic procedure is to write a code that returns response object as follows:
An XML element of Scala is useful and it can be use as a template, however, can not output HTML pages which conforms with (X)HTML.
By setting HTML type in reponse.documentType, HTML generated from XML element conforms (X)HTML.
HTML constants are
Constant | (X)HTML/XML Type |
---|---|
HTML_4_01_STRICT | HTML 4.01 Strict Type |
HTML_4_01_TRANSITIONAL | HTML 4.01 Transitional Type |
XHTML_1_0_STRICT | XHTML 1.0 Strict Type |
XHTML_1_0_TRANSITIONAL | XHTML 1.0 Transitional Type |
XML_1_0 | XML 1.0 |
An example is shown as follows:
// Write your code ... // Set HTML type as XHTML 1.01 Transitional response.documentType = XHTML_1_01_TRANSITIONAL // XML object to output <html> <body> </body> </html>
By setting Response#documentType,
For html element, it outputs as written in XML elements, therefore, the developer should define attributes such as xmlns or xml:lang.
In Flavor sources, the class
is instantiated and imported, therefore, its methods are available.
Flavor sources are to be deployed in directory WEB-INF/src/ . The deployed sources are compiled and executed at need.
Examples
If Web Flavor is deployed as http://localhost:8080/webflavor/, mapped as follows:
URL path | Flavor source path |
---|---|
/webflavor/Foo.scala | WEB-INF/src/Foo.scala |
/webflavor/Foo | WEB-INF/src/Foo.scala |
/webflavor/ | WEB-INF/src/Index.scala |
/webflavor/Index | WEB-INF/src/Index.scala |
/webflavor/Index.scala | WEB-INF/src/Index.scala |
/webflavor/examples/Boo.scala | WEB-INF/src/examples/Boo.scala |
/webflavor/examples/Boo | WEB-INF/src/examples/Boo.scala |
If access path ends with "/", it is handles as ".../index.scala".
Web Flavor filter is a runtime for Web Flavor and implemented as servlet filter.
Default configuration (web.xml) is as follow:
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" version="2.5"> ... <filter> <filter-name>WebFlabor</filter-name> <filter-class> jp.ne.cappuccino.keisuken.servlet.flavor.WebFlavorFilter </filter-class> <init-param> <param-name>filterChain</param-name> <param-value>false</param-value> </init-param> <!-- <init-param> <param-name>source</param-name> <param-value>WEB-INF/src</param-value> </init-param> <init-param> <param-name>libSource</param-name> <param-value>WEB-INF/lib_src</param-value> </init-param> <init-param> <param-name>temporary</param-name> <param-value>WEB-INF/temp</param-value> </init-param> <init-param> <param-name>startupCompileAll</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>updateCheckInterval</param-name> <param-value>60</param-value> </init-param> <init-param> <param-name>staticMode</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>bbsHome</param-name> <param-value>/WEB-INF/bbs_data</param-value> </init-param> <init-param> <param-name>wikiHome</param-name> <param-value>/WEB-INF/wiki_data</param-value> </init-param> --> </filter> <filter-mapping> <filter-name>WebFlabor</filter-name> <url-pattern>/</url-pattern> </filter-mapping> <filter-mapping> <filter-name>WebFlabor</filter-name> <url-pattern>/Index.scala</url-pattern> </filter-mapping> <filter-mapping> <filter-name>WebFlabor</filter-name> <url-pattern>*.scala</url-pattern> </filter-mapping> <filter-mapping> <filter-name>WebFlabor</filter-name> <url-pattern>/samples/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>WebFlabor</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
It is mapped to "/"、"/Index.scala"、"*.scala"、"/samples/*"、"/admin/*".
Web Flavor Filter has following parameters:
パラメータ名 | 内容 |
---|---|
filterChain | Used for chaining filters. Default is "fale". In case of "true", filters are chained. |
source | The directory where Flavor sources are to be deployed. Default is "WEB-INF/src". If modified, it shall be designated by the relative path from the directory where the WAR file is deployed. |
libSource | The directory for dymanic libraries that Flavor sources depend. Default is "WEB-INF/lib_src". If modified, it shall be designated by the relative path from the directory where the WAR file is deployed. |
temporary | Temporary directory for Flavor compilation. Default is "WEB-INF/temp". If modified, it shall be designated by the relative path from the directory where the WAR file is deployed. |
startupCompileAll | Whether all Flavor sources are compiled or not on startup. Default is false, and they are not compiled. In case of true, all of them are compiled, and it may cause delay of startup. |
updateCheckInterval | Time interval (in second) to check modification of Flavor sources. Default is 60 seconds. |
staticMode | Whether Flavors are static mode (which instantiates from static class) or not. Default is false. In case of true, it generates Flavors from default class loader and executes them. In static mode, it starts up faster because of pre-compilation. However, it does not compile dynamically. |
Administrator menu is an administrative menu of Web Flavor.
It provides the function to
Security configuration (in web.xml) is as follows. The menu is BASIC authenticated with "web-flavor-admin" roll. Change if you need.
<security-constraint> <web-resource-collection> <web-resource-name>Admin area</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>web-flavor-admin</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> <realm-name>Admin area</realm-name> </login-config>
Set PATH to $FLAVOR_HOME/bin for flavorc (UNIF/Linux shell) or flavorc.bat.
Arguments for flavorc are
Usage: flavorc CLASSPATH DESTDIR SRCDIR CLASSPATH: CLASSPATH needed to compile DESTDIR: Directory for compiled classes SRCDIR: Directory for Flavor sources
To use flavorc Ant task, the custom task is required to define in Ant task.
<taskdef name="flavorc" classname="jp.ne.cappuccino.keisuken.servlet.flavor.tools.FlavorCompilerTask" classpath="${scala-compiler-jar}:${scala-library-jar}:${webflavor-jar}" />
Next, compilation is defined with flavorc Ant task.
<!-- ${classpath}: CLASSPATH needed to compile ${destdir}: Directory for compiled classes ${srcdir}: Directory for Flavor sources --> <flavorc srcdir="${flavor-srcdir}" destdir="${classes}" classpath="${classpath}" />
POHP Template is an HTML file written in UTF-8.
Embedding XML resourses given by Flavor into this template, the final page (HTML/XHTML) is outputed.
Deploy wiith a same name and in the same directory of Flavor source. Suffix ".html" is required.
Flavor source path | HTML template path |
---|---|
src/examples/Foo.scala | src/examples/Foo.html |
Put resorce tag into the place in POHP template where you want to inject from Flavor.
<!-- src/examples/Foo.html --> <html> <body> <span flavor:id="foo">dummy message</span> </body> </html>
There are two formats for resource tag.
Flavor is described as follows:
// src/examples/Foo.scala Template("page name", "foo" -> <h1>Hello, world!</h1> )
The XML element (Seq[scala.xml.Node]) given by the resource name is inserted into the place of the resource tag in Foo.html.
Naming rules of POHP templates are as follws:
Flavor path | Page name | HTML template path |
---|---|---|
examples/Foo.scala | "" | examples/Foo.html |
examples/Foo.scala | "boo" | examples/Foo_boo.html |
exmaples/Foo.scala | "bar" | examples/Foo_bar.html |
Dynamic libraries are the libraries which depends on Flavor and is determined dynamically. They are compiled with Flavors dynamically, and executed on the same ClassLoader of Flavor.
Dynamic libraries enables sharing codes of web application and developing with try-and-error.
Dynamic libraries are usually deployed in "WEB-INF/lib_src" and referenced by Flavors.
Because they cannot be referenced by root package, they have to be packaged.
// WEB-INF/lib_src/examples/HelloWorld.scala package examples object HelloWorld { def message = "Hello, world!" }