Quantcast
Channel: SmartClient Forums
Viewing all articles
Browse latest Browse all 4756

ISC_FileLoader for perfect caching on StartUp of login screen

$
0
0
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()=&quot;version&quot;]/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 = &quot;${sgwtee.buildversion}&quot;;" 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

Viewing all articles
Browse latest Browse all 4756

Trending Articles