Repository: syncope Updated Branches: refs/heads/master 720b48f97 -> f5905afc1
[SYNCOPE-1255] provides max execution time for all operations executed through submittable modals Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/f5905afc Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/f5905afc Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/f5905afc Branch: refs/heads/master Commit: f5905afc133ab3cfa79e3689ed936422608ca9ec Parents: 720b48f Author: fmartelli <[email protected]> Authored: Thu Dec 21 19:58:46 2017 +0100 Committer: fmartelli <[email protected]> Committed: Thu Dec 21 20:01:16 2017 +0100 ---------------------------------------------------------------------- .../console/SyncopeConsoleApplication.java | 8 ++ .../client/console/SyncopeConsoleSession.java | 6 ++ .../console/panels/NotificationPanel.java | 6 +- .../client/console/wizards/AjaxWizard.java | 88 +++++++++++++++++++- .../console/wizards/AjaxWizardBuilder.java | 12 +-- .../resources/ResourceWizardBuilder.java | 6 +- .../src/main/resources/console.properties | 3 + .../SyncopeConsoleApplication.properties | 2 + .../SyncopeConsoleApplication_it.properties | 2 + .../SyncopeConsoleApplication_pt_BR.properties | 2 + .../SyncopeConsoleApplication_ru.properties | 2 + .../console/panels/NotificationPanel.html | 8 ++ .../src/main/resources/console.properties | 3 + .../src/test/resources/console.properties | 3 + 14 files changed, 136 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java index ba08b8a..e9dd9a6 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java @@ -106,6 +106,8 @@ public class SyncopeConsoleApplication extends AuthenticatedWebApplication { private Integer maxUploadFileSizeMB; + private Integer maxWaitTime; + private List<String> domains; private Map<String, Class<? extends BasePage>> pageClasses; @@ -159,6 +161,8 @@ public class SyncopeConsoleApplication extends AuthenticatedWebApplication { ? null : Integer.valueOf(props.getProperty("maxUploadFileSizeMB")); + maxWaitTime = Integer.valueOf(props.getProperty("maxWaitTimeOnApplyChanges", "30")); + String csrf = props.getProperty("csrf"); // process page properties @@ -289,6 +293,10 @@ public class SyncopeConsoleApplication extends AuthenticatedWebApplication { return maxUploadFileSizeMB; } + public Integer getMaxWaitTimeInSeconds() { + return maxWaitTime; + } + public SyncopeClientFactoryBean newClientFactory() { return new SyncopeClientFactoryBean(). setAddress(scheme + "://" + host + ":" + port + "/" + rootPath). http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java index 9bba50c..3ca1edd 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java @@ -26,7 +26,9 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.Callable; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.MediaType; @@ -120,6 +122,10 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession { executorService.execute(command); } + public <T> Future<T> execute(final Callable<T> command) { + return executorService.submit(command); + } + public PlatformInfo getPlatformInfo() { return platformInfo; } http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/java/org/apache/syncope/client/console/panels/NotificationPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/NotificationPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/NotificationPanel.java index b113195..221ae41 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/NotificationPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/NotificationPanel.java @@ -47,7 +47,7 @@ public class NotificationPanel extends Panel implements IFeedback, IGenericCompo "[ { type: 'success', template: $('#successTemplate').html() }," + " { type: 'info', template: $('#successTemplate').html() }," + " { type: 'error', template: $('#errorTemplate').html() }," - + " { type: 'warning', template: $('#errorTemplate').html() } ] "); + + " { type: 'warning', template: $('#warningTemplate').html() } ] "); notification = new Notification(Constants.FEEDBACK, options) { @@ -66,6 +66,10 @@ public class NotificationPanel extends Panel implements IFeedback, IGenericCompo for (FeedbackMessage message : this.getModelObject()) { if (message.isError()) { this.notification.error(handler, message.getMessage()); + } else if (message.isWarning()) { + // this is necessary before check for success and info in order to show warnings: isSuccess and isInfo + // return true also in case of warnings ... + this.notification.warn(handler, message.getMessage()); } else if (message.isSuccess() || message.isInfo()) { this.notification.success(handler, message.getMessage()); } else { http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java index 04449e2..a26f6b7 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizard.java @@ -22,7 +22,14 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.syncope.client.console.SyncopeConsoleApplication; import org.apache.syncope.client.console.SyncopeConsoleSession; import org.apache.syncope.client.console.pages.BasePage; import org.apache.wicket.Component; @@ -41,7 +48,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.syncope.client.console.panels.SubmitableModalPanel; import org.apache.syncope.client.console.panels.WizardModalPanel; +import org.apache.wicket.Application; import org.apache.wicket.PageReference; +import org.apache.wicket.Session; +import org.apache.wicket.ThreadContext; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; @@ -149,7 +159,13 @@ public abstract class AjaxWizard<T extends Serializable> extends Wizard protected abstract void onCancelInternal(); - protected abstract Serializable onApplyInternal(final AjaxRequestTarget target); + /** + * Apply operation + * + * @param target request target + * @return a pair of payload (maybe null) and resulting object. + */ + protected abstract Pair<Serializable, Serializable> onApplyInternal(final AjaxRequestTarget target); /** * @see org.apache.wicket.extensions.wizard.Wizard#onCancel() @@ -179,12 +195,21 @@ public abstract class AjaxWizard<T extends Serializable> extends Wizard public final void onFinish() { final AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class); try { - final Serializable res = onApplyInternal(target); + final Serializable res = onApply(target); if (eventSink == null) { send(AjaxWizard.this, Broadcast.BUBBLE, new NewItemFinishEvent<>(item, target).setResult(res)); } else { send(eventSink, Broadcast.EXACT, new NewItemFinishEvent<>(item, target).setResult(res)); } + } catch (TimeoutException te) { + LOG.warn("Operation applying took to long", te); + if (eventSink == null) { + send(AjaxWizard.this, Broadcast.BUBBLE, new NewItemCancelEvent<>(item, target)); + } else { + send(eventSink, Broadcast.EXACT, new NewItemCancelEvent<>(item, target)); + } + SyncopeConsoleSession.get().warn(getString("timeout")); + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); } catch (Exception e) { LOG.error("Wizard error on finish", e); SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) @@ -337,11 +362,68 @@ public abstract class AjaxWizard<T extends Serializable> extends Wizard @Override public void onSubmit(final AjaxRequestTarget target, final Form<?> form) { - onApplyInternal(target); + try { + onApply(target); + } catch (TimeoutException te) { + LOG.warn("Operation applying took to long", te); + send(eventSink, Broadcast.EXACT, new NewItemCancelEvent<>(item, target)); + SyncopeConsoleSession.get().warn(getString("timeout")); + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } } @Override public void onError(final AjaxRequestTarget target, final Form<?> form) { ((BasePage) getPage()).getNotificationPanel().refresh(target); } + + private Serializable onApply(final AjaxRequestTarget target) throws TimeoutException { + try { + final Future<Pair<Serializable, Serializable>> executor + = SyncopeConsoleSession.get().execute(new ApplyFuture(target)); + + final Pair<Serializable, Serializable> res + = executor.get(SyncopeConsoleApplication.get().getMaxWaitTimeInSeconds(), TimeUnit.SECONDS); + + if (res.getLeft() != null) { + send(pageRef.getPage(), Broadcast.BUBBLE, res.getLeft()); + } + + return res.getRight(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + private class ApplyFuture implements Callable<Pair<Serializable, Serializable>>, Serializable { + + private static final long serialVersionUID = -4657123322652656848L; + + private final AjaxRequestTarget target; + + private final Application application; + + private final RequestCycle requestCycle; + + private final Session session; + + ApplyFuture(final AjaxRequestTarget target) { + this.target = target; + this.application = Application.get(); + this.requestCycle = RequestCycle.get(); + this.session = Session.exists() ? Session.get() : null; + } + + @Override + public Pair<Serializable, Serializable> call() throws Exception { + try { + ThreadContext.setApplication(this.application); + ThreadContext.setRequestCycle(this.requestCycle); + ThreadContext.setSession(this.session); + return AjaxWizard.this.onApplyInternal(this.target); + } finally { + ThreadContext.detach(); + } + } + } } http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java index 32514ad..f43b57b 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AjaxWizardBuilder.java @@ -22,10 +22,10 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.commons.lang3.tuple.Pair; import org.apache.wicket.Component; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.event.Broadcast; import org.apache.wicket.extensions.wizard.WizardModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -100,8 +100,8 @@ public abstract class AjaxWizardBuilder<T extends Serializable> extends Abstract } @Override - protected Serializable onApplyInternal(final AjaxRequestTarget target) { - final Serializable res = AjaxWizardBuilder.this.onApplyInternal(modelObject); + protected Pair<Serializable, Serializable> onApplyInternal(final AjaxRequestTarget target) { + Serializable res = AjaxWizardBuilder.this.onApplyInternal(modelObject); Serializable payload; switch (mode) { @@ -116,11 +116,7 @@ public abstract class AjaxWizardBuilder<T extends Serializable> extends Abstract payload = null; } - if (payload != null) { - send(pageRef.getPage(), Broadcast.BUBBLE, payload); - } - - return res; + return Pair.of(payload, res); } }.setEventSink(eventSink).addOuterObject(outerObjects); } http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java index 14187b0..b08e29b 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceWizardBuilder.java @@ -81,13 +81,13 @@ public class ResourceWizardBuilder extends AbstractResourceWizardBuilder<Resourc @Override protected ResourceTO onApplyInternal(final Serializable modelObject) { - final ResourceTO resourceTO = ResourceTO.class.cast(modelObject); + ResourceTO resourceTO = ResourceTO.class.cast(modelObject); if (createFlag) { - return resourceRestClient.create(resourceTO); + resourceTO = resourceRestClient.create(resourceTO); } else { resourceRestClient.update(resourceTO); - return resourceTO; } + return resourceTO; } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/resources/console.properties ---------------------------------------------------------------------- diff --git a/client/console/src/main/resources/console.properties b/client/console/src/main/resources/console.properties index bc9a009..9c46f7a 100644 --- a/client/console/src/main/resources/console.properties +++ b/client/console/src/main/resources/console.properties @@ -28,6 +28,9 @@ rootPath=/syncope/rest/ useGZIPCompression=true maxUploadFileSizeMB=5 +# Max wait time on apply changes from modals/wizards (given in seconds) +maxWaitTimeOnApplyChanges=30 + csrf=true flowableModelerDirectory=${flowable-modeler.directory} http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties ---------------------------------------------------------------------- diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties index cca9dea..f668185 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties +++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties @@ -72,3 +72,5 @@ intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to gr confirmGlobalLogout=Do you really want to perform global logout? administration=Administration implementations=Implementations + +timeout=Operation is taking to long: it will be executed in background. Please check later for the result (errors won't be triggered). http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties ---------------------------------------------------------------------- diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties index 8aadcef..fa983f7 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties +++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties @@ -72,3 +72,5 @@ intAttrNameInfo.help=Oltre agli attributi auto-completati, \u00e8 possibile fare confirmGlobalLogout=Vuoi davvero procedere al logout globale? administration=Amministrazione implementations=Implementazioni + +timeout=L'operazione sta durando troppo: sar\u00e0 eseguita in background. Verifica il risultato pi\u00f9 tardi (gli errori non saranno notificati). http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties ---------------------------------------------------------------------- diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties index 6916cf2..8676cdb 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties +++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties @@ -72,3 +72,5 @@ intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to gr confirmGlobalLogout=Do you really want to perform global logout? administration=Administra\u00e7\u00e3o implementations=Implementa\u00e7\u00f5es + +timeout=Operation is taking to long: it will be executed in background. Please check later for the result (errors won't be triggered). http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties ---------------------------------------------------------------------- diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties index fc2a17a..e77a0d4 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties +++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties @@ -71,3 +71,5 @@ intAttrNameInfo.help=\u041f\u043e\u043c\u0438\u043c\u043e \u0430\u0432\u0442\u04 confirmGlobalLogout=Do you really want to perform global logout? administration=Administration implementations=\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 + +timeout=Operation is taking to long: it will be executed in background. Please check later for the result (errors won't be triggered). http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/client/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html ---------------------------------------------------------------------- diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html index 2870588..1d5a8a2 100644 --- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html +++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/NotificationPanel.html @@ -40,6 +40,14 @@ under the License. #= message # </div> </script> + + <script id="warningTemplate" type="text/x-kendo-template"> + <div class="alert alert-warning alert-dismissible" style="margin-bottom: 0px; min-width: 370px"> + <button aria-hidden="true" data-dismiss="alert" class="close" type="button">Ã</button> + <h4><i class="icon fa fa-ban"></i> Warning!</h4> + #= message # + </div> + </script> <script id="successTemplate" type="text/x-kendo-template"> <div class="alert alert-success alert-dismissible" style="margin-bottom: 0px; min-width: 370px"> http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/fit/console-reference/src/main/resources/console.properties ---------------------------------------------------------------------- diff --git a/fit/console-reference/src/main/resources/console.properties b/fit/console-reference/src/main/resources/console.properties index 2612894..bce070a 100644 --- a/fit/console-reference/src/main/resources/console.properties +++ b/fit/console-reference/src/main/resources/console.properties @@ -28,6 +28,9 @@ rootPath=/syncope/rest/ useGZIPCompression=true maxUploadFileSizeMB=5 +# Max wait time on apply changes from modals/wizards (given in seconds) +maxWaitTimeOnApplyChanges=30 + csrf=true flowableModelerDirectory=${flowable-modeler.directory} http://git-wip-us.apache.org/repos/asf/syncope/blob/f5905afc/fit/core-reference/src/test/resources/console.properties ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/resources/console.properties b/fit/core-reference/src/test/resources/console.properties index 24fe5f9..43ee365 100644 --- a/fit/core-reference/src/test/resources/console.properties +++ b/fit/core-reference/src/test/resources/console.properties @@ -28,6 +28,9 @@ rootPath=/syncope/rest/ useGZIPCompression=true maxUploadFileSizeMB=5 +# Max wait time on apply changes from modals/wizards (given in seconds) +maxWaitTimeOnApplyChanges=30 + csrf=false flowableModelerDirectory=${flowable-modeler.directory}
