From dc7561b67fef9fa7078041fb5fe02ddc4e4d2303 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 20 Apr 2018 12:10:09 +0200 Subject: [PATCH] Add tree-wide task suspend/resume actions Now the multi-worker task trees can be suspended and resumed as a whole. (Coordinator-only suspend and resume is available from the task context menu for multi-worker tasks. It is intended to be used only on special occasions.) --- .../web/page/admin/server/PageTasks.java | 1828 +++++++++-------- .../localization/Midpoint.properties | 2 + .../midpoint/model/api/TaskService.java | 5 +- .../impl/controller/ModelController.java | 16 +- 4 files changed, 1004 insertions(+), 847 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java index e0b158639de..015d89044d9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java @@ -94,6 +94,7 @@ import javax.xml.namespace.QName; import java.util.*; +import java.util.stream.Collectors; /** * @author lazyman @@ -112,148 +113,152 @@ public class PageTasks extends PageAdminTasks implements Refreshable { private static final Trace LOGGER = TraceManager.getTrace(PageTasks.class); - private static final String DOT_CLASS = PageTasks.class.getName() + "."; - private static final String OPERATION_SUSPEND_TASKS = DOT_CLASS + "suspendTasks"; - private static final String OPERATION_RESUME_TASKS = DOT_CLASS + "resumeTasks"; - private static final String OPERATION_RESUME_TASK = DOT_CLASS + "resumeTask"; - private static final String OPERATION_DELETE_TASKS = DOT_CLASS + "deleteTasks"; - private static final String OPERATION_RECONCILE_WORKERS = DOT_CLASS + "reconcileWorkers"; - private static final String OPERATION_DELETE_ALL_CLOSED_TASKS = DOT_CLASS + "deleteAllClosedTasks"; - private static final String OPERATION_SCHEDULE_TASKS = DOT_CLASS + "scheduleTasks"; - private static final String OPERATION_DELETE_NODES = DOT_CLASS + "deleteNodes"; - private static final String OPERATION_START_SCHEDULERS = DOT_CLASS + "startSchedulers"; - private static final String OPERATION_STOP_SCHEDULERS_AND_TASKS = DOT_CLASS + "stopSchedulersAndTasks"; - private static final String OPERATION_STOP_SCHEDULERS = DOT_CLASS + "stopSchedulers"; - private static final String OPERATION_DEACTIVATE_SERVICE_THREADS = DOT_CLASS + "deactivateServiceThreads"; - private static final String OPERATION_REACTIVATE_SERVICE_THREADS = DOT_CLASS + "reactivateServiceThreads"; - private static final String OPERATION_SYNCHRONIZE_TASKS = DOT_CLASS + "synchronizeTasks"; - private static final String OPERATION_SYNCHRONIZE_WORKFLOW_REQUESTS = DOT_CLASS + "synchronizeWorkflowRequests"; - private static final String OPERATION_REFRESH_TASKS = DOT_CLASS + "refreshTasks"; - private static final String ALL_CATEGORIES = ""; - - public static final long WAIT_FOR_TASK_STOP = 2000L; - - private static final String ID_REFRESH_PANEL = "refreshPanel"; - private static final String ID_MAIN_FORM = "mainForm"; - private static final String ID_SEARCH_FORM = "searchForm"; - private static final String ID_STATE = "state"; - private static final String ID_CATEGORY = "category"; - private static final String ID_SHOW_SUBTASKS = "showSubtasks"; - private static final String ID_TASK_TABLE = "taskTable"; - private static final String ID_NODE_TABLE = "nodeTable"; - private static final String ID_SEARCH_CLEAR = "searchClear"; - private static final String ID_TABLE_HEADER = "tableHeader"; + private static final String DOT_CLASS = PageTasks.class.getName() + "."; + private static final String OPERATION_SUSPEND_TASKS = DOT_CLASS + "suspendTasks"; + private static final String OPERATION_SUSPEND_TASK = DOT_CLASS + "suspendTask"; + private static final String OPERATION_RESUME_TASKS = DOT_CLASS + "resumeTasks"; + private static final String OPERATION_RESUME_TASK = DOT_CLASS + "resumeTask"; + private static final String OPERATION_DELETE_TASKS = DOT_CLASS + "deleteTasks"; + private static final String OPERATION_RECONCILE_WORKERS = DOT_CLASS + "reconcileWorkers"; + private static final String OPERATION_DELETE_ALL_CLOSED_TASKS = DOT_CLASS + "deleteAllClosedTasks"; + private static final String OPERATION_SCHEDULE_TASKS = DOT_CLASS + "scheduleTasks"; + private static final String OPERATION_DELETE_NODES = DOT_CLASS + "deleteNodes"; + private static final String OPERATION_START_SCHEDULERS = DOT_CLASS + "startSchedulers"; + private static final String OPERATION_STOP_SCHEDULERS_AND_TASKS = DOT_CLASS + "stopSchedulersAndTasks"; + private static final String OPERATION_STOP_SCHEDULERS = DOT_CLASS + "stopSchedulers"; + private static final String OPERATION_DEACTIVATE_SERVICE_THREADS = DOT_CLASS + "deactivateServiceThreads"; + private static final String OPERATION_REACTIVATE_SERVICE_THREADS = DOT_CLASS + "reactivateServiceThreads"; + private static final String OPERATION_SYNCHRONIZE_TASKS = DOT_CLASS + "synchronizeTasks"; + private static final String OPERATION_SYNCHRONIZE_WORKFLOW_REQUESTS = DOT_CLASS + "synchronizeWorkflowRequests"; + private static final String OPERATION_REFRESH_TASKS = DOT_CLASS + "refreshTasks"; + private static final String ALL_CATEGORIES = ""; + + public static final long WAIT_FOR_TASK_STOP = 2000L; + + private static final String ID_REFRESH_PANEL = "refreshPanel"; + private static final String ID_MAIN_FORM = "mainForm"; + private static final String ID_SEARCH_FORM = "searchForm"; + private static final String ID_STATE = "state"; + private static final String ID_CATEGORY = "category"; + private static final String ID_SHOW_SUBTASKS = "showSubtasks"; + private static final String ID_TASK_TABLE = "taskTable"; + private static final String ID_NODE_TABLE = "nodeTable"; + private static final String ID_SEARCH_CLEAR = "searchClear"; + private static final String ID_TABLE_HEADER = "tableHeader"; public static final String ID_SYNCHRONIZE_WORKFLOW_REQUESTS = "synchronizeWorkflowRequests"; - public static final String SELECTED_CATEGORY = "category"; - private static final int REFRESH_INTERVAL = 60000; // don't set too low to prevent refreshing open inline menus (TODO skip refresh if a menu is open) + public static final String SELECTED_CATEGORY = "category"; + private static final int REFRESH_INTERVAL = 60000; // don't set too low to prevent refreshing open inline menus (TODO skip refresh if a menu is open) private IModel searchModel; - private String searchText = ""; + private String searchText = ""; private IModel refreshModel; private AutoRefreshPanel refreshPanel; - public PageTasks() { + public PageTasks() { this("", null); - } + } - public PageTasks(String searchText) { - this(searchText, null); - } + public PageTasks(String searchText) { + this(searchText, null); + } - public PageTasks(PageParameters parameters) { - this("", parameters); - } + public PageTasks(PageParameters parameters) { + this("", parameters); + } - // TODO clean the mess with constructors - public PageTasks(String searchText, PageParameters parameters) { - if (parameters != null) { - getPageParameters().overwriteWith(parameters); - } + // TODO clean the mess with constructors + public PageTasks(String searchText, PageParameters parameters) { + if (parameters != null) { + getPageParameters().overwriteWith(parameters); + } - this.searchText = searchText; - searchModel = LoadableModel.create(this::loadTasksSearchDto, false); + this.searchText = searchText; + searchModel = LoadableModel.create(this::loadTasksSearchDto, false); refreshModel = new Model<>(new AutoRefreshDto(REFRESH_INTERVAL)); - initLayout(); + initLayout(); refreshPanel.startRefreshing(this, null); - } + } - private TasksSearchDto loadTasksSearchDto() { - TasksStorage storage = getSessionStorage().getTasks(); - TasksSearchDto dto = storage.getTasksSearch(); + private TasksSearchDto loadTasksSearchDto() { + TasksStorage storage = getSessionStorage().getTasks(); + TasksSearchDto dto = storage.getTasksSearch(); - if (dto == null) { - dto = new TasksSearchDto(); - dto.setShowSubtasks(false); - } + if (dto == null) { + dto = new TasksSearchDto(); + dto.setShowSubtasks(false); + } - if (getPageParameters() != null) { - StringValue category = getPageParameters().get(SELECTED_CATEGORY); - if (category != null && category.toString() != null && !category.toString().isEmpty()) { - dto.setCategory(category.toString()); - } - } + if (getPageParameters() != null) { + StringValue category = getPageParameters().get(SELECTED_CATEGORY); + if (category != null && category.toString() != null && !category.toString().isEmpty()) { + dto.setCategory(category.toString()); + } + } - if (dto.getStatus() == null) { - dto.setStatus(TaskDtoExecutionStatusFilter.ALL); - } + if (dto.getStatus() == null) { + dto.setStatus(TaskDtoExecutionStatusFilter.ALL); + } - return dto; - } + return dto; + } - private void initLayout() { + private void initLayout() { refreshPanel = new AutoRefreshPanel(ID_REFRESH_PANEL, refreshModel, this, false); add(refreshPanel); - Form mainForm = new com.evolveum.midpoint.web.component.form.Form(ID_MAIN_FORM); - add(mainForm); + Form mainForm = new com.evolveum.midpoint.web.component.form.Form(ID_MAIN_FORM); + add(mainForm); List> taskColumns = initTaskColumns(); - TaskDtoProviderOptions options = TaskDtoProviderOptions.minimalOptions(); + TaskDtoProviderOptions options = TaskDtoProviderOptions.minimalOptions(); options.setGetNextRunStartTime(true); options.setUseClusterInformation(true); options.setResolveObjectRef(true); - TaskDtoProvider provider = new TaskDtoProvider(PageTasks.this, options) { - private static final long serialVersionUID = 1L; - @Override - protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) { - TasksStorage storage = getSessionStorage().getTasks(); - storage.setPaging(paging); - } + TaskDtoProvider provider = new TaskDtoProvider(PageTasks.this, options) { + private static final long serialVersionUID = 1L; - @Override - public TaskDto createTaskDto(PrismObject task, boolean subtasksLoaded, Task opTask, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { - TaskDto dto = super.createTaskDto(task, subtasksLoaded, opTask, result); - addInlineMenuToTaskRow(dto); + @Override + protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) { + TasksStorage storage = getSessionStorage().getTasks(); + storage.setPaging(paging); + } - return dto; - } - - @Override - public IModel model(TaskDto object) { - return new LoadableDetachableModel(object) { - - private static final long serialVersionUID = 1L; + @Override + public TaskDto createTaskDto(PrismObject task, boolean subtasksLoaded, Task opTask, OperationResult result) + throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { + TaskDto dto = super.createTaskDto(task, subtasksLoaded, opTask, result); + addInlineMenuToTaskRow(dto); + + return dto; + } + + @Override + public IModel model(TaskDto object) { + return new LoadableDetachableModel(object) { + + private static final long serialVersionUID = 1L; private String oid; - - protected void onDetach() { - this.oid = getObject().getOid(); - } - + + protected void onDetach() { + this.oid = getObject().getOid(); + } + @Override protected TaskDto load() { Task task = createSimpleTask("load task"); OperationResult result = task.getResult(); - PrismObject taskType = WebModelServiceUtils.loadObject(TaskType.class, oid, PageTasks.this, task, result); + PrismObject taskType = WebModelServiceUtils + .loadObject(TaskType.class, oid, PageTasks.this, task, result); if (taskType == null) { return null; } - + TaskDto taskDto = null; try { taskDto = new TaskDto(taskType.asObjectable(), null, getModel(), getTaskService(), @@ -265,71 +270,74 @@ protected TaskDto load() { e.printStackTrace(); } return taskDto; - }; - + } + + ; + }; - } - }; + } + }; - provider.setQuery(createTaskQuery()); - BoxedTablePanel taskTable = new BoxedTablePanel(ID_TASK_TABLE, provider, taskColumns, - UserProfileStorage.TableId.PAGE_TASKS_PANEL, - (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_TASKS_PANEL)) { + provider.setQuery(createTaskQuery()); + BoxedTablePanel taskTable = new BoxedTablePanel(ID_TASK_TABLE, provider, taskColumns, + UserProfileStorage.TableId.PAGE_TASKS_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_TASKS_PANEL)) { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; @Override - protected WebMarkupContainer createHeader(String headerId) { - return new SearchFragment(headerId, ID_TABLE_HEADER, PageTasks.this, searchModel); - } + protected WebMarkupContainer createHeader(String headerId) { + return new SearchFragment(headerId, ID_TABLE_HEADER, PageTasks.this, searchModel); + } - @Override - protected WebMarkupContainer createButtonToolbar(String id) { - CsvDownloadButtonPanel exportDataLink = new CsvDownloadButtonPanel(id) { + @Override + protected WebMarkupContainer createButtonToolbar(String id) { + CsvDownloadButtonPanel exportDataLink = new CsvDownloadButtonPanel(id) { - private static final long serialVersionUID = 1L; - @Override - protected DataTable getDataTable() { - return getTaskTable().getDataTable(); - } + private static final long serialVersionUID = 1L; - @Override - protected String getFilename() { - return "TaskType_" + createStringResource("MainObjectListPanel.exportFileName").getString(); - } + @Override + protected DataTable getDataTable() { + return getTaskTable().getDataTable(); + } + + @Override + protected String getFilename() { + return "TaskType_" + createStringResource("MainObjectListPanel.exportFileName").getString(); + } }; - return exportDataLink; - } - }; - taskTable.setOutputMarkupId(true); + return exportDataLink; + } + }; + taskTable.setOutputMarkupId(true); - TasksStorage storage = getSessionStorage().getTasks(); - taskTable.setCurrentPage(storage.getPaging()); + TasksStorage storage = getSessionStorage().getTasks(); + taskTable.setCurrentPage(storage.getPaging()); - mainForm.add(taskTable); + mainForm.add(taskTable); - List> nodeColumns = initNodeColumns(); - BoxedTablePanel nodeTable = new BoxedTablePanel<>(ID_NODE_TABLE, new NodeDtoProvider(PageTasks.this) { + List> nodeColumns = initNodeColumns(); + BoxedTablePanel nodeTable = new BoxedTablePanel<>(ID_NODE_TABLE, new NodeDtoProvider(PageTasks.this) { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public NodeDto createNodeDto(PrismObject node) { - NodeDto dto = super.createNodeDto(node); - addInlineMenuToNodeRow(dto); + @Override + public NodeDto createNodeDto(PrismObject node) { + NodeDto dto = super.createNodeDto(node); + addInlineMenuToNodeRow(dto); - return dto; - } - }, nodeColumns, - UserProfileStorage.TableId.PAGE_TASKS_NODES_PANEL, - (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_TASKS_NODES_PANEL)); - nodeTable.setOutputMarkupId(true); - nodeTable.setShowPaging(false); - mainForm.add(nodeTable); - - initDiagnosticButtons(); - } + return dto; + } + }, nodeColumns, + UserProfileStorage.TableId.PAGE_TASKS_NODES_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_TASKS_NODES_PANEL)); + nodeTable.setOutputMarkupId(true); + nodeTable.setShowPaging(false); + mainForm.add(nodeTable); + + initDiagnosticButtons(); + } @Override public void refresh(AjaxRequestTarget target) { @@ -347,211 +355,210 @@ public int getRefreshInterval() { } private List> initNodeColumns() { - List> columns = new ArrayList<>(); + List> columns = new ArrayList<>(); - IColumn column = new CheckBoxHeaderColumn<>(); - columns.add(column); + IColumn column = new CheckBoxHeaderColumn<>(); + columns.add(column); column = new PropertyColumn<>(createStringResource("pageTasks.node.name"), "name", "name"); - columns.add(column); + columns.add(column); - columns.add(new EnumPropertyColumn(createStringResource("pageTasks.node.executionStatus"), - "executionStatus") { + columns.add(new EnumPropertyColumn(createStringResource("pageTasks.node.executionStatus"), + "executionStatus") { - @Override - protected String translate(Enum en) { - return createStringResource(en).getString(); - } - }); + @Override + protected String translate(Enum en) { + return createStringResource(en).getString(); + } + }); - columns.add(new PropertyColumn(createStringResource("pageTasks.node.managementPort"), "managementPort")); - columns.add(new AbstractColumn(createStringResource("pageTasks.node.lastCheckInTime")) { + columns.add(new PropertyColumn(createStringResource("pageTasks.node.managementPort"), "managementPort")); + columns.add(new AbstractColumn(createStringResource("pageTasks.node.lastCheckInTime")) { - @Override - public void populateItem(Item> item, String componentId, - final IModel rowModel) { - item.add(new Label(componentId, new AbstractReadOnlyModel() { + @Override + public void populateItem(Item> item, String componentId, + final IModel rowModel) { + item.add(new Label(componentId, new AbstractReadOnlyModel() { - @Override - public Object getObject() { - return getLastCheckInTime(rowModel); - } - })); - } - }); - CheckBoxColumn check = new CheckBoxColumn(createStringResource("pageTasks.node.clustered"), "clustered"); - check.setEnabled(false); - columns.add(check); - columns.add(new PropertyColumn(createStringResource("pageTasks.node.statusMessage"), "statusMessage")); - - IColumn menuColumn = new InlineMenuButtonColumn(createNodesInlineMenu(false), 2, PageTasks.this){ - @Override - protected int getHeaderNumberOfButtons() { - return 2; - } + @Override + public Object getObject() { + return getLastCheckInTime(rowModel); + } + })); + } + }); + CheckBoxColumn check = new CheckBoxColumn(createStringResource("pageTasks.node.clustered"), "clustered"); + check.setEnabled(false); + columns.add(check); + columns.add(new PropertyColumn(createStringResource("pageTasks.node.statusMessage"), "statusMessage")); - @Override - protected List getHeaderMenuItems() { - return createNodesInlineMenu(true); - } - }; - columns.add(menuColumn); + IColumn menuColumn = new InlineMenuButtonColumn(createNodesInlineMenu(false), 2, + PageTasks.this) { + @Override + protected int getHeaderNumberOfButtons() { + return 2; + } - return columns; - } + @Override + protected List getHeaderMenuItems() { + return createNodesInlineMenu(true); + } + }; + columns.add(menuColumn); - private List createNodesInlineMenu(boolean isHeader) { - List items = new ArrayList<>(); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.stopScheduler"), - new Model<>(false), - new Model<>(false), - false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - stopSchedulersPerformed(target); - } else { - NodeDto rowDto = getRowModel().getObject(); - stopSchedulersPerformed(target, rowDto); - } - } - }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.NODE_STOP_SCHEDULER.getMenuItemId(), - GuiStyleConstants.CLASS_STOP_MENU_ITEM, - DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()){ + return columns; + } - private static final long serialVersionUID = 1L; + private List createNodesInlineMenu(boolean isHeader) { + List items = new ArrayList<>(); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.stopScheduler"), + new Model<>(false), + new Model<>(false), + false, + new ColumnMenuAction() { - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); - } + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + stopSchedulersPerformed(target); + } else { + NodeDto rowDto = getRowModel().getObject(); + stopSchedulersPerformed(target, rowDto); + } + } + }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.NODE_STOP_SCHEDULER.getMenuItemId(), + GuiStyleConstants.CLASS_STOP_MENU_ITEM, + DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()) { - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.stopSchedulerAction").getString(); - return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } + private static final long serialVersionUID = 1L; - }); + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); + } - items.add(new InlineMenuItem(createStringResource("pageTasks.button.stopSchedulerAndTasks"), false, - new ColumnMenuAction() { + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.stopSchedulerAction").getString(); + return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } - @Override - public void onClick(AjaxRequestTarget target) { - stopSchedulersAndTasksPerformed(target, getRowModel() != null ? getRowModel().getObject() : null); - } - }){ + }); - private static final long serialVersionUID = 1L; + items.add(new InlineMenuItem(createStringResource("pageTasks.button.stopSchedulerAndTasks"), false, + new ColumnMenuAction() { - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); - } + @Override + public void onClick(AjaxRequestTarget target) { + stopSchedulersAndTasksPerformed(target, getRowModel() != null ? getRowModel().getObject() : null); + } + }) { - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.stopSchedulerTasksAction").getString(); - return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); - - - items.add(new InlineMenuItem(createStringResource("pageTasks.button.startScheduler"), - new Model<>(false), - new Model<>(false), - false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - startSchedulersPerformed(target); - } else { - NodeDto rowDto = getRowModel().getObject(); - startSchedulersPerformed(target, rowDto); - } - } - }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.NODE_START.getMenuItemId(), - GuiStyleConstants.CLASS_START_MENU_ITEM, - DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()){ + private static final long serialVersionUID = 1L; - private static final long serialVersionUID = 1L; + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); + } - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); - } + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.stopSchedulerTasksAction").getString(); + return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.startSchedulerAction").getString(); - return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteNode"), false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - deleteNodesPerformed(target); - } else { - NodeDto rowDto = getRowModel().getObject(); - deleteNodesPerformed(target, rowDto); - } - } - }){ + items.add(new InlineMenuItem(createStringResource("pageTasks.button.startScheduler"), + new Model<>(false), + new Model<>(false), + false, + new ColumnMenuAction() { - private static final long serialVersionUID = 1L; + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + startSchedulersPerformed(target); + } else { + NodeDto rowDto = getRowModel().getObject(); + startSchedulersPerformed(target, rowDto); + } + } + }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.NODE_START.getMenuItemId(), + GuiStyleConstants.CLASS_START_MENU_ITEM, + DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()) { - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); - } + private static final long serialVersionUID = 1L; - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.deleteAction").getString(); - return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); + } - return items; - } + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.startSchedulerAction").getString(); + return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteNode"), false, + new ColumnMenuAction() { - private List> initTaskColumns() { - List> columns = new ArrayList<>(); + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + deleteNodesPerformed(target); + } else { + NodeDto rowDto = getRowModel().getObject(); + deleteNodesPerformed(target, rowDto); + } + } + }) { - IColumn column = new CheckBoxHeaderColumn() - { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - protected void onUpdateRow(AjaxRequestTarget target, DataTable table, IModel rowModel) { - TaskDtoProvider taskTableProvider = (TaskDtoProvider) table.getDataProvider(); - List objects = taskTableProvider.getAvailableData(); - if (objects == null || objects.isEmpty()) { - return; - } - objects.forEach(taskDto -> { - if (taskDto.getOid().equals(rowModel.getObject().getOid())){ - boolean selected = rowModel.getObject().isSelected(); - taskDto.setSelected(selected); - } - }); - super.onUpdateRow(target, table, rowModel); - } - }; - columns.add(column); + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isNodeShowConfirmationDialog((ColumnMenuAction) getAction()); + } + + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.deleteAction").getString(); + return PageTasks.this.getNodeConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); + + return items; + } - column = createTaskNameColumn(this, "pageTasks.task.name"); - columns.add(column); + private List> initTaskColumns() { + List> columns = new ArrayList<>(); - columns.add(createTaskCategoryColumn(this, "pageTasks.task.category")); + IColumn column = new CheckBoxHeaderColumn() { + private static final long serialVersionUID = 1L; + + @Override + protected void onUpdateRow(AjaxRequestTarget target, DataTable table, IModel rowModel) { + TaskDtoProvider taskTableProvider = (TaskDtoProvider) table.getDataProvider(); + List objects = taskTableProvider.getAvailableData(); + if (objects == null || objects.isEmpty()) { + return; + } + objects.forEach(taskDto -> { + if (taskDto.getOid().equals(rowModel.getObject().getOid())) { + boolean selected = rowModel.getObject().isSelected(); + taskDto.setSelected(selected); + } + }); + super.onUpdateRow(target, table, rowModel); + } + }; + columns.add(column); + + column = createTaskNameColumn(this, "pageTasks.task.name"); + columns.add(column); + + columns.add(createTaskCategoryColumn(this, "pageTasks.task.category")); columns.add(new IconColumn(createStringResource("")) { @Override @@ -583,545 +590,609 @@ public void populateItem(Item> item, String componentId, } }); - columns.add(new AbstractExportableColumn(createStringResource("pageTasks.task.objectRef")) { + columns.add(new AbstractExportableColumn(createStringResource("pageTasks.task.objectRef")) { - @Override - public void populateItem(Item> item, String componentId, - final IModel rowModel) { - item.add(new Label(componentId, new AbstractReadOnlyModel() { + @Override + public void populateItem(Item> item, String componentId, + final IModel rowModel) { + item.add(new Label(componentId, new AbstractReadOnlyModel() { - @Override - public Object getObject() { - return createObjectRef(rowModel); - } - })); - } + @Override + public Object getObject() { + return createObjectRef(rowModel); + } + })); + } - @Override - public IModel getDataModel(IModel rowModel) { - return Model.of(createObjectRef(rowModel)); - } + @Override + public IModel getDataModel(IModel rowModel) { + return Model.of(createObjectRef(rowModel)); + } - }); - columns.add(createTaskExecutionStatusColumn(this, "pageTasks.task.execution")); - columns.add(new PropertyColumn<>(createStringResource("pageTasks.task.executingAt"), "executingAt")); - columns.add(createProgressColumn(this, "pageTasks.task.progress")); - columns.add(new AbstractExportableColumn(createStringResource("pageTasks.task.currentRunTime")) { - - @Override - public void populateItem(final Item> item, final String componentId, - final IModel rowModel) { - - DateLabelComponent dateLabel = new DateLabelComponent(componentId, new AbstractReadOnlyModel() { - - @Override - public Date getObject() { - Date date = getCurrentRuntime(rowModel); - TaskDto task = rowModel.getObject(); - if (task.getRawExecutionStatus() == TaskExecutionStatus.CLOSED && date != null) { - ((DateLabelComponent) item.get(componentId)).setBefore("closed at "); - } else if (date != null) { - ((DateLabelComponent) item.get(componentId)).setBefore(DurationFormatUtils.formatDurationWords(date.getTime(), true, true)); - } - return date; - } - }, DateLabelComponent.MEDIUM_MEDIUM_STYLE); - item.add(dateLabel); - } + }); + columns.add(createTaskExecutionStatusColumn(this, "pageTasks.task.execution")); + columns.add(new PropertyColumn<>(createStringResource("pageTasks.task.executingAt"), "executingAt")); + columns.add(createProgressColumn(this, "pageTasks.task.progress")); + columns.add(new AbstractExportableColumn(createStringResource("pageTasks.task.currentRunTime")) { - @Override - public IModel getDataModel(IModel rowModel) { - TaskDto task = rowModel.getObject(); - Date date = getCurrentRuntime(rowModel); - String displayValue = ""; - if (date != null) { - if (task.getRawExecutionStatus() == TaskExecutionStatus.CLOSED) { - displayValue = "closed at " + WebComponentUtil.getLocalizedDate(date, DateLabelComponent.LONG_MEDIUM_STYLE); - } else { - displayValue = DurationFormatUtils.formatDurationWords(date.getTime(), true, true); - } - } - return Model.of(displayValue); - } - }); - columns.add(new AbstractExportableColumn(createStringResource("pageTasks.task.scheduledToRunAgain")) { - - @Override - public void populateItem(Item> item, String componentId, - final IModel rowModel) { - item.add(new Label(componentId, new AbstractReadOnlyModel() { - - @Override - public Object getObject() { - return createScheduledToRunAgain(rowModel); - } - })); - } - @Override - public IModel getDataModel(IModel rowModel) { - return Model.of(createScheduledToRunAgain(rowModel)); - } - }); + @Override + public void populateItem(final Item> item, final String componentId, + final IModel rowModel) { - columns.add(new IconColumn(createStringResource("pageTasks.task.status")) { + DateLabelComponent dateLabel = new DateLabelComponent(componentId, new AbstractReadOnlyModel() { - @Override - protected IModel createTitleModel(final IModel rowModel) { + @Override + public Date getObject() { + Date date = getCurrentRuntime(rowModel); + TaskDto task = rowModel.getObject(); + if (task.getRawExecutionStatus() == TaskExecutionStatus.CLOSED && date != null) { + ((DateLabelComponent) item.get(componentId)).setBefore("closed at "); + } else if (date != null) { + ((DateLabelComponent) item.get(componentId)) + .setBefore(DurationFormatUtils.formatDurationWords(date.getTime(), true, true)); + } + return date; + } + }, DateLabelComponent.MEDIUM_MEDIUM_STYLE); + item.add(dateLabel); + } - return new AbstractReadOnlyModel() { + @Override + public IModel getDataModel(IModel rowModel) { + TaskDto task = rowModel.getObject(); + Date date = getCurrentRuntime(rowModel); + String displayValue = ""; + if (date != null) { + if (task.getRawExecutionStatus() == TaskExecutionStatus.CLOSED) { + displayValue = + "closed at " + WebComponentUtil.getLocalizedDate(date, DateLabelComponent.LONG_MEDIUM_STYLE); + } else { + displayValue = DurationFormatUtils.formatDurationWords(date.getTime(), true, true); + } + } + return Model.of(displayValue); + } + }); + columns.add(new AbstractExportableColumn(createStringResource("pageTasks.task.scheduledToRunAgain")) { - @Override - public String getObject() { - TaskDto dto = rowModel.getObject(); + @Override + public void populateItem(Item> item, String componentId, + final IModel rowModel) { + item.add(new Label(componentId, new AbstractReadOnlyModel() { - if (dto != null && dto.getStatus() != null) { - return createStringResourceStatic(PageTasks.this, dto.getStatus()).getString(); - } else { - return createStringResourceStatic(PageTasks.this, OperationResultStatus.UNKNOWN).getString(); - } - } - }; - } + @Override + public Object getObject() { + return createScheduledToRunAgain(rowModel); + } + })); + } - @Override - protected IModel createIconModel(final IModel rowModel) { - return new AbstractReadOnlyModel() { - - @Override - public String getObject() { - if (rowModel != null && rowModel.getObject() != null && rowModel.getObject().getStatus() != null) { - return OperationResultStatusPresentationProperties.parseOperationalResultStatus(rowModel.getObject().getStatus().createStatusType()).getIcon() + " fa-lg"; - } else - return OperationResultStatusPresentationProperties.UNKNOWN.getIcon() + " fa-lg"; - } - }; - } - }); + @Override + public IModel getDataModel(IModel rowModel) { + return Model.of(createScheduledToRunAgain(rowModel)); + } + }); - IColumn menuColumn = new InlineMenuButtonColumn(createTasksInlineMenu(false, null), 2, PageTasks.this){ - @Override - protected int getHeaderNumberOfButtons() { - return 2; - } + columns.add(new IconColumn(createStringResource("pageTasks.task.status")) { - @Override - protected List getHeaderMenuItems() { - return createTasksInlineMenu(true, null); - } - }; - columns.add(menuColumn); + @Override + protected IModel createTitleModel(final IModel rowModel) { - return columns; - } + return new AbstractReadOnlyModel() { + + @Override + public String getObject() { + TaskDto dto = rowModel.getObject(); + + if (dto != null && dto.getStatus() != null) { + return createStringResourceStatic(PageTasks.this, dto.getStatus()).getString(); + } else { + return createStringResourceStatic(PageTasks.this, OperationResultStatus.UNKNOWN).getString(); + } + } + }; + } + + @Override + protected IModel createIconModel(final IModel rowModel) { + return new AbstractReadOnlyModel() { + + @Override + public String getObject() { + if (rowModel != null && rowModel.getObject() != null && rowModel.getObject().getStatus() != null) { + return OperationResultStatusPresentationProperties + .parseOperationalResultStatus(rowModel.getObject().getStatus().createStatusType()).getIcon() + + " fa-lg"; + } else + return OperationResultStatusPresentationProperties.UNKNOWN.getIcon() + " fa-lg"; + } + }; + } + }); + + IColumn menuColumn = new InlineMenuButtonColumn(createTasksInlineMenu(false, null), 2, + PageTasks.this) { + @Override + protected int getHeaderNumberOfButtons() { + return 2; + } + + @Override + protected List getHeaderMenuItems() { + return createTasksInlineMenu(true, null); + } + }; + columns.add(menuColumn); + + return columns; + } @NotNull public static AbstractExportableColumn createProgressColumn(PageBase pageBase, final String titleKey) { return new AbstractExportableColumn(pageBase.createStringResource(titleKey)) { - @Override - public void populateItem(Item> cellItem, String componentId, final IModel rowModel) { - cellItem.add(new Label(componentId, new AbstractReadOnlyModel() { - @Override - public Object getObject() { - rowModel.getObject().ensureSubtasksLoaded(pageBase); - return rowModel.getObject().getProgressDescription(pageBase); - } - })); - } - - @Override - public IModel getDataModel(IModel rowModel) { - rowModel.getObject().ensureSubtasksLoaded(pageBase); - return Model.of(rowModel.getObject().getProgressDescription(pageBase)); - } + @Override + public void populateItem(Item> cellItem, String componentId, final IModel rowModel) { + cellItem.add(new Label(componentId, new AbstractReadOnlyModel() { + @Override + public Object getObject() { + rowModel.getObject().ensureSubtasksLoaded(pageBase); + return rowModel.getObject().getProgressDescription(pageBase); + } + })); + } + + @Override + public IModel getDataModel(IModel rowModel) { + rowModel.getObject().ensureSubtasksLoaded(pageBase); + return Model.of(rowModel.getObject().getProgressDescription(pageBase)); + } }; } private List createTasksInlineMenu(boolean isHeader, TaskDto dto) { - List items = new ArrayList<>(); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.suspendTask"), - new Model<>(false), - new Model<>(false), - false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - suspendTasksPerformed(target); - } else { - TaskDto rowDto = getRowModel().getObject(); - suspendTaskPerformed(target, rowDto); - } - } - }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.SUSPEND.getMenuItemId(), - GuiStyleConstants.CLASS_SUSPEND_MENU_ITEM, - DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()){ - private static final long serialVersionUID = 1L; - - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); - } + List items = new ArrayList<>(); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.suspendTask"), + new Model<>(false), + new Model<>(false), + false, + new ColumnMenuAction() { - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.suspendAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + suspendTasksPerformed(target); + } else { + TaskDto rowDto = getRowModel().getObject(); + suspendTaskPerformed(target, rowDto); + } + } + }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.SUSPEND.getMenuItemId(), + GuiStyleConstants.CLASS_SUSPEND_MENU_ITEM, + DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()) { + private static final long serialVersionUID = 1L; - }); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.resumeTask"), - new Model<>(false), - new Model<>(false), - false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - resumeTasksPerformed(target); - } else { - TaskDto rowDto = getRowModel().getObject(); - resumeTaskPerformed(target, rowDto); - } - } - }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.RESUME.getMenuItemId(), - GuiStyleConstants.CLASS_RESUME_MENU_ITEM, - DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()){ + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - private static final long serialVersionUID = 1L; + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.suspendAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); - } + }); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.resumeTask"), + new Model<>(false), + new Model<>(false), + false, + new ColumnMenuAction() { - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.resumeAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.scheduleTask"), false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - scheduleTasksPerformed(target); - } else { - TaskDto rowDto = getRowModel().getObject(); - scheduleTaskPerformed(target, rowDto); - } - } - }){ + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + resumeTasksPerformed(target); + } else { + TaskDto rowDto = getRowModel().getObject(); + resumeTaskPerformed(target, rowDto); + } + } + }, InlineMenuItem.TASKS_INLINE_MENU_ITEM_ID.RESUME.getMenuItemId(), + GuiStyleConstants.CLASS_RESUME_MENU_ITEM, + DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString()) { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); - } + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.runNowAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.resumeAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.scheduleTask"), false, + new ColumnMenuAction() { - }); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteTask"), false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null){ - deleteTaskConfirmedPerformed(target, null); - } else { - TaskDto rowDto = getRowModel().getObject(); - deleteTaskConfirmedPerformed(target, rowDto); - } - } - }){ + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + scheduleTasksPerformed(target); + } else { + TaskDto rowDto = getRowModel().getObject(); + scheduleTaskPerformed(target, rowDto); + } + } + }) { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); - } + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - @Override - public IModel getConfirmationMessageModel(){ - String actionName = createStringResource("pageTasks.message.deleteAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.runNowAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } - }); - if (!isHeader && dto != null) { - if (dto.getTaskType().getWorkManagement() != null && dto.getTaskType().getWorkManagement().getTaskKind() == TaskKindType.COORDINATOR) { - items.add(new InlineMenuItem(createStringResource("pageTasks.button.reconcileWorkers"), false, - new ColumnMenuAction() { - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null) { - throw new UnsupportedOperationException(); - } else { - TaskDto rowDto = getRowModel().getObject(); - reconcileWorkersConfirmedPerformed(target, rowDto); - } - } - }) { - - private static final long serialVersionUID = 1L; - - @Override - public boolean isShowConfirmationDialog() { - return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); - } - - @Override - public IModel getConfirmationMessageModel() { - String actionName = createStringResource("pageTasks.message.reconcileWorkersAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); - } - } - if (isHeader) { - items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteAllClosedTasks"), false, - new ColumnMenuAction() { + }); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteTask"), false, + new ColumnMenuAction() { - @Override - public void onClick(AjaxRequestTarget target) { - deleteAllClosedTasksConfirmedPerformed(target); - } - }){ + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + deleteTaskConfirmedPerformed(target, null); + } else { + TaskDto rowDto = getRowModel().getObject(); + deleteTaskConfirmedPerformed(target, rowDto); + } + } + }) { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public boolean isShowConfirmationDialog() { - return true; - } + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - @Override - public IModel getConfirmationMessageModel(){ - return createStringResource("pageTasks.message.deleteAllClosedTasksConfirm"); - } + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.deleteAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } - }); - } - return items; - } + }); + if (!isHeader && dto != null) { + if (dto.getTaskType().getWorkManagement() != null + && dto.getTaskType().getWorkManagement().getTaskKind() == TaskKindType.COORDINATOR) { + items.add(new InlineMenuItem(createStringResource("pageTasks.button.reconcileWorkers"), false, + new ColumnMenuAction() { + + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + reconcileWorkersConfirmedPerformed(target, rowDto); + } + } + }) { + + private static final long serialVersionUID = 1L; + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - // used in SubtasksPanel as well - public static IColumn createTaskNameColumn(final Component component, String label) { - LinkColumn column = new LinkColumn(createStringResourceStatic(component, label), TaskDto.F_NAME, TaskDto.F_NAME) { + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.reconcileWorkersAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.suspendCoordinatorOnly"), false, + new ColumnMenuAction() { + + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + suspendCoordinatorOnly(target, rowDto); + } + } + }) { + + private static final long serialVersionUID = 1L; - @Override - public void onClick(AjaxRequestTarget target, IModel rowModel) { - TaskDto task = rowModel.getObject(); - taskDetailsPerformed(target, task.getOid()); - } + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - private void taskDetailsPerformed(AjaxRequestTarget target, String oid) { - PageParameters parameters = new PageParameters(); - parameters.add(OnePageParameterEncoder.PARAMETER, oid); + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.suspendAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); + items.add(new InlineMenuItem(createStringResource("pageTasks.button.resumeCoordinatorOnly"), false, + new ColumnMenuAction() { + + @Override + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + resumeCoordinatorOnly(target, rowDto); + } + } + }) { + + private static final long serialVersionUID = 1L; - PageBase page = (PageBase) component.getPage(); - page.navigateToNext(PageTaskEdit.class, parameters); - } + @Override + public boolean isShowConfirmationDialog() { + return PageTasks.this.isTaskShowConfirmationDialog((ColumnMenuAction) getAction()); + } - @Override - public boolean isEnabled(IModel rowModel) { - return super.isEnabled(rowModel) && rowModel.getObject().getOid() != null; - } - }; - return column; - } + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.resumeAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }); + } + } + if (isHeader) { + items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteAllClosedTasks"), false, + new ColumnMenuAction() { - public static AbstractColumn createTaskCategoryColumn(final Component component, String label) { - return new AbstractExportableColumn(createStringResourceStatic(component, label)) { + @Override + public void onClick(AjaxRequestTarget target) { + deleteAllClosedTasksConfirmedPerformed(target); + } + }) { - @Override - public void populateItem(Item> item, String componentId, - final IModel rowModel) { - item.add(new Label(componentId, WebComponentUtil.createCategoryNameModel(component, new PropertyModel<>(rowModel, TaskDto.F_CATEGORY)))); - } + private static final long serialVersionUID = 1L; - @Override - public IModel getDataModel(IModel rowModel) { - return WebComponentUtil.createCategoryNameModel(component, new PropertyModel<>(rowModel, TaskDto.F_CATEGORY)); - } - }; - } + @Override + public boolean isShowConfirmationDialog() { + return true; + } - public static EnumPropertyColumn createTaskResultStatusColumn(final Component component, String label) { - return new EnumPropertyColumn(createStringResourceStatic(component, label), "status") { + @Override + public IModel getConfirmationMessageModel() { + return createStringResource("pageTasks.message.deleteAllClosedTasksConfirm"); + } - @Override - protected String translate(Enum en) { - return createStringResourceStatic(component, en).getString(); - } - }; - } + }); + } + return items; + } - public static EnumPropertyColumn createTaskExecutionStatusColumn(final Component component, String label) { - return new EnumPropertyColumn(createStringResourceStatic(component, label), "execution") { + // used in SubtasksPanel as well + public static IColumn createTaskNameColumn(final Component component, String label) { + LinkColumn column = new LinkColumn(createStringResourceStatic(component, label), TaskDto.F_NAME, + TaskDto.F_NAME) { - @Override - protected String translate(Enum en) { - return createStringResourceStatic(component, en).getString(); - } - }; - } + @Override + public void onClick(AjaxRequestTarget target, IModel rowModel) { + TaskDto task = rowModel.getObject(); + taskDetailsPerformed(target, task.getOid()); + } -// public static IColumn createTaskDetailColumn(final Component component, String label, boolean workflowsEnabled) { -// -// if (workflowsEnabled) { -// -// return new LinkColumn(createStringResourceStatic(component, label), TaskDto.F_WORKFLOW_LAST_DETAILS) { -// -// @Override -// public void onClick(AjaxRequestTarget target, IModel rowModel) { -// TaskDto task = rowModel.getObject(); -// taskDetailsPerformed(target, task); -// } -// -// // todo display a message if process instance cannot be found -// private void taskDetailsPerformed(AjaxRequestTarget target, TaskDto task) { -// if (task.getWorkflowProcessInstanceId() != null) { -// PageParameters parameters = new PageParameters(); -// parameters.add(OnePageParameterEncoder.PARAMETER, task.getWorkflowProcessInstanceId()); -// component.setResponsePage(new PageProcessInstance(parameters, (PageBase) component.getPage())); -// } -// } -// -// }; -// } else { -// return new PropertyColumn(createStringResourceStatic(component, label), TaskDto.F_WORKFLOW_LAST_DETAILS); -// } -// } - - private String createObjectRef(IModel taskModel) { - TaskDto task = taskModel.getObject(); - if (task.getObjectRef() == null) { - return ""; - } - if (StringUtils.isNotEmpty(task.getObjectRefName())) { - return task.getObjectRefName(); - } else { - return task.getObjectRef().getOid(); - } - } + private void taskDetailsPerformed(AjaxRequestTarget target, String oid) { + PageParameters parameters = new PageParameters(); + parameters.add(OnePageParameterEncoder.PARAMETER, oid); + + PageBase page = (PageBase) component.getPage(); + page.navigateToNext(PageTaskEdit.class, parameters); + } + + @Override + public boolean isEnabled(IModel rowModel) { + return super.isEnabled(rowModel) && rowModel.getObject().getOid() != null; + } + }; + return column; + } + + public static AbstractColumn createTaskCategoryColumn(final Component component, String label) { + return new AbstractExportableColumn(createStringResourceStatic(component, label)) { - private String createScheduledToRunAgain(IModel taskModel) { - TaskDto task = taskModel.getObject(); + @Override + public void populateItem(Item> item, String componentId, + final IModel rowModel) { + item.add(new Label(componentId, + WebComponentUtil.createCategoryNameModel(component, new PropertyModel<>(rowModel, TaskDto.F_CATEGORY)))); + } + + @Override + public IModel getDataModel(IModel rowModel) { + return WebComponentUtil.createCategoryNameModel(component, new PropertyModel<>(rowModel, TaskDto.F_CATEGORY)); + } + }; + } + + public static EnumPropertyColumn createTaskResultStatusColumn(final Component component, String label) { + return new EnumPropertyColumn(createStringResourceStatic(component, label), "status") { + + @Override + protected String translate(Enum en) { + return createStringResourceStatic(component, en).getString(); + } + }; + } + + public static EnumPropertyColumn createTaskExecutionStatusColumn(final Component component, String label) { + return new EnumPropertyColumn(createStringResourceStatic(component, label), "execution") { + + @Override + protected String translate(Enum en) { + return createStringResourceStatic(component, en).getString(); + } + }; + } + + // public static IColumn createTaskDetailColumn(final Component component, String label, boolean workflowsEnabled) { + // + // if (workflowsEnabled) { + // + // return new LinkColumn(createStringResourceStatic(component, label), TaskDto.F_WORKFLOW_LAST_DETAILS) { + // + // @Override + // public void onClick(AjaxRequestTarget target, IModel rowModel) { + // TaskDto task = rowModel.getObject(); + // taskDetailsPerformed(target, task); + // } + // + // // todo display a message if process instance cannot be found + // private void taskDetailsPerformed(AjaxRequestTarget target, TaskDto task) { + // if (task.getWorkflowProcessInstanceId() != null) { + // PageParameters parameters = new PageParameters(); + // parameters.add(OnePageParameterEncoder.PARAMETER, task.getWorkflowProcessInstanceId()); + // component.setResponsePage(new PageProcessInstance(parameters, (PageBase) component.getPage())); + // } + // } + // + // }; + // } else { + // return new PropertyColumn(createStringResourceStatic(component, label), TaskDto.F_WORKFLOW_LAST_DETAILS); + // } + // } + + private String createObjectRef(IModel taskModel) { + TaskDto task = taskModel.getObject(); + if (task.getObjectRef() == null) { + return ""; + } + if (StringUtils.isNotEmpty(task.getObjectRefName())) { + return task.getObjectRefName(); + } else { + return task.getObjectRef().getOid(); + } + } + + private String createScheduledToRunAgain(IModel taskModel) { + TaskDto task = taskModel.getObject(); boolean runnable = task.getRawExecutionStatus() == TaskExecutionStatus.RUNNABLE; - Long scheduledAfter = task.getScheduledToStartAgain(); + Long scheduledAfter = task.getScheduledToStartAgain(); Long retryAfter = runnable ? task.getRetryAfter() : null; - if (scheduledAfter == null) { - if (retryAfter == null || retryAfter <= 0) { - return ""; - } - } else if (scheduledAfter == TaskDto.NOW) { // TODO what about retryTime? - return getString(runnable ? "pageTasks.now" : "pageTasks.nowForNotRunningTasks"); - } else if (scheduledAfter == TaskDto.RUNS_CONTINUALLY) { // retryTime is probably null here - return getString("pageTasks.runsContinually"); - } else if (scheduledAfter == TaskDto.ALREADY_PASSED && retryAfter == null) { - return getString(runnable ? "pageTasks.alreadyPassed" : "pageTasks.alreadyPassedForNotRunningTasks"); - } + if (scheduledAfter == null) { + if (retryAfter == null || retryAfter <= 0) { + return ""; + } + } else if (scheduledAfter == TaskDto.NOW) { // TODO what about retryTime? + return getString(runnable ? "pageTasks.now" : "pageTasks.nowForNotRunningTasks"); + } else if (scheduledAfter == TaskDto.RUNS_CONTINUALLY) { // retryTime is probably null here + return getString("pageTasks.runsContinually"); + } else if (scheduledAfter == TaskDto.ALREADY_PASSED && retryAfter == null) { + return getString(runnable ? "pageTasks.alreadyPassed" : "pageTasks.alreadyPassedForNotRunningTasks"); + } - long displayTime; - boolean displayAsRetry; - if (retryAfter != null && retryAfter > 0 && (scheduledAfter == null || scheduledAfter < 0 || retryAfter < scheduledAfter)) { - displayTime = retryAfter; - displayAsRetry = true; + long displayTime; + boolean displayAsRetry; + if (retryAfter != null && retryAfter > 0 && (scheduledAfter == null || scheduledAfter < 0 + || retryAfter < scheduledAfter)) { + displayTime = retryAfter; + displayAsRetry = true; } else { - displayTime = scheduledAfter; - displayAsRetry = false; + displayTime = scheduledAfter; + displayAsRetry = false; } String key; - if (runnable) { - key = displayAsRetry ? "pageTasks.retryIn" : "pageTasks.in"; + if (runnable) { + key = displayAsRetry ? "pageTasks.retryIn" : "pageTasks.in"; } else { - key = "pageTasks.inForNotRunningTasks"; + key = "pageTasks.inForNotRunningTasks"; } - //todo i18n - return PageBase.createStringResourceStatic(this, key, DurationFormatUtils.formatDurationWords(displayTime, true, true)).getString(); - } + //todo i18n + return PageBase.createStringResourceStatic(this, key, DurationFormatUtils.formatDurationWords(displayTime, true, true)) + .getString(); + } - private Date getCurrentRuntime(IModel taskModel) { - TaskDto task = taskModel.getObject(); + private Date getCurrentRuntime(IModel taskModel) { + TaskDto task = taskModel.getObject(); - if (task.getRawExecutionStatus() == TaskExecutionStatus.CLOSED) { + if (task.getRawExecutionStatus() == TaskExecutionStatus.CLOSED) { - //todo i18n and proper date/time formatting - Long time = task.getCompletionTimestamp(); - if (time == null) { - return null; - } - return new Date(time); + //todo i18n and proper date/time formatting + Long time = task.getCompletionTimestamp(); + if (time == null) { + return null; + } + return new Date(time); - } else { - Long time = task.getCurrentRuntime(); - if (time == null) { - return null; - } - //todo i18n - return null; - } - } + } else { + Long time = task.getCurrentRuntime(); + if (time == null) { + return null; + } + //todo i18n + return null; + } + } - private String getLastCheckInTime(IModel nodeModel) { - NodeDto node = nodeModel.getObject(); - Long time = node.getLastCheckInTime(); - if (time == null || time == 0) { - return ""; - } + private String getLastCheckInTime(IModel nodeModel) { + NodeDto node = nodeModel.getObject(); + Long time = node.getLastCheckInTime(); + if (time == null || time == 0) { + return ""; + } - //todo i18n - return DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - time, true, true) - + " ago"; - } + //todo i18n + return DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - time, true, true) + + " ago"; + } - private void initDiagnosticButtons() { - AjaxButton deactivate = new AjaxButton("deactivateServiceThreads", - createStringResource("pageTasks.button.deactivateServiceThreads")) { + private void initDiagnosticButtons() { + AjaxButton deactivate = new AjaxButton("deactivateServiceThreads", + createStringResource("pageTasks.button.deactivateServiceThreads")) { - @Override - public void onClick(AjaxRequestTarget target) { - deactivateServiceThreadsPerformed(target); - } - }; - add(deactivate); + @Override + public void onClick(AjaxRequestTarget target) { + deactivateServiceThreadsPerformed(target); + } + }; + add(deactivate); - AjaxButton reactivate = new AjaxButton("reactivateServiceThreads", - createStringResource("pageTasks.button.reactivateServiceThreads")) { + AjaxButton reactivate = new AjaxButton("reactivateServiceThreads", + createStringResource("pageTasks.button.reactivateServiceThreads")) { - @Override - public void onClick(AjaxRequestTarget target) { - reactivateServiceThreadsPerformed(target); - } - }; - add(reactivate); + @Override + public void onClick(AjaxRequestTarget target) { + reactivateServiceThreadsPerformed(target); + } + }; + add(reactivate); - AjaxButton synchronize = new AjaxButton("synchronizeTasks", - createStringResource("pageTasks.button.synchronizeTasks")) { + AjaxButton synchronize = new AjaxButton("synchronizeTasks", + createStringResource("pageTasks.button.synchronizeTasks")) { - @Override - public void onClick(AjaxRequestTarget target) { - synchronizeTasksPerformed(target); - } - }; - add(synchronize); + @Override + public void onClick(AjaxRequestTarget target) { + synchronizeTasksPerformed(target); + } + }; + add(synchronize); AjaxButton synchronizeWorkflowRequests = new AjaxButton(ID_SYNCHRONIZE_WORKFLOW_REQUESTS, createStringResource("pageTasks.button.synchronizeWorkflowRequests")) { @@ -1133,88 +1204,121 @@ public void onClick(AjaxRequestTarget target) { }; add(synchronizeWorkflowRequests); -// adding Refresh button - AjaxButton refresh = new AjaxButton("refreshTasks", - createStringResource("pageTasks.button.refreshTasks")) { + // adding Refresh button + AjaxButton refresh = new AjaxButton("refreshTasks", + createStringResource("pageTasks.button.refreshTasks")) { - @Override - public void onClick(AjaxRequestTarget target) { - refreshTasks(target); - } - }; + @Override + public void onClick(AjaxRequestTarget target) { + refreshTasks(target); + } + }; - add(refresh); - } + add(refresh); + } - private Table getTaskTable() { - return (Table) get(createComponentPath(ID_MAIN_FORM, ID_TASK_TABLE)); - } + private Table getTaskTable() { + return (Table) get(createComponentPath(ID_MAIN_FORM, ID_TASK_TABLE)); + } - private Table getNodeTable() { - return (Table) get(createComponentPath(ID_MAIN_FORM, ID_NODE_TABLE)); - } + private Table getNodeTable() { + return (Table) get(createComponentPath(ID_MAIN_FORM, ID_NODE_TABLE)); + } - private boolean isSomeTaskSelected(List tasks, AjaxRequestTarget target) { - if (!tasks.isEmpty()) { - return true; - } + private boolean isSomeTaskSelected(List tasks, AjaxRequestTarget target) { + if (!tasks.isEmpty()) { + return true; + } - warn(getString("pageTasks.message.noTaskSelected")); - target.add(getFeedbackPanel()); - return false; - } + warn(getString("pageTasks.message.noTaskSelected")); + target.add(getFeedbackPanel()); + return false; + } - private boolean isSomeNodeSelected(List nodes, AjaxRequestTarget target) { - if (!nodes.isEmpty()) { - return true; - } + private boolean isSomeNodeSelected(List nodes, AjaxRequestTarget target) { + if (!nodes.isEmpty()) { + return true; + } - warn(getString("pageTasks.message.noNodeSelected")); - target.add(getFeedbackPanel()); - return false; - } + warn(getString("pageTasks.message.noNodeSelected")); + target.add(getFeedbackPanel()); + return false; + } - private void suspendTasksPerformed(AjaxRequestTarget target, List oidList) { - Task opTask = createSimpleTask(OPERATION_SUSPEND_TASKS); - OperationResult result = opTask.getResult(); - try { - boolean suspended = getTaskService().suspendTasks(oidList, WAIT_FOR_TASK_STOP, opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - if (suspended) { - result.recordStatus(OperationResultStatus.SUCCESS, "The task(s) have been successfully suspended."); // todo i18n - } else { - result.recordWarning("Task(s) suspension has been successfully requested; please check for its completion using task list."); // todo i18n - } - } - } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError("Couldn't suspend the task(s)", e); - } - showResult(result); + private void suspendTasksPerformed(AjaxRequestTarget target, List dtoList) { + Task opTask = createSimpleTask(OPERATION_SUSPEND_TASKS); + OperationResult result = opTask.getResult(); + try { + List plainTasks = dtoList.stream().filter(dto -> !dto.isCoordinator()).collect(Collectors.toList()); + List coordinators = dtoList.stream().filter(dto -> dto.isCoordinator()).collect(Collectors.toList()); + boolean suspendedPlain = suspendPlainTasks(plainTasks, result, opTask); + boolean suspendedCoordinators = suspendCoordinators(coordinators, result, opTask); + result.computeStatus(); + if (result.isSuccess()) { + if (suspendedPlain && suspendedCoordinators) { + result.recordStatus(OperationResultStatus.SUCCESS, + "The task(s) have been successfully suspended."); // todo i18n + } else { + result.recordWarning( + "Task(s) suspension has been successfully requested; please check for its completion using task list."); // todo i18n + } + } + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError("Couldn't suspend the task(s)", e); + } + showResult(result); - //refresh feedback and table - refreshTables(target); - } + //refresh feedback and table + refreshTables(target); + } - private void suspendTaskPerformed(AjaxRequestTarget target, TaskDto dto) { - suspendTasksPerformed(target, Arrays.asList(dto.getOid())); + private boolean suspendPlainTasks(List plainTasks, OperationResult result, Task opTask) + throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, + CommunicationException, ConfigurationException { + if (!plainTasks.isEmpty()) { + return getTaskService().suspendTasks(TaskDto.getOids(plainTasks), WAIT_FOR_TASK_STOP, opTask, result); + } else { + return true; + } + } + + private boolean suspendCoordinators(List coordinators, OperationResult result, Task opTask) + throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, + CommunicationException, ConfigurationException { + boolean suspended = true; + if (!coordinators.isEmpty()) { + for (TaskDto coordinator : coordinators) { + boolean s = getTaskService().suspendTaskTree(coordinator.getOid(), WAIT_FOR_TASK_STOP, opTask, result); + suspended = suspended && s; + } + } + return suspended; + } + + private void suspendTaskPerformed(AjaxRequestTarget target, TaskDto dto) { + suspendTasksPerformed(target, Collections.singletonList(dto)); } //region Task-level actions private void suspendTasksPerformed(AjaxRequestTarget target) { - List taskTypeList = WebComponentUtil.getSelectedData(getTaskTable()); - if (!isSomeTaskSelected(taskTypeList, target)) { + List dtoList = WebComponentUtil.getSelectedData(getTaskTable()); + if (!isSomeTaskSelected(dtoList, target)) { return; } - suspendTasksPerformed(target, TaskDto.getOids(taskTypeList)); + suspendTasksPerformed(target, dtoList); } - private void resumeTasksPerformed(AjaxRequestTarget target, List oids) { + private void resumeTasksPerformed(AjaxRequestTarget target, List dtoList) { Task opTask = createSimpleTask(OPERATION_RESUME_TASKS); OperationResult result = opTask.getResult(); try { - getTaskService().resumeTasks(oids, opTask, result); + List plainTasks = dtoList.stream().filter(dto -> !dto.isCoordinator()).collect(Collectors.toList()); + List coordinators = dtoList.stream().filter(dto -> dto.isCoordinator()).collect(Collectors.toList()); + getTaskService().resumeTasks(TaskDto.getOids(plainTasks), opTask, result); + for (TaskDto coordinator : coordinators) { + getTaskService().resumeTaskTree(coordinator.getOid(), opTask, result); + } result.computeStatus(); if (result.isSuccess()) { result.recordStatus(OperationResultStatus.SUCCESS, "The task(s) have been successfully resumed."); @@ -1228,8 +1332,9 @@ private void resumeTasksPerformed(AjaxRequestTarget target, List oids) { refreshTables(target); } + private void resumeTaskPerformed(AjaxRequestTarget target, TaskDto dto) { - resumeTasksPerformed(target, Arrays.asList(dto.getOid())); + resumeTasksPerformed(target, Collections.singletonList(dto)); } private void resumeTasksPerformed(AjaxRequestTarget target) { @@ -1238,7 +1343,7 @@ private void resumeTasksPerformed(AjaxRequestTarget target) { return; } - resumeTasksPerformed(target, TaskDto.getOids(taskDtoList)); + resumeTasksPerformed(target, taskDtoList); } private void scheduleTasksPerformed(AjaxRequestTarget target, List oids) { @@ -1339,7 +1444,7 @@ private void startSchedulersPerformed(AjaxRequestTarget target, List ide } private void startSchedulersPerformed(AjaxRequestTarget target, NodeDto dto) { - startSchedulersPerformed(target, Arrays.asList(dto.getNodeIdentifier())); + startSchedulersPerformed(target, Collections.singletonList(dto.getNodeIdentifier())); } private void startSchedulersPerformed(AjaxRequestTarget target) { @@ -1370,7 +1475,7 @@ private void stopSchedulersPerformed(AjaxRequestTarget target, List iden } private void stopSchedulersPerformed(AjaxRequestTarget target, NodeDto dto) { - stopSchedulersPerformed(target, Arrays.asList(dto.getNodeIdentifier())); + stopSchedulersPerformed(target, Collections.singletonList(dto.getNodeIdentifier())); } private void stopSchedulersPerformed(AjaxRequestTarget target) { @@ -1411,7 +1516,7 @@ private void deleteNodesPerformed(AjaxRequestTarget target, List nodes) } private void deleteNodesPerformed(AjaxRequestTarget target, NodeDto dto) { - deleteNodesPerformed(target, Arrays.asList(dto)); + deleteNodesPerformed(target, Collections.singletonList(dto)); } private void deleteNodesPerformed(AjaxRequestTarget target) { @@ -1656,6 +1761,39 @@ private void reconcileWorkersConfirmedPerformed(AjaxRequestTarget target, @NotNu refreshTables(target); } + private void suspendCoordinatorOnly(AjaxRequestTarget target, @NotNull TaskDto task) { + Task opTask = createSimpleTask(OPERATION_SUSPEND_TASK); + OperationResult result = opTask.getResult(); + try { + getTaskService().suspendTasks(Collections.singleton(task.getOid()), WAIT_FOR_TASK_STOP, opTask, result); + // TODO check whether the suspension was complete + result.computeStatus(); + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError("Couldn't suspend the coordinator", e); // todo i18n + } + showResult(result); + + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); + refreshTables(target); + } + + private void resumeCoordinatorOnly(AjaxRequestTarget target, @NotNull TaskDto task) { + Task opTask = createSimpleTask(OPERATION_RESUME_TASK); + OperationResult result = opTask.getResult(); + try { + getTaskService().resumeTasks(Collections.singleton(task.getOid()), opTask, result); + result.computeStatus(); + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError("Couldn't resume the coordinator", e); // todo i18n + } + showResult(result); + + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); + refreshTables(target); + } + private static class SearchFragment extends Fragment { public SearchFragment(String id, String markupId, MarkupContainer markupProvider, diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index adf9927a846..dd064577115 100755 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -2139,6 +2139,8 @@ pageTasks.button.deactivateServiceThreads=Stop all threads pageTasks.button.deleteNode=Delete pageTasks.button.deleteTask=Delete pageTasks.button.reconcileWorkers=Reconcile workers +pageTasks.button.suspendCoordinatorOnly=Suspend (coordinator only) +pageTasks.button.resumeCoordinatorOnly=Resume (coordinator only) pageTasks.button.deleteAllClosedTasks=Delete all closed tasks pageTasks.button.reactivateServiceThreads=Start all threads pageTasks.button.refreshTasks=Refresh tasks diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/TaskService.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/TaskService.java index 122d82719dd..9f17da546ee 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/TaskService.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/TaskService.java @@ -54,7 +54,9 @@ public interface TaskService { */ boolean suspendTasks(Collection taskOids, long waitForStop, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException; - /** + boolean suspendTaskTree(String taskOid, long waitForStop, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException; + + /** * Suspends tasks and deletes them. * * @param taskOids Collection of task OIDs to be suspended and deleted. @@ -76,6 +78,7 @@ public interface TaskService { * @throws com.evolveum.midpoint.util.exception.ObjectNotFoundException */ void resumeTasks(Collection taskOids, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException; + void resumeTaskTree(String coordinatorOid, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException; /** * Schedules a RUNNABLE/CLOSED tasks to be run immediately. (If a task will really start immediately, diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java index 69871aee582..f928c5dbcaf 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java @@ -96,6 +96,8 @@ import java.io.*; import java.util.*; +import static java.util.Collections.singleton; + /** * This used to be an interface, but it was switched to class for simplicity. I * don't expect that the implementation of the controller will be ever replaced. @@ -1806,6 +1808,12 @@ public boolean suspendTasks(Collection taskOids, long waitForStop, Task return taskManager.suspendTasks(taskOids, waitForStop, parentResult); } + @Override + public boolean suspendTaskTree(String taskOid, long waitForStop, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + authorizeTaskCollectionOperation(ModelAuthorizationAction.SUSPEND_TASK, singleton(taskOid), operationTask, parentResult); + return taskManager.suspendTaskTree(taskOid, waitForStop, parentResult); + } + @Override public void suspendAndDeleteTasks(Collection taskOids, long waitForStop, boolean alsoSubtasks, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException { authorizeTaskCollectionOperation(ModelAuthorizationAction.DELETE, taskOids, operationTask, parentResult); @@ -1818,6 +1826,12 @@ public void resumeTasks(Collection taskOids, Task operationTask, Operati taskManager.resumeTasks(taskOids, parentResult); } + @Override + public void resumeTaskTree(String coordinatorOid, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + authorizeTaskCollectionOperation(ModelAuthorizationAction.RESUME_TASK, singleton(coordinatorOid), operationTask, parentResult); + taskManager.resumeTaskTree(coordinatorOid, parentResult); + } + @Override public void scheduleTasksNow(Collection taskOids, Task operationTask, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException { authorizeTaskCollectionOperation(ModelAuthorizationAction.RUN_TASK_IMMEDIATELY, taskOids, operationTask, parentResult); @@ -2153,7 +2167,7 @@ public void completeWorkItem(@NotNull String caseOid, long workItemId, AbstractW .item(CaseType.F_WORK_ITEM, workItem.getId(), WorkItemType.F_CLOSE_TIMESTAMP).replace(now) .asItemDelta()); } - executeChanges(Collections.singleton(delta), null, task, result); + executeChanges(singleton(delta), null, task, result); result.computeStatus(); } catch (Throwable t) { result.recordFatalError("Couldn't complete work item: " + t.getMessage(), t);