jbe/bsw@0: jbe/bsw@0:
jbe@381: jbe/bsw@0: jbe@446:jbe@278: WebMCP is a web development framework based on the Lua programming language (read more about Lua here). jbe/bsw@0:
jbe/bsw@0:jbe@387: WebMCP has been developed on Linux and FreeBSD. Using it with Mac OS X is untested as of yet; Microsoft Windows is not supported. Beside the operating system, the only mandatory dependencies for WebMCP are the programming language Lua version 5.2 or 5.3, the Moonbridge Network Server for Lua Applications version 1.0.1 or higher, PostgreSQL version 8.2 or higher, and a C compiler. jbe/bsw@0:
jbe/bsw@0:jbe@507: After downloading the tar.gz package, unpack it, enter the unpacked directory and type make. If you use Mac OS X or if you experience problems during compilation, you need to edit the Makefile.options file prior to compilation. The framework itself will be available in the framework/ directory, while a demo application is available in the demo-app/ directory. The framework.precompiled/ and demo-app.precompiled/ directories will contain a version with all Lua files being byte-code pre-compiled, which can be used instead. You may copy these directories (with cp -L to follow links) to any other place you like. Don't forget to setup a database, and make the tmp/ directory of the application writable for user who executes WebMCP. Good luck and have fun! jbe@507:
jbe@507:jbe@507: WebMCP uses the Moonbridge Network Server to handle HTTP requests. The Moonbridge Network Server listens to a TCP port and passes control to WebMCP by calling request.handler(...) for each request. However, before each request is processed, WebMCP will initialize the environment. This initialization includes tasks such as jbe@507:
jbe@507:jbe@507: For each request, it is also possible to execute filters. Filters can be used to jbe@278:
jbe@507:jbe@507: Filters and initializers are created by adding files in the application's directory structure. The filename determins the execution order of otherwise equally ranked initializers and/or filters. It is a common idiom to start the filename of a filter or initializer with a two digit number to be easily able to change the execution order when desired. Filters and initializers are executed both before and after a request. Each file must contain a command execute.inner(). The part before that command is executed before the request, and the part after that command is executed after the request. jbe@507:
jbe@507:jbe@507: The Moonbridge server creates forks (i.e. clones) of the application server process (i.e. the whole Lua engine including all libraries and variables) in order to handle concurrent requests. Certain initializations may be performed before forking, other initializations must be performed after forking. For this purpose, WebMCP allows an application to provide so-called "pre-fork" and "post-fork" initializers. The application's configuration files as well as its pre-fork initializers are executed before forking. The application's post-fork initializers are executed after forking. In particular, any libraries that open file or network handles during initialization must not be loaded before the server process is forked. Opening database connections must be performed after forking as well. WebMCP follows the following execution order (directory structure is explained further down): jbe@278:
jbe@278:jbe@439: As a minimum configuration, the used configuration file or pre-fork initializer should at least contain a listen{...} call, e.g.: jbe@439:
jbe@439:jbe@439: listen{ jbe@439: { proto = "tcp", host = "::", port = 8080 }, jbe@439: { proto = "tcp", host = "0.0.0.0", port = 8080 } jbe@439: } jbe@507: execute.inner() -- only use this line if done in pre-fork initializerjbe/bsw@0:
jbe/bsw@0: Lua itself has only very few built-in data types. The atom library gives support for extra data types. Currently the following extra data types are provided: jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: In addition the following pseudo-types are existent, corresponding to Lua's base types: jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: Both atom.integer and atom.number refer to Lua's base type “number”. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: New values of atom data types are created by either calling atom.type:load(string_representation) or by calling atom.type{...}, e.g. atom.date{year=1970, month=1, day=1}. You can dump any atom value as a string by calling atom.dump(value) and later reload it with atom.type:load(string). jbe/bsw@0:
jbe/bsw@0:jbe@278: The library “mondelefant” shipping with WebMCP can be used to access PostgreSQL databases. It also serves as an Object-Relational Mapper (ORM). The database connection is usually configured in the config file (e.g. in config/devel.lua): jbe@278:
jbe@278:jbe@439: config.db = { engine="postgresql", dbname="webmcp_demo" }jbe@278:
jbe@278: In addition to configuring the database, it must be opened within a post-fork initializer (e.g. in app/_postfork/01_database.lua): jbe/bsw@0:
jbe/bsw@0:jbe@278: _G.db = assert(mondelefant.connect(config.db)) jbe@439: function mondelefant.class_prototype:get_db_conn() return db end jbe@439: execute.inner()jbe/bsw@0:
jbe@295: The parameters for mondelefant.connect are directly passed to PostgreSQL's client library libpq. See PostgreSQL's documentation on PQconnect for information about supported parameters. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: To define a model to be used within a WebMCP application, create a file named with the name of the model and .lua as extension in the model/ directory of your application. The most basic definition of a model (named “movie” in this example) is: jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: Movie = mondelefant.new_class() jbe/bsw@0: Movie.table = 'movie'jbe/bsw@0:
jbe/bsw@0: Note: Model classes are always written CamelCase, while the name of the file in model/ is written lower_case. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: To select objects from the database, the mondelefant library provides a selector framework: jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: local s = Movie:new_selector() jbe/bsw@0: s:add_where{ 'id = ?', param.get_id() } jbe/bsw@0: s:single_object_mode() -- return single object instead of list jbe/bsw@0: local movie = s:exec()jbe/bsw@0:
jbe/bsw@0: A short form of the above query would be: jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: local movie = Movie:new_selector():add_where{ 'id = ?', param.get_id() }:single_object_mode():exec()jbe/bsw@0:
jbe/bsw@0: For more examples about how to use the model system, please take a look at the demo application. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: As opposed to other web application frameworks, WebMCP does not use a Model-View-Controller (MVC) concept, but a Model-View-Action (MVA) concept. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: The models in MVA are like the models in MVC; they are used to access data stored in a relational database (PostgreSQL) in an object oriented way. They can also be used to provide methods for working with objects representing the database entries. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: The views in the MVA concept are different from the views in the MVC concept. As WebMCP has no controllers, the views are responsible for processing the GET/POST parameters from the webbrowser, fetching the data to be displayed, and creating the output by directly writing HTML to slots in a layout or by calling helper functions for the user interface. jbe/bsw@0:
jbe/bsw@0:jbe/bsw@0: Actions are similar to views, but supposed to change data in the database, hence only callable by HTTP POST requests. They are also responsible for processing the POST parameters from the webbrowser. They can modify the database, but instead of rendering a page to be displayed, they just return a status code. Depending on the status code there will be an internal forward or an HTTP 303 redirect to a view. When calling an action via a POST request, additional POST parameters, which are usually added by hidden form fields, determine the view to be displayed for each status code returned by the action. jbe/bsw@0:
jbe/bsw@0:jbe@278: Ensure that the moonbridge binary is within your system's search path and that the moonbridge_http.lua file is included in the LUA_PATH or linked into the framework's lib/ directory (alternatively the MOONBR_LUA_PATH option might be set accordingly at compile-time of the Moonbridge Network Server). To start an application, call the mcp.lua executable (found in framework/bin/mcp.lua) with the following arguments: jbe@278:
jbe@278: