Magnolia Templating

SCIPIO ERP templates are essentially Magnolia templates enriched with a SCIPIO-specific API and context for use in code. To get started on Magnolia templating visit: http://documentation.magnolia-cms.com/display/DOCS/Introduction+to+templating

 

A fully written example of a very dynamic page is included in this package. Though a basic understanding of Magnolia templating is required, the CatoDemoCheckout is an excellent starting point in understanding the power of SCIPIO templating as a whole. It essentially replaces the checkout page of a modern store front-end and is compatible with the demo store “syracus” that is included in this package. The example is available within the template editor or already assigned to a page within the page editor, and as page template model “com.ilscipio.cato.magnolia.demo.model.CatoDemoCheckoutModel” and template cato-magnolia-demo/templates/pages/catoDemoCheckout.ftl.

 

The Magnolia templates invoked for rendering through SCIPIO ERP have access to all usual standard Magnolia facilities but are supplemented with a wealth of SCIPIO-related data and contextual information, similar to SCIPIO ERP widget screens. SCIPIO ERP makes available a number of context variables and provides a special communication API to be able to invoke SCIPIO functionality from Magnolia. These are the essentials of the SCIPIO ERP Render and Platform Communication API.

 

The typical process and usage is as follows: SCIPIO enhances a CMS rendering request with a number of context variables, including some typical for SCIPIO ERP usage (Delegator) and information about the original request. To use these context variables safely from within the Magnolia environment, most of them are wrapped in some way using the SCIPIO ERP communication API, which makes it safe for Magnolia-based code to iterate them and invoke methods on them. The code also has access to a static communication interface that can be used to invoke the SCIPIO-environment API and scripts.

 

In general, when talking about template or any other Magnolia code for SCIPIO ERP and OFbiz, it is important to distinguish between execution and request environments:

 

  • CMS/Magnolia environment vs SCIPIO ERP environment:

Magnolia code runs in a (Tomcat) webapp environment with its own libraries, many of which can conflict with libraries found on the SCIPIO classpath. For this and other reasons, Magnolia code that wishes to invoke SCIPIO must do so carefully using a special communication API, which we call the “SCIPIO ERP Platform Communication API” or simply comm API. Conversely, in general code written in the SCIPIO environment does not have access to Magnolia functionality and can only receive from Magnolia invocations basic-type arguments (primitives, etc.) and arguments of types which live in the SCIPIO ERP environment. SCIPIO ERP makes all of this safely possible, but proper usage ultimately is the client developer’s responsibility.

 

  • “SCIPIO ERP environment” code typically refers to the SCIPIO ERP Java API and utilities, but it can includes potentially any other Java libraries and classes that are loaded through SCIPIO ERP component loader.
  • In the context of a Magnolia rendering invocation, “Magnolia environment” is roughly interchangeable with “webapp environment” as set up by SCIPIO ERP webapp container.
  • In practical technical terms, the Magnolia and SCIPIO ERP environments must be considered and kept separate due to library and ClassLoader conflicts.

 

  • Original SCIPIO ERP webapp request vs CMS rendering request:

A SCIPIO ERP rendering request first begins with a request to an SCIPIO ERP webapp, which when intercepted by SCIPIO ERP makes a second separate request for the CMS to render a page. As a result, during a SCIPIO ERP-based template rendering, the standard Magnolia request/session/application attributes are present, but they reflect only the CMS rendering request itself. SCIPIO ERP provides separate, additional and “mock” context variables containing similar information but about the original request made to the SCIPIO ERP webapp/store.

 

In practical terms, these distinctions are necessary to prevent various context variable conflicts; the CMS rendering request may be implemented through a second HTTP request, and code that uses the Apache servlet API interface needs to know for which request it is getting its information.

 

SCIPIO ERP Render API and Context

The first thing SCIPIO ERP does into a CMS render invocation is set up a context for templates and models to use. This is represented by the catoRenderContext bean-like class.

 

The context can be retrieved using CatoRenderContextHelper.getContext() by template model code, which is the same as MgnlContext.getAttribute(“catoCtx”). In Freemarker template, it is accessible through ctx.catoCtx and its getter can be accessed in a bean-like way as is usual for Magnolia template code.

 

CatoRenderContext contains everything needed for communication with OFBiz and notably a ofbizCtx member, which is an emulation of an OFBiz screen render context and is used to carry over data between OFBiz and Magnolia and between calls.

 

SCIPIO ERP Render Actions

Some essential rendering functions – calling scripts, loading property maps – are defined in a CatoRenderActions class, which can be gotten through CatoRenderContext.getRenderActions(). This is essentially a wrapper around the OFBiz API and emulates some OFBiz screen widget actions. It is preferable to use these over the more generic SCIPIO ERP Platform Communication API functionality, wherever it suffices.

 

SCIPIO ERP Helper Templating Functions

Additionally, SCIPIO ERP defines a CatoTemplatingFunctions class analogous to Magnolia’s TemplatingFunctions. It is hooked into the stock Freemarker and STK renderers’ context attributes and is accessible as SCIPIO ERP from the root context (in addition to the ctx.catoCtx variable). These functions provide template-centric helper functions such as link functions and FTL-specific workarounds for the SCIPIO ERP comm API. e.g.: catofn.ofbizLink(“main”) creates a simple intra-webapp OFBiz controller link. See the CatoTemplatingFunctions class Javadoc for available functions.

 

OFBiz Mock Request Servlet Objects

The SCIPIO ERP context contains Java Servlet API HttpServletRequest, HttpSession and ServletContext implementations that represent and emulate the request objects of the request originally made to the OFBiz webapp which triggered this Magnolia rendering. These are stored in context as:

 

  • ofbizRequest – HttpServletRequest
  • ofbizSession – HttpSession
  • ofbizServletContext – ServletContext

 

These are imperfect, best-effort emulations, but should be sufficient for most general code. In general, calling the getAttribute methods on these objects and other informational method will return the attributes and information about the original OFBiz request.

 

SCIPIO ERP Platform Communication API

SCIPIO ERP has a special communication API for invoking OFBiz environment functionality from the Magnolia environment, which we dub the comm API. This API exposes OFBiz functionality to Magnolia and wraps all calls to OFBiz-environment code to make it safe to invoke. The classes for this API are found in the com.ilscipio.cato.magnolia.api.platform.comm package.

The comm API is implemented using dynamic Java language features and as a result is able to invoke the majority of the OFBiz Java API (org.ofbiz.*) of any OFBiz version from Magnolia code, provided the arguments to methods are properly prepared, as well as any Java code that lives in the OFBiz component-level environment in general. In addition it also provides methods for invoking OFBiz and OFBiz-environment scripts (see OFBiz Scripts section).

The comm API generally works as follows: A piece of Magnolia code invokes a static OFBiz API method through the CatoCommStatic object’s execution methods (runXxx), whose result is wrapped a SCIPIO ERP object wrapper (when applicable). This wrapper essentially represents the result returned from the OFBiz API call. The CMS code can then use the special methods on the returned wrapper to invoke methods on the underlying wrapped object. The wrapped object can also be passed back as argument another OFBiz method method call through the comm API, which automatically interprets and unwraps it as necessary (with some guidelines).

The CatoCommStatic object can be retrieved from the CatoRenderContext instance during a template model execution (CatoRenderContext.getCommStatic()).

In general, execution methods on CatoCommStatic wrap results in a standard reflexive wrapper, represented by the CatoCommStdObject class, with the exception of primitive and some elementary types. Such exceptions are listed in the method description of CatoCommStatic.autoWrapStd(Object). For example, there would be no reason to wrap a String. In general for many dynamic methods the caller is responsible for predicting the return type of the call.

The standard wrapper is the most verbose but safest and general way to access any kind of object living in the OFBiz environment and is the default. However there are alternative wrappers that can help with writing template model code more succinctly in Java (and Freemarker) code. The CatoCommStatic and CatoCommStdObject interfaces provide wrapXxx methods that can be used to return a different wrapper type (or “convert” them).

Notably, there is an interface-based (dynamic proxy) wrapper for wrapping objects that implement arbitrary (but mostly simple Java/collection) interfaces – CatoCommInterfaceObject, a bean-like wrapper for classes that consist mostly of getters (especially useful for making simple beans available to a template from a model) – CatoCommBeanObject, and a new container wrapper for Java collections and maps (for easier iteration) – CatoCommContainerObject. They each have their strengths and weaknesses and the many alternatives should be able to suit most situations. See the CatoCommXxxObject interface Javadocs and their corresponding CatoCommStatic.wrapXxx methods for more information.

Care must be taken when passing arguments to OFBiz invocation methods through CatoCommStatic or the wrappers (runXxx methods): Only types which are safe for the OFBiz environment or wrappers may be passed to such invocations. See the Javadoc for these methods.

In addition to wrapper variety, there are methods that can be used to bypass wrapping mechanisms altogether in esoteric situations, but these should be avoided and are generally marked deprecated.

 

General Recommendations

  • AVOID importing OFBiz classes and types directly into a template model entirely. The comm API allows to specify types via strings when it is necessary.
  • AVOID using the interface-based wrapper for anything outside of standard Java packages.
  • It is almost always an error to call an OFBiz class directly from Magnolia model or template, and having imports can easily make it error-prone. The SCIPIO ERP comm API exists to make a separation at the invocation. In general, when handling comm API invocation arguments and results, try to stick to simple Java types and implementations.
  • For more complex types, always look to CatoCommStatic to see if a helper method exists which would create a guaranteed-safe type for you. For example, the result of CatoCommStatic.makeCntrMap() is recommended to make maps to pass to OFBiz invocations. Whenever one does not exist, stick to standard Java implementations such as HashMap, ArrayList, etc.
  • In general, the bean-based wrapper is best for preparing Freemarker variables from model; the container-based wrapper is best for iteration (except for when elements are interfaces; then interface-based wrapper may be useful); and the standard wrapper is the safest whenever in doubt.

 

OFBiz Scripts

SCIPIO ERP makes it possible to execute per-page-template OFBiz scripts for a Magnolia page render, which can be useful for reusing OFBiz scripts, during migration, or simply to move out data preparation code into the OFBiz environment (anywhere no CMS functionality is needed, or where the code is pure data lookup, though arguments can also be passed in context).

There are two ways in which these can be invoked:

  • Calling CatoRenderActions helper methods from a Magnolia template model: CatoRenderActions.runOFbizGroovyScript, CatoRenderActions.runOFbizSimpleMethod
    The context passed to these methods should normally be: CatoRenderContext.getOFbizCtx()
  • Script includes defined per-template using the SCIPIO ERP Template Helper app

The template helper app allows to define script includes that SCIPIO ERP automatically executes moments before the template model is executed in a Magnolia render. It is sufficient to initialize a template using the apps and add entries, and upon execution SCIPIO ERP will run them in order with the CatoRenderContext.getOFbizCtx() context. The results can then be retrieved from the template model (recommended) using CatoRenderContext.getOFbizCtx() or in Freemarker using ctx.catoCtx.ofbizCtx. Note: ofbizCtx is a Map and at current time gets duplicated by Freemarker upon access.