Lemansys Bonsai Guide

Version 5.0.0

AuthorOperationDescription
Giacomo Mauriio2017-04-16 Released Version 5.0.0
Mario Saccone2012-01-12 Released Version 4.1.0
Giacomo Maurizio2011-01-09 Eclipse Plugin Section Completed
Mario Saccone2012-01-06 Content review of Bonsai Guide
Giacomo Maurizio2011-01-05 First Release of Bonsai Guide
Giacomo Maurizio2011-12-25 Starts to deploy Bonsai Guide

Topics

Preface

This guide is NOT a complete tutorial on LEWS framework and is addressed to new Lemansys ® Server Pages developers under LEWS framework and provides a quick and (we hope) clean approach to .lem philosophy.

If you're already Java Web and J2EE Developer this framework will speed up your development time with provided set of prepared components and a less complex syntax than Java™ and JSP.

This guide is "under construction": we do apologize for mistakes and partial descriptions and we'll be delighted to receive any suggestion.

License


  Copyright (c) 2000-2017 Lemansys, Inc. All rights reserved.
 
  LEWS is a free framework; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free
  Software Foundation; either version 2.1 of the License, or (at your choice)
  any later version.
 
  This library is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  details.
  
  LGPL 2.1 license
  
  LEWS interacts with other components such as Apache Tomcat, Elcipse and Java™ 
  with licenses provided by related owners.
  

About LEWS

LEWS is an acronym of Lightweight Extensible Web Scripting

LEWS is a lightweight framework Servlet/JSP compliant, but very quick, easy and addressed to Java ™ developers with no big experience.

LEWS is absolutely free and open source and released under LGPL 2.1 license

LEWS is fully integrable with Eclipse WTP IDE and bundled with Apache Tomcat Application Server

LEWS is downloadable from SourceForge site

Other important provided features:


At this moment we’re working to release the framework with other Application Sever such as Apache ™ Geronimo, JBOSS ™ , IBM ® Websphere Application Server. If you’re interested and wish to participate please contact us into SourceForge LEWS section.
Please consider LEWS as an absolutely free product; in any case Lemansys cannot be responsible to damages or thoughtless use of the software.

LEWS Installation

LEWS is provided as Tomcat 7.0 extension. You’ve two common ways to install it.

  1. Download full LEWS from Source Forge site
  2. Integrate LEWS into an existing Tomcat 7.0.x environment
Download LEWS from Source Forge is the best, easy and common way to retrieve LEWS framework with zero costs. Once downloaded you’ve simply to configure your system with JAVA HOME linking to a version of Java 1.6.x (JRE or SDK) By default LEWS 4.1 will run over 8080 port.

If you're under Unix Os please remember to assign rights to execute server.

LEWS is provided with full Tomcat Help documentation. In any case we redirect you to Official Tomcat 7.0 documentation page: http://tomcat.apache.org/tomcat-7.0-doc/ You’ve “simply” to launch server and verify that Lews is running copying this url into your browser http://localhost:8080

Integrating LEWS into an existing Tomcat 7.0.x environment is a way addressed to expert and skilled users, so we expect you know Tomcat components and folder structure. P.S. : Please be careful in reading and comparing LEWS api and related Tomcat Version to avoid conflicts and running problems: LEWS development follows Tomcat project evolution!!!
To complete LEWS installation into your Tomcat Environment you’ve to: PS: you should do this only for web applications. In this case you’ve “simply” to add this jar and apply web.xml variations to specidied project(s) ... Force LEWSListener at "top of xml file"

  <listener>
      <listener-class>org.lemansys.j2ee.LEWSApplicationListener</listener-class>
   </listener>

After this, please integrate this following code into "servlet" declaration:

 <servlet>
      <servlet-name>lem</servlet-name>
    <servlet-class>org.lemansys.j2ee.LemansysLemServlet</servlet-class>
       <init-param>
           <param-name>fork</param-name>
           <param-value>false</param-value>
       </init-param>
       <init-param>
           <param-name>xpoweredBy</param-name>
           <param-value>false</param-value>
       </init-param>
    <init-param>
        <param-name>compilerClassName</param-name>
        <param-value>org.lemansys.j2ee.LemansysLemCompiler</param-value>
    </init-param>
       <load-on-startup>3</load-on-startup>
 </servlet>
          
  <servlet>
       <servlet-name>lmh</servlet-name>
    <servlet-class>org.lemansys.j2ee.LemansysLmhServlet</servlet-class>
       <init-param>
           <param-name>fork</param-name>
           <param-value>false</param-value>
       </init-param>
       <init-param>
           <param-name>xpoweredBy</param-name>
           <param-value>false</param-value>
       </init-param>
       <load-on-startup>3</load-on-startup>
   </servlet>
  
and related Servlet mapping:

  <servlet-mapping>
       <servlet-name>lem</servlet-name>
       <url-pattern>*.lem</url-pattern>
   </servlet-mapping>
   <!-- The mapping for the Lemansys servlet -->
   <servlet-mapping>
       <servlet-name>lmh</servlet-name>
       <url-pattern>*.lmh</url-pattern>
   </servlet-mapping>   
   <!-- End of Lemansys Mapping Servlet -->
at last, on the same $CATALINA_HOME/conf/web.xml you can update default "home" page sequence list for any web application overwriting with:

 <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.lem</welcome-file>
        <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>

We suggest to clean up your Tomcat work directory after .jar substitution or any update action!!!

Lemansys Server Pages

Lemansys Server Pages are text files saved into your web application with .lem suffix. Every Lemanys Server Page is usually composed by 2 (two) sections:


Page section is required. Content section is optional (for example when a page will redirect response to another Lemansys Server Page or any internal or external url)
Use “page” section for variable declarations and occasional computation that precedes the answer to user browser that is coded into “content” section specifying related markup (default is text/html with UTF-8 encoding).

Any "standard" output operation must be performed only inside @content section !!!

This is an “hello world” Lemansys Server Page example:
<@page version=”4.1”@>
    <@// put your computational code here... @>
    <@dim name as string@>
    <@set name=”mgshow”@>
<@/page@>
<@content type=”text/html” encoding=”UTF-8”@>
    <html>
        <head><title>Hello World!</head>
        <body>
            Hello Mr. <@=name@> !!!
        </body>
    </html>
<@/content@>

You declare a string variable named “name” with value “mgshow”. Then you respond to connected user browser with a message “Hello Mr. mgshow !!!”

Lemansys Server pages are tag based identified by sequence <@ … @> (and “closure” sequence where needed <@/ … @> ) and can be mixed with html (or xml) tags.
Lem pages are converted in Servlet, compiled and executed by the Application Server.
Lemansys provides a small, powerful and self explain tag set (@dim, @set, @if, @for, @while …): for complete list please see Appendix A.
LEWS provides also a set of functions that speed up your developement (isblank(), tointeger(), htmlformat() …): for complete list please see Appendix B.

Lemansys Applications

You've to create necessarly a LEWS project to run your set of .lem pages.
A LEWS Project is a JSP/Servlet application: any LEWS application is "simply" deployed as JSP/Servlet application.

You can import, export and deploy LEWS application such as .WAR files.

Lemansys is already providing an Eclipse plugin suite to better and quick development of your applications.

To deploy and undeploy applications you so can use Tomcat console manager or (at development phase) related embedded test server (ex: Eclipse WTP)

LEWS Variables and Expressions

Lemansys Variables
Any .lem page lets you define variables.
You can define variables both in page and content sections.
You cannot define an already declared variable.
Any declared "base"variable must not be necessarly initialized: LEWS will do it!!!

To declare LEWS variables you must use the @dim tag


<@dim varname as vartype@>

To initialize LEWS variables you must use the @set tag

<@set varname = value or expression@>

You can use the following variable types:
VarTypeRelated Java class/primitiveNotes
booleanbooleanboolean values (default = false)
cookiecom.lemansys.http.LemansysCookienew cookie instance
datecom.lemansys.datatype.LemansysDatedate(/time) values (default is "now")
doubledoubledouble values (default = 0.0d)
floatfloatfloat values (default = 0.0f)
integerintinteger values (default = 0)
longlonglong values (default = 0L)
stringjava.lang.StringString values (default = "" [empty string])

In addition you can define multiple instance of "base" variables (arrays), but in this case you'll have to initialize it using related Java class:
VarTypeRelated Java class/primitiveNotes
booleanarrayboolean[]boolean array
cookiearraycom.lemansys.http.LemansysCookie[]cookie arrays
datearraycom.lemansys.datatype.LemansysDate[]date arrays
doublearraydouble[]double arrays
floatarrayfloat[]float arrays
integerarrayint[]integer arrays
longarraylong[]long arrays
stringarrayjava.lang.String[]String arrays

Lemansys can also provide you a few very useful objects. These objects can be declared with the same @dim statement and will be discussed later in this guide.
ObjectTypeRelated Java class/primitiveNotes
genericdatabasecom.lemansys.datatype.LemansysGenericDatabaseVery useful when connecting with a "sql" database
localizercom.lemansys.datatype.LemansysLocalizerUseful when localizing application (same scope of Resource Bundle)
optioncom.lemansys.datatype.LemansysOptionUseful to manage list options and automatically binding values into "select" html tag
rssnewscom.lemansys.xml.LemansysRSSNewsManage a single RSS Item
rssnewsreadercom.lemansys.xml.LemansysRSSNewsReaderLets you to connect with a RSS channel and retrive results as "rssnews"
sqlformcom.lemansys.datatype.LemansysSQLFormEasy (and simple mapper) between a SQL Table and Form. Under development: for testing purpose only
sqlviewcom.lemansys.datatype.LemansysSQLViewEasy (and simple mapper) between a SQL Query and Form. Under development: for testing purpose only
textfilereadercom.lemansys.datatype.LemansysTextFileReaderManage Text File Input Streams
textfilewritercom.lemansys.datatype.LemansysTextFileWriterManage Text File Output Streams
xmlbuildercom.lemansys.xml.LemansysXMLBuilderUsed to quickly compose XML streaming in memory
xmldocumentcom.lemansys.xml.LemansysXMLDocumentXML DOM parser from multiple source (StringBuffer, URL, File and generic input stream)
xmlparsercom.lemansys.xml.LemansysXMLParserThis is a very quick and easy version of XML SAX from multiple source (StringBuffer, URL, File and generic input stream): you can parse a lot of MB in a few seconds!!!
xmlvalidatorcom.lemansys.xml.LemansysXMLValidator/td>Validate an XML source using specified xsd
xsltransformercom.lemansys.xml.LemansysXSLTranformerUse this component when transforming an XML streaming with a XSL stylesheet: usually HTML markup is returned.


And finally you can also declare not LEWS standard variables using the javatype @dim tag attribute

<@dim varname as javatype vartype@>
in this case you must initialize your variable
Example:

<@dim extDate as javatype java.util.Date@>
<@set extDate= new java.util.Date()@>


You can declare and initialize in the same way only a Java™ classes admitting "no args" constructor by using newjavatype statement !!!

Example:

<@dim myBuffer as javatype StringBuffer@>
<@set myBuffer= new StringBuffer()@>
is equivalent to:

<@dim myBuffer as newjavatype StringBuffer@>


This is a simple example of variable declaration and settings...

<@page version="4.1"@>

	<@// Some variable declaration...@>
	<@dim k as integer@>
	<@dim i,j as integer@>
	<@set i=100@>
	<@set j=i*2@>
	<@set k=j+3@>
	
	<@dim firstName as string@>
	<@set firstName="John"@>
	<@dim lastName as string@>
	<@set lastName="Doe"@>
	
	<@dim items as integerarray@>
	<@set items=new int[] {1,2}@>
<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<@//HTML (dynamic) code goes here...@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>Variables & Expressions</title>
	 </head>
	 <body>
		i= <@=i@> , j= <@=j@> , k = <@=k@>	
		<@dim fullname as string@>
		<@set fullname=(firstName+" "+lastName).toUpperCase()@>
		<br>Full name is <@=fullname@>
		<br>Sum is <@=items[0]+items[1]@>
	 </body>
	</html>
<@/content@>
... this page return
i= 100 , j= 200 , k = 203
Full name is JOHN DOE 
Sum is 3

Conditional Statements

LEWS allows you to manage conditional statements using the following tags:

expression follows the rules of Java™ syntax: for better understanding we suggest to view related topic
In any case LEWS don't use parentheses after @if statement conditional expression and you must not use brackets in sequences. But remember that in the Java™ sections that can be embedded in Lem pages you, of course, must follow Java™ rules.
@endif and @/if are equivalents.
Please follow this example:


<@page version="4.1"@>

	<@// How to use conditional statements...@>
	<@dim connectionDate as date@>
	
	<@dim MORNING_HELLO,AFTERNOON_HELLO,EVENING_HELLO as string@>
	
	<@set MORNING_HELLO="Good Morning"@>
	<@set AFTERNOON_HELLO="It's Afternoon"@>
	<@set EVENING_HELLO="Good Evening"@>
	
	
<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>Conditional Statements with LEWS 4.1</title>
	 </head>
	 <body>

	<@dim hour as integer@>
	<@set hour=connectionDate.gethour()@>

		<@if hour<14@>
			<@=MORNING_HELLO@>
		<@elseif hour<18@>	
			<@=AFTERNOON_HELLO@>
		<@else@>
			<@=EVENING_HELLO@>
		<@endif@>
				
		dear user...
	 </body>
	</html>

<@/content@>

and a possible return message should be...
Good Evening dear user... 

Loops

LEWS allows you to manage loops using the following tag sequences:

Every @for variable must be declared before and outside loop sequence.
Every @forall variable must be declared inside tag with specified Java™ type and must have the same javaType of ARRAY item!

@next, @endfor and @/for are equivalents.
@wend, @endwhile and @/while are equivalents.
@endforall and @/forall are equivalents.

Please follow this example:


<@page version="4.1"@>

	<@// Running Loops on LEWS platform...@>
	<@dim i as integer@>
	<@dim bestFriends as stringarray@>
	<@set bestFriends=new String[] {"Mark","Paul","Mattew","Gino"}@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Loops</title>
	 </head>
	 <body>
	 	<@dim base as integer@>
	 	<@set base=4@>
		<@for i=1 to 11 step 3@>
			<@=base@>*<@=i@> = <@=base*i@> |
		<@endfor@><br>
		
		<@set i=10@>Wild sequence:
		<@while i<100@>
			<@=i@>
			<@set i*=2@>&nbsp; <@// equals to i=i*2 @>
		<@wend@>
		
		<br>My best Friends are 
		<@forall String friend in bestFriends@>
			<@=friend@>&nbsp;
		<@endforall@>
		
	 </body>
	</html>

<@/content@>

and the output is...

4*1 = 4 | 4*4 = 16 | 4*7 = 28 | 4*10 = 40 | 
Wild sequence: 10  20  40  80 
My best Friends are Mark  Paul  Mattew  Gino 

Modules (.lmh)

Sometime should be very useful to share content between pages or split content management of very long pages in multiple sub entities.

LEWS provides a @external tag wich you can import "shared" code from one or more module(s)


<@external src="[[$root/]path/]module-name.lmh" @>

The inclusion is made at compilation time and not at runtime!!!

A Lemansys Server Page module is a text file with suffix .lmh

A Lemansys Server Page module is not a complete .lem page and may not contains lem tags but, for example, only markup tags such as html or static text.

A Lemansys Server Page module cannot be directly called by browser url.

When you save a .lmh module the main page will be refreshed and recompiled!

A .lmh module can include another module: in this case the path will be referred to main including .lem page path, or if your specify $root prefix LEWS will search module from Application Root (Web)Content.

See this example:

> main file: modules.lem
>> modules: modules/header.lmh, modules/footer.lmh, modules/menu.lmh


modules.lem - source: <@page version="4.1"@> <@/page@> <@content type="text/html" encoding="UTF-8"@> <html> <head> <meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/> <title>LEWS Modules (.lmh)</title> </head> <body> <@external src="modules/header.lmh"@> !!! I'm in body section !!! <@external src="modules/footer.lmh"@> </body> </html> <@/content@>
modules/header.lmh - source: <@dim currentTime as date@> [Company Logo] current time: <@=currentTime.format("hh:mn:ss")@> <@external src="modules/menu.lmh"@>
modules/menu.lmh - source: <hr> Home | Contacts | Who We Are
modules/footer.lmh - source: <hr> POWERED by <@=com.lemansys.lews.runtime.LemansysApplicationServer.SERVER_NAME@>


and result should appear similar to:

[Company Logo] current time: 01:10:39


Home | Contacts | Who We Are
!!! I'm in body section !!!
POWERED by Lemansys LEWS

Text File I/O

LEWS provides a quick way to read/parse text file streaming using textfilereader component ( com.lemansys.datatype.LemansysTextFileReader) and to write using textfilewriter component ( com.lemansys.datatype.LemansysTextFileWriter).

You can read or write "line by line" from and to multiple streaming sources.

Let us to show just some example about opening read methods of textfilewriter:
MethodDescription
openfromfile(string filename, string encoding) tries to open a text streaming from filename source path with specified encoding returning true if operation was successfully accomplished, otherwise false.
openfromfile(string filename) tries to open a text streaming from filename source path without specified encoding. Returns true if operation was successfully accomplished, otherwise false.
openfromurl(string url, string encoding) tries to open a text streaming from url address with specified encoding returning true if operation was successfully accomplished, otherwise false.
openfromurl(string url) tries to open a text streaming from url address without specified encoding. Returns true if operation was successfully accomplished, otherwise false.
openfromstream(InputStream stream, string encoding) tries to open a text streaming from stream generic inputstream with specified encoding returning true if operation was successfully accomplished, otherwise false.
openfromstream(InputStream stream) tries to open a text streaming from stream generic inputstream without specified encoding. Returns true if operation was successfully accomplished, otherwise false.


Let us to show just some example about opening write methods of textfilewriter:
MethodDescription
opentofile(string filename, string encoding) tries to open a text streaming to filename source path with specified encoding returning true if operation was successfully accomplished, otherwise false.
opentofile(string filename) tries to open a text streaming to filename source path without specified encoding. Returns true if operation was successfully accomplished, otherwise false.
opentostream(OutputStream stream, string encoding) tries to send a text streaming to stream outputstream with specified encoding returning true if operation was successfully accomplished, otherwise false.
opentostream(OutputStream stream) tries to send a text streaming to stream outputstream without specified encoding. Returns true if operation was successfully accomplished, otherwise false.


Please see the related javadoc for complete documentation.

With this example we'll try to read a local simple .csv file and display splitted data row at video such as HTML table.

This is resources/users.csv file:


# User list
# Username; First Name; Last Name; Email

a.scott;Alfred;Scott;ascott@acme.com
p.green;Paul;Green;pgreen@acme.org

# End of file


This is textfilereader.lem source code:


<@page version="4.1"@>

	<@dim reader as textfilereader@>
	
<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Text I/O - Reader</title>
	 </head>

	 <body>
		<h1>LEWS - Reading Text File</h1>
		
		<@if reader.openfromfile(toURI("resources/users.csv"))@>
		
			<table>
				<tr><th>User Name</th><th>First Name
				</th><th>Last Name</th>
				<th>Email</th></tr>
			
			<@dim line as string@>
			<@dim items as stringarray@>
			<@dim i as integer@>
			
			<@while reader.hasline()@>
			
				<@set line=reader.nextline()@>
				
		<@if !isblank(line) && !line.startsWith("#")@>
		
			<@set items=line.split(";")@>

			<@if items.length==4@>
				<tr>
					<@for i=0 to 3@>
					<td><@=items[i]@></td>
					<@endfor@>
				</tr>
			<@endif@>
		<@/if@>
				
			<@wend @>
			
			</table>
		
		
			<@call reader.close()@>
		
		<@else@>
		
			ERROR= <font color='red'><@=reader.geterror()@></font>
		
		<@endif@>
		
	 </body>
	</html>
<@/content@>


This is the final output response:

LEWS - Reading Text File

User NameFirst NameLast NameEmail
a.scott Alfred Scott ascott@acme.com
p.green Paul Green pgreen@acme.org


This example will try to save a file inside a "temporary" folder.

textfilewriter.lem source code:


<@page version="4.1"@>

	<@dim newFile as string@>
	<@set newFile=System.getProperty("java.io.tmpdir")+
	"lews-test-out.txt"@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Text I/O - Writer</title>
	 </head>

	 <body>
		File to save should be located at Server Path :
		<br><b> <@=newFile@></b>
		
		<@dim outF as textfilewriter@>
		 
		<@if outF.opentofile(newFile)@>
		
			<@call outF.writeline("FIRST LINE!")@>
			
			<@call outF.writeline("SECOND LINE ...")@>
			
			<@call outF.write("... and CONTINUE!")@>
			
			<@call outF.writeline("LAST LINE!")@> 
			
			<@call outF.close()@>
			
			<hr>File successfully saved and closed!!!
		
		<@else@>
		
			ERROR: <font color="red">
			<@=outF.geterror()@></font>
		<@endif@>
		
	 </body>
	</html>
<@/content@>


The output response should look similar:

File to save should be located at Server Path :

/TEMPORARY-SPECIFIC-PAT .../lews-test-out.txt
File was successfully saved and closed!!!


Please verify that saved lews-test-out.txt file looks like:


FIRST LINE!
SECOND LINE ...... and CONTINUE!
LAST LINE!

Error Management

As you'll se multiple time on this tutorial, LEWS "anticipate" developers in ERROR management.

Usually LEWS tags and components do not "trows" exceptions, but give back true if operation was successfully performed or false otherwise; in addition developer can retrieve error message details by calling .geterror() method of related component.

In any case LEWS is extensible and integrable with every Java™ component, bean and library: sometime developers should directly manage exceptions and errors.

To do it, LEWS provides a "simple" error management based on tags:


<@/try@> and <@endtry@> tags are equivalent.
<@/catch@> and <@endcatch@> tags are equivalent.
<@/finally@> and <@endfinally@> tags are equivalent.

@try and @catch sequence tag are mandatory, @finally section is optional!!!

You can throw one or more exception putting <@catch@> and <@/catch@> in sequence.

Into a <@catch;@>...</@catch@> sequence you'll have back a pre instantiated exception of java.lang.Throwable class type. This exception instance will be available only inside related @catch section!!!

LEWS provide a quick and easy way to manage errors; in any case, as we will show on next chapters you'll use directly Java™ code and relate logic to do it ... better.

The following example (error-management.lem) show a few simple lines of code for error management :


<@page version="4.1"@>

	<@dim filename as string@>
	<@set filename="non-existent-file.ext"@>
	
	<@dim fis as javatype java.io.FileInputStream@>
	<@set fis=null@>
	
<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>Error Management with LEWS</title>
	 </head>

	 <body>
		<@try@>
			<@set fis=new java.io.FileInputStream(filename)@>
			
			<@// Do something... @>
			
		<@/try@>
		<@catch java.io.FileNotFoundException@>
			FILE NOT FOUND "<@=filename@>" :((<hr>
			<font color='red'><@=exception.toString()@></font>
		<@/catch@>
		<@catch Exception@>
			GENERIC ERROR opening <@=filename@><hr>
			<font color='red'><@=exception.toString()@></font>
		<@/catch@>
		<@finally @>
			<@if !isnull(fis)@><@call fis.close()@><@/if@>
		<@/finally@>
	 </body>

	</html>

<@/content@>



This should be the final output page result:


FILE NOT FOUND "no-existent-file.ext" :((
java.io.FileNotFoundException: no-existent-file.ext (No such file or directory)

XML parsing, building and validating

LEWS provides the following components to accomplish xml integration into your dynamic .lem applications



 Parsing
 
   xmlparser
   xmldocument	

 Building
 
   xmlbuilder
  	
 Validation
 
   xmlvalidator

XSL Engine

LEWS provides the following component to accomplish xsl integration into your dynamic .lem applications



  xsltransformer


With XSL transformer you might better separate data from rendering.

XML/XSL is a good solution for mobile platform developement (or generally when you have to provide mutliple devices rendering using the same data set ).

You have to define a xml source (from buffer, file or url) and related xsl "mask" (buffer, file or url)

You can find more info about XSL directly at W3C related page http://www.w3.org/TR/xslt

You can find more info about xsltransformer by seeing LEWS javadoc and related Java™ class com.lemansys.xsl.LemansysXSLTransformer

To better understand the component, please follow the example:

Now we'll show the xml book list (resources/demo.xml) as html

This is the xsl file: (resources/xsl-books.xsl)
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output method="html" indent="yes" doctype-public="-//W3C//DTD HTML 4.01//EN" /> <xsl:template match="books"> <html> <head> <title>Available books</title> </head> <body> <h1>Available books:</h1> <ul><xsl:apply-templates/></ul> </body> </html> </xsl:template> <xsl:template match="book"> <li><b><xsl:value-of select="title"/></b> author: <xsl:value-of select="author/name"/></li> </xsl:template> </xsl:stylesheet>

This is the xmltransformer.lem page:


<@page version="4.1"@>

	<@dim transf as xsltransformer@>
	<@dim xsl_error as string@>
	<@dim res as string@>
	
	<@try@>
		<@call transf.setsourceasfile(toURI("resources/demo.xml"))@>
		<@call transf.setstyleasfile(toURI("resources/xsl-books.xsl"))@>
		<@set res=transf.transform()@>
	<@/try@>	
	<@catch Exception@>
		<@set xsl_error=exception.getMessage()@>
	<@/catch@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

<@if !isblank(res)@>
	<@=res@>
<@else@>	
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>XSL Transnformer error</title>
	 </head>
	 <body>
		Error transforming XSL= 
		<font color="red"><br>
		<b><@=xsl_error@></b><hr>
		<@=transf.geterror()@>
		</font>
	 </body>
	</html>
<@endif@>
<@/content@>

and the ouptput result will be:

Available books:

User (http) request and response handling

HTTP protocol is based on http request and response.

Lemansys developers can interact with these objects using:

These components are automatically provided as "instances" inside any .lem page.

The request component is based on java class com.lemansys.http.LemansysHTTPRequest and implements javax.servlet.http.HttpServletRequest.

In addition to all interface provided methods, to speed up your data checking and retrieving, you can also use:
MethodDescription
getheaders() return a String Array containing name of all current user request http headers
getheader(String headerName) tries to return request header name headerName as string; if it does not exist will return "" (empty string)
toboolean(String rqParam) tries to return request parameter rqParam as boolean; if does not exist or it is not convertible, will return false
todouble(String rqParam) tries to return request parameter rqParam as double; if does not exist or it is not convertible will return 0.0d
tofloat(String rqParam) tries to return request parameter rqParam as float; if it does not exist or it is not convertible, will return 0.0f
tointeger(String rqParam) tries to return request parameter rqParam as integer; if it does not exist or it is not convertible will return 0
tolong(String rqParam) tries to return request parameter rqParam as long; if it does not exist or it is not convertible will return 0L
tostring(String rqParam) tries to return request parameter rqParam as string; if it does not exist or it is not convertible will return "" (empty string)
decode(String value,String encoding) tries to return a value "url-decoded" with specified encoding if it is not possible request will return the same value parameter
decode(String value) = decode(String value,"UTF-8")
encode(String value,String encoding) tries to return a value "url-encoded" with specified encoding if it is not possible request will return the same value parameter
encode(String value) = encode(String value,"UTF-8")

With methods: tobooleanarray(rqParam),todoublearray(...),tofloatarray(...), tointegerarray(...),tolongarray(...),tostringarray(...) you can try to retrieve request parameters as array of related "type"; if rqParam not found null LEWS will return null

Please be careful because request parameter names are "case sensitive"; header names are case insensitive!!!

The querystring component is based on java class com.lemansys.http.LemansysQueryString and automatically provides a powerful method to retrieve parameters from query string:
MethodDescription
toboolean(String query parameter) tries to return request parameter qryParam as boolean; if it does not exist or it is not convertible will return false
todouble(String qryParam) tries to return query parameter qryParam as double; if it does not exist or it is not convertible will return 0.0d
tofloat(String qryParam) tries to return query parameter qryParam as float; if it does not exists or it is not convertible will return 0.0f
tointeger(String qryParam) tries to return query parameter qryParam as integer; if it does not exist or it is not convertible will return 0
tolong(String qryParam) tries to return query parameter qryParam as long; if it does not exist or it is not convertible will return 0L
tostring(String qryParam) tries to return query parameter qryParam as string; if it does not exist or it is not convertible will return "" (empty string)

Query parameter names are "case insensitive".

To better manage your querystring, please remember that you can use the method request.getQueryString() and you'll have back a string representing current user querystring

The response component is based on java class com.lemansys.http.LemansysHTTPResponse and implements javax.servlet.http.HttpServletResponse.

In addition to provided interface methods you can use also:
response.redirect(stirng url) (equivalent to response.sendRedrect(...) method)
Redirect operations are only allowed in <@page@>...</@page@> section.


Now let us provide a simple request and response example:

Suppose to have two .lem pages:

First (login.lem)page simply shows a form where user put username (text) and password.
The other (login_welcome.lem) will process form data and if is user is 'mgshow' and password is = '123456' then shows welcome message otherwise will redirect to login.lem page adding user in querystring.
The login.lem page fill the retrieved user name in querystring inside html user field.

login.lem page source code:

<@page version="4.1"@>

	<@dim currentUser as string@>
	<@set currentUser=querystring.tostring("usr")@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Login Form example</title>
	 </head>

	 <body>
	 <div align="center">
	 	<h1>Login Form</h1>
	 	<form name="loginForm" method="post" 
	 	action="login_welcome.lem">
	 	<table>
	 	<tr><td>User:</td></tr>
	 	<tr><td>
	 	<input type="text" name="username" 
	 		value="<@=htmlformat(currentUser)@>"
	 	</td></tr>
	 	<tr><td>Password:</td></tr>
	 	<tr><td><input type="password" 
	 	name="userpassword"></td></tr>
	 	<tr><td align="right">
	 		<input type="submit" name="btLogin" 
	 		value="Login..."></td></tr>
	 	</table>
	 	</form>
	 </div>	
	 </body>

	</html>
<@/content@>



login_welcome.lem page source code:

<@page version="4.1"@>

	<@dim uname,upass as string@>
	<@set uname=request.tostring("username")@>
	<@set upass=request.tostring("userpassword")@>

	<@dim okDisplay as boolean@>
	<@set okDisplay=("mgshow".equals(uname) && 
		"123456".equals(upass))@>
	
	<@if !okDisplay@>
		<@call response.redirect("login.lem?usr="+
		request.encode(uname))@>
	<@/if@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
<@if okDisplay@>
	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>Welcome <@=uname@></title>
	 </head>

	 <body>
	 <div align="center">
	 	<br><br>
	 	Please Welcome <b><@=uname@></b>,
	 	<br><br>Have a nice day !!!!
	 	<br><br>You've sent this headers:
	 	<@dim headers as stringarray@>
	 	<@set headers=request.getheaders()@>
	 	<@forall String header in headers@>
	 		<hr><@=header@> = 
	 		<@=request.getheader(header)@>
	 	<@endforall@>
	 	
	 </div>	
	 </body>

	</html>
<@/if@>
<@/content@>

In case of successful connection, page output should be like this:

Please Welcome mgshow,

Have a nice day !!!!

You've sent this headers:

host = localhost:8080
user-agent = Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
accept = text/html,application/xhtml+xml, application/xml;q=0.9,*/*;q=0.8
accept-language = en-us,en;q=0.5
accept-encoding = gzip, deflate
accept-charset = ISO-8859-1,utf-8;q=0.7,*;q=0.7
connection = keep-alive
referer = http://localhost:8080/lews41-examples/login.lem
content-type = application/x-www-form-urlencoded
content-length = 52

User (http) session handling

LEWS provides to developers session component that fully manages http user session.

LEWS links one session per current user to a data (or better "attributes") that developers can read (get) and write (set) to make persistent the info across multiple user requests.

This component is derived from Java™ class com.lemansys.http.LemansysHTTPSession that implements javax.servlet.http.HttpSession interface.

Unlike .jsp, any Lemansys Server Pages, by default, does not activate user session management !!!!

To activate http user session management you've to specify into <@page@> tag the following attributes:


 <@page version="4.1"

	session="true" [if not present = "false"]

	createonfail = "true/false" (if not present ="true")

 @>
 

With createonfail="true" you'll force LEWS to create session if it does not already exists.

Once activated, you'll be enabled to use session instance inside your .lem page. If not, every call over session instance will return a null pointer exception: be careful!!!!

In addition with all interface provided methods, to speed up your data checking and retrieving, you can also use:
MethodDescription
getid() return the session unique id as string
exists(String sessionAttribute) return true if sessionAttribute exists, otherwise false
getboolean(String sAttr) tries to return session attribute sAttr as boolean; if it does not exist or it is not convertible will return false
getdate(String sAttr) tries to return session attribute sAttr as date (com.lemansys.datatype.LemansysDate); if it does not exist or it is not convertible will return null
getdouble(String sAttr) tries to return session attribute sAttr as double; if it does not exist or it is not convertible, will return 0.0d
getfloat(String sAttr) tries to return session attribute sAttr as float; if it does not exist or it is not convertible will return 0.0f
getinteger(String sAttr) tries to return session attribute sAttr as integer; if it does not exist or it is not convertible, will return 0
getlong(String sAttr) tries to return session attribute sAttr as long; if it does not exist or it is not convertible will return 0L
getstring(String sAttr) tries to return session attribute sAttr as string; if it does not exist or it is not convertible will return "" (empty string)
get(String sAttr) returns session attribute sAttr as java.lang.Object; if it does not exist or it is not convertible will return null
setboolean(String sAttr, boolean value) assigns boolean value to session attribute sAttr
setdouble(String sAttr, double value) assigns double value to session attribute sAttr
setdate(String sAttr, date value) assigns date (com.lemansys.datatype.LemansysDate) value to session attribute sAttr
setfloat(String sAttr, float value) assigns float value to session attribute sAttr
setinteger(String sAttr, integer value) assigns integer value to session attribute sAttr
setlong(String sAttr, long value) assigns long value to session attribute sAttr
setstring(String sAttr, string value) assigns string value to session attribute sAttr
set(String sAttr, java.lang.Object value) assigns "some" value to session attribute sAttr

With methods: getbooleanarray(sAttr),getdoublearray(...),getfloatarray(...), getintegerarray(...),getlongarray(...),getstringarray(...) you can try to retrieve session attributes as array of related "type"; if sAttr not found null LEWS will return null

Please be careful because session attribute names are "case sensitive" !!!

Now's the time for classic "page hint" example to better explain user session handling:

<@page version="4.1" session="true" createonfail="true"@>

	<@dim hints as integer@>
	<@set hints=session.getinteger("MY_HINTS")@>

<@/page@>
<@content type="text/html" encoding="UTF-8"@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS User Session Management</title>
	 </head>
	 <body>
		You're visited this page <@=++hints@> times!
		<@call session.setinteger("MY_HINTS",hints)@>
	 </body>
	</html>
<@/content@>


Depending on your browser settings, every page refresh counter will be incremented; if you'll close and re-open browser (or open different browser) on the same page url, counter should be resetted.

Application Data Management

LEWS provides application component to developers that fully manage current web application.

Please consider application as "shared" session across all users!

LEWS provides only one application instance per application.

This application can store data (or better "attributes") that developers can read (get) and write (set) to make persistent info across all user requests.

This component is derived from Java™ class com.lemansys.http.LemansysServletContext that implements javax.servlet.ServletContext interface.

In addition with all interface provided methods, to speed up your data checking and retrieving, you can also use:
MethodDescription
exists(String applicationAttribute) return true if applicationAttribute exists, otherwise false
getboolean(String appAttr) tries to return application attribute appAttr as boolean; if it does not exist or it is not convertible will return false
getdate(String appAttr) tries to return application attribute appAttr as date (com.lemansys.datatype.LemansysDate); if it does not exist or it is not convertible will return null
getdouble(String appAttr) tries to return application attribute appAttr as double; if it does not exist or it is not convertible will return 0.0d
getfloat(String appAttr) tries to return application attribute appAttr as float; if it does not exist or it is not convertible will return 0.0f
getinteger(String appAttr) tries to return application attribute appAttr as integer; if it does not exist or it is not convertible will return 0
getlong(String appAttr) tries to return application attribute appAttr as long; if it doesnot exists or it is not convertible will return 0L
getstring(String appAttr) tries to return application attribute appAttr as string; if it does not exist or it is not convertible will return "" (empty string)
get(String appAttr) returns application attribute appAttr as java.lang.Object; if it does not exist or it is not convertible will return null
setboolean(String appAttr, boolean value) assigns boolean value to application attribute appAttr
setdouble(String appAttr, double value) assigns double value to application attribute appAttr
setdate(String appAttr, date value) assigns date (com.lemansys.datatype.LemansysDate) value to application attribute appAttr
setfloat(String appAttr, float value) assigns float value to application attribute appAttr
setinteger(String appAttr, integer value) assigns integer value to application attribute appAttr
setlong(String appAttr, long value) assigns long value to application attribute appAttr
setstring(String appAttr, string value) assigns string value to application attribute appAttr
set(String appAttr, java.lang.Object value) assigns "some" value to application attribute appAttr

With methods: getbooleanarray(appAttr),getdoublearray(...),getfloatarray(...), getintegerarray(...),getlongarray(...),getstringarray(...) you can try to retrieve application attributes as array of related "type"; if appAttr not found null LEWS will return null

Please be careful because application attribute names are "case sensitive" !!!

Application data (attributes) will be persisted during your .lem application lifeciclye.


Now's the time to extend previous "page hint" example to better explain application data management and put focus on difference with single user session handling:



<@page version="4.1" session="true" createonfail="true"@>

	<@dim hints as integer@>
	<@set hints=session.getinteger("MY_HINTS")@>

	<@dim globalHints as integer@>
	<@set globalHints=1+application.getinteger("GLOBAL_HINTS")@>
	<@call application.setinteger("GLOBAL_HINTS",globalHints)@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Application Data Management</title>
	 </head>

	 <body>
		You're visited this page <@=++hints@> times.
		<br>Total visits <@=globalHints@>.
		<@call session.setinteger("MY_HINTS",hints)@>
	 </body>

	</html>
<@/content@>


Depending on your browser settings, every page refresh counters will be incremented; if you'll close and re-open browser (or open different browser) on the same page url, only "personal user " counter should be resetted; the global counter not!!!

Putting Java™ code inside Lemansys Server Pages

Lemansys Server Pages syntax and tags is very easy and powerful. However you should need to directly put Java™ scripting.

LEWS allows you to mix and switch from JAVA™ code to Lemansys tags simply calling <@java@> your script<@/java@> sequence.

You can share variables, instances and so on... : this make Lemansys Server Pages very extensible and programmable!!!

You can write output to the final user using out provided instance.

Let us to show this brief example:



<@page version="4.1"@>

	<@dim i as integer@>
	<@set i=4@>
	<@dim firstName as string@>
	<@set firstName="John"@>
	
	<@java@>
	
		int y=i*10;
		String lastName="Doe";
	
	<@/java@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>Putting Java code...</title>
	 </head>

	 <body>
		Hello <@=firstName@> <@=lastName@> !
		<hr>
		
		<@java@>
		
			out.write(i+" + "+y+" = "+(i+y));
		
		<@/java@>

	 </body>
	</html>
<@/content@>


and the page output will be:

Hello John Doe !
4 + 40 = 44

Custom Functions

LEWS allows you to define custom functions inside any Lemansys Server Page.

You must use the <@jfun@> tag.



<@jfun returnJavaType functionName (arguments) [throws ...]{

	... Java™ code ...

}@>

To call and use your functions you can use the <@call@> tag, assign returned function value to a specified variable using the <@set@> tag or directly put result (if available) with <@=@> tag.

You can put <@jfun@> tag in any tag sequence of current Lemansys Server Page (in both page and content section). LEWS parser will reallocate it before compile.

Custom functions will be located outside the "running" method of Lemansys Server Pages so you cannot directly use session, application, out, request, response (and so on...). You have to pass it as arguments if you need to use someone of this !!!

Please follow this example:


<@page version="4.1"@>

	<@jfun double average(int a,int b) {
		return (double) (a+b)/2;
	}@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Custom Functions</title>
	 </head>

	 <body>
		
		<@=hello("Mark Twain")@>

		<@jfun String hello(String name) {
			return "Hello <b>"+name+"</b> !";
		}@>
		
		<@dim res as double@>
		<@set res=average(2,7)@>
		<br>
		Average between 2 and 7 is <@=res@>
		<@call sayGoodbye(out)@>
	 </body>

	</html>
<@jfun void sayGoodbye(JspWriter writer) throws Exception{
	writer.println(
	"<hr><hr>Au revoir!<hr><hr>");
}@>

<@/content@>


This will be the output result:

Hello Mark Twain !
Average between 2 and 7 is 4.5

Au revoir!

Importing and extending LEWS with Java ™ Packages

Java™ is an Object Programming Language, extensible with standard or custom libraries.

Lemansys Server Page is a mix result between:

By default these libraries are automatically declared and imported into Lemansys Server Page.

If you need to import other packages, you can do it by using <@uselibrary@> tag.

Please correctly configure classpath of LEWS Application Server otherwise you cannot reach targeted libraries and packages!!!

You can "import" packages (and classes) inside "src" folder of your current web application (don't forget Lemansys LEWS Application is very similar to JSP/Servlet application )

You can put <@uselibrary@> tags in any tag sequence of current Lemansys Server Page (in both page and content section) or into a module (.lmh). LEWS parser will reallocate it on "top" before compile.

This is a brief example:

Suppose you have somewhere this Java™ class (for example into your src folder of your web application)

package test.lemansys.beans;

import java.io.Serializable;

public class TestBean implements Serializable {

	private static final long serialVersionUID =
		 -5351748588779926998L;
		 
	public TestBean() {
		super();
	}	 
		 
	private String firstName;
	private String lastName;
	
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String sayHello() {
	return "Hello from "+firstName+" "+lastName+"!";
	}
	
	
}


this is the Lemansys Server Page:


<@page version="4.1"@>

	<@uselibrary java.util.Properties@>
	<@dim myProperties as javatype Properties@>
	<@call myProperties=new Properties()@>
	<@call myProperties.setProperty("first","First Property")@>
	<@call myProperties.setProperty("last","Last Property")@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	
	<@dim test as javatype TestBean@>
	<@set test=new TestBean()@>
	<@call test.setFirstName("Paul")@>
	<@call test.setLastName("Smith")@>
	<@uselibrary test.lemansys.beans.TestBean@>

	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>Import and Extends Lews</title>
	 </head>
	 <body>
		<@=test.sayHello()@>
		<hr>My properties are:
		<ul>
		<li>First: <b>
		<@=myProperties.getProperty("first")@></b>
		</li>
		<li>Last: <b>
		<@=myProperties.getProperty("last")@></b>
		</li>
		</ul>
	 </body>
	</html>

<@/content@>

... and this is the final output result:

Hello from Paul Smith!

My properties are:

Global Variables

LEWS creates only an instance for each Lemansys Server Page inside Application Server Container.

Usually any .lem page runs multiple times (multithreaded) the same method for each connected user.

You can define "global variables" to share data between instances (such as application way, previously discussed).

This is the syntax (very similar to @dim statement):


<@global 
	varname as [javatype] vartype
@>	

Each javatype will be automatically instantiated.

You can put <@global@> tags in any tag sequence of current Lemansys Server Page (in both page and content section) or into a module (.lmh). LEWS parser will reallocate it outside "run" method, into a "global zone" before compile.

To change a global value you can use the same@set tag used for local variables.

Please be careful when using global variables and consider "synchronization" issues!!!

This is an example:

<@page version="4.1"@>

	<@global lastVisit as date@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Global Variables</title>
	 </head>
	 <body>
	 
	 <@dim now as date@>
		This page has been visited <@=++counter@> times!
		<br>Now is <@=now.format("yyyy-mm-dd hh:mn:ss")@>,
		<br>last visit <@=lastVisit.format("yyyy-mm-dd hh:mn:ss")@>
		<@set lastVisit=now@>
		<br>
	 </body>
	</html>
	
	<@global counter as integer@>
<@/content@>

A common challenge is to share variables and functions between pages.

To do it, we suggest to define a common module (.lmh), usually inside $APPLICATION_ROOT/dep/globals.lmh.
Every .lem page that would share these values and functions simply have to include with @external tag this module.

Let us better explain with a brief example:
  1. Create a /dep/globals.lmh module
    
    <@// Define variables here...@>
      <@dim maxResults as integer@>
      <@set maxResults = 100@>
      
      ... other declarations and settings...
      
      <@jfun void connectToDatabase (int results) {
       ....
      }@>
      
      ... other functions...
     <@// ... end of module@> 
        
    
  2. Create a first page/page-name.lem page
    Into a @page section (but already into content) import module and use variables and funcions...
    
    <@page ... @>
    
      ... main declarations
    
      <@external src="dep/globals.lmh" @>
    
      ... other declarations and settings...
    
      <@// implementation example... @>
      <@dim results as integer@>
      <@set results=querystring.tointeger("res")@>
      
      <@if results>maxResults@>
      	<@set results=maxResults@>
      <@endif@>
      
      <@call connectToDatabase(results)@> 
      
      ... next code...    
    
  3. Repeat similar steps for each interested page

With this best practise you'll mantain common changes across modules and this is a very good solution for code refactoring.

Embedded Http Client

Nowadays we cannot limit a web application life cycle inside himself.

Your web application may be connected to a remote site to retrieve partial html contents such as header of footer section, xml or JSON streams to build rich Web 2.0 applications and so on.

LEWS is providing the LemansysHttpClient component ( com.lemansys.datatype.LemansysHttpClient).

Every LemansysHttpClient call will be performed server side and not client side!!!

LemansysHttpClient offers static method to perform http get and post already using XML streaming.
MethodThrowsDescription
LemasnysHttpClient.get(String url) MalformedURLException, IOException Perform a call on specified url assuming "UTF-8" as character econding and returns html content as string
LemansysHttpClient.get(String url, String encoding) MalformedURLException, IOException Perform a call on specified url assuming encoding as character econding and returns html content as string
LemansysHttpClient.get(String url, String encoding, Properties props) MalformedURLException, IOException Perform a call on specified url assuming encoding as character econding and returns html content as string. At request pahse will be added headers contained into props Properties
LemansysHttpClient.post(String url, String bodyContent) MalformedURLException, IOException Send bodyContent (as sequence of &field1=value&field2=value...) to a specified url and returns html content remote response as string.
LemansysHttpClient.post(String url, String bodyContent, Properties props) MalformedURLException, IOException Send bodyContent (as sequence of &field1=value&field2=value...) to a specified url and returns html content remote response as string. At request pahse will be added headers contained into props Properties
LemansysHttpClient.postXML(String url, String bodyContent) MalformedURLException, IOException Send bodyContent (as xml sequence) to a specified url and returns xml (or html) remote response as string.
LemansysHttpClient.postXML(String url, String bodyContent, Properties props) MalformedURLException, IOException Send bodyContent (as xml sequence) to a specified url and returns xml (or html) remote response as string. At request pahse will be added headers contained into props Properties

In this example we're creating a spider that "grabs" the page title of specified url.



<@page version="4.1"@>

<@dim remoteURL as string@>
<@set remoteURL=querystring.tostring("url")@>
<@dim error as string@>

<@dim START_TAG,END_TAG as string@>
<@set START_TAG="<title>"@>
<@set END_TAG="</title>"@>


<@dim res as string@>
<@if !isblank(remoteURL)@>
	<@try@>
		<@set res=LemansysHttpClient.get(remoteURL)@>
		<@dim indx as integer@>
		<@set indx=res.toLowerCase().indexOf(START_TAG)@>
		<@if indx<0@>
	<@set error="I'm sorrt but... title not present :(( "@>
		<@else@>
			<@set res=res.substring(indx+START_TAG.length())@>
			<@set indx=res.toLowerCase().indexOf(END_TAG)@> 
			<@if indx<0@>
	<@set error="I'm sorry but... title tag is not well formed :(( "@>
			<@else@>
				<@set res=res.substring(0,indx)@>
			<@endif@>
		<@endif@>
		
	<@endtry@>
	<@catch Exception@>
		<@set error=exception.getMessage()@>
	<@endcatch@>
<@endif@>
<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Http Client</title>
	 </head>

	 <body>
	 	<h1>Page Title "grab"</h1>
		<form method="get" action="" name="searchTitle">
		Insert URL= <input 
		type="text" name="url" 
		value="<@=htmlformat(remoteURL)@>"
		size="60"> <input type="submit" 
		value="Grab title...">
		</form>
		
		<@if !isblank(error)@>
		ERROR:<br>
			<font color="red">
			<@=error@>
			</font>
		<@else@>
		
		PAGE TITLE at <a href=
		"<@=remoteURL@>"><@=remoteURL@></a> is " <@=res@> "
		<@endif@>		
	 </body>
	</html>
<@/content@>
and a response output example

Page Title "grab"

Insert URL=
PAGE TITLE at http://www.sourceforge.net is " SourceForge - Download, Develop and Publish Free Open Source Software "

Database Access

Nowadays many applications need to interacts with RDBMS database such as MySQL, Postgres, Oracle, IBM DB2 (...).

In this section we provide a simple overview: you're invited to follow future technical articles and tutorials and see related class javadoc!!!

LEWS provides a component named genericdatabase ( related to Java™ class com.lemansys.datatype.LemansysGenericDatabase ) that interacts with already existing javax.sql.DataSource or lets you to create a "pooled" connection using LDBC connector (we discuss soon...).

LEWS is already offering two extra components sqlview and sqlform to automatically bind (just in a primitive manner) SQL query results and create/modify simple table records. Be careful because this last components are under "hard" development!!!

Consider genericdatabase such as very simply and quick way to access to database. In any case you can retrieve a java.sql.Connection from current genericdatabase using the getconnection() method.

Any database connection is based on Java JDBC techonology, so be sure to have the proper JDBC driver related to your preferred database! Once retrieved driver file (.jar), you should place it inside a libraries folder of your current application ($WEB_APP_ROOT/WEB-INF/lib) or, if more apps needs to use the same database type, you can put this file into $CATALINA_HOME/lib folder!!!

Once defined a genericdatabase component, you've to "open" communication with a specific database.

Once successfully opened a genericdatabase instance, you can perform SQL queries (and manage result set) operations or execute SQL statements.

Application Localization

Developers usually have to maintain the same web application using different languages.

To do it, you can use localizer component (com.lemansys.datatype.LemansysLocalizer).

The localizer works like java.util.ResourceBundle

To localize your .lem applications you've to:

  1. declare a variable type localizer
  2. open the bundle passing optionally language specification
  3. get and display message keys
  4. close the localizer instance

To better understand, please consider this following example:

On the $WEB_APP_PATH/src we have created this Java™ package locale.example .

Inside this package we have created 3 (three) properties files:
This following example allows current user to change the display languages.

Available options will be
We have declared only 2 (two) alternative languages (italian and french), so only SERVER (where LEWS reside) with italian or french OS will display relative language by choosing first option (the others will have back "english" by default).

About second option you'll display italian or french by choosing only if your browser is set up for this languages (the others will have back "english" by default).

At last you can select "Italian" (you'll have back italian), "French" (you'll have back french ), "German" (you'll have back english, because we've not set up this language); by selecting "english" you've back the page in english language.

This is the page source code (localizer.lem):

<@page version="4.1"@>

	<@dim loc as localizer@>
	
	<@dim qKey as string@>
	<@set qKey=querystring.tostring("key")@>
	
	<@// Try to localize with current browser language...@>
	<@if "current".equals(qKey)@>
		<@call loc.open("locale.example.welcome",
		request.getLocale().toString())@>
	
	<@// Try to localize with current server OS language...@>	
	<@elseif "system".equals(qKey)@>
		<@call loc.open("locale.example.welcome")@>	
		
	<@// Try to localize with current retrieved key language...@>	
	<@else@>
		<@call loc.open("locale.example.welcome", qKey)@>
	<@endif@>

	<@dim languageBar as stringarray@>
	<@set languageBar=new String[] {"system","current","en","it","fr","de"}@>
	

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Application Localization</title>
	 </head>

	 <body>
	 	<h1><@=loc.getmessage("welcome.title")@></h1>
	 	<hr>
		<h2><@=loc.getmessage("welcome.message")@></h2>
		<h3><@=loc.getmessage("change.language")@></h3>
		
		<@forall String key in languageBar@>
		
			<a href="?key=<@=key@>"><@=loc.getmessage(key)@></a> |
		
		<@endforall@>
		
	 </body>
	</html>
<@/content@>


Let us to show the "italian" response:

Ciao!


Benvenuto nel fantastico mondo di LEWS!

Cambia lingua:

Linguaggio del sistema operativo | Lingua del browser | English | Italiano | Francese | Tedesco |

You suggest to add other languages or change browser setting default language to perform additional tests.

HTML 5 and CSS 3 development



LEWS il fully compatible with HTML 5 and CSS 3 programming.

Developing with HTML 5 is very easy because you've only to declare the proper doc type.

In addition you can mix html 5 tags and related objects (canvas, video, audio) with Lemansys Server Page tags and Javascript to create unlimited dynamic effects and applications.

Please see this example (html5.lem)


<@page version="4.1"@>

	<@dim canvasWidth,canvasHeight as integer@>
	<@set canvasWidth=180@>
	<@set canvasHeight=130@>
	
	<@dim baseImage as string@>
	<@set baseImage="resources/backdrop.png"@>
	
	<@dim textRotation as string@>
	<@set textRotation="2deg"@>
	
	<@// With "option" you can create dynamic option list@>
	<@// to aggregate with a selection html field@>
	<@dim choices as option@>
	<@call choices.add("0","Draw on canvas")@>
	<@call choices.add("1","Show Image")@>
	<@call choices.add("2","Image multiply")@>
	

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<!doctype html>
	<html lang="en">
	 <head>
	 	<meta charset="UTF-8" />
		<title>LEWS & HTML 5 - Canvas</title>
		<style type="text/css">
		body {font-family:Arial}
		h1{ 
		text-shadow: 2px 8px #b5c1b8, -1px -1px #fff;
		box-shadow: 4px 6px #b5c1b8;
		-webkit-transform: rotate(<@=textRotation@>);
		-moz-transform: rotate(<@=textRotation@>);
		-o-transform: rotate(<@=textRotation@>);
		 }
		h2{ color:#666;font-size:13px;padding:0 }
		p,li { font-size:11px }
		.code {color:#03f;}
		</style>
	 </head>

	 <body onLoad="javascript:drawImg(0);">
	 <h1>LEWS & HTML 5 - Canvas</h1>
	 <p>Draw Image </p>
	 <script type="application/x-javascript">
	 function removeChildrenFrom(id){
		var cal =document.getElementById(id);
		if ( cal.hasChildNodes() ){
			while ( cal.childNodes.length >= 1 ){
			 cal.removeChild( cal.firstChild ); } 
		}
	}
	 
	 function drawImg(vc) {
			
			removeChildrenFrom('canvasImg');
			
		var canvas=document.getElementById('canvasImg');
			
			
			
		if (canvas.getContext) {
		
			var ctx = canvas.getContext('2d');
				ctx.clearRect(0,0,0,0)
				
			var img = new Image();
				img.src = '<@=baseImage@>';
				// Esempio base...
				if(vc==0){
					
					<@// Draw Box #1..@>
					ctx.fillStyle = "rgb(200,0,0)";
			        ctx.fillRect (10, 10, 55, 50);
			        
					<@// Draw Box #2..@>
			        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
			        ctx.fillRect (30, 30, 55, 50);
				
				<@// Load image...@>
				}else if (vc==1){
						img.onload = function(){
						    
					    ctx.drawImage(img,0,0);
					    ctx.beginPath();
					    <@// Draw Line...@>
					    ctx.moveTo(30,96);
					    ctx.lineTo(70,66);
					    ctx.lineTo(103,76);
					    ctx.lineTo(170,15);
					    ctx.stroke();
					  	}
				 
				<@// Image multiply....@> 
				}else if(vc==2){
					
						
		img.onload = function(){
		    for (i=0;i<4;i++){
				for (j=0;j<3;j++){ 
				ctx.drawImage(img,j*50,i*38,50,38);}
		    }
		}	    
				} 
	 	
	 	
	 	
	 	
	 	}
	}
	 </script>
	 <canvas id="canvasImg" width="<@=canvasWidth@>" 
	 height="<@=canvasHeight@>">This text is displayed if 
	 your browser does not support HTML5 Canvas.</canvas>
	 
	 <br />
	 <select onchange="javascript:drawImg(this.value)">
	 	<@=choices.tohtml("0")@>
	 </select>
	 
	 </body>
	</html>
<@/content@>

Mobile development and device recognition

Mobile device support is today highly recommended more specifically when you're creating new web applications.

However mobile devices are very different by producer, display, resolution and so on...

Developers should be supported to recognize the best solution for current device navigating any (dynamic) web application.

Any Lemansys Server Pages can provide a set of useful functions to recognize most popular mobile devices:
Page FunctionDescription
is_android(String userAgent)Return true if an Android device is currently connected; otherwise false
is_blackberry(String userAgent)Return true if a BlackBerry device is currently connected; otherwise false
is_ipad(String userAgent)Return true if a iPad device is currently connected; otherwise false
is_iphone(String userAgent)Return true if a iPhone device is currently connected; otherwise false
is_windows_ce(String userAgent)Return true if a Windows CE device is currently connected; otherwise false
is_windows_mobile(String userAgent)Return true if a Windows Mobile device is currently connected; otherwise false
ismobile(String userAgent)Return true if a "supposed" device mobile is currently connected; otherwise false
is_mobile(String userAgent)The same of ismobile(...)

The userAgent can be retrieved by these following ways:

where request is provided current http user request.

This is a small but, we hope, very clear example (mobile.lem):


<@page version="4.1"@>

	<@dim uag as string@>
	<@set uag=request.getuseragent()@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>
	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>LEWS Mobile Device Recognition...</title>
	 </head>

	 <body>
	
	<h1>
		<@if is_iphone(uag)@>
			You're connected with I-Phone
			
		<@elseif is_blackberry(uag)@>
			You're connected with BlackBerry
			
		<@elseif is_ipad(uag)@>
			You're connected with I-Pad
			
		<@elseif is_mobile(uag)@>
			I suppose you're connected with a mobile device!
			
		<@else@>
			I suppose you're not connected with a mobile device!
		<@endif@>
	</h1>
	 </body>

	</html>

<@/content@>

RSS Feed reader

LEWS is providing two elementar components rssnewsreader ( com.lemansys.xml.LemansysRSSNewsReader)and rssnews (com.lemansys.xml.LemansysRSSNews) wich developers can use to retrieve RSS feeds.

The rssnewsreader component links to specified RSS feed: such as discussed about LEWS XML Streaming, the RSS news can be retrieved from multiple stream sources (local files, url, string buffers and generic input stream ).

The rssnews component is used to manage (reading scope) any available news.

LEWS converts reader fields and any news field/info as "properties": you've simply to retrieve preferred info using [component.]getproperty(propertyName).

For more info we suggest to consult related LEWS javadoc and take a look to this example were we'll try to connect with CNN RSS world channel (rss.lem).



<@page version="4.1"@>

	<@dim rss as rssnewsreader@>
	
	<@dim title as string@>
	<@dim image as string@>
	
	<@dim error as string@>
	
	<@if !rss.openfromurl("http://rss.cnn.com/rss/edition_world.rss")@>
	
		<@set error=rss.geterror()@>
		
	<@else@>	
	
		<@set title=rss.getproperty("title")@>
	
		<@if !isblank(rss.getproperty("image/url"))@>
		 <@set image="<img src=\""+
		  rss.getproperty("image/url")+"\"> "@>
		<@endif@>
		
	<@endif@>
	
	

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<html>
	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>RSS NEWS</title>
	 </head>

	 <body>
		<@if isblank(error)@>
		
			<h1><@=image@> NEWS CHANNEL : <@=title@> </h1>
			
			<p><@=rss.getproperty("description")@></p>
			
			<p>Last updated: <b><@=rss.getproperty("pubdate")@></b></p>
			
			<p>Available news: <b><@=rss.news()@></b><hr></p>
			
			<@dim i as integer@>
			<@dim news as rssnews@>
			<@for i = 1 to rss.news()@>
			
				<@set news=rss.getnews(i-1)@>
			
			<div>
				<font size=-1><@=news.getproperty("pubdate")@></font><br>
				#<@=i@>: <b><@=news.getproperty("title")@></b>
				<div>
				<font size="-1"><@=news.getproperty("description")@></font>
				</div>
				<hr>
			</div>
			
			<@endfor@>
		
		<@else@>
		
			ERROR: <font color="red"><@=error@></font>
		
		<@endif@>
	 </body>
	</html>
<@/content@>

And this should be a "summary" output return response:

[ IMG LOGO]   NEWS CHANNEL : CNN.com - WORLD

CNN.com delivers up-to-the-minute news and information on the latest top stories, weather, entertainment, politics and more.

Last updated: Wed, 04 Jan 2012 02:13:41 EST

Available news: 3


Wed, 04 Jan 2012 01:05:58 EST
#1: Taliban ready to talk, spokesman says
The Afghan Taliban are prepared to open...

Wed, 04 Jan 2012 00:48:28 EST
#2: Maldives' top court to rule on spa ban
The Supreme Court of the Maldives is expected to...

Tue, 03 Jan 2012 09:42:40 EST
#3: Ex-Tunisia leader faces trial over killings
Tunisian ex-President Zine el Abidine Ben Ali, who was...

Advanced output features (switchout)

If you take a look back at previous examples when returning some content via http response, we've used:


Any "standard" output operation must be performed only inside @content section !!!

With <@switchout@> tag you can redirect any subsequent output operation (except out.write case) to specified buffer (java.lang.StringBuffer) until the <@/switchout@> is called.

In this way you can compose dynamic output sequence inside @page@ section and retrieve the "shifted" output whenever you needs.

Depending on your output dynamic implementation you may need to dynamically change the content type (and encoding) response: you can do this by omitting the content and/or encoding attributes of @contentsection!!!

Please see the following example (switchout.lem) where we provide a different output content type depending on provided "enc" querystring parameter:


<@page version="4.1"@>

	<@dim encType as string@>
	<@set encType=querystring.tostring("enc")@>

	<@// Declare and instantiate a "buffer" @>
	<@dim bfr as newjavatype StringBuffer@>
	
	<@dim welcomeMsg as string@>
	<@set welcomeMsg="Hello now it's "+
		new LemansysDate().format("yyyy-mm-dd hh:mn:ss")@>
	
	<@if encType.equals("xml")@>
	
		<@// Enforce response content type @>
		<@// outside @content section !!!!!@>
		<@call response.setContentType("text/xml")@>
		
		<@switchout bfr@><?xml version="1.0" encoding="UTF-8"?>
		<tags>
		<tag><@=htmlformat(welcomeMsg)@></tag>
		</tags>
		<@/switchout@>
		
	<@else@>	
		
		<@switchout bfr@>
		<html>
			<head><title>HTML RESPONSE</title></head>
			<body>
				<@=welcomeMsg@>
			</body>
		</html>
		<@/switchout@>
		
	<@endif@>
	

<@/page@>

<@// Please forget "content" attribute if you like@>
<@// to make DYNAMIC the content response type!!!!@>
<@// You'll can do also with encoding attribute...@>
<@content encoding="UTF-8"@><@=bfr.toString()@><@/content@>

<@// End of Lemansys Web Page Code...@>

Mixing .lem pages with .jsp (and Servlets)

LEWS is fully compliant with Servlet API 3.0 so you can run JSP and servlets in addition to .lem pages: you can mix them all using "including" features!!!

LEWS provides you the pageContext instance inside any .lem page.

With include(...) pageContext method you can include (at runtime level) an existing .jsp, servlet or another .lem inside the same project!!!

A .jsp or servlet can do also calling a .lem page (...) [ on a LEWS context :)) !!!!]

JSPs, servlets, ans LEMs can share data at Application, Session and Request [as attributes] level.

In this example a lem2jsp.lem page will include a target.jsp page:

lem2jsp.lem source code:



<@page version="4.1" session="true" createonfail="true"@>

	<@call session.setstring("session.attribute","lem_123456")@>
	<@call application.setstring("application.attribute","lem_35545454")@>
	<@call request.setstring("request.attribute","lem_rq12345")@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	<@//HTML (dynamic) code goes here...@>

	<html>

	 <head>
		<meta HTTP-EQUIV="content-type" 
		CONTENT="text/html; charset=UTF-8"/>
		<title>LEM including JSP</title>
	 </head>

	 <body>
		Hello from LEM,
		now I'm trying to open a .jsp page ....<hr>
		
		<@try@>
			<@call pageContext.include("target.jsp")@>
		<@/try@>
		<@catch Exception@>
	ERROR: <font color="red"><@=exception.toString()@></font>
		<@/catch@>
		
	 </body>
	</html>
<@/content@>



target.jsp source code:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

Hello from .jsp
<hr> 

<ul>

<li>
Application attribute is 
 <b><%=application.getAttribute("application.attribute") %></b>   
</li>

<li>
Session attribute is 
 <b><%=session.getAttribute("session.attribute") %></b>   
</li>

<li>
Request attribute is 
 <b><%=request.getAttribute("request.attribute") %></b>   
</li>

</ul>


And this is the output response:

Hello from LEM, now I'm trying to open a .jsp page ....
Hello from .jsp


In this other example a jsp2lem.jsp page will include a target.lem page:

jsp2lem.jsp source code:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP including LEM</title>
</head>
<body>

	Hello from JSP,
	now I'm trying to open a .lem page ....<hr>
	
	<%
	
	session.setAttribute("session.attribute","jsp_123456");
	application.setAttribute("application.attribute","jsp_35545454");
	request.setAttribute("request.attribute","jsp_rq12345");

	%>
	
	
	<%try {
		pageContext.include("target.lem");
	} catch (Exception ex) {%>
		ERROR: <font color="red"><%=ex.toString()%></font>
	<%} %>

</body>
</html>


target.lem source code:


<@page version="4.1" session="true" createonfail="true"@>

	<@//Nothing to do...@>

<@/page@>

<@content type="text/html" encoding="UTF-8"@>

	Hello from .lem
<hr> 

<ul>

<li>
Application attribute is 
 <b><@=application.getstring("application.attribute") @></b>   
</li>

<li>
Session attribute is 
 <b><@=session.getstring("session.attribute") @></b>   
</li>

<li>
Request attribute is 
 <b><@=request.getstring("request.attribute") @></b>   
</li>

</ul>
	
<@/content@>


And this is the output response:

	Hello from JSP, now I'm trying to open a .lem page ....
Hello from .lem

LEWS Development under Eclipse platform - Plugins

Eclipse (http://www.eclipse.org) is one of must popular free and open source Java (and J2EE) IDE.

LEWS provides this following plugin suite:


We recomend use of Eclipse WTP version, otherwise you should unabled to integrate, testing and deploy your applications into LEWS application server bundled with Tomcat 7.

You can download last Eclipse IDE for Java EE Developers version here...

Obviously we suppose you've also downloaded and installated last version of LEWS Application Server.
Go to LEWS Eclipse plugin section and download last plugin version.

Please see complete pdf document for visual plugin configuration.