Cached Annotation watch property seems to use '==' instead of 'equals'
I'm trying to use the '@Cached' annotation with a watch expression to cache results of methods in a form contained within a loop. For some watch expressions, I construct a string, so the code basically looks like @Cached(watch="watchKey") Object getData() { // return data; } String getWatchKey() { return a.toString() + ":" + b.toString(); } When I do this, though, the cached annotation does not seem to work properly, in that the 'getData()' method is called multiple times in a request. The problem seems to be that '==' is used instead of 'equals' in the code 'CachedWorker' generates to compare the result of the watch expression. Is this intentional, so we need to make sure the watch expression returns the exact same object if we want to use a cached value? Or should it be changed to use 'equals'? Doug - To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org
How should one create a mixin that can be used to optionally hide a component
We would like to implement a mixin 'IsVisible' that can be applied to an existing component to specify whether or not the component should be displayed. Basically, it should evaluate its parameter and 1) if false, it should skip all rendering phases of the component 2) if true, it should continue rendering the component normally This seems to be an ideal use for mixins, I can't seem to find a way to get it to work that conforms to the documentation at http://tapestry.apache.org/tapestry5/tapestry-core/guide/rendering.html. The naive implementation public class IsVisible { @Parameter(required = true) private boolean isVisible; @SetupRender boolean setupRender() { return isVisible; } } Works for the most part when returning 'false', but as of Tapestry 5.0.15 returning 'true' causes the component's 'setupRender' to be skipped. Changing the 'setupRender' signature to Boolean setupRender() and returning 'null' to continue instead of 'true' seemed to work, but the documentation doesn't indicate that this is allowed, so I wasn't sure that it is intended behavior and will be supported in the future. There is another slight problem when returning 'false', in that the component's 'cleanupRender' will be called even when its 'setupRender' was skipped (similar problem to what was reported in TAP5-126). This means that the 'IsVisible' cannot be applied to any component, only those whose 'cleanupRender' was implemented in such a way that it protects against 'setupRender' not having been called. This is one instance of a general problem with writing mixins that are intended to be applied to arbitrary components, in that if a forward phase is short-circuited by a mixin, that render phase method is not called for the component, but the corresponding reverse phase of the component is still called. Regards, Doug
RE: Changing the behavior of short-circuiting render phases (re: TAP5-128, TAP5-126)
Hi Kris, Thanks, I'll try reopening the issue. From your work on refactoring the code, do you think the changes that will be needed so solve the problem are reasonably isolated? Doug > -Original Message- > From: Kristian Marinkovic [mailto:[EMAIL PROTECTED] > Sent: Monday, November 17, 2008 1:28 AM > To: Tapestry users > Subject: Re: Changing the behavior of short-circuiting render phases > (re: TAP5-128, TAP5-126) > > hi doug, > > all we can do is to reopen the bug and vote for it ... :) > > > > i guess one of the reasons why this issue does not get resolved > is the added complexity to the page rendering. first because the > responsible class ComponentPageElementImpl is already very > complex (>1000 loc) and it would be necessary to add some state > information to the rendering process. currently the rendering is > completely stateless only relying on the static structure of the page. > > i've started to refactor ComponentPageElementImpl just to see > how it could be solved > > > > g, > kris > > > > > "Doug Hauge" <[EMAIL PROTECTED]> > 15.11.2008 01:57 > Bitte antworten an > "Tapestry users" > > > An > "Tapestry users" > Kopie > "Doug Hauge" <[EMAIL PROTECTED]>, "Adam Ayres" > <[EMAIL PROTECTED]>, "Matt Ayres" <[EMAIL PROTECTED]> > Thema > Changing the behavior of short-circuiting render phases (re: TAP5-128, > TAP5-126) > > > > > > > > > As of Tapestry 5.0.16 (after the fix for TAP5-128), we are now running > into > a problem related to that described in TAP5-126. You closed the TAP5- > 126 > issue > saying that the code was behaving as documented and designed, but it > seems > that this behavior leads to problems when trying to implement generic > mixins > that can safely be added to arbitrary components. I'd like to check > whether > there is any possibility of convincing you to change the behavior so > the > reverse phases of a component/mixin are only called if the positive > phase is > for the same component mixin (e.g. a component's cleanupRender is > called > if > and only if the component's setupRender was called). > > It also seems odd that returning 'true' will cause other methods within > the > same phase to be bypassed. There thus seems to be no way according to > the > documentation at > http://tapestry.apache.org/tapestry5/tapestry-core/guide/rendering.html > to design a mixin that will either short-circuit or continue rendering > as > if it didn't exist. The Tapestry code still seems to allow the behavior > we need by declaring the render phase method to return 'Boolean', and > return > 'null' instead of 'true' to continue processing. However, unless I am > missing > something obvious, this is not documented behavior, so it is not clear > that > I can rely on it continuing to work. > > The fundamental problem with the short-circuiting behavior as > documented > is > that if a mixin short-circuits a render phase by returning either true > or > false, any component that contains it must be carefully written so it > can > handle it. Consider a component > > class Component { > >void setupRender() {} > >void beginRender() {} > >void afterRender() {} > >void cleanupRender() {} > } > > Where 'setupRender' constructs some objects from the component > parameters, 'beginRender' begins > an HTML element, 'afterRender' closes the HTML element, and > 'cleanupRender' cleans up. > > And a mixin > > class Mixin { >Boolean setupRender() { ... } > >Boolean beforeRender() { ... } > >Boolean afterRender() { ... } > >Boolean cleanupRender() { ... } > } > > We are returning 'Boolean' here instead of 'boolean' so we have the > option of not short-circuiting > anything. If this is not considered supported, instead of returning > 'null' in the examples below > simply remove the render phase method from the mixin. > > 1) If 'Mixin.setupRender()' returns 'true', then > 'Component.cleanupRender()' is not called because > the phase is short-circuited, but 'Component.beginRender()' is called, > so 'Component.beginRender()' > would have to be written in such a way that it handles when > 'Component.setupRender()' is not called. > > 2) If 'Mixin.setupRender()' returns
Changing the behavior of short-circuiting render phases (re: TAP5-128, TAP5-126)
As of Tapestry 5.0.16 (after the fix for TAP5-128), we are now running into a problem related to that described in TAP5-126. You closed the TAP5-126 issue saying that the code was behaving as documented and designed, but it seems that this behavior leads to problems when trying to implement generic mixins that can safely be added to arbitrary components. I'd like to check whether there is any possibility of convincing you to change the behavior so the reverse phases of a component/mixin are only called if the positive phase is for the same component mixin (e.g. a component's cleanupRender is called if and only if the component's setupRender was called). It also seems odd that returning 'true' will cause other methods within the same phase to be bypassed. There thus seems to be no way according to the documentation at http://tapestry.apache.org/tapestry5/tapestry-core/guide/rendering.html to design a mixin that will either short-circuit or continue rendering as if it didn't exist. The Tapestry code still seems to allow the behavior we need by declaring the render phase method to return 'Boolean', and return 'null' instead of 'true' to continue processing. However, unless I am missing something obvious, this is not documented behavior, so it is not clear that I can rely on it continuing to work. The fundamental problem with the short-circuiting behavior as documented is that if a mixin short-circuits a render phase by returning either true or false, any component that contains it must be carefully written so it can handle it. Consider a component class Component { void setupRender() {} void beginRender() {} void afterRender() {} void cleanupRender() {} } Where 'setupRender' constructs some objects from the component parameters, 'beginRender' begins an HTML element, 'afterRender' closes the HTML element, and 'cleanupRender' cleans up. And a mixin class Mixin { Boolean setupRender() { ... } Boolean beforeRender() { ... } Boolean afterRender() { ... } Boolean cleanupRender() { ... } } We are returning 'Boolean' here instead of 'boolean' so we have the option of not short-circuiting anything. If this is not considered supported, instead of returning 'null' in the examples below simply remove the render phase method from the mixin. 1) If 'Mixin.setupRender()' returns 'true', then 'Component.cleanupRender()' is not called because the phase is short-circuited, but 'Component.beginRender()' is called, so 'Component.beginRender()' would have to be written in such a way that it handles when 'Component.setupRender()' is not called. 2) If 'Mixin.setupRender()' returns 'null', but 'Mixin.beforeRender()' returns 'false', then rendering is short-circuited to the after render phase and 'Component.beforeRender()' is not called. However, the 'Component.afterRender()' method is called, so it would have to be written in such a way that it handles The 'Component.beforeRender()' not being called, in this case it would have to create a property that records whether the HTML element was started, and only add an end tag if it was. Thus, in the most general case, each render phase in the component would have to be written assuming that any subset of its previous render phase methods may not have been called, which leads to overly complicated code. Doug - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: [T5] Localization
Passing parameters into the message formatter directly from HTML seems more natural than having to inject a 'Messages' interface into the page and add an accessor method for the message any time the number of format parameters is not 0. Doug > -Original Message- > From: Massimo Lusetti [mailto:[EMAIL PROTECTED] > Sent: Tuesday, August 28, 2007 2:32 PM > To: Tapestry users > Subject: Re: [T5] Localization > > On 8/28/07, Christoph Jaeger <[EMAIL PROTECTED]> wrote: > > > If not, does this seem difficult to implement? > > Using normal ResourceBundle features? And doing that inside javacode > where logic belongs? > > -- > Massimo > http://meridio.blogspot.com > > - > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > >> -Original Message- >> From: Christoph Jaeger [mailto:[EMAIL PROTECTED] >> Sent: Tuesday, August 28, 2007 2:13 PM >> To: users@tapestry.apache.org >> Subject: [T5] Localization >> >> Hi, >> >> is there a way to use messages with parameters directly from a HTML >> template? >> >> Something like: >> >> ${message:results,prop:numberOfDatasets} >> >> with >> >> Page.java >> >> ... >> public int getNumberOfDatasets() >> { >> return numberOfDatasets; >> } >> ... >> >> Page_en.properties: >> >> results: Found %d datasets. >> >> Page_de.properties: >> >> results: %d Datensätze gefunden. >> >> If not, does this seem difficult to implement? >> >> Thanks, >> >> Best Regards, >> >> Christoph Jäger >> >> - >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
T5: Tapestry message localization, java.util.Formatter vs. java.text.MessageFormat
Is there some reason Tapestry chose to use 'java.util.Formatter' style formatting as opposed to 'java.text.MessageFormat' style? The latter seems preferable for localization, primarily because it has the 'choice' format type. We would like to use the 'java.text.MessageFormat' style for our application, and are considering providing our own implementation of the 'MessageFormatter' service, but the question becomes how to use this formatting for only our messages. We have considered decorating the 'ComponentMessagesSource' service, but this would then apply to all component messages, including those for core components, which have some text properties that use 'java.util.Formatter' style formatting. We could override these messages as described in http://wiki.apache.org/tapestry/Tapestry5HowToOverrideTheDefaultErrorMes sageBanner, but that seems a bit brittle. Does anyone else have any need to use 'java.text.MessageFormat' style formatting, or are we the only ones? Do the solutions mentioned above sound reasonable? Thanks, Doug - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: T5: Changing locale within OnActivate event
I was afraid that would be the answer (I couldn't see any other way after looking at the code). I was wanting to avoid having to add duplicate redirection logic to each page, but I'll give it a try and see how it works. Thanks for the response. Doug > -Original Message- > From: Jesse Kuhnert [mailto:[EMAIL PROTECTED] > Sent: Tuesday, August 14, 2007 7:22 PM > To: Tapestry users > Subject: Re: T5: Changing locale within OnActivate event > > If it's anything like T4 you'll have to either do a redirect back to > the same page or whatever mechanism is in place to "make a page > active" somehow and have it do that to the same page. > > All the i18n stuff probably happens in the very beginning while > setting up the page/components/resources so it has to start over if > you want to change locales. I'm sure you know more than I do about > redirects/page activations in T5 though. > > On 8/14/07, Doug Hauge <[EMAIL PROTECTED]> wrote: > > In several of our pages, the default locale we want to use for > messages > > depends on its activation context. We tried updating the locale using > > 'ThreadLocale' from within the activate event handler, but it seems > that > > this is too late, for the page has already been loaded and all > messages > > in the template resolved using whatever locale was in effect at the > time > > of loading. Is there some way we can force the messages to be > reloaded > > after setting the thread locale in the activate event handler, or is > > there some point before the page is loaded at which we can access the > > page class and the activation context in order to set the locale? > > > > Thanks, > > Doug > > > > > > - > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > -- > Jesse Kuhnert > Tapestry/Dojo team member/developer > > Open source based consulting work centered around > dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com > > - > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
T5: Changing locale within OnActivate event
In several of our pages, the default locale we want to use for messages depends on its activation context. We tried updating the locale using 'ThreadLocale' from within the activate event handler, but it seems that this is too late, for the page has already been loaded and all messages in the template resolved using whatever locale was in effect at the time of loading. Is there some way we can force the messages to be reloaded after setting the thread locale in the activate event handler, or is there some point before the page is loaded at which we can access the page class and the activation context in order to set the locale? Thanks, Doug - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Problem with non-ASCII form parameters in form containing upload component
I am running into an encoding problem with form parameter values that contain non-ASCII characters in a form that contains an upload component. Without the upload component everything works fine. The problem appears to be in the handling of strings in 'multipart/form-data', in that both Firefox and Mozilla seem to send strings encoded as UTF-8, but don't specify a character set, and the upload component interprets these as ISO-8559-1. This actually seems to be the correct response to incorrect behavior by the browsers, but in practice we need to find a workaround. I can't find a way to get around this without modifying the tapestry-upload project, and I was wondering if anyone could suggest a better solution, and if not whether Tapestry itself will deal with this in the future Our simple, hack workaround is to modify 'MultipartDecoderImpl.processFileItems(...)' to call wrapper.addParameter(item.getFieldName(), item.getString("UTF8")) instead of wrapper.addParameter(item.getFieldName(), item.getString()) To improve this, I think we would need 1) To have a way of passing in an appropriate default encoding to use. We could contribute a 'HttpServletRequestHandler' that sets the request's default character encoding, but is there a way to guarantee that our handler would be called before the 'MultipartServletRequestFilter'? 2) Even if did (1), we would need a way to use this encoding to parse strings multipart form fields. Passing the encoding to 'FileItem.getString()' is undesirable because it would not handle the case where the part's 'charset' parameter was explicitly set. The parameterless version of 'FileItem.getString()' cannot be used, however, because it explicitly defaults to 'ISO-8859-1' if the character set is not specified (e.g. it uses neither the request's character encoding or the header encoding set by 'FileUpload.setHeaderEncoding'). I can't find a nice way to do this without duplicating some code in 'commons-fileupload' or relying on public methods of 'DiskFileItem' that aren't in the 'FileItem' interface. Thanks, Doug - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
T5: Passing parameters to deeply nested components without having to pass it to all intervening components
Is there a way to pass a parameter from an outer component to a deeply nested inner component without having to explicitly pass the parameter to all intervening components? Basically, we have a parameter, 'node', whose value is calculated at the page level when handling the 'activate' event from the activation parameters. Suppose we have components 'A', 'B', 'C', 'D', where the page references 'A', 'A' references 'B', 'B' references 'C', and 'C' references 'D'. Component 'D' needs the value of 'node', but 'A', 'B', and 'C' don't, so we would like to avoid having to declare the 'node' parameter in those intervening components and passing the value in explicitly. I can't seem to find a way to do this. I have considered 1) Creating a service for calculating the code, but the calculation requires page parameters, and I can't think of a way to access to these from a service builder method (outside of nasty hacks like setting the value in a thread local variable). 2) Creating a new parameter binding factory that traverses up component containers until it finds one that has the named binding. However, 'ComponentResources' can get a binding type and see if a parameter is bound, but it does not provide access to the parameter binding itself. 'InternalComponentResources' provides read and write access to the parameter, but we aren't supposed to use internal services. Am I missing something? - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
T5: Problems with Upload component interaction with non-Tapestry servlets
We are running Tapestry in a hybrid environment, where some pages are handled by Tapestry and the rest are handled by a legacy servlet. We are using the new Upload component, and are running into a problem where requests with multipart content are processed by services installed by the Upload component even if the page is not a Tapestry page, which interferes with the processing of multipart content on our pages. What seems to happen is 1) A request with multipart content is received 2) Control is passed to the Tapestry Filter 3) Before determining whether the request is for a tapestry page, the MultipartServletRequestFilter process the request 4) The Tapestry Filter decides it does not recognize the page, and passes the request on to our servlet 5) Our servlet tries to process the multipart request, but fails because the request stream has already been read We have a workaround where we turn our servlet into a filter that is included before the Tapestry filter, but we run into the same problem in reverse: our filter processes the multipart request before passing control to the Tapestry filter, preventing it from being able to process the multipart request. We can avoid the problem if we can recognize whether we should pass control on to Tapestry before we process the multipart request, but I do not know of a way to ask Tapestry if a URL is for one of its pages (and doing the same for ours would be a bit of work at this time). I guess there are two fundamental questions 1) Should Tapestry avoid having its handlers process a request until it knows that it is processing a Tapestry page? 2) Is there a call we can make to determine whether Tapestry will handle a given URL? Thanks, Doug - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: T5: Customizing generation of client id from component id
Thanks for the response. We are in the process of migrating our application to Tapestry, and in the process making it more easily customizable and testable. The solution we are looking for seems to be a reasonable way to satisfy the following constraints: 1) Within a component, identifiers given to sub-components should be as simple as possible while being descriptive. For most components, little thought should be required about what other components might appear in the page. 2) Within a page, components should be able to be rearranged, added, and removed without affecting the identifier given to the associated element(s) in the rendered HTML. Such an immutable identifier is useful for Selenium tests that are valid across such page modifications. 3) In keeping with the DRY principle, we would like to avoid requiring a mixin or other boilerplate code to be included in all our components in order to construct unique identifiers. The problem is that (1) can easily lead to a case where multiple components specify the same component id for their children, because the component writer has no knowledge of what other components may be placed in the page, and in order to keep the component id simple we don't want to require the component writer to always apply a prefix to increase the likelihood of uniqueness. All that we want to require of the component writer is that within the component, all the identifiers are unique. There might also be cases where the same component is included multiple times within a page, either directly or indirectly. Note that an ideal solution for us would also allow us to similarly transform id attributes on HTML elements in the template. If we can't, we either have to avoid specifying identifiers on raw HTML elements or to make sure that all components that may ever be placed on a page choose identifiers that are unique among those components. We have a temporary solution now that uses a mixin that traverses the DOM and adjusts identifiers in its 'afterRender' method, but this violates (3) and is a bit of a kludge. Thanks, Doug > -Original Message- > From: Howard Lewis Ship [mailto:[EMAIL PROTECTED] > Sent: Friday, March 23, 2007 3:56 PM > To: Tapestry users > Subject: Re: T5: Customizing generation of client id from component id > > I'm afraid that's a use case that wasn't foremost in my mind when > coding this stuff up for T5. Still, if you explicitly set component > ids, it's highly unlikely that they'll change dramatically from one > build to the next ... could you elaborate on the situation that drove > you towards this kind of solution? > > On 3/23/07, Doug Hauge <[EMAIL PROTECTED]> wrote: > > Is there a way to customize the generation of a unique client id from a > > component id? We would like to generate the unique id in such a way that > > it would not change across most modifications to a page, mainly so > > Selenium tests can be written that will work across page redesign. The > > current method of appending a suffix to a component id does not seem to > > allow this, so we would like to be able to generate a unique id by > > prepending the component ids of ancestral components. We could > > potentially implement our own PageRenderSupport service, but the > > 'allocateClientId' method only takes a string parameter, so we don't > > have the context we would need (in particular, the ComponentResources of > > the component for which we are generating the id). > > > > > > > > Thanks, > > > > Doug > > > > > > > > > > > > > > > -- > Howard M. Lewis Ship > TWD Consulting, Inc. > Independent J2EE / Open-Source Java Consultant > Creator and PMC Chair, Apache Tapestry > Creator, Apache HiveMind > > Professional Tapestry training, mentoring, support > and project work. http://howardlewisship.com > > - > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
T5: Customizing generation of client id from component id
Is there a way to customize the generation of a unique client id from a component id? We would like to generate the unique id in such a way that it would not change across most modifications to a page, mainly so Selenium tests can be written that will work across page redesign. The current method of appending a suffix to a component id does not seem to allow this, so we would like to be able to generate a unique id by prepending the component ids of ancestral components. We could potentially implement our own PageRenderSupport service, but the 'allocateClientId' method only takes a string parameter, so we don't have the context we would need (in particular, the ComponentResources of the component for which we are generating the id). Thanks, Doug