Uploaded image for project: 'Tapestry'
  1. Tapestry
  2. TAPESTRY-1422

Thread safety bug when creating pages with @Asset annotations

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 4.1.1
    • 4.1.7
    • Annotations
    • None
    • Windows, JDK 1.5, Tomcat 6.0.x

    Description

      I have a thread safety bug in Tapestry when using the Annotations.

      PageSpecificationResolverImpl is a threaded service, but its Namespace objects are not; they're provided by the singleton tapestry.parse.SpecificationSource.

      A problem arises when two threads are building the same page at the same time. They create two ComponentSpecification objects for the page, but only ONE Of those is changed (due to processing the annotations) when the ComponentConstructor is being created by ComponentConstructorFactoryImpl. The two PageSpecificationResolverImpl's attempt to install() both of them, and sometimes, the wrong one pushes the good one out of the Namespace's page map.

      I have a sleazy partial fix that works for our application for now, but it's not a true fix. I currently let the two PageSpecificationResolvers build up two parallel copies of the Page's specification, but down in the install() method, make a thread-safe decision not to add one if there's one already in there, and moreso, to grab that first one back out of the Namespace.

      It's a poor solution, but it gets me past my jMeter tests. In reality, The second thread should just wait for the first thread to finish constructing the page, or Tapestry needs a different way of managing the side-effects of processing annotations that have to add stuff to ComponentSpecifications.

      Here's what I did in PageSpecificationResolverImpl.install(), but it's not a real fix (order of thread execution could still cause the broken behavior, though this is currently working for me):

      private void install()
      {
      INamespace namespace = getNamespace();
      IComponentSpecification specification = getSpecification();

      if (_log.isDebugEnabled())
      _log.debug(ResolverMessages.installingPage(_simpleName, namespace,
      specification));

      synchronized(namespace)
      {
      if( !namespace.containsPage(_simpleName) )

      { namespace.installPageSpecification(_simpleName, specification); }

      else

      { setSpecification(namespace.getPageSpecification(_simpleName)); }

      }
      }

      Attachments

        Activity

          People

            Unassigned Unassigned
            jonmcsj Jon McCarty
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated: