The Source for Java Technology Collaboration
User: Password:



Jacob Hookom's Blog

December 2006 Archives


JSE 7 No Arrows Please

Posted by jhook on December 28, 2006 at 09:11 PM | Permalink | Comments (13)

I'm finding so much of Java's APIs to be extremely literal and long-winded at times. While this produces self documenting code, I'd still like to see some better ideas for the getter/setter shorthand than '->'.

More on the topic here: Dion's Blog

I'm of the opinion that if you are willing to make a commitment to closures, then we do the same for properties-- something similar to C#. Spending time extending the long winded get/set convention is the wrong direction for the spec. Do everyone a favor and do properties right-- leaving the old Bean Property spec alone for APIs to accommodate and treating properties as a first class citizen in the metadata starting in SE 7.

Property[] p = class.getProperties();

Aside from the misread syntax of an assignment arrow ('->'), I can see a lot of people get confused by implying method associations by some naming convention. Actually introducing a literal property syntax into the spec will make code much more maintainable in the long run, than visual guessing games around field accessors.

Some senior developers may scoff at the thought of bean naming conventions as confusing, but from being on web/el/mvc dev lists for many years, you are guaranteed to get those people who have problems with reading properties because they didn't capitalize/lowercase the right letter.

Please SE folks-- think outside the box.



Class Metadata Caching

Posted by jhook on December 10, 2006 at 04:38 PM | Permalink | Comments (11)

A lot of frameworks are building off of simple Annotations or dynamic invocation, basically extensions per Class instance. To avoid re-mining this data, we attempt to cache it. This works fine, except when we deal with hot deploys or restarts with statically scoped caches. Keeping reference to some classes/ClassLoaders after repeated restarts could quickly gobble resources.

So I've been seriously looking for strategies that would prevent memory leaks, detecting dynamic changes in ClassLoaders or Classes. Some solutions go as far as to check the file system for class file changes, seems like a quite of overhead.

From talking with some of the guys from Sun, looking at ClassLoaders/Class implementations within the JVM, I thought looking at using WeakHashMaps and ConcurrentHashMaps together might provide a solution.

First, we would have a top-level WeakHashMap of ClassLoaders as the key. Secondly, we'll make the value of this ClassLoader WeakHashMap be a child Map of Class names to metadata (finally).

WeakHashMap<ClassLoader, ConcurrentHashMap<String, ClassMetaData>>

The reason for this setup is:

  1. WeakHashMaps keep weak references to the key, not the value-- so we can prevent retaining reference to old ClassLoaders.
  2. Using the ClassLoader at the top level key is less volatile than per Class, can help avoid synchronization locks with WeakHashMaps.
  3. We use a ConcurrentHashMap for efficient synchronization, for the per ClassLoader information.
  4. We key off of the Class name instead of the Class instance based on the fact that per ClassLoader can only have one instance loaded, but we know that the class could possibly change.
  5. The final value stored is wrapped by a touple that retains reference to the target class so we can check that the one instance cached matches the class passed, even though they have the same name.

Based on these points, I started throwing together a generic cache implementation that can be used to store anything per class, while attemping to avoid long term memory leaks.

public class ClassCache<V> {
    
    private class ClassValue<V> {
        private final Class type;
        private V value;
        
        public ClassValue(Class type, V value) {
            this.type = type;
            this.value = value;
        }
        
        public boolean matches(Class type) {
            return this.type.equals(type);
        }
        
        public V get() {
            return this.value;
        }
    }
    
    private class ClassMap<V> extends ConcurrentHashMap<String, ClassValue<V>> {}
    
    private class ClassLoaderMap extends WeakHashMap<ClassLoader, ClassMap> {}
    
    private ClassLoaderMap classLoaders = new ClassLoaderMap();
    
    public ClassCache() {}
    
    public void set(Class type, V value) {
        if (type == null) return;
        ClassLoader loader = type.getClassLoader();
        if (loader == null) loader = Thread.currentThread().getContextClassLoader();
        
        ClassMap map = this.classLoaders.get(loader);
        if (map == null) {
            map = new ClassMap();
            ClassLoaderMap replace = new ClassLoaderMap();
            
            // copy on write
            replace.putAll(this.classLoaders);
            replace.put(loader, map);
            this.classLoaders = replace;
        }
        
        map.put(type.getName(), new ClassValue(type, value));
    }
    
    public V get(Class type) {
        if (type == null) return null;
        ClassLoader loader = type.getClassLoader();
        if (loader == null) loader = Thread.currentThread().getContextClassLoader();
        
        ClassMap<V> map = this.classLoaders.get(loader);
        if (map != null) {
            ClassValue<V> value = map.get(type.getName());
            if (value != null && value.matches(type)) {
                return value.get();
            } else {
                map.remove(type.getName());
            }
        }
        
        return null;
    }
}

This is just some ideas I've put together, does anyone else have specific suggestions on how to do this better/properly?



JSF StateSaving and Compression

Posted by jhook on December 07, 2006 at 11:25 PM | Permalink | Comments (4)

StateSaving in JSF is the uncle no one wants to talk about. You get a lot of things for 'free' with JSF, but for the most part, these features end up adversely affecting the state size of the view.

JSF has two options for StateSaving: client and server (actually pluggable for anything you want). The basic rule of thumb is if you want to save memory, you go with client state saving-- pushing Object state to the client, encoded in the view. StateSaving server is a bit more performant, but retains stacks of views in the user's HttpSession.

What I want to focus on is client StateSaving. With saving state on the client, you are basically serializing an object graph and outputting it into the page as a Base64 String. Optional features here include encryption and compression. Encryption is only needed in rare cases-- but compression is often enabled. From my own tests, compressing JSF state means a reduction in size by at least a factor of 10 (hmmm... maybe this tells us something ;-).

By default, client state is compressed with normal GZip. I believe MyFaces actually opts out of compression by default, but any of Jason Hunter's old articles on Compression Filters actually tell you that compression is a good thing with network latency. Yes, compression adds processor overhead, but lets see if we can't look at some alternatives to GZip?

Diving through java.util.zip, I know that there are other 'Deflaters' available which have interesting 'types'-- such as Best Performance, Huffman, Best Compression, etc. Let's see how these compare with a grossly large JSF page (basically 100 pages put together in one) and averaged over hundreds of iterations of StateSaving:

Update: I've added Ryan's JMeter results from trying some of these algorithms against the CarDemo app with 50 threads running for 5 minutes at random intervals of 200-300ms.

Algorithm/Type Size in Bytes Write in Milliseconds Read in Milliseconds Total in Milliseconds Request/Second Bytes/Second # of Hits
None (Default MyFaces) 174,345 78.14 198.12 276.26 91.8 2,529.89 27,598
GZip (Default RI) 12,864 103.72 205.68 309.4 58.6 518.05 17,633
Default Compress 12,852 93.42 174.08 267.50 - - -
Best Compress 11,855 110.24 171.04 281.28 62.2 544.76 18,695
Best Speed 16,480 86.58 176.24 262.82 63.5 569.02 19,091
Huffman 15,190 79.46 175.22 254.68 63.8 590.21 19,181
Filtered 16,480 79.36 176.88 256.24 64.1 600.97 19,272

The different algorithms are listed within the java.util.zip package in the javadocs, but I found the numbers to be pretty interesting. Of course, I'm a compression n00b, so if anyone had any comments on why it would be bad to switch to one of the other algorithms as a set-able option with JSF, please let me know!

I should note too that smaller page sizes, all the algorithms fluxate in timings between runs by quite a bit (5ms > 0ms) which may be attributed purely to GC or the ObjectOutput/InputStream itself.



AJAX Responses Strategies

Posted by jhook on December 03, 2006 at 06:12 PM | Permalink | Comments (4)

Part of Avatar for JSF was being able to make a single, lightweight request to the Server and actually receive multiple elements at once in a single HTTP Response. An example would be a single button that would force re-rendering of 5 different parts of the page with one AJAX request. IMHO, this approach is MUCH more efficient that all of these client-side event/observer systems that produce 4 or 5 separate AJAX requests for updates (the network sucks).

Anyways, if we have 5 different things we want to respond back with at once, how do we structure the HTTP response without ruining the original data-- may it be Strings, HTML, XML, or JSON?

We also have the use case of accepting the targeted response data, in addition to any other elements that are to be refreshed. An example would be responding back with some String, but your listeners on the server also want to re-render the cart total and a few other elements on the screen-- not part of the original response.

Response Headers

My first solution was to demarcate the response into separate headers. Each element to be updated had it's own header to occupy, leaving the body of the message alone (see above). This was a perfect or natural way of separating the response up based on HTTP's own spec. The problem is that HTTP containers never intended to carry that much information in their headers, and to prevent buffer attacks, many are capped at a few kb in size. So your refresh of the main table of data would always get chopped off or force an error in the container. Anyways, I think IE also caps the header size acceptable in the response.

So while this solution worked, it has a size cap which is very hard for a framework to enforce.

XML Response

Another idea, which many use, is to break up the response into separate XML nodes in a parent document, allowing CDATA chunks of XML, HTML, or JSON:

<async-response id="5434">
    <encode id="table"><![CDATA[ ... ]]></encode>
    <encode id="cartSpan"><![CDATA[ ... ]]></encode>
    <encode id="footerTotal"><![CDATA[ ... ]]></encode>
    <body><![CDATA[ ... ]]></body>
</async-response>

While we've moved all of the response out of headers and into the body, we've created issues for ourselves around doubling CDATA blocks, which are illegal according to the w3c police. Even if you do the ']]]]>' trick, you will still have problems with some browsers. It's still somewhat tricky.

JSON Response

JSON offers the same capabilities as using XML, being extremely flexible in representing different bits of data, but there's one major problem-- double encoding JSON. If we are trying to create a solution that accomodates all response types, who's to say that one of the responses isn't already JSON, and if we re-encode as JSON, we could end up with unusable garbage in the response.

{
    id:543,
    state:'REALLY+LONG+STRING',
    encode: {
        'table':'....',
        'cartSpan':'....',
        'footerTotal':'....'
    },
    body: '....'
}

VLSN Response

If we choose XML or JSON, it seems we might clobber encoding by either doubling CDATA/entity markup or double escaping JavaScript. So lets try to take those strategies out and just take the simplest approach of producing one Very Long String Notation!

Instead of trying to demarcate within a single body (XML, JSON), we just write everything out in one continuous String, noting when each chunk starts and stops in a separate table. This table can then be stored as a much smaller Response Header or as the first line of the response body.

{id:[0,3],state:[4,4503],encode:{'table':[4504,6004],'cartSpan':[6005,6240],'footerTotal':[6241,6733]},body:[6734,7320]}
340XHHUERe+JeKljfaefe.....

Now you don't have to worry about encoding at all, you just take everything written as is!



Facelets 1.1.12 Uploaded

Posted by jhook on December 01, 2006 at 10:12 PM | Permalink | Comments (0)

Facelets 1.1.12 was just uploaded to Java.net and includes many small bug fixes for JSF 1.1 (MyFaces 1.1.4) and JSF 1.2 (RI 1.2_03b5).

Download Here

This release is considered 'draft' until users call it stable for production use. More information is found over at Facelets' web site.

Please give it a whirl and post any issues to the tracker or dev/user lists so we can push for another stable release!





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds