Re: @SessionState Bug?
Hi everybody, To partially address the concerns raised, and following Pierce's suggestion (and using many of his words), I have updated this page in the User Guide to help make it clearer what the pitfalls and decision points are for using @SessionState and @SessionAttribute: http://tapestry.apache.org/session-storage.html Let me know if I didn't capture everything or if anything isn't clear. On Thu, Jan 6, 2011 at 7:48 PM, Pierce Wetter pie...@paceap.com wrote: I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? This is ultimately a _documentation_ error. (If we ignore the problem with generics for the moment.) That is, the real problem is that the docs for @SessionState/@SessionAttribute really need to discuss the tradeoffs, and the documentation for @SessionState should say in big giant bold letters DO NOT USE THIS FOR SIMPLE VARIABLES. BUILD A CUSTOM CLASS OR USE @SessionAttribute. Similarly, the documentation for @SessionAttribute should say: DO NOT USE A SIMPLE NAME. Qualify the name with some sort of package, i.e. instead of 'user' use: com.yourcompany.User Sample paragraphs to be inserted: For both of these annotations, you are essentially creating global data that will have to be serialized/deserialized/distributed and so on, because its stored in the servlet session. As with all global data, there is the possibility of collisions, not just with your app but with other Frameworks. For that reason, DO NOT USE @SessionState FOR SIMPLE VARIABLES. It is worth taking the time to build a class to hold this information, because it will force you to consolidate that information into a single, logical unit. Over time, you'll be glad you did. That's why @SessionState is the older, and more traditional way to do this, because it forces you to build such an object. That said, there are times when you just want to store a single string, etc. In this instance, you can use @SessionAttribute. But you should qualify the name with some sort of package, again so you don't have collisions. That is, don't use 'username', use 'com.mycompany.username'. DO NOT USE A SIMPLE NAME. When deciding between the two, it's best to use SessionState for complex objects, and SessionAttribute for simple types. If you use SessionState for complex objects, you will be immune to any typos in the variable name because the compiler will check for you. For SessionAttribute, its best to define a constant, and use that rather then defaulting to the instance variable name, because otherwise, you could have a subtle runtime error due to a typo. Pierce Pierce - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do is give a warning at List strings2 = strings because you're doing some potentially type unsafe things. On Thu, Jan 6, 2011 at 9:38 AM, Michael Gentry mgen...@masslight.netwrote: Hi everyone, Given the following page class: public class Bug { @Inject private Logger log; @SessionState(create=false) private ListBoolean booleans; @SessionState(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
Tapestry will treat the two as the exact same SessionState since they both are java.util.List - the Boolean/String type parameters will not help differentiate between the two. It is possible to get around this by changing one of them to Collection/Iterable/ArrayList/etc so that they use two distinct types: @SessionState(create=false) private ListBoolean booleans; @SessionState(create=false) private CollectionString strings; but I wouldn't recommend that since it's easy to mix them up and have them reversed in some other page class. I believe Josh Canfield has been working on better generics support for Tapestry 5.3, it's possible that his improvements cover this particular case so that it works as you expect. On Thu, 06 Jan 2011 15:38:21 +0100, Michael Gentry mgen...@masslight.net wrote: Hi everyone, Given the following page class: public class Bug { @Inject private Logger log; @SessionState(create=false) private ListBoolean booleans; @SessionState(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do is give a warning at List strings2 = strings because you're doing some potentially type unsafe things. On Thu, Jan 6, 2011 at 9:38 AM, Michael Gentry mgen...@masslight.netwrote: Hi everyone, Given the following page class: public class Bug { �...@inject private Logger log; �...@sessionstate(create=false) private ListBoolean booleans; �...@sessionstate(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
The reason why they're both considered the same: this has to do with how generics work in Java. I'm building in better generics support for 5.3, this seems like something I can make work. All of the generic information is available for fields, methods, and method parameters via reflection. Luckily most everything Tapestry needs to do is acting on things that are compiled in to the class! Currently the current 5.3 codebase has support for generic components, and the Loop has been updated to pull the type information for the value from the bound source parameter. If you have a ListPerson then you can access the properties of Person; @Property private ListPerson personSource; t:loop t:id=personLoop source=personSource div id=person_${personLoop.index}${personLoop.value.name}/div /t:loop Next on my list is generic services (@Inject GenericDAOPerson personDao;) it's implemented but working through tests/use cases. I'll add @Persist. Josh On Jan 6, 2011 6:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do is give a warning at List strings2 = strings because you're doing some potentially type unsafe things. On Thu, Jan 6, 2011 at 9:38 AM, Michael Gentry mgen...@masslight.net wrote: Hi everyone, Given the following page class: public class Bug { @Inject private Logger log; @SessionState(create=false) private ListBoolean booleans; @SessionState(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
On Thu, 06 Jan 2011 13:09:43 -0200, Michael Gentry mgen...@masslight.net wrote: Hi Donny, Hi! Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: You're not correct. All @SessionState fields of a given type are mapped to the same HttpSession attribute, so the behaviour you're experiencing is exactly the expected, documented one. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
Ah that's the problem then. You're expecting them to be assigned based on the name of the variable, but @SessionState assigns them based on their type. You could have in page1: @SessionState private String username; In page 2: @SessionState private String email; And they would be assigned to the same thing, because it's done based on the type rather than the variable name. I see how this would be confusing though - it does seem intuitive that they would be assigned based on the variable name. On Thu, Jan 6, 2011 at 10:09 AM, Michael Gentry mgen...@masslight.netwrote: Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do is give a warning at List strings2 = strings because you're doing some potentially type unsafe things. On Thu, Jan 6, 2011 at 9:38 AM, Michael Gentry mgen...@masslight.net wrote: Hi everyone, Given the following page class: public class Bug { @Inject private Logger log; @SessionState(create=false) private ListBoolean booleans; @SessionState(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
On Thu, 06 Jan 2011 13:14:09 -0200, Josh Canfield joshcanfi...@gmail.com wrote: Next on my list is generic services (@Inject GenericDAOPerson personDao;) it's implemented but working through tests/use cases. I'll add @Persist. Shouldn't it be @SessionState? ;) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
yeah, typing too fast, kids running around my legs getting into stuff! :) On Thu, Jan 6, 2011 at 7:17 AM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 13:14:09 -0200, Josh Canfield joshcanfi...@gmail.com wrote: Next on my list is generic services (@Inject GenericDAOPerson personDao;) it's implemented but working through tests/use cases. I'll add @Persist. Shouldn't it be @SessionState? ;) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. You did assign them to the same thing, you just didn't know it. You told tapestry to store the value of type List pulled from the session into your attribute, twice. Imagine you put in your constructor: list1 = getFieldFromSession(List) list2 = getFieldFromSession(List) the name of the attribute is based on the type. On Thu, Jan 6, 2011 at 7:09 AM, Michael Gentry mgen...@masslight.net wrote: Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do is give a warning at List strings2 = strings because you're doing some potentially type unsafe things. On Thu, Jan 6, 2011 at 9:38 AM, Michael Gentry mgen...@masslight.netwrote: Hi everyone, Given the following page class: public class Bug { �...@inject private Logger log; �...@sessionstate(create=false) private ListBoolean booleans; �...@sessionstate(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
On Thu, Jan 6, 2011 at 10:14 AM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 13:09:43 -0200, Michael Gentry mgen...@masslight.net Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: You're not correct. All @SessionState fields of a given type are mapped to the same HttpSession attribute, so the behaviour you're experiencing is exactly the expected, documented one. Hi Thiago, How does this even begin to make sense? If I have: @Property private ListString list1; @Property private ListString list2; Are they going to be the same lists, too? (They shouldn't -- I know I've had multiple ValueEncoders in the same page class and they persisted separately). I know I have variables like: private boolean cancelClicked; private boolean saveClicked; Java keeps those two separate. Why would @SessionState operate in an completely different manner? (OK, so maybe it is documented somewhere -- I did look, but didn't find it.) What if you have this? public class Page1 { @SessionState(create=false) private ListString strings; } public class Page2 { @SessionState(create=false) private ListString strings; } Are those two lists in two different pages going to be the same, too? This seems pretty confusing. :-) It seems like I just need a global HashMap somewhere and manage things by key. Thanks again, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi Donny, If you think a bit further, assigning the value based on the type is the only sensible way to do it. If the value was assigned based on the variable name, you would have to use that exact variable name in every component and page you want to use your SessionState-Object. That is extremely intrusive and surely not easy to maintain. And even if you were able to maintain that. What would you expect Tapestry to do in the following case? Component1 @SessionState private String eMailAddress; Component2 @SessionState private EmailAddress emailAddress; regards nillehammer - original Nachricht Betreff: Re: @SessionState Bug? Gesendet: Do, 06. Jan 2011 Von: Donny Nadolnydonny.nado...@gmail.com Ah that's the problem then. You're expecting them to be assigned based on the name of the variable, but @SessionState assigns them based on their type. You could have in page1: @SessionState private String username; In page 2: @SessionState private String email; And they would be assigned to the same thing, because it's done based on the type rather than the variable name. I see how this would be confusing though - it does seem intuitive that they would be assigned based on the variable name. On Thu, Jan 6, 2011 at 10:09 AM, Michael Gentry mgen...@masslight.netwrote: Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do is give a warning at List strings2 = strings because you're doing some potentially type unsafe things. On Thu, Jan 6, 2011 at 9:38 AM, Michael Gentry mgen...@masslight.net wrote: Hi everyone, Given the following page class: public class Bug { @Inject private Logger log; @SessionState(create=false) private ListBoolean booleans; @SessionState(create=false) private ListString strings; void onActivate() { log.debug(booleans = + booleans); log.debug(strings = + strings); if (booleans == null) booleans = new ArrayListBoolean(); booleans.add(Boolean.TRUE); log.debug(booleans: + booleans); log.debug(strings: + strings); log.debug(equal? + booleans.equals(strings)); } } I get this output: DEBUG 2011-01-06 09:35:24,014 booleans = null DEBUG 2011-01-06 09:35:24,014 strings = null DEBUG 2011-01-06 09:35:24,014 booleans: [true] DEBUG 2011-01-06 09:35:24,014 strings: [true] DEBUG 2011-01-06 09:35:24,015 equal? true Even though I don't add anything to the strings list or even allocate the strings list, it seems to be pointing to the booleans list, which is, of course, incorrect. This seems to be happening on both 5.1 and 5.2. Am I missing something? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e
Re: @SessionState Bug?
Hi Mike, I understand that the behavior seems a bit non-intuitive. It has to do with the fact that the @SessionState objects are global (ie not per-page) objects. The decision was made early on to base these solely on the type of the object, rather than on the name of the object. Usually, @SessionState objects are some unique, application-specific object (eg: a Visit object for T3/T4 users). I know you're also a cayenne user, so imagine: Page1.java: @SessionState private ObjectContext context; Page2.java @SessionState private ObjectContext objectContext; Assuming you're using the common paradigm of an ObjectContext-per-session, wouldn't you expect the context, stored in the session, to be the same in these two pages? @SessionState can be thought of as an easy way to map a page variable to an HttpSession-bound variable, based on teh type of the variable. It's a little more convoluted than that (or can be), but that sums up the typical use-case. Robert On Jan 6, 2011, at 1/69:55 AM , Michael Gentry wrote: On Thu, Jan 6, 2011 at 10:14 AM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 13:09:43 -0200, Michael Gentry mgen...@masslight.net Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: You're not correct. All @SessionState fields of a given type are mapped to the same HttpSession attribute, so the behaviour you're experiencing is exactly the expected, documented one. Hi Thiago, How does this even begin to make sense? If I have: @Property private ListString list1; @Property private ListString list2; Are they going to be the same lists, too? (They shouldn't -- I know I've had multiple ValueEncoders in the same page class and they persisted separately). I know I have variables like: private boolean cancelClicked; private boolean saveClicked; Java keeps those two separate. Why would @SessionState operate in an completely different manner? (OK, so maybe it is documented somewhere -- I did look, but didn't find it.) What if you have this? public class Page1 { @SessionState(create=false) private ListString strings; } public class Page2 { @SessionState(create=false) private ListString strings; } Are those two lists in two different pages going to be the same, too? This seems pretty confusing. :-) It seems like I just need a global HashMap somewhere and manage things by key. Thanks again, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi Nille, I don't think it's the only way to do it. Determining it based on the variable name (or maybe name/type pair) would work. It would just have a different set of problems. Based on types, the problems are that you get unintuitive results, especially with generics - it's not clear just from a brief description of the feature, eg values are assigned based on the type, which way it will behave (are types with different generic arguments different or the same? right now they're considered the same type, but it was mentioned earlier in this thread that it's going to change). Also, whoever implements it is going to have to decide how it works when the types are different but compatible. Should ListObject automatically get assigned if there's a ListString there? How about just List? With it based on name/type pair, it's clear how it would work in the case you gave - they would be different values because even though they have the same name (ignoring case), they have different types. The disadvantage is with refactoring, and being forced to use the same name if you want to get the same object (although I don't think that's too much of a downside, especially if you could give an override name, like it's done with @InjectComponent - by default it uses the variable name to link it, but you can pass a name if you want to name them differently). Doing it by name essentially creates the equivalent of global variables - but in a way that makes more sense, because that's what session state is: a global variables in your application. On Thu, Jan 6, 2011 at 10:56 AM, nille hammer tapestry.nilleham...@winfonet.eu wrote: Hi Donny, If you think a bit further, assigning the value based on the type is the only sensible way to do it. If the value was assigned based on the variable name, you would have to use that exact variable name in every component and page you want to use your SessionState-Object. That is extremely intrusive and surely not easy to maintain. And even if you were able to maintain that. What would you expect Tapestry to do in the following case? Component1 @SessionState private String eMailAddress; Component2 @SessionState private EmailAddress emailAddress; regards nillehammer - original Nachricht Betreff: Re: @SessionState Bug? Gesendet: Do, 06. Jan 2011 Von: Donny Nadolnydonny.nado...@gmail.com Ah that's the problem then. You're expecting them to be assigned based on the name of the variable, but @SessionState assigns them based on their type. You could have in page1: @SessionState private String username; In page 2: @SessionState private String email; And they would be assigned to the same thing, because it's done based on the type rather than the variable name. I see how this would be confusing though - it does seem intuitive that they would be assigned based on the variable name. On Thu, Jan 6, 2011 at 10:09 AM, Michael Gentry mgen...@masslight.netwrote: Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString, but it doesn't because at runtime it doesn't do any checks, or even know that you put String there (well, there's certain ways of figuring it out, but generally just accept that it doesn't know). All it can do
Re: Re: @SessionState Bug?
One other point - part of the downside of the current way could be avoided with error messages. You should probably get a warning if you have two @SessionState variables in your page that map to the same session variable, because it's unlikely that's what you actually intended to do. On Thu, Jan 6, 2011 at 11:42 AM, Donny Nadolny donny.nado...@gmail.comwrote: Hi Nille, I don't think it's the only way to do it. Determining it based on the variable name (or maybe name/type pair) would work. It would just have a different set of problems. Based on types, the problems are that you get unintuitive results, especially with generics - it's not clear just from a brief description of the feature, eg values are assigned based on the type, which way it will behave (are types with different generic arguments different or the same? right now they're considered the same type, but it was mentioned earlier in this thread that it's going to change). Also, whoever implements it is going to have to decide how it works when the types are different but compatible. Should ListObject automatically get assigned if there's a ListString there? How about just List? With it based on name/type pair, it's clear how it would work in the case you gave - they would be different values because even though they have the same name (ignoring case), they have different types. The disadvantage is with refactoring, and being forced to use the same name if you want to get the same object (although I don't think that's too much of a downside, especially if you could give an override name, like it's done with @InjectComponent - by default it uses the variable name to link it, but you can pass a name if you want to name them differently). Doing it by name essentially creates the equivalent of global variables - but in a way that makes more sense, because that's what session state is: a global variables in your application. On Thu, Jan 6, 2011 at 10:56 AM, nille hammer tapestry.nilleham...@winfonet.eu wrote: Hi Donny, If you think a bit further, assigning the value based on the type is the only sensible way to do it. If the value was assigned based on the variable name, you would have to use that exact variable name in every component and page you want to use your SessionState-Object. That is extremely intrusive and surely not easy to maintain. And even if you were able to maintain that. What would you expect Tapestry to do in the following case? Component1 @SessionState private String eMailAddress; Component2 @SessionState private EmailAddress emailAddress; regards nillehammer - original Nachricht Betreff: Re: @SessionState Bug? Gesendet: Do, 06. Jan 2011 Von: Donny Nadolnydonny.nado...@gmail.com Ah that's the problem then. You're expecting them to be assigned based on the name of the variable, but @SessionState assigns them based on their type. You could have in page1: @SessionState private String username; In page 2: @SessionState private String email; And they would be assigned to the same thing, because it's done based on the type rather than the variable name. I see how this would be confusing though - it does seem intuitive that they would be assigned based on the variable name. On Thu, Jan 6, 2011 at 10:09 AM, Michael Gentry mgen...@masslight.netwrote: Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException
Re: @SessionState Bug?
Hi Robert, I understand what it is doing now, but still find it non-intuitive. I think part of this goes back to the whole POJO subclasses-are-evil debate. In my use case, I had an abstract wizard page that had a lot of concrete subclasses that needed to share data on multiple pages (@Persist doesn't work in this case, because it persists on the concrete subclass rather than being shared -- even when defined in the superclass). In my view of the world, this should all inherit (I'm old-school). However, even if it is a global session-based variable, I'd expect it to be isolated by a key (defaulting to the variable name, perhaps) and not a type so that if you wanted to use different variable names, you'd have: Page1.java: @SessionState(key=Constants.SESSION_OBJECT_CONTEXT) private ObjectContext context; Page2.java @SessionState(key=Constants.SESSION_OBJECT_CONTEXT) private ObjectContext objectContext; Leave out the key, and you get two session state variables by different names. Just my opinion, of course. :-) Thanks, mrg On Thu, Jan 6, 2011 at 11:03 AM, Robert Zeigler robert.zeig...@roxanemy.com wrote: Hi Mike, I understand that the behavior seems a bit non-intuitive. It has to do with the fact that the @SessionState objects are global (ie not per-page) objects. The decision was made early on to base these solely on the type of the object, rather than on the name of the object. Usually, @SessionState objects are some unique, application-specific object (eg: a Visit object for T3/T4 users). I know you're also a cayenne user, so imagine: Page1.java: @SessionState private ObjectContext context; Page2.java @SessionState private ObjectContext objectContext; Assuming you're using the common paradigm of an ObjectContext-per-session, wouldn't you expect the context, stored in the session, to be the same in these two pages? @SessionState can be thought of as an easy way to map a page variable to an HttpSession-bound variable, based on teh type of the variable. It's a little more convoluted than that (or can be), but that sums up the typical use-case. Robert On Jan 6, 2011, at 1/69:55 AM , Michael Gentry wrote: On Thu, Jan 6, 2011 at 10:14 AM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 13:09:43 -0200, Michael Gentry mgen...@masslight.net Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: You're not correct. All @SessionState fields of a given type are mapped to the same HttpSession attribute, so the behaviour you're experiencing is exactly the expected, documented one. Hi Thiago, How does this even begin to make sense? If I have: @Property private ListString list1; @Property private ListString list2; Are they going to be the same lists, too? (They shouldn't -- I know I've had multiple ValueEncoders in the same page class and they persisted separately). I know I have variables like: private boolean cancelClicked; private boolean saveClicked; Java keeps those two separate. Why would @SessionState operate in an completely different manner? (OK, so maybe it is documented somewhere -- I did look, but didn't find it.) What if you have this? public class Page1 { �...@sessionstate(create=false) private ListString strings; } public class Page2 { �...@sessionstate(create=false) private ListString strings; } Are those two lists in two different pages going to be the same, too? This seems pretty confusing. :-) It seems like I just need a global HashMap somewhere and manage things by key. Thanks again, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
On Thu, 06 Jan 2011 14:42:09 -0200, Donny Nadolny donny.nado...@gmail.com wrote: Hi Nille, Hi, guys! I don't think it's the only way to do it. Determining it based on the variable name (or maybe name/type pair) would work. It would just have a different set of problems. Don't forget that @SessionState can't change its implementation details without breaking almost every single application out there. And you always have the option of creating your own annotation and corresponding ComponentClassTransformer. Also, whoever implements it is going to have to decide how it works when the types are different but compatible. Should ListObject automatically get assigned if there's a ListString there? How about just List? I think that, in this case, it should be considered different types. Anyway, I'd suggest everyone to create a class to hold this list instead. With it based on name/type pair, it's clear how it would work in the case you gave - This is not an option due to backward compatibility. Doing it by name essentially creates the equivalent of global variables - but in a way that makes more sense, because that's what session state is: a global variables in your application. This could be easily implemented as a different annotation. And yes, I agree the session is a kind of global variable, but user-scoped. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... On Thu, Jan 6, 2011 at 8:42 AM, Donny Nadolny donny.nado...@gmail.com wrote: Hi Nille, I don't think it's the only way to do it. Determining it based on the variable name (or maybe name/type pair) would work. It would just have a different set of problems. Based on types, the problems are that you get unintuitive results, especially with generics - it's not clear just from a brief description of the feature, eg values are assigned based on the type, which way it will behave (are types with different generic arguments different or the same? right now they're considered the same type, but it was mentioned earlier in this thread that it's going to change). Also, whoever implements it is going to have to decide how it works when the types are different but compatible. Should ListObject automatically get assigned if there's a ListString there? How about just List? With it based on name/type pair, it's clear how it would work in the case you gave - they would be different values because even though they have the same name (ignoring case), they have different types. The disadvantage is with refactoring, and being forced to use the same name if you want to get the same object (although I don't think that's too much of a downside, especially if you could give an override name, like it's done with @InjectComponent - by default it uses the variable name to link it, but you can pass a name if you want to name them differently). Doing it by name essentially creates the equivalent of global variables - but in a way that makes more sense, because that's what session state is: a global variables in your application. On Thu, Jan 6, 2011 at 10:56 AM, nille hammer tapestry.nilleham...@winfonet.eu wrote: Hi Donny, If you think a bit further, assigning the value based on the type is the only sensible way to do it. If the value was assigned based on the variable name, you would have to use that exact variable name in every component and page you want to use your SessionState-Object. That is extremely intrusive and surely not easy to maintain. And even if you were able to maintain that. What would you expect Tapestry to do in the following case? Component1 @SessionState private String eMailAddress; Component2 @SessionState private EmailAddress emailAddress; regards nillehammer - original Nachricht Betreff: Re: @SessionState Bug? Gesendet: Do, 06. Jan 2011 Von: Donny Nadolnydonny.nado...@gmail.com Ah that's the problem then. You're expecting them to be assigned based on the name of the variable, but @SessionState assigns them based on their type. You could have in page1: @SessionState private String username; In page 2: @SessionState private String email; And they would be assigned to the same thing, because it's done based on the type rather than the variable name. I see how this would be confusing though - it does seem intuitive that they would be assigned based on the variable name. On Thu, Jan 6, 2011 at 10:09 AM, Michael Gentry mgen...@masslight.netwrote: Hi Donny, Thanks for the explanation, but the types might be a red herring. I'm less concerned about that than the fact that Tapestry seems to be assigning one of my variables to a different variable. It doesn't matter if the types are the same or different. I could've had: @SessionState(create=false) private ListString list1; @SessionState(create=false) private ListString list2; And I'd still expect to have two separate/distinct variables and lists, not two variables pointing to the same list (unless I specifically assigned them to the same list myself). Thanks, mrg On Thu, Jan 6, 2011 at 9:57 AM, Donny Nadolny donny.nado...@gmail.com wrote: Your two lists are the same - they're both of type List so they both get assigned to the same thing. See below for why. The solution is to make two classes, one that holds the booleans, and one that holds the strings. Technically you would only need to do that for one, but it's probably a good idea to do it for both anyway. The reason why they're both considered the same: this has to do with how generics work in Java. It's called type erasure - after the class is compiled, the generic type is erased, so at runtime it doesn't care what the type is. Generics are a compile time check. For example, you could do: ListString strings = new ArrayListString(); List strings2 = strings; strings2.add(new Object()); //this line is fine String string = strings.get(0); //throws ClassCastException You might think that the strings2.add(new Object()) would have a problem because strings2 is pointing to strings which is an ArrayListString
Re: Re: @SessionState Bug?
Hi Thiago, Absolutely, I agree - @SessionState can't be changed to be based on name. I was just arguing that handling session state based on name is an alternate solution, just they both solutions have a set of problems. On Thu, Jan 6, 2011 at 11:53 AM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 14:42:09 -0200, Donny Nadolny donny.nado...@gmail.com wrote: Hi Nille, Hi, guys! I don't think it's the only way to do it. Determining it based on the variable name (or maybe name/type pair) would work. It would just have a different set of problems. Don't forget that @SessionState can't change its implementation details without breaking almost every single application out there. And you always have the option of creating your own annotation and corresponding ComponentClassTransformer. Also, whoever implements it is going to have to decide how it works when the types are different but compatible. Should ListObject automatically get assigned if there's a ListString there? How about just List? I think that, in this case, it should be considered different types. Anyway, I'd suggest everyone to create a class to hold this list instead. With it based on name/type pair, it's clear how it would work in the case you gave - This is not an option due to backward compatibility. Doing it by name essentially creates the equivalent of global variables - but in a way that makes more sense, because that's what session state is: a global variables in your application. This could be easily implemented as a different annotation. And yes, I agree the session is a kind of global variable, but user-scoped. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, SessionAttribute sounds much more promising to me. Thanks for the tip! mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
On Thu, 06 Jan 2011 14:56:00 -0200, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Ooops, I missed that. Thanks Josh! -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
You could still have the problem of someone using @SessionAttribute and giving the variable the same name as some other session variable. I might take it one step further - declare a single class/enum with the names of all of your session variables, and *always* use the name parameter for @SessionAttribute. With this way, you can easily check who else is using the same session variable. It's ugly to have all these names that are for different pages/components all in one class, but it just mirrors the fact that you have global variables. Now that I think about it, there are potential conflicts with component libraries. A component could declare a @SessionAttribute with a certain name, and you just happen to use the same name in your application (or worse - a component library uses the same name as another component library). Maybe SessionAttribute names should be scoped by default somehow, by library/project name? In such a way that you could still access a different namespace's session variables if necessary. Or, a backwards compatible solution is just to make it common practice for session variable names to be prefixed with the project/library name to prevent these conflicts. On Thu, Jan 6, 2011 at 2:21 PM, Michael Gentry mgen...@masslight.netwrote: On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Michael, @SessionState will not be deprecated. I guess you are missing the use case for this very useful annotation. Some examples are a logged in user or a shopping basket. Usually you have only one instance of such an object in your app, so it is absolutely fine to same only one instance per app. Regards On Thu, Jan 6, 2011 at 8:21 PM, Michael Gentry mgen...@masslight.netwrote: On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org -- Best regards, Igor Drobiazko http://tapestry5.de
Re: Re: @SessionState Bug?
On Thu, 06 Jan 2011 17:21:32 -0200, Michael Gentry mgen...@masslight.net wrote: I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. I'm completely against. @SessionState has been used as it is since Tapetry 5 exists. I think @SessionAttribute is dangerous for almost the same arguments you use against @SessionState. One thing that I loved in Tapestry, coming from a Struts (argh!) background, was that @SessionState avoids the problem of having different parts of the code ending up using the same session attribute name for very different things (including storing different object types). @SessionState is type-safe, @SessionAttribute isn't (if one page stores a string in the user session attribute and then another one has a @SessionAttribute(user) private User user; field, unless you provided a CoercionTupleString, User, it will probably fail). Conclusion: what is a heaven for one can be a hell for another. :) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi Donny, I will always use the name attribute. Thanks, mrg On Thu, Jan 6, 2011 at 2:40 PM, Donny Nadolny donny.nado...@gmail.com wrote: You could still have the problem of someone using @SessionAttribute and giving the variable the same name as some other session variable. I might take it one step further - declare a single class/enum with the names of all of your session variables, and *always* use the name parameter for @SessionAttribute. With this way, you can easily check who else is using the same session variable. It's ugly to have all these names that are for different pages/components all in one class, but it just mirrors the fact that you have global variables. Now that I think about it, there are potential conflicts with component libraries. A component could declare a @SessionAttribute with a certain name, and you just happen to use the same name in your application (or worse - a component library uses the same name as another component library). Maybe SessionAttribute names should be scoped by default somehow, by library/project name? In such a way that you could still access a different namespace's session variables if necessary. Or, a backwards compatible solution is just to make it common practice for session variable names to be prefixed with the project/library name to prevent these conflicts. On Thu, Jan 6, 2011 at 2:21 PM, Michael Gentry mgen...@masslight.netwrote: On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi Igor, How am I missing the use case of doing something like: @SessionAttribute(value=Constants.USER) private User user; or @SessionAttribute(value=Constants.SHOPPING_CART) private ListShoppingCartItem shoppingCartItems; This does everything that @SessionState does, but gives you more control. Plus you can easily use a data type more than once. Thanks, mrg On Thu, Jan 6, 2011 at 2:41 PM, Igor Drobiazko igor.drobia...@gmail.com wrote: Michael, @SessionState will not be deprecated. I guess you are missing the use case for this very useful annotation. Some examples are a logged in user or a shopping basket. Usually you have only one instance of such an object in your app, so it is absolutely fine to same only one instance per app. Regards On Thu, Jan 6, 2011 at 8:21 PM, Michael Gentry mgen...@masslight.netwrote: On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org -- Best regards, Igor Drobiazko http://tapestry5.de - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi Thiago, You argue that @SessionState is type-safe, but it is data-dangerous. Is that a good trade-off? I personally want my data to be safe, too. :-) Also, If I do: @SessionAttribute(user) private String user; On something that was already set to be a User record (instead of a string), it'll blow up immediately with a class cast exception. (Or vice-versa.) That at least seems safer to me. Ideally I'd prefer something more safe, but that doesn't seem to be an option, currently. Also, I'm planning on using more verbose keys than user. That's just a convention, though, and not a guarantee of safety. Thanks! mrg On Thu, Jan 6, 2011 at 2:45 PM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 17:21:32 -0200, Michael Gentry mgen...@masslight.net wrote: I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. I'm completely against. @SessionState has been used as it is since Tapetry 5 exists. I think @SessionAttribute is dangerous for almost the same arguments you use against @SessionState. One thing that I loved in Tapestry, coming from a Struts (argh!) background, was that @SessionState avoids the problem of having different parts of the code ending up using the same session attribute name for very different things (including storing different object types). @SessionState is type-safe, @SessionAttribute isn't (if one page stores a string in the user session attribute and then another one has a @SessionAttribute(user) private User user; field, unless you provided a CoercionTupleString, User, it will probably fail). Conclusion: what is a heaven for one can be a hell for another. :) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
I'm with Igor. :) I've never used @SessionState for simple object types (List, Boolean, String, and the like). I've only ever used it for composite object types that will only ever have a single object per session (Visit, ShoppingCart, User, and that ilk). For that matter, in practice, I almost never use @SessionState. Instead, I usually have a service that interacts directly with ApplicationStateManager and hides the details (so my pages don't know anything about the current user, but they do know to ask the Authorization service whether the current thread/request can perform action xyz). I don't see myself using @SessionAttribute anytime soon, either, really. For sharing data across pages, I really do tend to write small services. I find that in the large majority of cases, shared data also implies some form of shared functionality (eg: does the user have permission to do xyz?) and the service model fits better. At least it fits me better. :) Robert On Jan 6, 2011, at 1/62:13 PM , Michael Gentry wrote: Hi Igor, How am I missing the use case of doing something like: @SessionAttribute(value=Constants.USER) private User user; or @SessionAttribute(value=Constants.SHOPPING_CART) private ListShoppingCartItem shoppingCartItems; This does everything that @SessionState does, but gives you more control. Plus you can easily use a data type more than once. Thanks, mrg On Thu, Jan 6, 2011 at 2:41 PM, Igor Drobiazko igor.drobia...@gmail.com wrote: Michael, @SessionState will not be deprecated. I guess you are missing the use case for this very useful annotation. Some examples are a logged in user or a shopping basket. Usually you have only one instance of such an object in your app, so it is absolutely fine to same only one instance per app. Regards On Thu, Jan 6, 2011 at 8:21 PM, Michael Gentry mgen...@masslight.netwrote: On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org -- Best regards, Igor Drobiazko http://tapestry5.de - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi! As I said, in this case, what you consider dangerous I consider safe and vice-versa. Just different opinions. :) I agree that there's no completely safe option. Both have their pros and cons. And I don't consider @SessionState data-dangerous at all. I'd never use non-specific object types with it, though, such as collections, string or numbers, just classes belonging to the project being developed. On Thu, 06 Jan 2011 18:24:25 -0200, Michael Gentry mgen...@masslight.net wrote: Hi Thiago, You argue that @SessionState is type-safe, but it is data-dangerous. Is that a good trade-off? I personally want my data to be safe, too. :-) Also, If I do: @SessionAttribute(user) private String user; On something that was already set to be a User record (instead of a string), it'll blow up immediately with a class cast exception. (Or vice-versa.) That at least seems safer to me. Ideally I'd prefer something more safe, but that doesn't seem to be an option, currently. Also, I'm planning on using more verbose keys than user. That's just a convention, though, and not a guarantee of safety. Thanks! mrg On Thu, Jan 6, 2011 at 2:45 PM, Thiago H. de Paula Figueiredo thiag...@gmail.com wrote: On Thu, 06 Jan 2011 17:21:32 -0200, Michael Gentry mgen...@masslight.net wrote: I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. I'm completely against. @SessionState has been used as it is since Tapetry 5 exists. I think @SessionAttribute is dangerous for almost the same arguments you use against @SessionState. One thing that I loved in Tapestry, coming from a Struts (argh!) background, was that @SessionState avoids the problem of having different parts of the code ending up using the same session attribute name for very different things (including storing different object types). @SessionState is type-safe, @SessionAttribute isn't (if one page stores a string in the user session attribute and then another one has a @SessionAttribute(user) private User user; field, unless you provided a CoercionTupleString, User, it will probably fail). Conclusion: what is a heaven for one can be a hell for another. :) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. Consultor, desenvolvedor e instrutor em Java, Tapestry e Hibernate Coordenador e professor da Especialização em Engenharia de Software com Ênfase em Java da Faculdade Pitágoras http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
Hi Thiago, I meant to mention that I don't consider @SessionState has been used as it is since Tapetry 5 exists. to be a very good reason/excuse because @IncludeJavaScriptLibrary and @IncludeStylesheet are now deprecated. Things sometimes change (and hopefully for the better). :-) Cheers, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
On Thu, Jan 6, 2011 at 9:13 PM, Michael Gentry mgen...@masslight.netwrote: Hi Igor, This does everything that @SessionState does, but gives you more control. Plus you can easily use a data type more than once. Nope, with @SessionState you have auto-building of SSOs and co-called accompany-fields to check the existence of the SSO. You have ApplicationStateManager which gives you the power over your SSOs. And you don't have to repeat yourself as you don't have to provide the session key every time you use the annotation. In fact, you don't even need the session for SSOs as you can change the persistent strategy. Furthermore, if your SSO is a Hibernate entity only its primary key is persisted into the session, not the entire object. This ensures a lean HTTP session usage. All this is not possible with @SessionAttribute. Convinced? -- Best regards, Igor Drobiazko http://tapestry5.de
Re: Re: @SessionState Bug?
On Thu, 06 Jan 2011 19:40:31 -0200, Michael Gentry mgen...@masslight.net wrote: Hi Thiago, Hi, Michael! I meant to mention that I don't consider @SessionState has been used as it is since Tapetry 5 exists. to be a very good reason/excuse because @IncludeJavaScriptLibrary and @IncludeStylesheet are now deprecated. I don't think this is the same situation, as internally there have been some internal changes to the JavaScript support, including the JS stacks. My argument was that you're maybe the first to complain/dislike the @SessionState behaviour since Tapestry 5 was created. Most people, including the Tapestry team, are happy with @SessionState as it is implemented. Things sometimes change (and hopefully for the better). :-) Things do sometimes change, but this is a very sensitive issue for Tapestry. Great food for trolls (not you, of course). Some trolls still complain that T5 isn't compatible at all with T4, even after three years of T5 with minimum non-backward compatible changes. -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
I'm also opposed to deprecating @SessionState, for many of the reasons below. Perhaps you could build a CYASessionStateWorker that looks at @SessionState annotated fields and pukes if the type is outside of some package you specify. For instance, all of my @SessionState objects generally go in a state package as a sibling to pages, components etc. Josh On Thu, Jan 6, 2011 at 11:21 AM, Michael Gentry mgen...@masslight.net wrote: On Thu, Jan 6, 2011 at 11:56 AM, Josh Canfield joshcanfi...@gmail.com wrote: In 5.2 there is SessionAttribute which pulls the value from the session by name, defaulting to the name of the field... Hi Josh, @SessionAttribute is working great so far. Thanks again for the tip. For discussion by others (if desired): I'm going to banish @SessionState from our application soon -- it is far too dangerous. Imagine you have a large application and you don't know every single detail on every page/component/mixin/service. The fact that it it stores things by type instead of a more unique key means it is quite possible to add an @SessionState somewhere that conflicts with another somewhere and never know it. You are testing your little piece of the application and it works fine and it isn't until some later point (maybe even after deployed) that the application starts breaking randomly as other parts of the code are used/tested. To give an example of what I mean by a large application, I just ran this: find . -name *.tml -print | wc -l 323 It is pretty impossible to know what variables (let alone types) are declared over 300+ Tapestry 5 pages/components. This isn't even counting mixins or services. I was lucky that my conflict happened to be in the same page, but it easily could've been in one of the others and not noticed for some time. I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? Thanks, mrg - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: Re: @SessionState Bug?
On Thu, 06 Jan 2011 21:38:15 -0200, Josh Canfield joshcanfi...@gmail.com wrote: Perhaps you could build a CYASessionStateWorker that looks at @SessionState annotated fields and pukes if the type is outside of some package you specify. For instance, all of my @SessionState objects generally go in a state package as a sibling to pages, components etc. This gave me an idea: we could create a very pedantic mode or separate package that checks for things that are valid but not recommended (such as using @SessionState with String fields or initializing component fields with known mutable objects) and throws an exception if some offending code is found. This could include Josh's idea of checking for @SessionState fields which types are outside some configurable safe package (.sessionstate?). A little bit like a FindBugs for Tapestry. What do you think? :) -- Thiago H. de Paula Figueiredo Independent Java, Apache Tapestry 5 and Hibernate consultant, developer, and instructor Owner, Ars Machina Tecnologia da Informação Ltda. http://www.arsmachina.com.br - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
Re: @SessionState Bug?
I'd like to suggest that @SessionState be deprecated in favor of @SessionAttribute in the future. Thoughts? This is ultimately a _documentation_ error. (If we ignore the problem with generics for the moment.) That is, the real problem is that the docs for @SessionState/@SessionAttribute really need to discuss the tradeoffs, and the documentation for @SessionState should say in big giant bold letters DO NOT USE THIS FOR SIMPLE VARIABLES. BUILD A CUSTOM CLASS OR USE @SessionAttribute. Similarly, the documentation for @SessionAttribute should say: DO NOT USE A SIMPLE NAME. Qualify the name with some sort of package, i.e. instead of 'user' use: com.yourcompany.User Sample paragraphs to be inserted: For both of these annotations, you are essentially creating global data that will have to be serialized/deserialized/distributed and so on, because its stored in the servlet session. As with all global data, there is the possibility of collisions, not just with your app but with other Frameworks. For that reason, DO NOT USE @SessionState FOR SIMPLE VARIABLES. It is worth taking the time to build a class to hold this information, because it will force you to consolidate that information into a single, logical unit. Over time, you'll be glad you did. That's why @SessionState is the older, and more traditional way to do this, because it forces you to build such an object. That said, there are times when you just want to store a single string, etc. In this instance, you can use @SessionAttribute. But you should qualify the name with some sort of package, again so you don't have collisions. That is, don't use 'username', use 'com.mycompany.username'. DO NOT USE A SIMPLE NAME. When deciding between the two, it's best to use SessionState for complex objects, and SessionAttribute for simple types. If you use SessionState for complex objects, you will be immune to any typos in the variable name because the compiler will check for you. For SessionAttribute, its best to define a constant, and use that rather then defaulting to the instance variable name, because otherwise, you could have a subtle runtime error due to a typo. Pierce Pierce smime.p7s Description: S/MIME cryptographic signature