IntroductionToMoquiFramework-1 0 1
IntroductionToMoquiFramework-1 0 1
This Work is in the public domain and is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using this Work and assume any risks associated with your use of this Work. This Work includes contributions authored by David E. Jones, not as a "work for hire", who hereby disclaims any copyright to the same.
w w w. m o q u i . o r g
Table of Contents
1. Introduction to the Introduction!
About Moqui Framework! About This Document! A Note on Conguration! The Execution Context! 1 1 1 1 1 2 2 2 3 4 4 4 4 6 6 7 7 7 8 8 9 9 9 10 10 10 10 11 11 11 11 12
Introduction to Moqui Framework i
2. Tour of a Request!
Web Browser to Database! Web Services! Incoming and Outgoing Email!
Factory, Servlet & Listeners! Resource and Cache Facades! Screen Facade!
Screen Denition! Screen/Form Render Templates!
Service Facade!
Service Naming! Parameter Cleaning, Conversion and Validation! Quartz Scheduler! Web Services!
Entity Facade!
Multi-Tenant! Connection Pool and Database! Database Meta-Data!
Transaction Facade!
Transaction Manager (JTA)!
13 13 13 13 13 13 14
w w w. m o q u i . o r g! ii
A Note on Conguration
The conguration for Moqui Framework is done in a single XML le with the root element moqui-conf, and this le will be referred to as the moqui-conf le throughout this document. When running Moqui two locations must be specied: the runtime directory, and the moqui-conf le. Moqui Framework has a default conguration le called MoquiDefaultConf.xml (in framework/impl/conf-default) and at runtime the moqui-conf le specied is merged with the MoquiDefaultConf.xml le to make the actual conguration to use. There are three examples of runtime moqui-conf les: MoquiDevConf.xml, MoquiStagingConf.xml, and MoquiProductionConf.xml (all under runtime/conf/* directories). The default conf le and these three example runtime moqui-conf les are good examples and have various comments to help you get started with conguration of Moqui Framework.
w w w. m o q u i . o r g! 1
2. Tour of a Request
Web Browser to Database
A request from a Web Browser will nd its way to the framework by way of the Servlet Container (the default is the embedded Winstone Servlet Container, also works well with Apache Tomcat or any Java Servlet implementation). The Servlet Container nds the requested path on the server in the standard way using the web.xml le and will nd the MoquiServlet mounted there. The MoquiServlet is quite simple and just sets up an ExecutionContext, then renders the requested Screen. The screen is rendered based on the congured root screen for the webapp, and the subscreens path to get down to the desired target screen. Beyond the path to the target screen there may be a transition name for a transition of that screen. Transitions are used to process input (and not to prepare data for presentation), which is separated from the screen actions which are used to prepare data for presentation (and not to process input). If there is a transition name the service or actions of the transition will be run, a response to the transition selected (based on conditions and whether or not there was an error), and then the response will be followed, usually to another screen. When a service is called (often from a transition or screen action) the Service Facade validates and cleans up the input map according to the service denition, and then calls the dened inline or external script, Java method, auto or implicit entity operation, or remote service. Entity operations, which interact with the database, should only be called from services for write operations and can be called from actions anywhere for read operations (transition or screen actions, service scripts/methods, etc).
Browser
Web
Servlet Container
Screen
Transition
Service
Entity
Database
Web Services
Web Service requests generally follow the same path as a form submission request from a web browser that is handled by a Screen Transition. The incoming data will be handled by the transition actions, and typically the response will be handled by an action that sends back the encoded response (in XML, JSON,
w w w. m o q u i . o r g! 2 Introduction to Moqui Framework
etc) and the default-response for the transition will be of type none so that no screen is rendered and no redirecting to a screen is done.
w w w. m o q u i . o r g! 3
JCR (Jackrabbit) Groovy Free Marker WikiText Resource Facade Execution Context
ehcache
Servlet (Tomcat)
User Facade
JTA/DBCP (Atomikos)
Transaction Facade
Database (Derby)
w w w. m o q u i . o r g! 5
Servlet Container. In either case the Moqui root webapp is loaded and the WEB-INF/web.xml le tells the servlet container to load the MoquiServlet, the MoquiSessionListener, and the MoquiContextListener. These are default classes included in the framework, and you can certainly create your own if you want to change the lifecycle of the ExecutionContextFactory and ExecutionContext. With these default classes the ExecutionContextFactory is created by the MoquiContextListener on the contextInitialized() event, and is destroyed by the same class on the contextDestroyed() event. The ExecutionContext is created using the factory by the MoquiServlet for each request in the doGet() and doPost() methods, and is destroyed by the MoquiServlet at the end of each request by the same method.
Screen Facade
The API of the Screen Facade is deceptively simple, mostly just acting as a factory for the ScreenRender interface implementation. Through the ScreenRender interface you can render screens in a variety of contexts, the most common being in a service with no dependence on a servlet container, or in response to a HttpServletRequest using the ScreenRender.render(request, response) convenience method.
w w w. m o q u i . o r g! 6 Introduction to Moqui Framework
Generally when rendering and a screen you will specify the root screen location, and optionally a subscreen path to specify which subscreens should be rendered (if the root screen has subscreens, and instead of the default-item for each screen with subscreens). For web requests this sub-screen path is simply the request pathInfo (the remainder of the URL path after the location where the webapp/servlet are mounted). Screen Denition The real magic of the Screen Facade is in the screen denition XML les. Each screen denition can specify web-settings, parameters, transitions with responses, subscreens, pre-render actions, render-time actions, and widgets. Widgets include subscreens menu/active/panel, sections, container, container-panel, render-mode-specic content (ie html, xml, csv, text, xsl-fo, etc), and forms. There are two types of forms: form-single and form-list. They both have a variety of layout options and support a wide variety of eld types. One important note about forms based on a service (using the auto-elds-service element) is that various client-side validations will be added automatically based on the validations dened for the service the form eld corresponds to. For more details about these see the example screens in the runtime/component/example component, and the annotations (inline documentation) in the xml-screen-1.0.xsd, xml-form-1.0.xsd, and xml-actions-1.0.xsd les. Screen/Form Render Templates The output of the ScreenRender is created by running a template with macros for the various XML elements in screen and form denitions. If a template is specied through the ScreenRender.macroTemplate() method then it will be used, otherwise a template will be determined with the renderMode and the conguration in the screen-facade.screen-text-output element of the moqui-conf le. You can create your own templates that override the default macros, or simply ignore them altogether, and congure them in the moqui-conf le to get any output you want. There is an example of one such template in the runtime/template/screen-macro/ScreenHtmlMacros.ftl le, with the override conguration in the runtime/conf/development/MoquiDevConf.xml le. The default HTML screen and form template uses jQuery Core and UI for dynamic client-side interactions. Other JS libraries could be used by modifying the screen HTML macros as described above, and by changing the theme data (defaults in runtime/component/webroot/data/WebrootThemeData.xml le) to point to the desired JavaScript and CSS les.
Service Facade
The Service Facade is used to call services through a number of service call interfaces for synchronous, asynchronous, scheduled and special (TX commit/rollback) service calls. Each interface has different
w w w. m o q u i . o r g! 7
methods to build up information about the call you want to do, and they have have methods for the name and parameters of the service. When a service is called the caller doesnt need to know how it is implemented or where it is located. The service denition abstracts that out to the service denition so that those details are part of the implementation of the service, and not the calling of the service. Service Naming Service names are composed of 3 parts: path, verb, and noun. When referring to a service these are combined as: ${path}.${verb}#${noun}, where the hash/pound sign is optional but can be used to make sure the verb and noun match exactly. The path should be a Java package-style path such as org.moqui.impl.UserServices for the le at classpath://service/org/moqui/impl/UserServices.xml and that service denition le will be found based on that path with location patterns: classpath:// service/$1 and component://.*/service/$1 where $1 is the path with . changed to / and .xml appended to the end. While it is somewhat inconvenient to specify a path this makes it easier to organize services, nd denitions based on a call to the service, and improve performance and caching since the framework can lazy-load service denitions as they are needed. The verb (required) and noun (optional) parts of a service name are separate to better to describe what a service does and what it is acting on. When the service operates on a specic entity the noun should be the name of that entity. The Service Facade supports CrUD operations based solely on entity denitions. To use these entityimplicit services just use a service name with no path, a noun of create, update, or delete, a hash/pound sign, and the name of the entity. For example to update a UserAccount use the service name update#UserAccount. When dening entity-auto services the noun must also be the name of the entity, and the Service Facade will use the in- and out-parameters along with the entity denition to determine what to do (most helpful for create operations with primary/secondary sequenced IDs, etc). Parameter Cleaning, Conversion and Validation When calling a service you can pass in any parameters you want, and the service caller will clean up the parameters based on the service denition (remove unknown parameters, convert types, etc) and validate parameters based on validation rules in the service denition before putting those parameters in the context for the service to run. When a service actually runs the parameters will be in the ec.context map along with other inherited context values, and will be in a map in the context called parameters to access the parameters segregated from the rest of the context. One important validation is congured with the parameter.allow-html attribute in the service denition. By default no HTML is allowed, and you can use that attribute to allow any HTML or just safe HTML for the service parameter. Safe HTML is determined using the OWASP ESAPI and Antisamy libraries, and conguration for what is considered safe is done in the antisamy-esapi.xml le.
w w w. m o q u i . o r g! 8 Introduction to Moqui Framework
Quartz Scheduler The Service Facade uses Quartz Scheduler for asynchronous and scheduled service calls. Some options are available when actually calling the services and conguration in the moqui-conf le, but to congure Quartz itself use the quartz.properties le (there is a default in the framework/impl/conf-default directory that may be overridden on the classpath). Web Services For Web Services the Service Facade uses Redstone XML-RPC for incoming and outgoing XML-RPC service calls, and Dzhuvinov JSON-RPC for incoming and outgoing JSON-RPC 2.0 calls. The outgoing calls are handled by the RemoteXmlRpcServiceRunner and RemoteJsonRpcServiceRunner classes, which are congured in the service-facade.service-type element in the moqui-conf le. To add support for other outgoing service calls through the Service Facade implement the ServiceRunner interface (as those two classes do) and add a service-facade.service-type element for it. Incoming web services are handled using default transitions dened in the runtime/component/webroot/screen/MoquiRoot/rpc.xml screen. The remote URL for these, if MoquiRoot.xml is mounted on the root (/) of the server, would be something like: http://hostname/ rpc/xml or http://hostname/rpc/json. To handle other types of incoming services similar screen transitions can be added to the rpc.xml screen, or to any other screen.
Entity Facade
The Entity Facade is used for common database interactions including create/update/delete and nd operations, and for more specialized operations such as loading and creating entity XML data les. While these operations are versatile and cover most of the database interactions needed in typical applications, sometimes you need lower-level access, and you can get a JDBC Connection object from the Entity Facade that is based on the entity-facade datasource conguration in the moqui-conf le. Each individual record is represented by an instance of the EntityValue interface. This interface extends the Map interface for convenience, and has additional methods for getting special sets of values such as the primary key values. It also has methods for database interactions for that specic record including create, update, delete, and refresh, and for getting setting primary/secondary sequenced IDs, and for nding related records based on relationships in the entity denition. To create a new EntityValue object use the EntityFacade.makeValue() method, though most often youll get EntityValue instances through a nd operation. For nding (querying) entity records use the EntityFind interface. To get an instance of this interface use the EntityFacade.makeFind() method. This nd interface allows you to set various conditions for the nd (both where and having, more convenience methods for where), specify elds to select and order by, set offset and limit values, and ags including use cache, for update, and distinct. Once options are set you can call methods to do the actual nd including: one(), list(), iterator(), count(), updateAll(), and deleteAll().
w w w. m o q u i . o r g! 9 Introduction to Moqui Framework
Multi-Tenant When getting an EntityFacade instance from the ExecutionContext the instance retrieved will be for the active tenantId on the ExecutionContext (which is set before authentication either specied by the user, or set by the servlet or a listener before the request is processed). If there is no tenantId the EntityFacade will be for the DEFAULT tenant and use the settings from the moqui-conf le. Otherwise it will use the active tenantId to look up settings on the Tenant* entities that will override the defaults in the moqui-conf le for the datasource. Connection Pool and Database The Entity Facade uses Atomikos TransactionsEssentials for XA-aware database connection pooling by default. To congure Atomikos use the jta.properties le. With conguration in the entity-facade element of the moqui-conf le you can change this to use any DataSource or XADataSource in JNDI instead. The default database included with Moqui Framework is Apache Derby. This is easy to change with conguration in the entity-facade element of the moqui-conf. To add a database not yet supported in the MoquiDefaultConf.xml le, add a new database-list.database element. Currently databases supported by default include Apache Derby, HSQL, MySQL, Postgres, and Oracle. Database Meta-Data The rst time (in each run of Moqui) the Entity Facade does a database operation on an entity it will check to see if the table for that entity exists. If not it will create the table, indexes, and foreign keys (for related tables that already exist only) based on the entity denition. If a table for the entity does exist it will check the columns and add any that are missing, and can do the same for indexes and foreign keys.
Transaction Facade
Transactions are used mostly for services and screens. Service denitions have transaction settings, based on those the service callers will pause/resume and begin/commit/rollback transactions as needed. For screens a transaction is always begun for transitions (if one is not already in place), and for rendering actual screens a transaction is only begun if the screen is setup to do so (mostly for performance reasons). You can also use the Transaction Facade for manual transaction demarcation. The JavaDoc comments have some code examples with recommended patterns for begin/commit/rollback and for pause/begin/ commit/rollback/resume to use try/catch/nally clauses to make sure the transaction is managed properly. When debugging transaction problems, such as tracking down where a rollback-only was set, the TransactionFacade can also be use as it keeps a stack trace when setRollbackOnly is called. It will automatically log this on later errors, and you can manually get those values at other times too.
w w w. m o q u i . o r g! 10
Transaction Manager (JTA) By default the Transaction Facade uses the Atomikos TransactionsEssentials library (also used for a connection pool by the Entity Facade). To congure Atomikos use the jta.properties le. Any JTA transaction manager, such as one from an application server, can be used instead through JNDI by conguring the locations of the UserTransaction and TransactionManager implementations in the entity-facade element of the moqui-conf le.
w w w. m o q u i . o r g! 12
Install a Component
Load the Component There are two ways to tell Moqui about a component: put the component directory in the runtime/component directory add a component-list.component element in the moqui-conf le Mounting Screen(s) Each webapp in Moqui (including the default webroot webapp) must have a root screen specied in the moqui-conf.webapp-list.webapp.@root-screen-location attribute. The default root screen is called MoquiRoot which is located at runtime/component/webroot/screen/MoquiRoot.xml.
w w w. m o q u i . o r g! 13
For screens from your component to be available in a screen path under the MoquiRoot screen you need to make each top-level screen in your component (i.e. each screen in the components screen directory) a subscreen of another screen that is an ancestor of the MoquiRoot screen. There are two ways to do this (this does not include putting it in the MoquiRoot directory as an implicit subscreen since that is not an option for screens dened elsewhere): add a screen.subscreens.subscreen-item element to the parent screen (what the subscreen to be under; for example see the apps screen (runtime/component/webroot/screen/WebRoot/apps.xml) where the example and tools root screens are mounted add a record in the SubscreensItem entity, specifying the parent screen in the screenLocation eld, the subscreen in the subscreenLocation eld, the mount point in the subscreenName eld (equivalent to the subscreens-item.@name attribute), and either _NA_ in the userId eld for it to apply to all users, or an actual userId for it to apply to just that user If you want your screen to use its own decoration and be independent from other screens, put it under the MoquiRoot screen directly. To have your screen part of the default apps menu structure and be decorated with the default apps decoration, put it under the apps screen. Other Moqui Conf File Changes You may want have things in your component add to or modify various things that come by default with Moqui Framework, including: Resource Reference: see the moqui-conf.resource-facade.resource-reference element Template Renderer: see the moqui-conf.resource-facade.template-renderer element Screen Text Output Template: see the moqui-conf.screen-facade.screen-text-output element Service Type Runner: see the moqui-conf.service-facade.service-type element Explicit Entity Data and Denition les: see the moqui-conf.entity-facade.load-entity and moqui-conf.entity-facade. load-data elements There are examples of all of these in the MoquiDefaultConf.xml le since the framework uses the moquiconf le for its own default conguration.
w w w. m o q u i . o r g! 14