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.
lib
folder of Tomcatweb.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>
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...
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"%]
bin/startup.bat
(or startup.sh
in Linux/MacOS)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.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.
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.
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.
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 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 metamodelsCurrently, 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
By default App Engine will treat EGL files as static content and serve their source code instead of executing them. To work around this, add the following snippet under the root element of the appengine-web.xml
configuration file of your App Engine application.
<static-files> <exclude path="*.egl"/> </static-files>
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 PSI Probe useful for figuring out what's going wrong.