ISIS: переход от устаревшего @Action(invokeOn=) к @Action(associateWith=)

Я работаю над проектом, используя ISIS 1.16.2. У меня есть суперкласс под названием ConfigurationItem, который имеет некоторые общие свойства (name, createdTimestamp и т.д.). Например, у него есть метод действия удаления, аннотированный @Action(invokeOn = InvokeOn.OBJECT_AND_COLLECTION, ...), который мне нужно вызывать из подробного представления сущностей, а также из представлений коллекции с полями выбора.

Пример:

public class ConfigurationItem {

    @Action(
            invokeOn = InvokeOn.OBJECT_AND_COLLECTION,
            semantics = SemanticsOf.NON_IDEMPOTENT_ARE_YOU_SURE,
            domainEvent = DeletedDomainEvent.class)
    public Object delete() {
        repositoryService.remove(this);
        return null;
    }

    // ...
}

public class ConfigurationItems {

    @Action(semantics = SemanticsOf.SAFE)
    public List<T> listAll() {
        return repositoryService.allInstances(<item-subclass>.class);
    }

    // ...
}

Это работает довольно хорошо, но аннотация «invokeOn» теперь устарела. JavaDoc говорит, что нужно переключиться на @Action(associateWith="..."), но я не знаю, как передать семантику «InvokeOn», так как у меня нет поля коллекции для справки. Вместо этого у меня есть только коллекция объектов, возвращаемых действием извлечения базы данных.

Мой вопрос: как перенести устаревшую семантику @Action(invokeOn=...) в новую концепцию @Action(associateWith="...") для возвращаемых значений коллекции без резервного поля свойства?

Заранее спасибо!


person JND    schedule 30.01.2019    source источник


Ответы (1)


Хороший вопрос, очевидно, это недостаточно хорошо объяснено в документации Apache Isis.

@Action(invokeOn=InvokeOn.OBJECT_AND_COLLECTION) всегда был чем-то вроде кладжа, потому что он включает в себя вызов действия над отдельной коллекцией (то есть списком объектов, возвращенных из предыдущего запроса). Нам это не нравится, потому что нет «единственного» объекта, над которым можно было бы вызвать действие.

Когда мы реализовали эту функцию, поддержка моделей представлений была далеко не такой всеобъемлющей, как сейчас. Итак, наша рекомендация теперь заключается в том, что вместо того, чтобы возвращать голую автономную коллекцию, вместо этого оберните ее в модель представления, которая содержит коллекцию.

Затем модель представления дает нам единственную цель для вызова некоторого поведения; идея заключается в том, что модель представления отвечает за перебор всех выбранных элементов и вызов действия над ними.

С вашим кодом мы можем ввести SomeConfigItems в качестве модели представления:

@XmlRootElement("configItems")
public class SomeConfigItems {

    @lombok.Getter @lombok.Setter
    private List<ConfigurationItem> items = new ArrayList<>();

    @Action(
        associateWith = "items",  // associates with the items collection
        semantics = SemanticsOf.NON_IDEMPOTENT_ARE_YOU_SURE,
        domainEvent = DeletedDomainEvent.class)
    public SomeConfigItems delete(List<ConfigurationItem> items) {
        for(ConfigurationItem item: items) {
           repositoryService.remove(item);
        }
        return this;
    }
    // optionally, select all items for deletion by default
    public List<ConfigurationItem> default0Delete() { return getItems(); }

    // I don't *think* that a choices method is required, but if present then 
    // is the potential list of items for the argument
    //public List<ConfigurationItem> choices0Delete() { return getItems(); }
}

а затем измените действие ConfigurationItems, чтобы вернуть эту модель представления:

public class ConfigurationItems {

    @Action(semantics = SemanticsOf.SAFE)
    public SelectedItems listAll() {
        List<T> items = repositoryService.allInstances(<item-subclass>.class);
        return new SelectedItems(items);
    }
}

Теперь, когда у вас есть модель представления для представления выходных данных, вы, вероятно, обнаружите, что с ней можно делать и другие вещи.

Надеюсь, это имеет смысл!

person Dan Haywood    schedule 30.01.2019
comment
Большое спасибо! Это имеет большой смысл. Должен ли я аннотировать модель представления JAXB с помощью @DomainObject(nature=VIEW_MODEL) или чего-то подобного, или это необязательно? - person JND; 01.02.2019
comment
Я думаю, что это необязательно, но в этом нет ничего плохого. - person Dan Haywood; 01.02.2019
comment
Я попробовал ваше решение. Оно работает. Но это не полная замена аннотации invokeOn, поскольку она вводит много стандартного кода и открывает дополнительное всплывающее диалоговое окно, которое мешает работе пользователя. Есть ли способ избавиться от этого всплывающего окна (которое, кстати, время от времени выдает некоторые NPE при удалении всех элементов)? - person JND; 05.02.2019
comment
Нет, я думаю, на данный момент нет. Поднимите тикет в нашей JIRA, чтобы получить улучшение/улучшение этого. - person Dan Haywood; 05.02.2019