PublisherService

TODO: this content has not yet been reviewed/updated for v2.0

The PublisherService API is intended for coarse-grained publish/subscribe for system-to-system interactions, from Apache Isis to some other system. Events that can be published are action invocations/property edits, and changed objects. A typical use case is to publish onto a pub/sub bus such as ActiveMQ with Camel to keep other systems up to date.

An alternative use is for profiling: for each execution (action invocation/property edit) the framework captures metrics of the number of objects loaded or dirtied as the result of that execution. If the WrapperFactory is used to call other objects then the metrics are captured for each sub-execution. The framework provides a default implementation, PublisherServiceLogging, that will log these execution graphs (in XML form, per the "ixn" schema) to an SLF4J logger.

Only actions/properties/domain objects annotated for publishing (using @Action#publishing(), @Property#publishing() or @DomainObject#publishing()) are published.

SPI

The SPI defined by the service is:

public interface PublisherService {

    void publish(final Interaction.Execution<?, ?> execution);  (1)

    void publish(final PublishedObjects publishedObjects);      (2)
}
1 to publish an individual action invocation or property edit, as captured within an Interaction.Execution.
2 to publish a set of changed objects.

where PublishedObjects is provides statistics on the interaction execution (action invocation or property edit):

public interface PublishedObjects
        extends HasUniqueId,            (1)
                HasUsername {           (2)

    Timestamp getCompletedAt();         (3)

    int getNumberLoaded();              (4)
    int getNumberCreated();             (5)
    int getNumberUpdated();             (6)
    int getNumberDeleted();             (7)

    int getNumberPropertiesModified();  (8)

    ChangesDto getDto();                (9)

}
1 inherited from HasUniqueId, correlates back to the unique identifier of the transaction in which these objects were changed.
2 inherited from HasUsername, is the user that initiated the transaction causing these objects to change
3 Time that the interaction execution completed
4 Number of domain objects loaded in this interaction
5 Number of domain objects created in this interaction
6 Number of domain objects updated in this interaction
7 Number of domain objects deleted in this interaction
8 Number of domain objects properties that were changed in this interaction
9 Same details, as per chg.xsd schema. This can be converted into a serializable XML representation using the ChangesDtoUtils utility class.

The numbers of objects loaded, created, updated or deleted and the number of object properties modified (in other words the "size" or "weight" of the transaction).

Each Interaction.Execution has an owning Interaction; this is the same object obtainable from InteractionContext. Implementations that publish member executions can use Interaction.Execution#getDto() method to return a DTO (as per the "ixn" schema) which can be converted into a serializable XML representation using the InteractionDtoUtils utility class. The XML can either serialize a single execution, or can be a "deep" serialization of an execution and all sub-executions.

Implementations

The framework allows multiple implementations of this service to be registered; all will be called.

There are two implementations provided by the framework:

  • The core framework provides one implementation of its own, PublisherServiceLogging (in o.a.i.applib.services.publish package). This logs serializations to a Log4j2 logger

    log4j2-spring.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
      <Properties> ... </Properties>
      <Appenders> ... </Appenders>
      <Loggers>
        ...
        <logger
          name="org.apache.isis.applib.services.publish.PublisherServiceLogging"
          level="debug"/>
        ...
      </Loggers>
    </Configuration>

    See the log4j2-spring.xml file in simpleapp for the omitted detail.

  • the Outbox Publisher in the Mappings catalog persists each interaction into a outbox table for subsequent processing. As its name implies, it uses JDO/DataNucleus to do this.

    TODO: v2 - need to migrate this across. Also, check the name is correct.

Usage

To indicate that:

The module also provide services that contribute to the UI. If contributions are not required in the UI, these can be suppressed either using security or by implementing a vetoing subscriber.

This service supports two main use cases:

  • coarse-grained publish/subscribe for system-to-system interactions, from Apache Isis to some other system.

  • profiling of interactions/transactions, eg to diagnose response/throughput issues.

To support these use cases several other services are involved:

  • the InteractionContext is used to obtain the Interaction from which the member executions are published.

  • the (internal) ChangedObjectsService domain service is used to obtain the set of objects modified throughout the transaction

  • the (internal) PublisherDispatchService domain service filters these down to those changed objects that are also published (as per @DomainObject#publishing()) and delegates to the PublisherService.

  • the MetricsService is used to obtain the objects that are loaded throughout the transaction; this info is used in order to instantiate the PublishedObjects object passed through to the PublisherService.

The services provided by this module combine very well with the CommandService and with AuditerService. The CommandService captures the cause of an interaction (an action was invoked, a property was edited), while the PublisherService captures the effect of that interaction in terms of events, and the AuditerService captures the effect of the interaction in terms of changed state. You may also want to configure the PublisherService, which also captures the effect of the interaction but as an event. All three of these services collaborate implicitly by way of the HasUniqueId interface.

The EventBusService differs from the PublisherService in that it is intended for fine-grained publish/subscribe for object-to-object interactions within an Apache Isis domain object model. The event propagation is strictly in-memory, and there are no restrictions on the object acting as the event; it need not be serializable, for example. That said, it is possible to obtain a serialization of the action invocation/property edit causing the current event to be raised using InteractionContext domain service.