Hello everyone,
in the Quick Start Guide, Chapter "Authentication and Authorization", Isomorphic suggests that one caches files while displaying the login-screen.
I tried to set this up and I think I succeeded now and wanted to share my approach.
Basic setup:
The login HTML looks like:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Login</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script type="text/javascript" language="javascript">var isomorphicDir = "lms/sc/";</script>
<script type="text/javascript" language="javascript" src="lms/sc/modules/ISC_FileLoader.js"></script>
<script type="text/javascript" language="javascript">FL.modulesDir = "modules/"; FL.defaultSkin = "Enterprise"; FL.cacheISC();</script>
</head>
<body>
<div id="box">
<form method="post" action="j_security_check">
<label>Name:</label>
<input type="text" name="j_username" />
<label>Password:</label>
<input type="password" name="password" />
<input type="password" name="j_password" style="display: none;" />
<input type="submit" value="Login" name="submit" class="submit" />
<input type="reset" value="Cancel" class="submit" />
</form>
</div>
<SCRIPT>//'"]]>>isc_loginRequired
//
// Embed this whole script block VERBATIM into your login page to enable
// SmartClient RPC relogin.
while (!window.isc && document.domain.indexOf(".") != -1) {
try {
if (parent.isc == null) {
document.domain = document.domain.replace(/.*?\./, '');
continue;
}
break;
} catch (e) {
document.domain = document.domain.replace(/.*?\./, '');
}
}
var isc = top.isc ? top.isc : window.opener ? window.opener.isc : null;
if (isc.Canvas) isc.RPCManager.delayCall("handleLoginRequired", [window]);
</SCRIPT>
</body>
</html>
When starting with an empty cache, the
ISC_FileLoader will issue requests to e.g.
http://myserver.com/myapp/sc/modules..._2014-03-30.js. Note the version in the query parameter. This is added automatically by the
ISC_FileLoader.js from its own version.
When calling again with "URL bar"->Enter, for my config the *.js files won't be loaded again, as I configured a 1 year expiry in Apache httpd (see below).
2nd is the main jsp file:
Code:
<!DOCTYPE html>
<%!
/** Ant task extractsgwtversion sets the version of the lib here **/
String regex_replaced = "v9.1p_2014-03-30";
String version = "?isc_version=" + regex_replaced + ".js";
%>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="gwt:property" content="locale=de">
<% /** <!-- Any title is fine -->**/ %>
<title>My title</title>
<% /** <!-- IMPORTANT : You must set the variable isomorphicDir to [MODULE_NAME]/sc/ so that the SmartGWT resource are
correctly resolved --> **/ %>
<script type="text/javascript">var isomorphicDir = "myApp/sc/";</script>
<% /** <!-- Needed here as SuperDev Mode can't use "include" in gwt.xml -->**/ %>
<script type="text/javascript" src="myApp/sc/modules/ISC_Core.js<% out.print(version); %>"></script>
<script type="text/javascript" src="myApp/sc/modules/ISC_Foundation.js<% out.print(version); %>"></script>
<script type="text/javascript" src="myApp/sc/modules/ISC_Containers.js<% out.print(version); %>"></script>
<script type="text/javascript" src="myApp/sc/modules/ISC_Grids.js<% out.print(version); %>"></script>
<script type="text/javascript" src="myApp/sc/modules/ISC_Forms.js<% out.print(version); %>"></script>
<% /** Unused so far
<script type="text/javascript" src="myApp/sc/modules/ISC_RichTextEditor.js"></script>
<script type="text/javascript" src="myApp/sc/modules/ISC_Calendar.js"></script>
**/ %>
<script type="text/javascript" src="myApp/sc/modules/ISC_DataBinding.js<% out.print(version); %>"></script>
<script type="text/javascript" src="myApp/sc/skins/Enterprise/load_skin.js<% out.print(version); %>"></script>
<% /**
<!-- -->
<!-- This script loads your compiled module. -->
<!-- If you add any GWT meta tags, they must -->
<!-- be added before this line. -->
<!-- -->
**/ %>
<script type="text/javascript" src="myApp/myApp.nocache.js"></script>
</head>
<% /**
<!-- -->
<!-- The body can have arbitrary html, or -->
<!-- you can leave the body empty if you want -->
<!-- to create a completely dynamic UI. -->
<!-- -->
**/ %>
<body>
<% /** <!--load the datasources--> **/ %>
<script type="text/javascript" src="myApp/sc/DataSourceLoader?dataSource=.........................................long list..............."></script>
<% /** <!-- OPTIONAL: include this if you want history support --> **/ %>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
</body>
</html>
Note that this uses JSP-comments that are not present in the final HTML in order to keep the result better looking.
In order to have the
ISC_*.js-files served from the cache, the URL must look exact the same as in the login screen. While in the login screen the
FileLoader takes care of the version-string, you have to do it on your own this time. As this is easily forgotten when done manually, I created an Ant-task for it:
Code:
...
<path id="catalina-ant-classpath">
<fileset dir="${tomcat-dir}/lib">
<include name="catalina-ant.jar" />
<include name="tomcat-coyote.jar" />
<include name="tomcat-util.jar" />
</fileset>
<fileset dir="${tomcat-dir}/bin">
<include name="tomcat-juli.jar" />
</fileset>
<fileset dir="${sgwtee.sdk}/../ant/">
<include name="xmltask.jar" />
</fileset>
</path>
...
...
<!-- Used in Ant Task extractsgwtversion -->
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask" classpathref="catalina-ant-classpath" />
...
...
<target name="extractsgwtversion" description="Extract version from SmartGWT library">
<xmltask>
<fileset file="${sgwtee.sdk}/maven/pom/smartclient-eval.xml" />
<copy path="//*[local-name()="version"]/text()" property="sgwtee.buildversion" />
<!--
Weird XPath stuff because of the namespace in the POM-file. See:
http://www.oopsconsultancy.com/software/xmltask/#usage.print
http://stackoverflow.com/questions/21928260/xpath-query-local-name-fetch-tag-based-on-other-tags-value
http://www.xml.com/pub/a/2004/02/25/qanda.html
-->
</xmltask>
<fail message="You must provide a file to extract the SGWT version from.">
<condition>
<not>
<resourcecount count="1">
<fileset id="fs" dir="${sgwtee.sdk}/maven/pom" includes="smartclient-eval.xml"/>
</resourcecount>
</not>
</condition>
</fail>
<fail unless="sgwtee.buildversion" message="You must supply a correct XPath expression in order to extract the version." />
<echo>${sgwtee.sdk}/maven/pom/smartclient-eval.xml</echo>
<echo>${sgwtee.buildversion}</echo>
<replaceregexp file="war/myApp.jsp" match="String regex_replaced.*" replace="String regex_replaced = "${sgwtee.buildversion}";" byline="true" />
</target>
The task tries to take one of the SmartGWT-maven-pom files and extract the version from it. Hopefully it's the same version as in
ISC_FileLoader.js. If there is a better way to extract the version number from the framework, any pointers are appreciated.
This way, after building and deploying a war, the browser should download the needed JS-files once on start-up and then never again.
My Apache httpd virtual host cache configuration looks like this:
Code:
<VirtualHost *:80>
ServerAdmin webmaster@mydomain.com
# DocumentRoot /var/www/centos.mydomain.com/public_html
DocumentRoot /usr/share/apache-tomcat-7.0.52/myapp_centos
RedirectMatch ^/$ /centos/MyApp.jsp
RedirectMatch ^/centos$ /centos/MyApp.jsp
RedirectMatch ^/centos/$ /centos/MyApp.jsp
ServerName centos.mydomain.com
TraceEnable Off
ErrorLog /var/www/centos.mydomain.com/logs/error_log
CustomLog /var/www/centos.mydomain.com/logs/access_log combined
<IfModule mod_jk.c>
JkMount /centos/j_security_check worker1
JkMount /centos/*.jsp worker1
JkMount /centos/myapp/sc/IDACall worker1
JkMount /centos/myapp/sc/DataSourceLoader worker1
JkMount /centos/myapp/sc/HttpProxy worker1
JkMount /centos/myapp/sc/ worker1
JkMount /centos/ServletLogin worker1
JkMount /centos/ServletLogout worker1
</IfModule>
# <Directory /var/www/centos.mydomain.com/public_html>
<Directory /usr/share/apache-tomcat-7.0.52/myapp_centos>
AllowOverride FileInfo AuthConfig Limit
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
#SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/plain text/html application/json text/xml text/css text/javascript
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<Files *.cache.*>
ExpiresActive on
ExpiresDefault "now plus 1 year"
</Files>
<Files *.js>
ExpiresActive on
ExpiresDefault "now plus 1 year"
</Files>
<FilesMatch "\.(gif|jpe?g|png)$">
ExpiresActive on
ExpiresDefault "now plus 1 year"
</FilesMatch>
<Files *.css>
ExpiresActive on
ExpiresDefault "now plus 1 year"
</Files>
<Files *.nocache.*>
ExpiresActive on
ExpiresDefault "now"
Header merge Cache-Control "public, max-age=0, must-revalidate"
</Files>
<Files *.html>
ExpiresActive on
ExpiresDefault "now"
Header merge Cache-Control "public, max-age=0, must-revalidate"
</Files>
# Correct, but done in some other way by Tomcat
<Files *.jsp>
ExpiresActive on
ExpiresDefault "now"
Header merge Cache-Control "public, max-age=0, must-revalidate"
</Files>
</Directory>
</VirtualHost>
This way, for me everything besides
Compression of the DataSourceLoader servlet result is now working in the best (?) possible way.
Best regards, I hope this HowTo helps someone,
Blama