dev@javaserverfaces.java.net

Re: [REVIEW] Minor state management and view handler tweaks

From: Mike Kienenberger <mkienenb_at_gmail.com>
Date: Wed, 20 Sep 2006 16:59:54 -0400

I've seen it recommended that the only safe implementation for hash
for a mutable object is "return 0;"


On 9/20/06, jacob_at_hookom.net <jacob_at_hookom.net> wrote:
> You can't just store the hash. hashes are never guaranteed to be unique, especially for Strings-- hashes help with lookup, but then equals(..) must be applied to actually return an exact match.
>
>
> >
> >
> >
> >Minor tweaks.
> >
> >
> >SECTION: Modified Files
> >----------------------------
> >M src/com/sun/faces/application/StateManagerImpl.java
> > - Instead of saving the String class name of the component,
> > save the hash value of the class itself. When restoring
> > the tree, look up the value based on the hash to obtain
> > the associated class. This results (at least in the
> > page I tested) a savings of 148 bytes. It's not huge,
> > but every little bit helps.
> >
> >M src/com/sun/faces/application/ViewHandlerImpl.java
> > - call the write() method of the writer instead
> > of writeText() to avoid extra processing associated
> > with that method.
> >
> >
> >SECTION: Diffs
> >----------------------------
> >Index: src/com/sun/faces/application/StateManagerImpl.java
> >===================================================================
> >RCS file:
> >/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/StateManagerI
> >mpl.java,v
> >retrieving revision 1.58
> >diff -u -r1.58 StateManagerImpl.java
> >--- src/com/sun/faces/application/StateManagerImpl.java 20 Sep 2006 17:50:21
> >-0000 1.58
> >+++ src/com/sun/faces/application/StateManagerImpl.java 20 Sep 2006 19:14:13
> >-0000
> >@@ -48,6 +48,7 @@
> > import java.util.Map.Entry;
> > import java.util.Set;
> > import java.util.concurrent.ConcurrentHashMap;
> >+import java.util.concurrent.ConcurrentMap;
> > import java.util.logging.Level;
> > import java.util.logging.Logger;
> >
> >@@ -74,8 +75,7 @@
> > /** Number of views in logical view to be saved in session. */
> > private int noOfViews;
> > private int noOfViewsInLogicalView;
> >- private Map<String,Class<?>> classMap =
> >- new ConcurrentHashMap<String,Class<?>>(32);
> >+ private ClassCache classCache = new ClassCache();
> >
> >
> >
> >@@ -423,7 +423,7 @@
> >
> >
> >
> >- private static void captureChild(List<TreeNode> tree,
> >+ private void captureChild(List<TreeNode> tree,
> > int parent,
> > UIComponent c,
> > FacesContext ctx) {
> >@@ -432,13 +432,15 @@
> > TreeNode n = new TreeNode(parent, c, ctx);
> > int pos = tree.size();
> > tree.add(n);
> >+ Class<?> cl = c.getClass();
> >+ classCache.addEntry(cl.hashCode(), cl);
> > captureRest(tree, pos, c, ctx);
> > }
> >
> > }
> >
> >
> >- private static void captureFacet(List<TreeNode> tree,
> >+ private void captureFacet(List<TreeNode> tree,
> > int parent,
> > String name,
> > UIComponent c,
> >@@ -448,13 +450,15 @@
> > FacetNode n = new FacetNode(parent, name, c, ctx);
> > int pos = tree.size();
> > tree.add(n);
> >+ Class<?> cl = c.getClass();
> >+ classCache.addEntry(cl.hashCode(), cl);
> > captureRest(tree, pos, c, ctx);
> > }
> >
> > }
> >
> >
> >- private static void captureRest(List<TreeNode> tree,
> >+ private void captureRest(List<TreeNode> tree,
> > int pos,
> > UIComponent c,
> > FacesContext ctx) {
> >@@ -509,15 +513,7 @@
> > throws FacesException {
> >
> > try {
> >- Class<?> t = classMap.get(n.componentType);
> >- if (t == null) {
> >- t = Util.loadClass(n.componentType, n);
> >- if (t != null) {
> >- classMap.put(n.componentType, t);
> >- } else {
> >- throw new NullPointerException();
> >- }
> >- }
> >+ Class<?> t = classCache.getEntry(n.componentType);
> >
> > UIComponent c = (UIComponent) t.newInstance();
> > c.setId(n.id);
> >@@ -609,7 +605,7 @@
> >
> > private static final String NULL_ID = "";
> >
> >- public String componentType;
> >+ public int componentType;
> > public String id;
> > public Serializable state;
> > public boolean trans;
> >@@ -629,7 +625,7 @@
> >
> > this.parent = parent;
> > this.id = c.getId();
> >- this.componentType = c.getClass().getName();
> >+ this.componentType = c.getClass().hashCode();
> > this.trans = c.isTransient();
> > if (!trans) {
> > this.state = (Serializable) c.saveState(ctx);
> >@@ -643,7 +639,7 @@
> > public void writeExternal(ObjectOutput out) throws IOException {
> >
> > out.writeInt(this.parent);
> >- out.writeUTF(this.componentType);
> >+ out.writeInt(this.componentType);
> > out.writeBoolean(this.trans);
> > if (this.id != null) {
> > out.writeUTF(this.id);
> >@@ -661,7 +657,7 @@
> > throws IOException, ClassNotFoundException {
> >
> > this.parent = in.readInt();
> >- this.componentType = in.readUTF();
> >+ this.componentType = in.readInt();
> > this.trans = in.readBoolean();
> > this.id = in.readUTF();
> > if (id.length() == 0) {
> >@@ -717,6 +713,28 @@
> >
> > }
> >
> >+ }
> >+
> >+
> >+ private static class ClassCache {
> >+
> >+ private ConcurrentMap<Integer,Class<?>> cache =
> >+ new ConcurrentHashMap<Integer,Class<?>>();
> >+
> >+
> >+ // ------------------------------------------------------ Public
> >Methods
> >+
> >+
> >+ public void addEntry(int hash, Class<?> clazz) {
> >+ if (!cache.containsKey(hash)) {
> >+ cache.put(hash, clazz);
> >+ }
> >+ }
> >+
> >+
> >+ public Class<?> getEntry(int hash) {
> >+ return cache.get(hash);
> >+ }
> > }
> >
> > } // END StateManagerImpl
> >Index: src/com/sun/faces/application/ViewHandlerImpl.java
> >===================================================================
> >RCS file:
> >/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ViewHandlerIm
> >pl.java,v
> >retrieving revision 1.85
> >diff -u -r1.85 ViewHandlerImpl.java
> >--- src/com/sun/faces/application/ViewHandlerImpl.java 15 Sep 2006 17:19:18
> >-0000 1.85
> >+++ src/com/sun/faces/application/ViewHandlerImpl.java 20 Sep 2006 19:14:13
> >-0000
> >@@ -611,8 +611,7 @@
> > context.getViewRoot().getViewId());
> > }
> >
> >- context.getResponseWriter().writeText(
> >- RIConstants.SAVESTATE_FIELD_MARKER, null);
> >+
> >context.getResponseWriter().write(RIConstants.SAVESTATE_FIELD_MARKER);
> > if (logger.isLoggable(Level.FINE)) {
> > logger.fine("End writing marker for viewId " +
> > context.getViewRoot().getViewId());
> >
> >
> >
> >
> >---------------------------------------------------------------------
> >To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
> >For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
> For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net
>
>