You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by rm...@apache.org on 2013/08/14 17:35:27 UTC

svn commit: r1513933 - in /bval/branches/bval-11: bval-core/src/main/java/org/apache/bval/MetaBeanManager.java bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java

Author: rmannibucau
Date: Wed Aug 14 15:35:27 2013
New Revision: 1513933

URL: http://svn.apache.org/r1513933
Log:
better locking when concurrently trying to create the same metadata in MetaBeanManager

Modified:
    bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java
    bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java

Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java?rev=1513933&r1=1513932&r2=1513933&view=diff
==============================================================================
--- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java (original)
+++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java Wed Aug 14 15:35:27 2013
@@ -19,7 +19,12 @@ package org.apache.bval;
 import org.apache.bval.model.MetaBean;
 import org.apache.bval.model.MetaProperty;
 
-import static org.apache.bval.model.Features.Property.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.apache.bval.model.Features.Property.REF_BEAN_ID;
+import static org.apache.bval.model.Features.Property.REF_BEAN_TYPE;
+import static org.apache.bval.model.Features.Property.REF_CASCADE;
 
 /**
  * Description: Default implementation for the interface to find, register and
@@ -36,6 +41,8 @@ public class MetaBeanManager implements 
     /** Complete flag */
     protected boolean complete = false;
 
+    protected final ConcurrentMap<Object, Object> cacheLocks = new ConcurrentHashMap<Object, Object>();
+
     /**
      * Create a new MetaBeanManager instance.
      */
@@ -73,40 +80,69 @@ public class MetaBeanManager implements 
     /**
      * {@inheritDoc}
      */
-    public MetaBean findForId(String beanInfoId) {
+    public MetaBean findForId(final String beanInfoId) {
         MetaBean beanInfo = cache.findForId(beanInfoId);
-        if (beanInfo != null)
+        if (beanInfo != null) {
             return beanInfo;
-        try {
-            beanInfo = builder.buildForId(beanInfoId);
-            cache.cache(beanInfo);
-            computeRelationships(beanInfo);
-            return beanInfo;
-        } catch (RuntimeException e) {
-            throw e; // do not wrap runtime exceptions
-        } catch (Exception e) {
-            throw new IllegalArgumentException("error creating beanInfo with id: " + beanInfoId, e);
+        }
+
+        synchronized (getLockFor(beanInfoId)) {
+            beanInfo = cache.findForId(beanInfoId);
+            if (beanInfo != null) {
+                return beanInfo;
+            }
+
+            try {
+                beanInfo = builder.buildForId(beanInfoId);
+                cache.cache(beanInfo);
+                computeRelationships(beanInfo);
+                return beanInfo;
+            } catch (final RuntimeException e) {
+                throw e; // do not wrap runtime exceptions
+            } catch (final Exception e) {
+                throw new IllegalArgumentException("error creating beanInfo with id: " + beanInfoId, e);
+            }
         }
     }
 
+    private Object getLockFor(final Object key) {
+        final Object newLock = new Object();
+        Object lock = cacheLocks.putIfAbsent(key, newLock);
+        if (lock == null) {
+            lock = newLock;
+        }
+        return lock;
+    }
+
     /**
      * {@inheritDoc}
      */
-    public MetaBean findForClass(Class<?> clazz) {
-        if (clazz == null)
+    public MetaBean findForClass(final Class<?> clazz) {
+        if (clazz == null) {
             return null;
+        }
+
         MetaBean beanInfo = cache.findForClass(clazz);
-        if (beanInfo != null)
+        if (beanInfo != null) {
             return beanInfo;
-        try {
-            beanInfo = builder.buildForClass(clazz);
-            cache.cache(beanInfo);
-            computeRelationships(beanInfo);
-            return beanInfo;
-        } catch (RuntimeException e) {
-            throw e; // do not wrap runtime exceptions
-        } catch (Exception e) {
-            throw new IllegalArgumentException("error creating beanInfo for " + clazz, e);
+        }
+
+        synchronized (getLockFor(clazz)) {
+            beanInfo = cache.findForClass(clazz);
+            if (beanInfo != null) {
+                return beanInfo;
+            }
+
+            try {
+                beanInfo = builder.buildForClass(clazz);
+                cache.cache(beanInfo);
+                computeRelationships(beanInfo);
+                return beanInfo;
+            } catch (final RuntimeException e) {
+                throw e; // do not wrap runtime exceptions
+            } catch (final Exception e) {
+                throw new IllegalArgumentException("error creating beanInfo for " + clazz, e);
+            }
         }
     }
 
@@ -118,8 +154,8 @@ public class MetaBeanManager implements 
      *            - the bean for which to compute relationships
      */
     protected void computeRelationships(MetaBean beanInfo) {
-        for (MetaProperty prop : beanInfo.getProperties()) {
-            String beanRef = (String) prop.getFeature(REF_BEAN_ID);
+        for (final MetaProperty prop : beanInfo.getProperties()) {
+            final String beanRef = prop.getFeature(REF_BEAN_ID);
             computeRelatedMetaBean(prop, beanRef);
         }
     }

Modified: bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java?rev=1513933&r1=1513932&r2=1513933&view=diff
==============================================================================
--- bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java (original)
+++ bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java Wed Aug 14 15:35:27 2013
@@ -100,6 +100,8 @@ public class ClassValidator implements C
      */
     protected final GroupsComputer groupsComputer = new GroupsComputer();
 
+    private final MetaBeanFinder metaBeanFinder;
+
     /**
      * Create a new ClassValidator instance.
      *
@@ -107,16 +109,7 @@ public class ClassValidator implements C
      */
     public ClassValidator(ApacheFactoryContext factoryContext) {
         this.factoryContext = factoryContext;
-    }
-
-    /**
-     * Get the metabean finder associated with this validator.
-     *
-     * @return a MetaBeanFinder
-     * @see org.apache.bval.MetaBeanManagerFactory#getFinder()
-     */
-    protected MetaBeanFinder getMetaBeanFinder() {
-        return factoryContext.getMetaBeanFinder();
+        metaBeanFinder = factoryContext.getMetaBeanFinder();
     }
 
     // Validator implementation
@@ -144,7 +137,7 @@ public class ClassValidator implements C
         try {
 
             final Class<T> objectClass = (Class<T>) object.getClass();
-            final MetaBean objectMetaBean = getMetaBeanFinder().findForClass(objectClass);
+            final MetaBean objectMetaBean = metaBeanFinder.findForClass(objectClass);
             final GroupValidationContext<T> context = createContext(objectMetaBean, object, objectClass, groups);
             return validateBeanWithGroups(context, context.getGroups());
         } catch (final RuntimeException ex) {
@@ -266,7 +259,7 @@ public class ClassValidator implements C
             throw new IllegalArgumentException("Class cannot be null");
         }
         try {
-            MetaBean metaBean = getMetaBeanFinder().findForClass(clazz); // don't throw an exception because of a missing validator here
+            MetaBean metaBean = metaBeanFinder.findForClass(clazz); // don't throw an exception because of a missing validator here
             BeanDescriptorImpl edesc = metaBean.getFeature(Jsr303Features.Bean.BEAN_DESCRIPTOR);
             if (edesc == null) {
                 edesc = createBeanDescriptor(metaBean);
@@ -1248,7 +1241,7 @@ public class ClassValidator implements C
         checkGroups(groups);
 
         try {
-            final MetaBean initialMetaBean = new DynamicMetaBean(getMetaBeanFinder());
+            final MetaBean initialMetaBean = new DynamicMetaBean(metaBeanFinder);
             initialMetaBean.setBeanClass(beanType);
             GroupValidationContext<T> context = createContext(initialMetaBean, object, beanType, groups);
             ValidationContextTraversal contextTraversal = createValidationContextTraversal(context);
@@ -1259,7 +1252,7 @@ public class ClassValidator implements C
             if (value != VALIDATE_PROPERTY) {
                 assert !context.getPropertyPath().isRootPath();
                 if (prop == null && value != null) {
-                    context.setMetaBean(getMetaBeanFinder().findForClass(value.getClass()));
+                    context.setMetaBean(metaBeanFinder.findForClass(value.getClass()));
                 }
                 if (!cascade) {
                     //TCK doesn't care what type a property is if there are no constraints to validate: