Invalidate previous page snapshot in Spring Webflow - java

I am using Spring Webflow and I am redirecting from a view-state to action-state to view-state. Now, when the user is on second view-state, I don't want the user to be able to click the browser back button and go to the previous page.
I found that, history="invalidate" can be used to invalidate the snapshot of previous page. I tried using it in the transition. However, its not working (the browser back button is not disabled).
So, what can I add to my webflow states in order to disable the back button and only allow the user to use the navigation controls provided inside the page?
Thank you

To which state did you add the history attribute?
First, <action-state> doesn't support it (https://jira.spring.io/browse/SWF-1481).
You'd have to add it to the first <view-state>'s transition. Which, if you only wanted to do it conditionally on something that happened in the <action-state>, wouldn't be sufficient. We ended up creating Java code to call from our <action-state> method to do this.
/**
* Invalidate WebFlow history. For use in action-state, where the transition element is not able
* to specify to invalidate history.
*/
public static void invalidateHistory() {
RequestContext context = RequestContextHolder.getRequestContext();
synchronized(context.getFlowExecutionContext()) {
DefaultFlowExecutionRepository r =
(DefaultFlowExecutionRepository)
((FlowExecutorImpl)
context.getActiveFlow().
getApplicationContext().
getBean(FlowExecutor.class)).getExecutionRepository();
r.removeAllFlowExecutionSnapshots((FlowExecution)context.getFlowExecutionContext());
}
}
(Also, note that "invalidate" invalidates the state and all before it. If you only want to prevent that single state, you'd use "discard" instead. https://docs.spring.io/spring-webflow/docs/current/reference/html/views.html#view-backtracking)

Related

How can I show a confirm dialog with Vaadin 23 when the user clicks on back button?

how can I show a dialog to stay or leave the current page with Vaadin 23, when a user clicks back button on browser?
Regards
It depends what you wish to achieve.
See this older discussion: Vaadin onbeforeunload event
Generally: use the onBeforeUnload javascript even for this
https://www.w3schools.com/tags/ev_onbeforeunload.asp
This is executed when the user would go away from your vaadin app, but not when using the back button inside your vaadin app.
For these you can use the navigation lifecycle events as documented here
https://vaadin.com/docs/latest/routing/lifecycle
Not sure if it also catches, when a user leaves your app...
Assuming you mean, that is it possible to prevent the navigation happening, you simply can't do that. If disabling back button is important for you, the only way is to enforce your users to use the application via desktop shortcut which starts the app using --app paramater (if using Chrome). This is not a limitation in Vaadin, but a general restriction in browser behavior.
There is already a possibility to handle Browser Back Button Event on Vaadin (https://vaadin.com/docs/v14/flow/routing/tutorial-routing-lifecycle):
public class SignupForm extends Div implements BeforeLeaveObserver {
#Override
public void beforeLeave(BeforeLeaveEvent event) {
if (this.hasChanges()) {
ContinueNavigationAction action = event.postpone();
ConfirmDialog.build("Are you sure you want"+
" to leave this page?")
.ifAccept(action::proceed)
.show();
}
}
private boolean hasChanges() {
// no-op implementation
return true;
}
}
This code works once but when you click on Cancel on Confirm Dialog so that you want to stay on current page and click again on Back Button on Browser, than you don't see any Confirm Dialog again... I can not understand, why...

Is there a way to call an anchor after a Context Menu Item is clicked?

Im trying to download a file using the anchor and a context menu. I need to create the anchor dynamically, so that means I need to call a function, before the anchor gets called.
I already tried the following:
this.ctmFilesGrid.addItem(" Download", click -> {
if(click.getItem().isPresent()) {
this.fDownloadingFile = click.getItem().get();
this.createDownloadingAnchor();
this.ancFileDownloader.getElement().callJsFunction("click");
}
}).addComponentAsFirst(FontAwesome.Solid.FILE_DOWNLOAD.create());
But the anchor isnt called.
I hope someone can help me with that.
Thanks in advance
You can't start a download from a server-side event listener, no. The browser will block this; it's a security limitation. This is because there's no way to link the "click" function call to the original user event, and all downloads must be directly initiated by the user.
The proper solution would probably be something like a custom Servlet or a RequestHandler that handles the generation of the content. Do also check https://vaadin.com/directory/component/lazy-download-button for ideas.

GWT Hyperlink strange behavior - redirecting to http://localhost:8080/#

Okay, this is very strange.
All I am having is a Hyperlink in my menu:
Hyperlink eventCalendar= new Hyperlink("Eventkalender", "eventCalendar=" + store.getId());
and I am listening to the ValueChangeEvent in the MainViewPresenter. Please notice that I am not doing anything. Right before the creation of the listener I am setting a SimplePanel to be the display for the ActivityManager:
App.activityManager.setDisplay(this.mainView.getMainContentContainer());
History.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
GWT.log("onValueChange() historyToken " + historyToken);
}
});
But if I click the link what happens is this:
First, for the blink of an eye I can see the browser URL change to
http://localhost:8080/#eventCalendar=1
but it changes immediately back to
http://localhost:8080/#
which causes my landing page to get loaded inside the SimplePanel which I declared as display (see above).
Does anybody have an idea what could cause this behavior because this does not make sense to me? Why does the URL get changed again? Am I using History or Hyperlink wrong?
Most probably your PlaceHistoryMapper returns null for the eventCalendar=1 token, so it's replaced with the default place you gave to the PlaceHistoryHandler. If you're using GWT.create() based on PlaceTokenizers, with a factory and/or #WithTokenizers, that means either you don't have a PlaceTokenizer for the empty-string prefix (#Prefix("")), or that one tokenizer returns null.
That being said, you probably should rather try to use places directly rather than going through the history. That means using a ClickHandler on some widget and calling PlaceController#goTo with the appropriate place. Ideally, that widget would be an Anchor whose href is computed from the result of getToken from your PlaceHistoryMapper with the given place (how the href actually looks depends on your Historian; if you stick to the default behavior, then just prepend a # to the returned token).

Disable spell check in SWT Browser widget

I'm working on an Eclipse based application in which we use a Browser widget.
When typing text in this widget, a spell check is executed. We would like to deactivate it.
Is it possible ?
If you have control over the page that is displayed, you can simply disable spell checking by setting the appropriate attribute(s) (see
Disable spell-checking on HTML textfields). But I think you wouldn't have asked if that was the case...
If however the page is loaded from elsewhere you need to let the browser widget execute Javascript code that disables spell checking after the page is fully loaded.
The snippet below uses a ProgressListener to that is called when the page has been loaded completely. The Javascript that then gets executed is off the top of my head and may need refinement.
Browser browser = new Browser( parent, SWT.NONE );
browser.addProgressListener( new ProgressAdapter() {
public void completed( ProgressEvent event ) {
browser.execute( "document.getElementsByTagName( 'html' )[ 0 ].spellcheck = false;" );
}
} );
browser.setUrl( ... );

In GWT, how to reset the URL when the user hits "Cancel" in the navigation confirmation dialog?

In my GWT application, I want to ask a user confirmation when he navigates out of the current application, i.e. by entering a URL or closing the browser. This is typically done by registering a ClosingHandler and setting the desired dialog message in the onWindowClosing method. This seems to work well.
However, if the user tries to navigate say to http://www.gmail.com (by typing it in the URL bar) and hits Cancel to indicate he doesn't want to navigate, then my app keeps running but the browser's URL bar keeps indicating http://www.gmail.com. This causes a number of problems later in my application and will give the wrong result if the user bookmarks the page.
Is there a way to automatically reset the URL when the user presses Cancel?
Or, alternatively, is there a way to detect the user pressed the Cancel button? If so, is there a way to set the URL without triggering a ValueChangeEvent? (I could add some logic to prevent this, but I'd rather use a built-in mechanism if it exists.)
Not sure if this works but did you try: History.newItem(History.getToken(), false); to reset the URL? It does set the history token without triggering a new history item.
I managed to do this. It looks like GWT DeferredCommand are executed after the confirmation window has been closed. This, combined with Hilbrand's answer above, give me exactly what I want. Here is exactly what I do:
public final void onWindowClosing(Window.ClosingEvent event) {
event.setMessage(onLeaveQuestion);
DeferredCommand.addCommand( new Command() {
public void execute() {
Window.Location.replace(currentLocation);
}
});
}
Where currentLocation is obtained by calling Window.Location.getHref() every time the history token changes.
I solved this by creating a custom PlaceController and replacing the token in the url. Not an ideal solution but it works!
if (warning == null || Window.confirm(warning)) {
where = newPlace;
eventBus.fireEvent(new PlaceChangeEvent(newPlace));
currentToken = History.getToken();
} else {
// update the url when user clicks cancel in confirm popup.
History.replaceItem(currentToken, false);
}

Categories