[[executionoutbox]]
= Execution Outbox

: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.


The _Execution Outbox_ module provides an implementation of xref:refguide:applib:index/services/publishing/spi/ExecutionSubscriber.adoc[ExecutionSubscriber] that persists xref:refguide:applib:index/services/iactn/Execution.adoc[Execution]s into an "outbox" (using either the xref:pjpa:ROOT:about.adoc[JPA/EclipseLink] or xref:pjdo:ROOT:about.adoc[JDO/DataNucleus] object store).
The purpose of the "outbox" is to act as a temporary store of executions to be propogated to other "downstream" systems.

The module also provides a REST API, a rest client and DTOs to represent the payloads between these two services.
The client polls the outbox through the REST API (for example every 15 seconds), and uses it to download any new executions.
Once processed (eg published to a message bus), the client then uses the same REST API to delete the executions.
The usage REST client is described xref:outbox-rest-client[below].

== Setup

=== Dependency Management

Add a section for _Execution Outbox_'s own BOM:

[source,xml,subs="attributes+"]
.pom.xml
----
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.causeway.extensions</groupId>
            <artifactId>causeway-extensions-executionoutbox</artifactId>
            <scope>import</scope>
            <type>pom</type>
            <version>{page-causewayprevv3}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
----

[#dependencies]
=== Dependencies / Imports

In the webapp module of your application, add the following dependency:

[source,xml]
.pom.xml
----
<dependencies>
    <dependency>
        <groupId>org.apache.causeway.extensions</groupId>
        <artifactId>causeway-extensions-executionoutbox-persistence-XXX</artifactId>    <!--.-->
    </dependency>
</dependencies>
----
<.> either:
** `causeway-extensions-executionoutbox-persistence-jpa` (xref:pjpa::about.adoc[]), or
** `causeway-extensions-executionoutbox-persistence-jdo` (xref:pjdo::about.adoc[])


In your application's xref:userguide::modules.adoc#appmanifest[App Manifest], import the _ExecutionOutbox_ modules.
The exact modules to use will depend upon the persistence mechanism in use:


[source,java]
.AppManifest.java
----
@Configuration
@Import({
        ...
        CausewayModuleExtExecutionOutboxPersistenceXxx.class,        // <.>
        ...
})
public class AppManifest {
}
----
<.> either:
** `CausewayModuleExtExecutionOutboxPersistenceJdo` (xref:pjpa::about.adoc[]), or
** `CausewayModuleExtExecutionOutboxPersistenceJpa` (xref:pjdo::about.adoc[])

If using xref:security:secman:about.adoc[], you will also need to import the xref:testing:fixtures:about.adoc[Fixture] module; SecMan uses fixture scripts to seed its entities.

[#configure-properties]
=== Configuration Properties

Add the database schema used by the _Execution Outbox_ entities to the configuration file:

[source,yaml]
.application.yml
----
causeway:
  persistence:
    schema:
      auto-create-schemas: causewayExtExecutionOutbox
----

Optionally, modify the configuration properties for the _Execution Outbox_ module itself:

[source,yaml]
.application.yml
----
causeway:
  extensions:
    execution-outbox:
      rest-api:
        max-pending: 100
----

== Programmatic usage (queueing up commands)

With the extension configured, any action (or property edit) that has execution publishing enabled will result in an xref:refguide:extensions:index/executionoutbox/applib/dom/ExecutionOutboxEntry.adoc[] being persisted.
The REST Client (described xref:#outbox-rest-client[below]) can then be set up to poll for and subsequent remove these entries.

Often the action in question should be a no-op; all that is required is create an `ExecutionOutboxEntry` with the appropriate state.
This state will include a bookmark of the target object (on which the action was invoked) along with a serialization of the parameters.

There are two options when publishing an action:

* make the event as "thin" as possible, ie inform the downstream systems that a significant event has occurred, but no more.
+
With this approach the downstream systems will probably make a RESTful API call to any additional information to perform their work

* alternatively, provide supplemental information in the event, which may obviate the requirement for a REST call.
+
This can be done by defining action that has `String` parameters that take XML or JSON; these can therefore publish as much information as is necessary to the downstream systems.

For example:

* define a no-op action taking XML parameters.
+
This should have publishing enabled, but we don't want it visible in the UI so it should also be hidden:
+
[source,java]
----
@Action(
        semantics = SemanticsOf.IDEMPOTENT,
        publishing = Publishing.ENABLED,
        hidden = Where.EVERYWHERE
)
public void addSupplier(
        final String addRequestXml,
        final String getRequestXml) {
    // no-op
}
----

* define a convenience method:
+
[source,java]
----
@Programmatic
public T toOutbox() {
    return (T)wrapperFactory.wrapSkipRules(this);
}
----

* queue up commands, eg:
+
[source,java]
----
val addRequestXml = ...;
val getRequestXml = ...;
toOutbox().addSupplier(addRequestXml, getRequestXml);
----



== User Interface

The extension provides a number of menu actions,that allow the administrator to query the persisted commands.
These should be added to menu bar, and access to these restricted.

The sections below describe how.

[#menubar-layout-xml]
=== menubar.layout.xml

Once configured, the extension provides a number of menu actions.
You can use `menubars.layout.xml` to arrange these as you see fit.
To get you started, the following fragment adds all of the actions to an "Activity" secondary menu:

[source,xml]
.menubars.layout.xml
----
<mb:secondary>
    ...
    <mb:menu>
        <mb:named>Activity</mb:named>
        ...
        <mb:section>
            <mb:named>Execution Outbox</mb:named>
            <mb:serviceAction id="findOldest" objectType="causeway.ext.executionOutbox.ExecutionOutboxMenu"/>
            <mb:serviceAction id="findAll" objectType="causeway.ext.executionOutbox.ExecutionOutboxMenu"/>
        </mb:section>
        ...
    </mb:menu>
</mb:secondary>
----

[#secman-security-roles]
=== SecMan Security Roles

If xref:security:secman:about.adoc[] extension is configured, then permissions must be granted to access the menu actions.

This can be done by granting the role set up by the xref:refguide:extensions:index/secman/applib/role/seed/CausewayExtExecutionOutboxRoleAndPermissions.adoc[] seed fixture script (see its `ROLE_NAME` constant).


[#outbox-rest-client]
== Outbox REST Client

Once an execution has been persisted into the outbox, it will stay there until it has been processed and removed by another process.
Typically that other process will be a microservice that forwards on the message to an event bus.

This is shown below.

.processing messages from the outbox
image::outbox.png[width=600px]

The module provides a REST service, along with a rest client, xref:refguide:extensions:index/executionoutbox/restclient/api/OutboxClient.adoc[OutboxClient].
The `OutboxClient` is used by the _message processor_ shown in the above diagram.


=== Prerequisites

To setup the message processor:

* in `dependencyManagement` section, add an entry for _Execution Outbox_'s own BOM:
+
[source,xml,subs="attributes+"]
.pom.xml
----
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.causeway.extensions</groupId>
            <artifactId>causeway-extensions-executionoutbox</artifactId>
            <scope>import</scope>
            <type>pom</type>
            <version>{page-causewayprevv3}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
----

* In the `dependencies` section, add the following dependency:
+
[source,xml]
.pom.xml
----
<dependencies>
    <dependency>
        <groupId>org.apache.causeway.extensions</groupId>
        <artifactId>causeway-extensions-executionoutbox-restclient</artifactId>
    </dependency>
</dependencies>
----


=== Usage

To instantiate the `OutboxClient`, specify the URL, user and password.
The URL will be something like: `http://localhost:8080/restful/`, where the last part is the default path obtainable from the `resteasy.jaxrs.defaultPath` configuration property of the Causeway app.

The `OutboxClient` API consists of three methods:

* to retrieve any pending interactions:
+
[source,java]
----
List<InteractionDto> pending = outboxClient.pending();
----

* to delete a single interaction:
+
[source,java]
----
val first = pending.get(0);
val interactionId = first.getInteractionId();
val sequence      = first.getExecution().getSequence();

outboxClient.delete(interactionId, sequence);
----

* to delete many interactions:
+
[source,java]
----
outboxClient.deleteMany(pending);
----

The maximum number of interactions that will be returned is configurable, see xref:configure-properties[above].


== See also

* xref:refguide:applib:index/services/publishing/spi/ExecutionSubscriber.adoc[] SPI
* xref:executionlog:about.adoc[] extension

