Details
-
Bug
-
Status: Closed
-
Critical
-
Resolution: Fixed
-
JCR ContentLoader 2.1.2
-
None
Description
After deploying to a new quad-core system, we encountered a node loaded by one bundle which contained file contents from a different bundle and different path. After re-deployment, several bundles' content were missing altogether. The log contained messages like:
27.06.2011 13:10:18.387 ERROR [FelixStartLevel] org.apache.sling.jcr.contentloader.internal.ContentLoaderService bundleChanged: Problem loading initial content of bundle org.sakaiproject.nakamura.org.sakaiproject.nakamura.uxloader-myberkeley (8) java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at java.util.Stack.pop(Stack.java:84)
at org.apache.sling.jcr.contentloader.internal.DefaultContentCreator.finishNode(DefaultContentCreator.java:470)
at org.apache.sling.jcr.contentloader.internal.Loader.createFile(Loader.java:603)
at org.apache.sling.jcr.contentloader.internal.Loader.handleFile(Loader.java:483)
at org.apache.sling.jcr.contentloader.internal.Loader.installFromPath(Loader.java:425)
at org.apache.sling.jcr.contentloader.internal.Loader.installFromPath(Loader.java:420)
at org.apache.sling.jcr.contentloader.internal.Loader.installContent(Loader.java:279)
at org.apache.sling.jcr.contentloader.internal.Loader.registerBundleInternal(Loader.java:172)
at org.apache.sling.jcr.contentloader.internal.Loader.registerBundle(Loader.java:103)
at org.apache.sling.jcr.contentloader.internal.ContentLoaderService.bundleChanged(ContentLoaderService.java:148)
and
27.06.2011 10:42:22.986 ERROR [FelixDispatchQueue] org.apache.sling.jcr.contentloader.internal.Loader Cannot load initial content for bundle org.sakaiproject.nakamura.user : Single-valued property can not be set to an array of values:property /var/notifications/search/sakai:propertyprovider javax.jcr.ValueFormatException: Single-valued property can not be set to an array of values:property /var/notifications/search/sakai:propertyprovider
at org.apache.jackrabbit.core.PropertyImpl.checkSetValue(PropertyImpl.java:230)
at org.apache.jackrabbit.core.PropertyImpl.setValue(PropertyImpl.java:690)
at org.apache.jackrabbit.core.NodeImpl.setProperty(NodeImpl.java:2413)
at org.apache.jackrabbit.core.NodeImpl.setProperty(NodeImpl.java:1555)
at org.apache.jackrabbit.core.NodeImpl.setProperty(NodeImpl.java:2134)
at org.apache.jackrabbit.core.NodeImpl.setProperty(NodeImpl.java:2156)
at org.apache.sling.jcr.contentloader.internal.DefaultContentCreator.createProperty(DefaultContentCreator.java:416)
at org.apache.sling.jcr.contentloader.internal.readers.JsonReader.createProperty(JsonReader.java:218)
at org.apache.sling.jcr.contentloader.internal.readers.JsonReader.createNode(JsonReader.java:199)
at org.apache.sling.jcr.contentloader.internal.readers.JsonReader.parse(JsonReader.java:159)
at org.apache.sling.jcr.contentloader.internal.readers.JsonReader.parse(JsonReader.java:140)
at org.apache.sling.jcr.contentloader.internal.Loader.createNode(Loader.java:543)
at org.apache.sling.jcr.contentloader.internal.Loader.handleFile(Loader.java:470)
at org.apache.sling.jcr.contentloader.internal.Loader.installFromPath(Loader.java:425)
at org.apache.sling.jcr.contentloader.internal.Loader.installFromPath(Loader.java:420)
at org.apache.sling.jcr.contentloader.internal.Loader.installFromPath(Loader.java:420)
at org.apache.sling.jcr.contentloader.internal.Loader.installContent(Loader.java:279)
at org.apache.sling.jcr.contentloader.internal.Loader.registerBundleInternal(Loader.java:172)
at org.apache.sling.jcr.contentloader.internal.Loader.registerBundle(Loader.java:103)
at org.apache.sling.jcr.contentloader.internal.ContentLoaderService.activate(ContentLoaderService.java:268)
The DefaultContentCreator object is written to be used by a single thread. However, the Loader class stores it as an instance variable, and in turn the ContentLoaderService stores the Loader as an instance variable. Apparently the coder assumed that a SynchronousBundleListener is effectively single-threaded. That assumption is wrong:
'Synchronous listeners get called "synchronously" on the same thread which caused the event to occur. If two threads are performing actions which cause bundle events to occur then synchronous listeners will be called (potentially at the same "time") from the different threads which are causing the events to occur. Bottom line, synchronous bundle listeners must be thread safe.'