[
http://www.stripesframework.org/jira/browse/STS-803?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12510#comment-12510
]
Tapio Koskinen commented on STS-803:
------------------------------------
I confirm this occurs in non-test code too. A JSP-page had <stripes:link> tag
which pointed to the same ActionBean that forwarded to that JSP-page in the
first place. On the first run that caused problems with resolving the
ActionBean and input-tags were not populated. On the second run everything went
fine.
Removing the <stripes:link> tag or changing it's beanClass-attribute fixed the
problem.
> MockRoundtrip:: trip.getActionBean() returns NULL 1st run but OK 2nd+
> ---------------------------------------------------------------------
>
> Key: STS-803
> URL: http://www.stripesframework.org/jira/browse/STS-803
> Project: Stripes
> Issue Type: Bug
> Affects Versions: Release 1.5.5
> Reporter: Nikolaos
> Assignee: Ben Gunter
> Fix For: Release 1.5.7
>
>
> While the issue outlined below is "Minor" there are 2 reasons why I am
> flagging this as "Major":
> (1) as it affects testing it does impede normal testing in that an expected
> non-null return of trip.getActionBean() and subsequent assertion failure test
> can not be made... so test code needs to be padded to expect and treat an
> error case as a normal case... problematic but yes not the end of the world
> (2) but the bigger reason is b/c Stripes UrlBinding mechanism determines one
> set of bindings when the Stripes initializes... and then as Stripes runs
> modifies those bindings... which is cause for concern / alarm as this may
> have adverse side effects on non-test / production code... i.e. I would
> expect Stripes to initialize the bindings properly from the get go and
> service all requests uniformly (also I am not so sure these changes occur at
> a specified point in time i.e. I don't think they necessarily occur after the
> 1st hit of a given UrlBinding and I also wonder how all other bindings are
> affected... in any event it may be harmless but at this point appears a
> little unsettling ;-)
> What follows is the e-mail sent to the list verbatim:
> ======================================
> This issue is very bizarre and VERY interesting indeed.
> I run 2 "identical" TestNG tests in a unit test - back to back - and the 1st
> fails and the 2nd succeeds:
> @DataProvider(name = "userIssueRequests")
> public Object[][] userIssueRequests() {
> return new Object[][] {
> { ShareActionBean.class, "en_US", "/share/3gi/_/edit",
> "/share/3gi/_/view" },
> { ShareActionBean.class, "en_US", "/share/3gi/_/edit",
> "/share/3gi/_/view" },
> };
> }
> ShareActionBean has the following URL binding:
> @UrlBinding("/share/{uuidRadix}/{titleUrlified}/{$event}")
> And the following default handler:
> @DefaultHandler
> @DontValidate
> public final Resolution view() {
> return (super.view(VIEW));
> }
> The test involves the following (relevant) code:
> MockRoundtrip trip = new MockRoundtrip(context, actionBeanUrl, new
> MockHttpSession(context));
> trip.execute();
> ShareActionBean bean = trip.getActionBean(ShareActionBean.class);
> In BOTH cases the ShareActionBean is created and the "edit" handler (as per
> URL) is invoked. All is well... so far...
> However, In the 1st run bean is NULL and in the 2nd run bean returns the
> action bean that handled the request... HUH????
> So, I did some debugging... if we drill down into trip.getActionBean(...) we
> find the following method:
> public <A extends ActionBean> A getActionBean(Class<A> type) {
> A bean = (A) this.request.getAttribute(getUrlBinding(type,
> this.context));
> if (bean == null) {
> bean = (A)
> this.request.getSession().getAttribute(getUrlBinding(type, this.context));
> }
> return bean;
> }
> Here is where it gets REALLY interesting - if we simply focus on the 1st line
> of the method call:
> A bean = (A) this.request.getAttribute(getUrlBinding(type,
> this.context));
> We find that getUrlBinding(type, this.context) returns the following as
> the key to the outer method call:
> /share/{uuidRadix}/{titleUrlified}/{$event=view}
> And in the 1st run this.request.getAttribute(...) has a map that contains:
> __stripes_resolved_action=/share/{uuidRadix}/{titleUrlified}/{$event},
> /share/{uuidRadix}/{titleUrlified}/{$event}=org.lightagents.ui.web.action.content.ShareActionBean@10fd9d27,
> actionBean=org.lightagents.ui.web.action.content.ShareActionBean@10fd9d27,
> __current_flash_scope=-1806527276,
> _stripes_defaultMessages=[org.lightagents.ui.stripes.extended.LocalizableMessageWarning@779dc644]}
>
> whereas in the 2nd run this.request.getAttribute(...) has a map that
> contains:
> __stripes_resolved_action=/share/{uuidRadix}/{titleUrlified}/{$event=view},
> /share/{uuidRadix}/{titleUrlified}/{$event=view}=org.lightagents.ui.web.action.content.ShareActionBean@44dd7637,
> actionBean=org.lightagents.ui.web.action.content.ShareActionBean@44dd7637,
> __current_flash_scope=-624278302,
> _stripes_defaultMessages=[org.lightagents.ui.stripes.extended.LocalizableMessageWarning@779dc644]}
> How can Stripes produce 2 different URL bindings for the same ActionBean in
> the same run????
> This behaviour is not only odd but worrisome if there is a bug at work here
> that may affect non-Test code.
> Now what is more interesting is that the ShareActionBean is setup with the
> Application logic such that if user is trying to change a Share that they do
> not have access to that they are redirected to the default handler with a
> message i.e.:
> /share/3gi/_/view?__fsk=-1806527276
> So we have the following things happening:
> (A) Stripes UrlBinding's are determined when Stripes fires up and receives an
> initial request. At this point the ShareActionBean is referenced to have
> cached UrlBinding of:
> /share/{uuidRadix}/{titleUrlified}/{$event}
> (B) Run #1 - we test the request to "/share/3gi/_/edit" and the
> ShareActionBean "edit" event handler redirects to "/share" with params "3gi"
> and "_" and as such no explicitly specified "event" handler so the default
> one should be determined by Stripes.
> But that causes UrlBindingParameter.getDefaultValue() to execute to determine
> that the "event" value for this action bean is the @DefaultHandler method
> "view"
> At this point though this changes the UrlBinding component for
> ShareActionBean to have "event" with defaultValue = "view" and moreover the
> ShareActionBean cached UrlBinding from this point forward is:
> /share/{uuidRadix}/{titleUrlified}/{$event=view}
> (C) However when the trip.getActionBean(...) method fires a lookup for the
> request attribute the key it got initially is used:
> /share/{uuidRadix}/{titleUrlified}/{$event}
> And of course this fails and no ActionBean is returned b/c this no longer
> maps to any cached UrlBinding.
> (D) When Run #2 comes along and does the same thing the same thing occurs as
> in Run #1 except from the start this time though the cached UrlBinding is:
> /share/{uuidRadix}/{titleUrlified}/{$event=view}
> And nothing changes and all is well in that the trip.getActionBean(...)
> method return the ShareActionBean instance
> So it appears that as long as an explicit "event" parameter is supplied the
> getDefaultValue() method will not get called on the "event"
> UrlBindingParameter and until then the binding of the ActionBean will not
> have the default value embedded in it for "event" but once a default event
> URL is produced that bindings will appear differently.
> Shouldn't Stripes ensure from the get-go try to trigger the
> getDefaultValue() for "event" to have it incorporated in the UrlBinding
> cached????
> What a ride!!!!
> --Nikolaos
> UrlBindingParameter.java:
> public String getDefaultValue() {
> // for $event parameters with no explicit default value, get default
> from action resolver
> if (this.defaultValue == null && PARAMETER_NAME_EVENT.equals(name)) {
> try {
> Method defaultHandler =
> StripesFilter.getConfiguration().getActionResolver()
> .getDefaultHandler(beanClass);
> HandlesEvent annotation =
> defaultHandler.getAnnotation(HandlesEvent.class);
> if (annotation != null)
> this.defaultValue = annotation.value();
> else
> this.defaultValue = defaultHandler.getName();
> }
> catch (Exception e) {
> /* Ignore any exceptions and just return null. */
> }
> }
> return defaultValue;
> }
--
This message is automatically generated by JIRA.
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create
new or port existing apps to sell to consumers worldwide. Explore the
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development