How to stop wicket-9 from throwing StalePageException - java

Wicket throws StalePageException only if some Ajax action has been performed on a page before duplicating the page.
Example wicket project can be found at, along with steps to reproduce the exception.
https://github.com/rjngshn/java-wicket-testing/tree/main
Is there a way to ensure this exception is not thrown?
Thanks
Rajani

The default behavior provided in Wicket is too queue AJAX requests as they come in. Let’s say you have a button with a callback that does some work when clicked and updates the UI. This means that if the button is quickly clicked three times successively, the last two requests will be queued up and processed after the first request finishes.
A simple solution is to change the behavior of the AjaxChannel from queueing to active. This means that if any AJAX requests are received while there is an active(unfinished) request being processed, they will be ignored.
So how do we override Wicket’s default behavior in one spot and ensure all AjaxChannel‘s are modified? We use a custom AjaxRequestTarget.IListener.
public class ActiveAjaxListener implements AjaxRequestTarget.IListener {
private static final AjaxChannel ACTIVE_CHANNEL = new AjaxChannel(AjaxChannel.DEFAULT_NAME, AjaxChannel.Type.ACTIVE);
#Override
public void updateAjaxAttributes(AbstractDefaultAjaxBehavior behavior, AjaxRequestAttributes attributes) {
attributes.setChannel(ACTIVE_CHANNEL);
}
}
Our ActiveAjaxListener class will modify every AJAX behavior and make sure it uses the active channel. To register it, we simple insert this line into our WebApplication init() method:
getAjaxRequestTargetListeners().add(new ActiveAjaxListener());
(I've copied this explanation from https://www.coderdreams.com/wicket-quick-tip-4-change-default-ajaxchannel-to-active/)
Another way is to use a veil that prevents the double clicks via JS/CSS. More details about this approach could be found at JavaScript / Wicket : How to display an overlay which prevents user interaction

Related

Form with field options loaded from DB and validation

The situation is the following:
I have a JSP page with a form.
This form contains various <select> tags with options loaded from DB.
I want to use validation with an XML file.
The problem is the following: if I use an XML file and there are some errors in the form fields, the struts framework doesn't pass through the class method I laid out, but it will directly return the input result. So what's the point? That in this way I can't load the options for the various <select> tags I mentioned above.
So I thought to do something like this:
<result name="input" type="chain">
<param name="actionName">Class_method</param>
</result>
but with this trick I lose all the error messages, i.e. hasFieldErrors() returns always false.
How can I solve that?
Many questions, all good though.
Conversion and validation errors forces the Workflow interceptor to trigger the INPUT result, and the workflow will execute the INPUT result instead of reaching the action method (execute() or whatever).
If you need to populate some static data, like selectboxes sources, that must be available also in case of INPUT result, you should put that loading in a prepare() method, and make your action implement the Preparable interface. This method is run by an Interceptor before the INPUT result is returned, as described in the official docs.
Avoid using the chain result. It is officially discouraged since many years.
If you want to prevent double submits (by pressing F5 after a page has been submitted and the result rendered), you can use the PRG pattern with the redirectAction result. This way, however, you'd encounter the same problem of the chain result: the messages (and the parameters) will be lost.
To preserve the error messages, action errors and field errors across the redirections, you can use a predefined interceptor called Message Store Interceptor, that you must include in your stack because the defaultStack doesn't include it. I've described how it works in this answer.
If you decide to use the Message Store along with PRG there are more considerations, too long to be written here, but that could be explained in the future, about preventing infinite recursion due to Field Error -> INPUT -> PRG -> Retrieve Field Error -> INPUT -> etc... that will be blocked by the browser near the 10th recursion... but that's another story.
One option:
public class Foo extends ActionSupport {
public string myAction() { return SUCCESS; }
public void validateMyAction() { // executed after XML validation
// other complex validation here if needed
if (hasErrors()) {
// repopulate form data from DB here
}
}
}
hasErrors() method comes from the ValidationAware interface which ActionSupport implements.
Another option is to do a redirect on input result and use the message store interceptor to keep action messages

Using Stripes, what is the best pattern for Show/Update/etc Action Beans?

I have been wrestling with this problem for a while. I would like to use the same Stripes ActionBean for show and update actions. However, I have not been able to figure out how to do this in a clean way that allows reliable binding, validation, and verification of object ownership by the current user.
For example, lets say our action bean takes a postingId. The posting belongs to a user, which is logged in. We might have something like this:
#UrlBinding("/posting/{postingId}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
Now, for the show action, we could define:
private int postingId; // assume the parameter in #UrlBinding above was renamed
private Posting posting;
And now use #After(stages = LifecycleStage.BindingAndValidation) to fetch the Posting. Our #After function can verify that the currently logged in user owns the posting. We must use #After, not #Before, because the postingId won't have been bound to the parameter before hand.
However, for an update function, you want to bind the Posting object to the Posting variable using #Before, not #After, so that the returned form entries get applied on top of the existing Posting object, instead of onto an empty stub.
A custom TypeConverter<T> would work well here, but because the session isn't available from the TypeConverter interface, its difficult to validate ownership of the object during binding.
The only solution I can see is to use two separate action beans, one for show, and one for update. If you do this however, the <stripes:form> tag and its downstream tags won't correctly populate the values of the form, because the beanclass or action tags must map back to the same ActionBean.
As far as I can see, the Stripes model only holds together when manipulating simple (none POJO) parameters. In any other case, you seem to run into a catch-22 of binding your object from your data store and overwriting it with updates sent from the client.
I've got to be missing something. What is the best practice from experienced Stripes users?
In my opinion, authorisation is orthogonal to object hydration. By this, I mean that you should separate the concerns of object hydration (in this case, using a postingId and turning it into a Posting) away from determining whether a user has authorisation to perform operations on that object (like show, update, delete, etc.,).
For object hydration, I use a TypeConverter<T>, and I hydrate the object without regard to the session user. Then inside my ActionBean I have a guard around the setter, thus...
public void setPosting(Posting posting) {
if (accessible(posting)) this.posting = posting;
}
where accessible(posting) looks something like this...
private boolean accessible(Posting posting) {
return authorisationChecker.isAuthorised(whoAmI(), posting);
}
Then your show() event method would look like this...
public Resolution show() {
if (posting == null) return NOT_FOUND;
return new ForwardResolution("/WEB-INF/jsp/posting.jsp");
}
Separately, when I use Stripes I often have multiple events (like "show", or "update") within the same Stripes ActionBean. For me it makes sense to group operations (verbs) around a related noun.
Using clean URLs, your ActionBean annotations would look like this...
#UrlBinding("/posting/{$event}/{posting}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
...where {$event} is the name of your event method (i.e. "show" or "update"). Note that I am using {posting}, and not {postingId}.
For completeness, here is what your update() event method might look like...
public Resolution update() {
if (posting == null) throw new UnauthorisedAccessException();
postingService.saveOrUpdate(posting);
message("posting.save.confirmation");
return new RedirectResolution(PostingsAction.class);
}

DJ JWebBrowser: how to show but disable Address and Button bars?

I am using chrriis.dj.nativeswing.swtimpl.components.JWebBrowser in my swing application to open web page.
The page is going to show "Facebook Authentication" page and I want to prevent user from inputting some other URL other than I specify and also Forward and Back buttons should be visible but not has no affect.
So following functions are applicable for my goal
setButtonBarVisible(false);
setLocationBarVisible(false);
Once user completes the authentication I will handle the locationChanged event.
#Override
public void locationChanged(WebBrowserNavigationEvent arg0) {
System.out.println("locationChanged!");
....
}
}
I think what you want is a custom decorator. Check the demo application, under "JWebBrowser > Custom Decorator".
In your case, you could create a new decorator class, as an adapted copy of DefaultWebBrowserDecorator or a subclass with appropriate override.
You would also have to decide if this decorator is to be used only by one instance of the JWebBrowser or all instances (like child popups, etc.)

Play Framework: Best practice for validation errors redirect

I am implementing a project with play 1.2.4, based on documentation the right way to handle validation is:
public static void signUp() {
render();
}
public static void doSignUp(#Required #Valid User user) {
if (validation.hasErrors()) {
params.flash();
validation.keep();
signUp();
}
user.create();
Application.index();
}
But based on samples provided with play, it seems that different approach is used:
public static void signUp() {
render();
}
public static void doSignUp(#Required #Valid User user) {
if (validation.hasErrors()) {
render("#signUp");
}
user.create();
Application.index();
}
For this small example the code difference is small, but in more complex examples it's not so simple.
Pros and cons I see are:
First approach:
Gives nice URLs to user
Always redirects after POST, so no confirm problem if user refreshes page
Only one method is responsible for filling renderArgs before calling
template
Compile time verification that signUp method exits if it gets renamed
Second approach:
Faster, no redirect/round-trip in browser
So what is the best practice? Which approach to use use along the application?
Let me go over your arguments:
First:
Gives nice URLs to user
The URL can always be fine in Play 1.x. You can use the following:
get /signUp myController.signUp
post /signUp myController.doSignUp
So the first argument doesn't matter.
Second:
Always redirects after POST, so no confirm problem if user refreshes page.
I think if a user makes a mistake and press F5 or refresh with other technique it's good if he get the same errors again. If the user should get the possibility to get a clean form, I prefer to have a cancel-button.
Third:
Only one method is responsible for filling renderArgs before calling template
Can't see the problem with render("#signUp");
Fourth:
Compile time verification that signUp method exits if it gets renamed.
Ok, this is an argument but I think it's weak. Will be false with play 2.0.
So I think both approaches can be good, depending on the situation. Specially if you have a large form, the redirect won't work. As default I would recommend the second solution.
However, I don't know how the situation with play 2.0 will be.
It depends. The first approach will be more RESTful. However because of the redirect, the errors and params need to be stored in the cookie to be retrieved.
Since there is a 4k limitation in the data stored in the cookie, this might not be suitable for large forms.

Modifying FormInjector context information in Tapestry 5 dynamically

My current problem regards updating context information dynamically in FormInjector, my previous question Updating a zone inside a form in Tapestry 5 probably contains useful background information.
I added the following in my template.
<div t:type="FormInjector" t:id="injector" t:context="item.id"/>
And the following in my component class.
#OnEvent(component = "injector")
Block loadItemFields(String id) {
item = itemRepository.find(id);
return itemFieldsBlock;
}
Everything is working fine, new form fields appear, but the search is always done with the same id. I would like to change the id with JavaScript before triggering the event, but I don't know how to achieve this.
If there is additional information required I am happy to supply it.
Using the context parameter to pass a dynamic value wouldn't be my first option. (The FormInjector component generates a URL to trigger the event handler, which then includes the context - however, this is done when the component renders, and is not meant to be dynamic.)
I'd get rid of the context parameter and find a different way to submit the value. One possibility would be to submit the form via AJAX and trigger the injection in the callback:
this.myFormElement.observe('change', this.onChange.bindAsEventListener(this));
...
onChange: function(event) {
this.myFormElement.form.request({
onSuccess: this.afterFormSubmitted.bind(this)
});
},
afterFormSubmitted: function() {
this.formInjector.trigger();
}
That way, the value of the form element has been set on the server side when you trigger the form injection, and you can use it in your injection event handler.

Categories

Resources