Using EGL as a server-side scripting language in Tomcat
The original purpose of
EGL was to enable batch generation of source code and other textual artefacts from EMF models. However, since there is no hard binding between the language and the file system, it is also possible to use EGL in other contexts.
In this article, we demonstrate using
EGL as a server-side scripting language in Tomcat, to produce web pages from EMF models on the fly.
Setup
Download a fresh copy of Tomcat 6.0 here and extract it
Download egl-servlet-full.zip
Extract all .jar files from the zip into the lib folder of Tomcat
Open web.xml in the conf directory of Tomcat and add the following snippet
<servlet>
<servlet-name>egl</servlet-name>
<servlet-class>org.eclipse.epsilon.egl.servlet.EglServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>egl</servlet-name>
<url-pattern>*.egl</url-pattern>
</servlet-mapping>
Make sure that there is an environment variable called JRE_HOME and it's pointing to your JRE installation directory (the root, not the bin). In Windows, you can create this variable from System Properties→Advanced→Environment Variables→System Variables→New...
Create a Hello World web application
To create a hello world web application and test your installation, you need to go through the following steps:
Go to the webapps folder and create a new directory named helloworld
Inside helloworld, create a new file called index.egl and add to it the following code
[%='Hello World'%]
Start Tomcat using bin/startup.bat (or startup.sh in Linux/MacOS)
Open your browser and go to http://localhost:8080/helloworld/index.egl
A web-page with the text Hello World should appear. If not, please make sure you've followed all the steps above and if it still doesn't work, please drop by the forum and we'll be happy to help.
Accessing parameters from the URL
To access parameters from the URL (or fields of a submitted form) you can use the
request.getParameter('parameter-name') method. For example, by modifying the source code of
index.egl to the following
[%='Hello '+request.getParameter('visitor')%]
and navigating to
http://localhost:8080/helloworld/index.egl?visitor=John, you should get a page reading
Hello John as a result.
Other built-in objects
EGL provides the following built-in objects which (should) function exactly like they do in JSP
request
response
config
application
session
You may want to have a look
here for a tutorial that explains their functionality.
Caching
EGL provides the built-in
cache object to facilitate two types of caching. Page caching can be used to ensure that repeated requests to the same URL do not result in the execution of EGL templates. Fragment caching can be used to share the text generated by a template between requests for different URLs.
For example, the following code is used to ensure that repeated requests for pages matching the regular expression
index.* are served from the page cache:
[% cache.pages('index.*'); %]
The page cache can be expired programmatically, as shown below, or by restarting the Tomcat server.
[% cache.expirePages('index.*'); %]
In addition to page caching, EGL supports fragment caching which allows the contents of a sub-template to be cached. For example, the following code processes
sidebar.egl only the first time that the template is executed:
[% var sidebarTemplate = TemplateFactory.load('Sidebar.egl'); %]
[%=cache.fragment(sidebarTemplate) %]
Note that the
fragment method should be used in a dynamic output section.
Like pages, fragments can be expired programmatically (or by restarting the Tomcat server):
[% cache.expireFragment(sidebarTemplate); %]
A simple caching strategy is to populate the page and fragment caches from your main EGL templates, and to provide a
ClearCache.egl template in a sub-directory that only administrators that can access.
Loading EMF models in EGL pages
The main motivation for turning EGL into a server-side scripting language is its ability to work well with EMF models. EGL provides the
modelManager built-in object to let you load EMF models that reside in the web application.
To experiment with
modelManager, download the
Graph.ecore and
Ecore.ecore models and place them in your helloworld directory. Then, change your
index.egl to look like this
[%
modelManager.registerMetamodel('Ecore.ecore');
modelManager.loadModel('Sample', 'Graph.ecore', 'http://www.eclipse.org/emf/2002/Ecore');
%]
The metamodel has [%=EClass.all.size()%] classes
Refresh the page in your browser and it should now read:
The metamodel has 3 classes
The Model Manager
The
modelManager built-in object provides the following methods:
registerMetamodel(file : String) : Registers the file (should be an Ecore metamodel) in EPackage.Registry.INSTANCE
loadModel(name : String, modelFile : String, metamodelURI : String) : Loads the model stored in modelFile using the registered metamodel metamodelURI.
loadModelByFile(name : String, modelFile : String, metamodelFile : String) : Loads the model stored in modelFile using the metamodel in metamodelFile.
loadModel(name : String, aliases : String, modelFile : String, metamodel : String, expand : Boolean, metamodelIsFilebased : Boolean) : Provides more parameters for loading models.
uncacheModel(modelFile : String) : Removes the modelFile from the cache (next call to loadModel() will actually reload it)
clear() : Clears cached models and metamodels
Sharing models between templates
Currently, each model is only loaded once (the first time the
loadModel() or
loadModelByFile() is called). If multiple pages need to access the same model, add the model loading logic in an operation in a separate
models.eol file:
operation loadModels() {
modelManager.registerMetamodel('Ecore.ecore');
modelManager.loadModel('Sample', 'Graph.ecore', 'http://www.eclipse.org/emf/2002/Ecore');
}
and then import and call it from each one of your pages:
[%
import 'models.eol';
loadModels();
%]
-- Page code here
Working with big models
If you encounter a Java
OutOfMemoryError while querying a big model you'll need to start Tomcat with more memory than the default 256 MB. To do this, go to
bin/catalina.bat (on Windows -- if you're on Linux you should modify
catalina.sh accordingly) and change line
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%
to
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER% -Xms1024m -Xmx1024m -XX:MaxPermSize=128m
If you keep getting out of memory errors, you may find
Lambda Probe useful for figuring out what's going wrong.