I'm beginning to think that we should simply check that the initialization of any field is an immutable value; we know what main JDK classes are immutable (String, Boolean, Number) and can have a service (combined with an @Immutable annotation) go further.
This is a recurring question on the list, but not one that fits into an FAQ meaningfully ... I think the framework needs to change. On Thu, May 5, 2011 at 5:35 AM, Thiago H. de Paula Figueiredo (JIRA) <[email protected]> wrote: > > [ > https://issues.apache.org/jira/browse/TAP5-1520?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel > ] > > Thiago H. de Paula Figueiredo closed TAP5-1520. > ----------------------------------------------- > > Resolution: Invalid > > Hi! > > The error here is in your code: you should never initialize a field with a > non-atomic value. An event handler like onActivate(), @BeginRender or some > event triggered by Form. > > Please post in the user mailing list before posting bugs. > > Cheers! > > Thiago > >> ConcurrentModificationException while modify unclaimed private collection >> from different Threads >> ------------------------------------------------------------------------------------------------ >> >> Key: TAP5-1520 >> URL: https://issues.apache.org/jira/browse/TAP5-1520 >> Project: Tapestry 5 >> Issue Type: Bug >> Components: tapestry-core >> Affects Versions: 5.2.5 >> Reporter: Maxim Ulanovskiy >> >> TestCase: create two parallel requests to the page bellow >> first request to read action - /TestConcurrency.read >> second request to write action - /TestConcurrency.write >> TestConcurrency.tml: >> ... >> <t:actionlink t:id="read">read</t:actionlink> >> <t:actionlink t:id="write">write</t:actionlink> >> ... >> public class TestConcurrency { >> private List<String> testDie = new ArrayList<String>(); >> >> public void onActivate() { >> for(int i=0; i<1000; i++) >> testDie.add("init"); >> } >> void onActionFromRead() { >> for(String s : testDie) >> System.out.println(s); >> } >> void onActionFromWrite() { >> for(int i=0; i<100000; i++) >> testDie.add("testDie"+i); >> } >> } >> From what I've found out with debugger is that direct access to List<String> >> testDie is replaced with UnclaimedFieldWorker.UnclaimedFieldConduit but >> when PerthreadManagerImpl is called it fails to find thread local value in >> internal map and returnes default value - the same object for both threads: >> public class PerthreadManagerImpl { >> <T> PerThreadValue<T> createValue(final Object key) >> { >> return new PerThreadValue<T>() >> { >> public T get() >> { >> return get(null); >> } >> public T get(T defaultValue) >> { >> Map map = getPerthreadMap(); >> // NO SUCH KEY IN map >> if (map.containsKey(key)) >> { >> Object storedValue = map.get(key); >> if (storedValue == NULL_VALUE) >> return null; >> return (T) storedValue; >> } >> return defaultValue; >> } > > -- > This message is automatically generated by JIRA. > For more information on JIRA, see: http://www.atlassian.com/software/jira > -- Howard M. Lewis Ship Creator of Apache Tapestry The source for Tapestry training, mentoring and support. Contact me to learn how I can get you up and productive in Tapestry fast! (971) 678-5210 http://howardlewisship.com --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
