I have been keeping the good people of PACKT Publishing waiting some time for this short review; they were kind and prompt in sending me their book - in my defence I have been very busy lately. I had hoped to include some example code but as I am still short on time right now I thought I would release a general review first and maybe something with some example code at a later date when I've had some more time to digest the book further. To business, Spring Web Flow 2 Web Development is a book for Spring developers who want to give Spring Web Flow a try. So what is Spring Web Flow? As described in following excerpts from the book (page 9):

"...- you can use Spring Web Flow to create conversational web applications. ...For example, take an application with a wizard-like interface. ...You are working in a predefined flow with a specific goal, such as ordering a book or creating a new user account. ...Spring Web Flow makes it very easy to create flows. Flows created by Spring Web Flow are not only decoupled from the applications logic, but are also re-usable in different applications. A flow in Spring Web Flow is a sequence of steps, that is, with states and transitions between them. There are also actions that can be executed on various points, for example, when the flow starts or the web page is rendered..."

This book is intended to describe Spring Web Flow 2 and any book which ties itself to a particular version is going to date quickly but that said you are bound to learn something new reading this book.

The book contains the obligatory chapters describing the Spring Web Flow 2 concepts and exploring what has changed since the last version, the distribution and example code. It also has a chapter on setting up your development environment be that Ant, Maven, Eclipse (and Spring IDE) or NetBeans. A chapter on JavaServerFaces integration using the Spring Web Flow 2 "Spring Faces" module, as I've never properly explored JavaServerFaces I'm not qualified to comment on this. The sample project that is used throughout the book is a simple bug tracking system ("flow.trac"). With this project there is plenty of scope to explore what Spring Web Flow 2 has to offer in terms of user interface (JavaScript including AJAX, Apache Tiles etc.), testing (JUnit and EasyMock) and security (Spring Security) whilst utilising a JPA (Hibernate) database layer. In the appendix it shows you how you can run your code on the SpringSource dm Server and gives a gentle introduction to making you application work in an OSGi environment. The source code for the book is available @ www.packtpub.com/files/code/5425_Code.zip

One of my early impressions was one of surprise, I admit to raising an eyebrow that they chose to use Microsoft SQL Server 2008 Express Edition as their example database server. I would expect something more lightweight such as H2 or Apache Derby -e.g. something you could easily bundle as part of a Maven build.

The intended audience for this book seems to be people who plan to use the triumvirate of Spring, Spring MVC and Spring Web Flow. From my perspective Spring is a gimme and you are obviously interested in Spring Web Flow (that is why you bought the book!) but I'm not so sure you are always free to choose Spring MVC. To be fair the book goes to great pains to say that Spring Web Flow can be used with other technologies but as my main web development MVC framework is still good ole' Struts 1.3, it would be nice to see some examples of using Spring Web Flow 2 with something other than Spring MVC or maybe even in a more exotic environment like inside a Spring MVC portlet. Spring Web Flow 2 includes components for integrating with JavaScript. I have to admit to being a jQuery devotee so any alternate JavaScript technology seems a bit unnecessary to me but I can see it could be useful to some folks.

All in all and so far, I have found reading this book to be very enjoyable. It is nice to see how other developers go about things, I found myself reading and thinking "I wouldn't do it that way" AND "That's clever, I'd never have thought of that!". The experience of reading this book is very much like shadowing some very experienced senior Java developers.

PACKT Publishing very kindly sent me a copy of Spring Web Flow 2 Web Development to review. I have been very busy with work so I have not yet gotten around to reviewing it but I plan to publish something in the not too distant future. So watch this space!

Whilst making preparations for upgrading to uPortal 3.1.x from uPortal 2.5.x I came into contact with jQuery UI themes.

In our previous portal the help screens were displayed using Cody Lindley's ThickBox. At the time I first introduced Thickbox to our portal I thought this was pretty revolutionary, clicking on a link made the background dim and the help text (via an IFRAME) was shown in sharp contrast in the foreground of the page (very Web 2.0!).

The interface for uPortal 3.1 has evolved considerably from 2.5.x. The fluid project have worked on uPortal 3.1 to improve the user experience. jQuery and jQuery UI have become an integral part of the uPortal interface. uPortal 3.1 makes good use of jQuery UI dialog and tab widgets. (Incidentally, when did dialogue become dialog?) As the range of jQuery UI widgetry expands so too will the options for portal improvement, all with a common look and feel and easily themed.

In our new portal I would still like to access the help pages in a Thickbox/IFRAME style. However, the jQuery plugins that provide this kind of functionality (Thickbox and jqModal) do not look like the other jQuery UI widgets and are not themeable via jQuery UI themes. I could probably map the plugin CSS to the jQuery UI theme CSS but this seems like it could be a lot of work. So I have produced my own version of a dialog using an IFRAME.

I am fairly new to jQuery and what I have produced isn't quite up to jQuery plugin standard but if somebody out there wanted to apply some finishes touches to it I would be happy to contribute it back to the jQuery effort. The main difference between my effort and Thickbox and jqModal is that I am only interested in IFRAMEs and my version should be ThemeRollerReady. All being well you should see the themeswitcher below and a click on the link below that should give you a dalog box IFRAME:

jQuery UI IFRAME dialog box example

alternatively you can see it at standalone jQuery UI IFRAME dialog box example.

A while ago I wrote some code and thought it a neat trick but totally forgot about it until recently. I am writing this blog entry, firstly to share the idea and secondly to see if somebody can give an alternative using only Spring classes (which would deepen my understanding). Using Spring's DelegatingFilterProxy it is possible to hand off creation of servlet filters to a bean defined in Spring's application context. This is very useful if you want to inject Spring managed beans into a your servlet filters.

I am using the DelegatingFilterProxy mechanism to configure my servlet filter init parameters and in conjunction using PreferencesPlaceholderConfigurer so these come from a properties file. This means I can easily switch between prod and dev environments without having to modify web.xml (I could even change the authenticationFilter implementation to something else but that is a different story!). My aim here is to minimize the number of files I need to edit when moving between prod and dev environments. I hope somebody else finds this approach useful.

As an example I am using the Yale CAS Filter, which is considered a little long in the tooth now (but I'm still using it). It makes for a good example because there are numerous filter properties that you might want to change. Even the most up to date version of the JA-SIG CAS Filter could potentially benefit from using my approach.

web.xml

    ...
    <filter>
        <filter-name>authenticationFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>authenticationFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/dev.properties" />
    </bean>

    <bean id="authenticationFilter" class="edu.bristol.web.ParameterPassingFilterProxy">
        <property name="parameters">
            <map>
                <entry key="edu.yale.its.tp.cas.client.filter.loginUrl" value="${cas.loginUrl}" />
                <entry key="edu.yale.its.tp.cas.client.filter.validateUrl" value="${cas.validateUrl}" />
                <entry key="edu.yale.its.tp.cas.client.filter.wrapRequest" value="${cas.wrapRequest}" />
                <entry key="edu.yale.its.tp.cas.client.filter.serverName" value="${cas.serverName}" />
                <entry key="edu.yale.its.tp.cas.client.filter.renew" value="${cas.renew}" />
            </map>
        </property>
        <property name="targetBeanName" value="casFilter" />
    </bean>

    <bean id="casFilter" class="edu.yale.its.tp.cas.client.filter.CASFilter"/>

</beans>

The extra class that I added to make this work is available from ParameterPassingFilterProxy.java you are free to use it as you wish.

For the past 9 months I have been using Hibernate Annotations (along with the Spring Framework) to build my development database. Although I have a reasonably strong grasp of SQL I would still not consider myself fluent. Hibernate does all the hard work for me. Truth be told, there is a substantial learning curve to mastering mapping entity bean associations/relationships with Hibernate annotations. However once you finally develop an understanding (or find enough examples of what you want) it is very easy to continually evolve a data model throughout system development. Using annotations in conjunction with a suitably crafted import.sql file I can go from zero to system in no time. So after several months' development I am on the brink of having a production ready database containing precious real data that I do not want to loose. Should I take the risk of using "hbm2ddl.auto=update" to incorporate last minute database changes? I think not. I would not do this and this is not because I don't trust Hibernate but more because I do not trust myself. If I accidentally used hbm2ddl.auto=create (as I do regularly in my development instance) then bang goes my production database and all the data it contains.

So I wrote a small program to let me see what Hibernate would do if I ran an update without the associated risk of actually performing an update. I have a Spring applicationContext.xml which contains something like the following (note the complete absence of hbm2ddl.auto property setting):

<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
    <property name="location" value="jdbc.prod.properties" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName">
        <value>${jdbc.driverClassName}</value>
    </property>
    <property name="url">
        <value>${jdbc.url}</value>
    </property>
    <property name="username">
        <value>${jdbc.username}</value>
    </property>
    <property name="password">
        <value>${jdbc.password}</value>
    </property>
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}
            </prop>
        </props>
    </property>
    <property name="annotatedClasses">
        <list>
            <value>edu.bristol.entity.Tom</value>
            <value>edu.bristol.entity.Dick</value>
            <value>edu.bristol.entity.Harry</value>
        </list>
    </property>
    <property name="dataSource" ref="dataSource" />
</bean>

Now for my program, one thing that I have noticed is that update scripts that Hibernate would create will add new fields to a database but will not delete existing columns (even if these have been removed from the annotated entity). It makes a good deal of sense not to delete columns from a production database without knowing exactly what you are doing so this is a good thing!

import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;

public class AcquireScripts {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // ampersand is very significant - it means get me an
        // instance of the beanfactory and not give me a bean
        LocalSessionFactoryBean sfb = (LocalSessionFactoryBean) context.getBean("&sessionFactory");
        Configuration cfg = sfb.getConfiguration();
        Dialect dialect = Dialect.getDialect(cfg.getProperties());
        //printDropSchemaScript(cfg, dialect);
        //printSchemaCreationScript(cfg, dialect);
        printSchemaUpdateScript((SessionFactory) sfb.getObject(), cfg, dialect);
    }

    private static void printSchemaCreationScript(final Configuration cfg, final Dialect dialect) {
        String[] schemaCreationScript = cfg.generateSchemaCreationScript(dialect);
        for (String stmt : schemaCreationScript) {
            System.out.println(stmt + ";");
        }
    }

    private static void printDropSchemaScript(final Configuration cfg, final Dialect dialect) {
        String[] dropSchemaScript = cfg.generateDropSchemaScript(dialect);
        for (String stmt : dropSchemaScript) {
            System.out.println(stmt + ";");
        }
    }

    private static void printSchemaUpdateScript(final SessionFactory sf, final Configuration cfg, final Dialect dialect) {
        HibernateTemplate hibernateTemplate = new HibernateTemplate(sf);
        hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER);
        hibernateTemplate.execute(
                new HibernateCallback() {
                    public Object doInHibernate(Session session) throws HibernateException, SQLException {
                        Connection con = session.connection();
                        Dialect dialect = Dialect.getDialect(cfg.getProperties());
                        DatabaseMetadata metadata = new DatabaseMetadata(con, dialect);
                        String[] schemaUpdateScript = cfg.generateSchemaUpdateScript(dialect, metadata);
                        for (String stmt : schemaUpdateScript) {
                            System.out.println(stmt + ";");
                        }
                        return null;
                    }
                });
    }
}

Notice the cunning use of the ampersand to acquire an instance of the LocalSessionFactoryBean rather than the actual SessionFactory itself. So there we have it, all of the cleverness of Hibernate annotations working out what SQL we might need to update our database but none of the risk.

My "other blog" is located at http://markmclaren.blogs.ilrt.org/. I'm looking to see how I get on with a more restricted environment!
Tags :

For me, HttpServletRequest's getRemoteUser() and isUserInRole(role) have always felt like the right place to obtain user information in a web application. My experience with JASIG CAS filter and SecurityFilter has taught me that it is easy to create a servlet filter and drop in a request wrapper (HttpServletRequestWrapper) and create a method to set the remoteUser value. Couple this filter with something like Spring's DelegatingFilterProxy and it is easy obtain user details from some dependency injected external database.

Once the remoteUser value exists in the wrapped request you can acquire the details in a JSP page using JSTL e.g:

<c:out value="${pageContext.request.remoteUser}"/>

or with simple expression language alone (JSP 2.4+), e.g:

${pageContext.request.remoteUser}

The question is how to obtain the role information for a user. Jakarta's Request tag library enables you to make use of role information.

<req:isUserInRole role="admin">
	<h1>Hello Admin User</h1>
</req:isUserInRole>

For some reason the request tag library is now deprecated. Of course you can still use it (and it is in the Maven repository) but there is something of a stigma associated with using deprecated code! So I have come up with an alternative. The issue is that it is not easy to invoke methods with parameter arguments from expression language. You cannot simply call:

${pageContext.request.isUserInRole('admin')}

Using expression language you can access scoped variables, arrays, lists and maps. Most of the time this data will be acquired and stored in some scope prior to loading the JSP page (such as in a typical MVC application). However, I have discovered that you can acquire runtime generated responses from a Map using Commons Collection's LazyMap and this technique can be used to effectively perform a user role lookup. I added the following method to my request wrapper (and made sure the request wrapper was publically accessible):

public Map getIsUserInRole() {
    Transformer factory = new Transformer() {
        public Object transform(Object mapKey) {
            return isUserInRole((String) mapKey);
         }
    };
    Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
    return lazyMap;
}

and this means I can now access role information in a way that looks very much like a direct call to request.isUserInRole(role).

${pageContext.request.isUserInRole['admin']}

Using an idea that Matthew Sgarlata had for the request tag library it is even possible to include support for multiple role queries.

public Map getIsUserInRole() {
    final String ROLE_DELIMITERS = ", \t\n\r\f";
    Transformer factory = new Transformer() {

    public Object transform(Object mapKey) {
           StringTokenizer tokenizer = new StringTokenizer((String) mapKey, ROLE_DELIMITERS);
           boolean result = false;
           while (tokenizer.hasMoreTokens() && !result) {
               if (isUserInRole(tokenizer.nextToken())) {
                   result = true;
               }
           }
           return result;
           }
     };
     Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
     return lazyMap;
}
  
and the expression language becomes:
${pageContext.request.isUserInRole['admin,staff']}

and this can be easily negated:

${!pageContext.request.isUserInRole['admin,staff']}

Sample WAR with source code available (Assuming Java 1.5+ and Maven build "mvn compile war:war").

Update

As an update to this, I am now using the above technqie with what I call a ClearingLazyMap. This class implements the LazyMap interface but does not cache any values when they are fetched. This is necessary in order to pick up the most recent database updates, see also LazyMap that always calls transform, good idea?

I am working on a web application where one of the requirements is that I use an in-house Java database access framework. Personally I would prefer to use something that complements Spring and that makes my life easier such as Hibernate Annotations, iBATIS or even Spring JDBCTemplates but requirements are requirements.

One of the problems I face is that I need to re-invent a lot of ORM wheels. The framework is very similar in essence to iBATIS. All the SQL is stored in external XML configuration files. The framework conducts the mappings conversion from ResultSets to lists of beans (using commons-beanutils). As such, like iBATIS there is plenty of scope to generate most of the repetitive Java code (interfaces, implementations, facades) and configuration files (SQL CRUD). I have previously experimented with the Middlegen code generation with iBATIS. Middlegen code is a little long in the tooth, as a project it seems to have stagnated back in 2005 (I suppose iBATOR and Hibernate Tools have long since superseded it). That said, because Middlegen is based on Velocity templates it is very flexible and perfect for this kind of thing. I was able to port my previous iBATIS code generating templates to produce suitable Java code for use with the in-house framework.

I have managed to get some quite sophisticated code generated. Apparently "Lazy Loading is easy", so I am attempting to implement that using CGLIB in my DAO. I have also produced a method that is similar to Hibernates's SaveOrUpdate method. A given entity may have two kinds of relationship; target one (OneToOne, ManyToOne) or target many (OneToMany). I have no ManyToMany relationships and this is deliberate!

How my SaveOrUpdate works is derived from some code I found in iBATIS in Action (By Clinton Begin, Brandon Goodin and Larry Meadors, Published by Manning). In section 5.3.2 Updating or deleting child records the following method is suggested:

public void saveOrder(SqlMapClient sqlMapClient, Order order) 
throws SQLException {
  if (null == order.getOrderId()) {
    sqlMapClient.insert("Order.insert", order);
  } else {
    sqlMapClient.update("Order.update", order);
  }
  sqlMapClient.delete("Order.deleteDetails", order);
  for(int i=0;i<order.getOrderItems().size();i++) {
    OrderItem oi = (OrderItem) order.getOrderItems().get(i); 
    oi.setOrderId(order.getOrderId());
    sqlMapClient.insert("OrderItem.insert", oi);
  }
}

The above method addresses the target many relationships but does not address the target one relationships. My method works more like this:

  1. Iterate through all the target one entities and SaveOrUpdate these. Inserting any generated ids into the current entity.
  2. Save the current entity data fields
  3. Iterate through all the target many relationships and SaveOrUpdate these.

At this point I got a little stuck. I found that relatively often my target one relationships should not be the subject of further SaveOrUpdates. The characteristic of these relationships is when the data is fairly static and mostly provides the conent of drop-down lists. When you make a selection from a such a list you do not usually need to update the list itself!

Essentially, Middlegen generates everything based on the contents of the database. For these relationships I needed some way to designate the code generation behaviour for certain database columns.

In Java Persistence API implementations, like Hibernate Annotations, this kind of behaviour is very easily represented by using @Column(insertable=false, updatable=false). I needed a way for Middlegen to acquire this information from the database. Then I had a brainwave, in the most recent version of Middlegen (from the CVS) you can "getRemarks" for tables and columns. Database remarks can be acquired from DatabaseMetaData. The unfortunate thing is that I am using an Oracle database which AFAICT uses a non-standard treatment of "remarks". It turns out that the default behaviour of Oracle drivers is not to populate the DatabaseMetaData with remarks. In Oracle remarks are contained inside two special tables; user_tab_comments and user_col_comments. You can override the default behaviour of Oracle driver to populate remarks, this can be done at the BasicDataSource (using addConnectionProperty("remarksReporting", "true")) or on a OracleConnection (using setRemarksReporting(true)).

Armed with this information I can "annotate" database columns, so I can use something like this:

COMMENT ON COLUMN <table>.<column> IS 'insertable=false, updatable=false';

I tweaked MiddlegenPopulator to allow it to acquire remarks for Oracle from the DatabaseMetaData. The database now contains all the information I need to generate my DAO code. I can now tweak my DAO generation templates to miss out the SaveOrUpdate code for target one relationships which match the column comment of 'insertable=false, updatable=false'.

Simple huh? Or maybe just plain scary... annotations with databases!

I recently attended the Google Developer Day 2008, Tuesday 16th September at Wembley Stadium (London). I went to the following sessions:
  • Keynote - Tom Stocky, Mike Jennings (Android bit), Sumit Chandel (GWT bit)
  • The State of AJAX - Dion Almaer
  • A Deeper Look at Google App Engine - Mano Marks
  • What's New in Geo - Jean-Laurent Wotton (Google), Russell Middleton (Google) and Angela Relle (Met Office)
  • V8: the Chrome engine - Kevin Millikin

What follows are my rough notes from my memory - by that I mean brain memory not USB memory. Also there liable to be some flaws in my understanding!

Keynote

Tom Stocky (Google's Director of Product Management) began the day with his keynote speech. This touched upon many of Google's latest and greatest offerings; Chrome, App Engine, Android, GWT and Open Social. The first European demo of an Android device (HTC dream?) was apparently the most newsworthy. The salient points for me where concerning Chrome and GWT. Concerning Chrome - a little bit of hype, some justification. Some explanation of what makes Chrome different, multiprocess architecture (therefore increased stability), high performance V8 javascript engine and something about re-invigorating the browser arms race. I have been aware of GWT (apparently pronounced "GWIT" as in twit) but never used it - it could be described as a superior high performance AJAX applications development tool, producing obfuscated JavaScript for people happier debugging their JavaScript in Java IDEs!

The State of AJAX

Dion Almaer (of Ajaxian.com fame) gave a very entertaining and detailed talk concerning the current AJAX landscape (not just what Google are doing but more general). Some of the thing this presentation touched on included:

  • Cloud computing; Amazon [E2/S3 etc], Google App Engine and Aptana Cloud.
  • GWT, jQuery(+ UI), prototype(+ Scripticulous), dojo: The convergence of JavaScript libraries and how they are ALL great, use them!
  • Mozilla Prism (although no reference of Mozilla Prism's similarity to Google Chrome)
  • Various Mozilla Monkey projects, of particular interested was Screaming Monkey, a project which can install a Mozilla JavaScript engine into IE.
  • A fun demo of using a Wii controller with a browser based game (using AJAX, applet and wiiusej).
  • Brenden Eich says "Threads suck" so why not use Google Gear's worker pools for thread-like functionality?

A Deeper Look at Google App Engine

Mano Marks lead a guided tour of some the things Google App Engine has to offer and he encouraged audience interaction. He was somewhat cagey on the topics of SLAs and future language support despite receiving numerous audience queries on these subjects. The audience seemed to be very well acquainted with this technology already, for example there was no explanation given about what Sharding was and the audience didn't ask (I could only assume everybody knew already, which I was very impressed with!). After fending off the SLA and future language questions the remainder of the talk highlighted numerous Google App Engine shortcomings and some workarounds for these. Limitations highlighted:

  • Limitations of BigTable:
    • fast hashtable - access by key (up to 512 chars) should be really fast
    • little in the way of referential integrity can have equivalent to foreign keys
    • exercise all your queries in the developer environments to ensure the appropriates indexes are created for production
    • sharding, expensive to perform an object count after the fact
    • use memcache to reduce use of resources
  • File upload/download/storage limitation of 1Mb
  • FetchUrl limit of 4 seconds (there was something that had a 10 second limit but I forget what)

What's New in Geo

After lunch, there was another very detailed and interesting review of the recent Google Geo developments, including:

  • New ajax loading mechanism
  • Geocoding
  • directions
  • integration with local search
  • StreetView
  • Google Maps API for Flash®
  • Google static maps - useful for mobile apps
  • Google Earth plugin
  • MET office Outreach climate change example - with world temperature map changing over time

V8 - the Chrome engine

Probably the most deeply technical session of the day, scarily so in places, in fact several people left the talk quite early, I'm glad that I stayed. I didn't quite understand all of it. Some of the audience looked in a trance like state for this talk (it was late in the day!), I was very surprised that so many non-Googlers seemed so casually conversant with the finer details of creating optimised JavaScript compilers! The take home message that I extracted was something along the lines of:

  • JavaScript is compiled into native machine code and not interpreted
  • Up to 200% faster than previous engines but there are areas that mess this up (e.g. usage of eval() and with)
  • It works on Windows, Linux and Macs, it is Chrome itself that doesn't as yet!
  • JavaScript is an intrinsically dynamic language but most of the time developers use it just like a statically typed language. Therefore, optimisation technique from statically typed languages can be applied (at least most of the time)
  • Functions are only complied when they have been used
  • Functions used more that once are cached for future use, unless they "change"
  • Functions go through numerous states and their state determines the V8 caching approach.
    • unitialised
    • pre-monomorphic - the function has only been used once - don't do anything yet, it could be use one time init code
    • monomorphic - fast - 90% of the time this is the case - e.g. objects are used in a single way
    • megamorphic - blast the developer is actually using the more dynamic features of the JavaScript language resort to the slower uncached approach
  • JavaScript standard libraries are written in JavaScript! So any improvement in performance for the compiler will improve the performance across the board.
  • Currently, no improvement in DOM accessing technologies

Related links