0

If a page or component class has one instance field which is a non-synchronized object, f.ex. an ArrayList, and the application has code that structurally modifies this field, should the access to this field be synchronized ?

F.ex.:

public class MyPageOrComponent
{
    @Persist
    private List<String> myList;

    void setupRender()
    {
        if (this.myList == null)
        {
            this.myList = new ArrayList<>();
        }
    }

    void afterRender(MarkupWriter writer)
    {
        // Should this be synchronized ?

        if (someCondition)
        {
            this.myList.add(something);
        }
        else
        {
            this.myList.remove(something);
        }
    }
}

I'm asking because I seem to understand that Tapestry creates only one instance of a page or component class and it uses this instance for all the connected clients (but please correct me if this is not true).

SantiBailors
  • 1,596
  • 3
  • 21
  • 44

2 Answers2

1

In short the answer is no, you don't have to because Tapestry does this for you. Tapestry will transform your pages and classes for you at runtime in such a way that wherever you interact with your fields, they will not actually be working on the instance variable but on a managed variable that is thread safe. The full inner workings are beyond me, but a brief reference to the transformation can be found here.

One warning, don't instantiate your page/component variables at decleration. I have seen some strange behaviour around this. So don't do this:

private List<String> myList = new ArrayList<String>;
joostschouten
  • 3,863
  • 1
  • 18
  • 31
1

Tapestry uses some runtime byte code magic to transform your pages and components. Pages and components are singletons but the properties are transformed so that they are backed by a PerThreadValue. This means that each request gets it's own copy of the value so no synchronization is required.

As suggested by @joostschouten you should never initialize a mutable property in the field declaration. The strange behaviour he discusses is caused beacause this will be shared by all requests (since the initializer is only fired once for the page/component singleton). Mutable fields should instead be initialized in a render method (eg @SetupRender)

lance-java
  • 25,497
  • 4
  • 59
  • 101