Skip to content

Commit

Permalink
Connect GUI to the new activity framework
Browse files Browse the repository at this point in the history
Fields of progress, errors, result status, start/end timestamp,
LS token, and (newly created - experimental) nodes, are now connected
to the data maintained by the activity framework. The connection is
via TaskInformation and AttachedTaskInformation objects.

Work in progress. The part in admin-gui should be cleaned up,
see TODO/FIXME in the code.

Also:
- added realization and execution start/end timestamps
to activity state,
- added node and "stalled since" information to the activity
tree state overview,
- extended ItemsProgressInformation with # of errors.

Related to MID-7214. Should resolve also MID-7079, MID-7042, MID-7054,
MID-6982, MID-7012, and MID-7068.
  • Loading branch information
mederly committed Sep 14, 2021
1 parent b3e24bc commit 7d24bd9
Show file tree
Hide file tree
Showing 42 changed files with 1,444 additions and 336 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,36 @@

package com.evolveum.midpoint.gui.api.model;

import com.evolveum.midpoint.util.Producer;

import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;

/**
* Loadable model whose object is always not null.
* Used to reduce checks of the 'model.getObject() != null' kind.
*
* TODO remove redundant checks after annotations are checked at runtime (needs to be done in maven build)
*
* @author mederly
*/
public abstract class NonEmptyLoadableModel<T> extends LoadableModel<T> implements NonEmptyModel<T> {

public NonEmptyLoadableModel(boolean alwaysReload) {
super(alwaysReload);
}

public static <T> NonEmptyLoadableModel<T> create(Producer<T> producer, boolean alwaysReload) {
return new NonEmptyLoadableModel<T>(alwaysReload) {
@Override
protected @NotNull T load() {
return Objects.requireNonNull(
producer.run(),
"model object is null");
}
};
}

@NotNull
public T getObject() {
T object = super.getObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,29 @@

package com.evolveum.midpoint.gui.impl.page.admin.component;

import static java.util.Collections.singletonList;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import com.evolveum.midpoint.gui.api.GuiStyleConstants;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.prism.ItemStatus;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.gui.impl.component.AjaxCompositedIconButton;
import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon;
import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder;
import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle;
import com.evolveum.midpoint.gui.impl.page.admin.task.PageTask;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismReference;
Expand All @@ -41,28 +53,10 @@
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.reports.PageCreatedReports;
import com.evolveum.midpoint.web.page.admin.server.LivesyncTokenEditorPanel;
import com.evolveum.midpoint.web.page.admin.users.component.ExecuteChangeOptionsDto;
import com.evolveum.midpoint.web.util.TaskOperationUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;

import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportDataType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static java.util.Collections.singletonList;

public class TaskOperationalButtonsPanel extends AssignmentHolderOperationalButtonsPanel<TaskType> {

private static final Trace LOGGER = TraceManager.getTrace(TaskOperationalButtonsPanel.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,28 @@

package com.evolveum.midpoint.gui.impl.page.admin.task;

import static java.util.Collections.singletonList;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper;
import com.evolveum.midpoint.gui.impl.page.admin.assignmentholder.AssignmentHolderDetailsModel;

import com.evolveum.midpoint.gui.impl.page.admin.component.OperationalButtonsPanel;

import com.evolveum.midpoint.gui.impl.page.admin.component.TaskOperationalButtonsPanel;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;

import com.evolveum.midpoint.gui.api.GuiStyleConstants;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.gui.impl.component.AjaxCompositedIconButton;
import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon;
import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder;
import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper;
import com.evolveum.midpoint.gui.impl.page.admin.assignmentholder.AssignmentHolderDetailsModel;
import com.evolveum.midpoint.gui.impl.page.admin.assignmentholder.PageAssignmentHolderDetails;
import com.evolveum.midpoint.gui.impl.page.admin.component.OperationalButtonsPanel;
import com.evolveum.midpoint.gui.impl.page.admin.component.TaskOperationalButtonsPanel;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismReference;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.report.api.ReportConstants;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.statistics.ActivityStatisticsUtil;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.application.AuthorizationAction;
import com.evolveum.midpoint.web.application.PageDescriptor;
import com.evolveum.midpoint.web.application.Url;
import com.evolveum.midpoint.web.component.AjaxButton;
import com.evolveum.midpoint.web.component.AjaxDownloadBehaviorFromStream;
import com.evolveum.midpoint.web.component.AjaxIconButton;
import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel;
import com.evolveum.midpoint.web.component.util.VisibleBehaviour;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.reports.PageCreatedReports;
import com.evolveum.midpoint.web.page.admin.server.LivesyncTokenEditorPanel;
import com.evolveum.midpoint.web.page.admin.server.TaskSummaryPanel;
import com.evolveum.midpoint.web.util.OnePageParameterEncoder;
import com.evolveum.midpoint.web.util.TaskOperationUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportDataType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;

@PageDescriptor(
Expand Down Expand Up @@ -109,7 +65,13 @@ protected Class<TaskType> getType() {

@Override
protected Panel createSummaryPanel(String id, LoadableModel<TaskType> summaryModel) {
return new TaskSummaryPanel(id, summaryModel, this);
// TODO create root task model in constructor - however, this method is called from super(), so it is executed
// before local constructors have a chance to run!
//
// TODO Propagate loaded root also to other parts of task page, namely to subtasks (and their subtasks, etc)
// (Unless we want to have really fresh information there.)
LoadableModel<TaskType> rootTaskModel = RootTaskLoader.createRootTaskModel(this::getModelObjectType, () -> this);
return new TaskSummaryPanel(id, summaryModel, rootTaskModel, this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.gui.impl.page.admin.task;

import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.annotation.Experimental;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.util.SerializableSupplier;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Responsible for creating a model for a root task (given any task in the task tree).
*
* TODO clean up as needed
* TODO optimize # of loads of the root task when navigating through the tree
*/
@Experimental
public class RootTaskLoader {

private static final Trace LOGGER = TraceManager.getTrace(RootTaskLoader.class);

private static final String OPERATION_LOAD_TASK_ROOT = RootTaskLoader.class.getName() + ".loadTaskRoot";

public static @NotNull LoadableModel<TaskType> createRootTaskModel(
SerializableSupplier<TaskType> taskSupplier,
SerializableSupplier<PageBase> pageBaseSupplier) {
return LoadableModel.create(() -> {
TaskType task = taskSupplier.get();
if (task == null || task.getOid() == null) {
return null;
} else if (task.getParent() == null) {
return task;
} else {
return doLoadRoot(task, pageBaseSupplier);
}
}, false);
}

/**
* Loads root task from the repository. Returns null if task cannot be loaded.
*
* Precondition: task is persistent.
*/
private static @Nullable TaskType doLoadRoot(@NotNull TaskType taskBean, SerializableSupplier<PageBase> pageBaseSupplier) {
PageBase pageBase = pageBaseSupplier.get();
Task opTask = pageBase.createSimpleTask(OPERATION_LOAD_TASK_ROOT);
OperationResult result = opTask.getResult();
try {
return pageBase.getTaskManager()
.createTaskInstance(taskBean.asPrismObject(), result)
.getRoot(result)
.getUpdatedTaskObject().asObjectable();
} catch (Exception e) {
LoggingUtils.logException(LOGGER, "Couldn't determine root for {}", e, taskBean);
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper;
import com.evolveum.midpoint.gui.impl.page.admin.AbstractObjectMainPanel;
import com.evolveum.midpoint.gui.impl.page.admin.ObjectDetailsModels;
import com.evolveum.midpoint.gui.impl.page.admin.task.RootTaskLoader;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismReference;
Expand All @@ -27,6 +28,7 @@
import com.evolveum.midpoint.web.component.util.SelectableListDataProvider;
import com.evolveum.midpoint.web.page.admin.server.RefreshableTabPanel;
import com.evolveum.midpoint.web.page.admin.server.TaskTablePanel;
import com.evolveum.midpoint.web.page.admin.server.dto.AttachedTaskInformation;
import com.evolveum.midpoint.web.session.UserProfileStorage;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ContainerPanelConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
Expand All @@ -36,6 +38,7 @@
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.ResourceModel;
import org.jetbrains.annotations.NotNull;

import javax.xml.namespace.QName;
import java.util.ArrayList;
Expand All @@ -58,18 +61,27 @@ public class TaskSubtasksAndThreadsPanel extends AbstractObjectMainPanel<TaskTyp
private static final String ID_SUBTASKS_LABEL = "subtasksLabel";
private static final String ID_SUBTASKS_PANEL = "subtasksPanel";

/**
* The root of the task tree is needed to have the activity tree overview. It is loaded on demand.
*
* TODO Eliminate repeated loading of the root task!
*/
@NotNull private final LoadableModel<TaskType> rootTaskModel =
RootTaskLoader.createRootTaskModel(
() -> getObjectWrapper().getObject().asObjectable(),
this::getPageBase);

public TaskSubtasksAndThreadsPanel(String id,
ObjectDetailsModels<TaskType> taskWrapperModel, ContainerPanelConfigurationType config) {
super(id, taskWrapperModel, config);
setOutputMarkupId(true);
}


private String createTaskKindExpression() {
return "none"; // FIXME
//return SelectableBeanImpl.F_VALUE + "." + TaskType.F_WORK_MANAGEMENT.getLocalPart() + "." + TaskWorkManagementType.F_TASK_KIND.getLocalPart();
}

protected void initLayout() {
Label subtasksLabel = new Label(ID_SUBTASKS_LABEL, new ResourceModel("pageTaskEdit.subtasksLabel"));
add(subtasksLabel);
Expand Down Expand Up @@ -101,6 +113,11 @@ protected List<IColumn<SelectableBean<TaskType>, String>> createDefaultColumns()
protected UserProfileStorage.TableId getTableId() {
return UserProfileStorage.TableId.TABLE_SUBTASKS;
}

@Override
protected @NotNull AttachedTaskInformation getAttachedTaskInformation(SelectableBean<TaskType> selectableTaskBean) {
return AttachedTaskInformation.getOrCreate(selectableTaskBean, rootTaskModel.getObject());
}
};

add(subtasksPanel);
Expand All @@ -124,6 +141,11 @@ protected UserProfileStorage.TableId getTableId() {
protected boolean isHeaderVisible() {
return false;
}

@Override
protected @NotNull AttachedTaskInformation getAttachedTaskInformation(SelectableBean<TaskType> selectableTaskBean) {
return AttachedTaskInformation.getOrCreate(selectableTaskBean, rootTaskModel.getObject());
}
};
add(workerThreadsTable);
}
Expand Down Expand Up @@ -152,7 +174,7 @@ private Collection<SelectorOptions<GetOperationOptions>> createOperationOptions(
}

private IModel<List<TaskType>> createWorkersModel() {
return (IModel<List<TaskType>>) () -> {
return () -> {
PrismObject<TaskType> taskPrism = TaskSubtasksAndThreadsPanel.this.getObjectWrapper().getObject();
PrismReference subtasks = taskPrism.findReference(TaskType.F_SUBTASK_REF);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.web.page.admin.server.dto.AttachedTaskInformation;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType;

public interface SelectableBean<T extends Serializable> extends Serializable, DebugDumpable {
Expand All @@ -28,4 +29,19 @@ public interface SelectableBean<T extends Serializable> extends Serializable, De
void setSelected(boolean selected);

boolean isSelected();

/**
* Obtains custom data related to T (e.g. information extracted from the value of T) into the bean.
* Currently used to store {@link AttachedTaskInformation} for tasks.
*
* FIXME: TEMPORARY SOLUTION! Replace by subclassing {@link SelectableBeanImpl} for tasks!
*/
Object getCustomData();

/**
* Stores custom data, see {@link #getCustomData()}.
*
* FIXME: TEMPORARY SOLUTION!
*/
void setCustomData(Object data);
}

0 comments on commit 7d24bd9

Please sign in to comment.