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:
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:
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:
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:
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
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:
- Tomcat with j_security_check, showing a plain login.html
- a JSP file (some easy logic here) as main page of the application.
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 = "myApp/sc/";</script> <script type="text/javascript" language="javascript" src="myApp/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 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>
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>
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>
Best regards, I hope this HowTo helps someone,
Blama
Comment