Fix XML serialiser for SpecConverter

It was not thread-safe. The XmlMementoSerializer uses a single
instance of SpecConverter. If multiple threads tried to deserialise
different objects at the same time, they’d overwrite the “instance”
value and cause serious problems deserialising.

Now use thread-local storage for the “instance” cache.

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b5dae5b7
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b5dae5b7
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b5dae5b7

Branch: refs/heads/master
Commit: b5dae5b7ad5b4d0919e00da1f02b5a54a1e4d3e1
Parents: 89b3a66
Author: Aled Sage <aled.s...@gmail.com>
Authored: Tue Mar 22 12:47:36 2016 +0000
Committer: Aled Sage <aled.s...@gmail.com>
Committed: Tue Mar 22 12:47:36 2016 +0000

----------------------------------------------------------------------
 .../core/mgmt/persist/XmlMementoSerializer.java       | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b5dae5b7/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
index 588f8fd..0df2340 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
@@ -393,6 +393,12 @@ public class XmlMementoSerializer<T> extends 
XmlSerializer<T> implements Memento
         }
     }
 
+    // Would prefer this as a field of SpecConverter, but can't do that 
because the class is not static.
+    // Must use thread-local storage because a single instance of the 
SpecConverter is used by this 
+    // XmlMementoSerializer. In 
BrooklynMementoPersisterToObjectStore.visitMemento, it uses a thread-pool
+    // for concurrently deserializing multiple objects.
+    private static final ThreadLocal<Object> SpecConverterLocalInstance = new 
ThreadLocal<Object>();
+
     /** When reading/writing specs, it checks whether there is a catalog item 
id set and uses it to load */
     public class SpecConverter extends ReflectionConverter {
         SpecConverter() {
@@ -454,25 +460,25 @@ public class XmlMementoSerializer<T> extends 
XmlSerializer<T> implements Memento
                 result.catalogItemId(catalogItemId);
                 return result;
             } finally {
-                instance = null;
+                SpecConverterLocalInstance.remove();
                 if (customLoaderSet) {
                     popXstreamCustomClassLoader();
                 }
             }
         }
 
-        Object instance;
-        
         @Override
         protected Object instantiateNewInstance(HierarchicalStreamReader 
reader, UnmarshallingContext context) {
             // the super calls getAttribute which requires that we have not 
yet done moveDown,
             // so we do this earlier and cache it for when we call 
super.unmarshal
+            Object instance = SpecConverterLocalInstance.get();
             if (instance==null)
                 throw new IllegalStateException("Instance should be created 
and cached");
             return instance;
         }
         protected void 
instantiateNewInstanceSettingCache(HierarchicalStreamReader reader, 
UnmarshallingContext context) {
-            instance = super.instantiateNewInstance(reader, context);
+            Object instance = super.instantiateNewInstance(reader, context);
+            SpecConverterLocalInstance.set(instance);
         }
     }
     

Reply via email to