:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:


[#command-processing]
=== Command Processing

Every action invocation (and xref:refguide:applib:index/annotation/Property.adoc#commandPublishing[property edit] for that matter) is normally reified into a concrete xref:refguide:applib:index/services/command/Command.adoc[Command] object, basically a wrapper around the xref:schema:cmd.adoc[CommandDto] that also captures some timing metrics about the execution as well as the outcome.

The main uses cases are:

* as a means to allow asynchronous child commands to be executed, using the xref:refguide:applib:index/services/wrapper/WrapperFactory.adoc[WrapperFactory] service;

* as a means to audit (persist) commands, by implementing the xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] SPI.
+
The xref:userguide:commandlog:about.adoc[Command Log] extension _does_ provide such an implementation.
+
TIP: Another option to achieve this is to use the xref:refguide:applib:index/services/publishing/spi/ExecutionSubscriber.adoc[ExecutionSubscriber] SPI.

// commandreplay moved to incubator for the time being
//* to replay commands onto a secondary system, for regression testing.
//+
//This is implemented by the xref:userguide:commandreplay:about.adoc[Command Replay] extension, working in conjunction with the xref:userguide:commandlog:about.adoc[Command Log] extension.

The xref:refguide:applib:index/annotation/Action.adoc#commandPublishing[commandPublishing()] element can be used to explicitly enable or disable command publishing for the action invocation.


==== CommandDtoProcessor implementations

The xref:refguide:applib:index/annotation/Action.adoc#commandDtoProcessor[commandDtoProcessor()] element allows an implementation of `CommandDtoProcessor` to be specified.
This interface has the following API:

[source,java]
----
public interface CommandDtoProcessor {
    CommandDto process(             // <.>
            CommandDto dto);        // <.>
}
----
<.> The returned `CommandDto`.
This will typically be the `CommandDto` passed in, but may be supplemented in some way.
<.> The `CommandDto` obtained already from the xref:refguide:applib:index/services/command/Command.adoc[Command].

This interface is used by the framework-provided implementations of xref:refguide:applib:index/services/conmap/ContentMappingService.adoc[ContentMappingService] for the REST API, allowing xref:refguide:applib:index/services/command/Command.adoc[Command]s implementations that also implement `CommandWithDto` to be further customised as they are serialized out.
The primary use case for this capability is in support of primary/secondary replication.

* on the primary, xref:refguide:applib:index/services/command/Command.adoc[Command]s are serialized to XML.
This includes the identity of the target object and the argument values of all parameters.

+
[IMPORTANT]
====
Any ``Blob``s and ``Clob``s are deliberately excluded from this XML (they are instead stored as references).
This is to prevent the storage requirements for xref:refguide:applib:index/services/command/Command.adoc[Command] from becoming excessive.
A `CommandDtoProcessor` can be provided to re-attach blob information if required.
====

* replaying xref:refguide:applib:index/services/command/Command.adoc[Command]s requires this missing parameter information to be reinstated.
The `CommandDtoProcessor` therefore offers a hook to dynamically re-attach the missing `Blob` or `Clob` argument.

As a special case, returning `null` means that the command's DTO is effectively excluded when retrieving the list of commands.
If replicating from master to slave, this effectively allows certain commands to be ignored.
The `CommandDtoProcessor.Null` class provides a convenience implementation for this requirement.

[NOTE]
====
If `commandDtoProcessor()` is specified, then `commandPublishing()` is assumed to be ENABLED.
====

==== Example

Consider the following method:

[source,java]
----
@Action(
    domainEvent = IncomingDocumentRepository.UploadDomainEvent.class,
    commandDtoProcessor = DeriveBlobArg0FromReturnedDocument.class
)
public Document upload(final Blob blob) {
    final String name = blob.getName();
    final DocumentType type = DocumentTypeData.INCOMING.findUsing(documentTypeRepository);
    final ApplicationUser me = meService.me();
    String atPath = me != null ? me.getAtPath() : null;
    if (atPath == null) {
        atPath = "/";
    }
    return incomingDocumentRepository.upsertAndArchive(type, atPath, name, blob);
}
----

The `Blob` argument will not be persisted in the memento of the xref:refguide:applib:index/services/command/Command.adoc[Command], but the information is implicitly available in the `Document` that is returned by the action.
The `DeriveBlobArg0FromReturnedDocument` processor retrieves this information and dynamically adds:

[source,java]
----
public class DeriveBlobArg0FromReturnedDocument
        extends CommandDtoProcessorForActionAbstract {

    @Override
    public CommandDto process(Command command, CommandDto commandDto) {
        final Bookmark result = commandWithDto.getResult();
        if(result == null) {
            return commandDto;
        }
        try {
            final Document document = bookmarkService.lookup(result, Document.class);
            if (document != null) {
                ParamDto paramDto = getParamDto(commandDto, 0);
                CommonDtoUtils.setValueOn(paramDto, ValueType.BLOB, document.getBlob(), bookmarkService);
            }
        } catch(Exception ex) {
            return commandDto;
        }
        return commandDto;
    }
    @Inject
    BookmarkService bookmarkService;
}
----

==== Null implementation

The null implementation can be used to simply indicate that no DTO should be returned for a xref:refguide:applib:index/services/command/Command.adoc[Command].
The effect is to ignore it for replay purposes:

[source,xml]
----
pubc interface CommandDtoProcessor {
    ...
    class Null implements CommandDtoProcessor {
        public CommandDto process(Command command, CommandDto commandDto) {
            return null;
        }
    }
}
----

