+per #16541 add missing java samples for persistence query

This commit is contained in:
Konrad Malawski 2015-06-08 12:26:19 +02:00 committed by Konrad Malawski
parent 3b94108e0c
commit 3314de4cb9
10 changed files with 589 additions and 92 deletions

View file

@ -4,71 +4,373 @@
package docs.persistence;
import static akka.pattern.Patterns.ask;
import akka.actor.*;
import akka.dispatch.Mapper;
import akka.event.EventStreamSpec;
import akka.japi.Function;
import akka.japi.Procedure;
import akka.japi.pf.ReceiveBuilder;
import akka.pattern.BackoffSupervisor;
import akka.persistence.*;
import akka.persistence.query.*;
import akka.persistence.query.javadsl.ReadJournal;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import akka.util.Timeout;
import docs.persistence.query.MyEventsByTagPublisher;
import docs.persistence.query.PersistenceQueryDocSpec;
import org.reactivestreams.Subscriber;
import scala.collection.Seq;
import scala.collection.immutable.Vector;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import scala.runtime.Boxed;
import scala.runtime.BoxedUnit;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class PersistenceQueryDocTest {
final Timeout timeout = Timeout.durationToTimeout(FiniteDuration.create(3, TimeUnit.SECONDS));
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
//#my-read-journal
class MyReadJournal implements ReadJournal {
private final ExtendedActorSystem system;
class MyReadJournal implements ReadJournal {
private final ExtendedActorSystem system;
public MyReadJournal(ExtendedActorSystem system) {
this.system = system;
}
final FiniteDuration defaultRefreshInterval = FiniteDuration.create(3, TimeUnit.SECONDS);
final FiniteDuration defaultRefreshInterval = FiniteDuration.create(3, TimeUnit.SECONDS);
@SuppressWarnings("unchecked")
public <T, M> Source<T, M> query(Query<T, M> q, Hint... hints) {
if (q instanceof EventsByTag) {
final EventsByTag eventsByTag = (EventsByTag) q;
final String tag = eventsByTag.tag();
long offset = eventsByTag.offset();
@SuppressWarnings("unchecked")
public <T, M> Source<T, M> query(Query<T, M> q, Hint... hints) {
if (q instanceof EventsByTag) {
final EventsByTag eventsByTag = (EventsByTag) q;
final String tag = eventsByTag.tag();
long offset = eventsByTag.offset();
final Props props = MyEventsByTagPublisher.props(tag, offset, refreshInterval(hints));
final Props props = MyEventsByTagPublisher.props(tag, offset, refreshInterval(hints));
return (Source<T, M>) Source.<EventEnvelope>actorPublisher(props)
.mapMaterializedValue(noMaterializedValue());
} else {
// unsuported
return Source.<T>failed(
new UnsupportedOperationException(
"Query $unsupported not supported by " + getClass().getName()))
.mapMaterializedValue(noMaterializedValue());
}
return (Source<T, M>) Source.<EventEnvelope>actorPublisher(props)
.mapMaterializedValue(noMaterializedValue());
} else {
// unsuported
return Source.<T>failed(
new UnsupportedOperationException(
"Query " + q + " not supported by " + getClass().getName()))
.mapMaterializedValue(noMaterializedValue());
}
}
private FiniteDuration refreshInterval(Hint[] hints) {
FiniteDuration ret = defaultRefreshInterval;
for (Hint hint : hints)
if (hint instanceof RefreshInterval)
ret = ((RefreshInterval) hint).interval();
return ret;
}
private FiniteDuration refreshInterval(Hint[] hints) {
for (Hint hint : hints)
if (hint instanceof RefreshInterval)
return ((RefreshInterval) hint).interval();
private <I, M> akka.japi.function.Function<I, M> noMaterializedValue () {
return param -> (M) null;
}
return defaultRefreshInterval;
}
private <I, M> akka.japi.function.Function<I, M> noMaterializedValue() {
return param -> (M) null;
}
}
//#my-read-journal
//#my-read-journal
void demonstrateBasicUsage() {
final ActorSystem system = ActorSystem.create();
//#basic-usage
// obtain read journal by plugin id
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
// issue query to journal
Source<Object, BoxedUnit> source =
readJournal.query(EventsByPersistenceId.create("user-1337", 0, Long.MAX_VALUE));
// materialize stream, consuming events
ActorMaterializer mat = ActorMaterializer.create(system);
source.runForeach(event -> System.out.println("Event: " + event), mat);
//#basic-usage
}
void demonstrateAllPersistenceIdsLive() {
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#all-persistence-ids-live
readJournal.query(AllPersistenceIds.getInstance());
//#all-persistence-ids-live
}
void demonstrateNoRefresh() {
final ActorSystem system = ActorSystem.create();
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#all-persistence-ids-snap
readJournal.query(AllPersistenceIds.getInstance(), NoRefresh.getInstance());
//#all-persistence-ids-snap
}
void demonstrateRefresh() {
final ActorSystem system = ActorSystem.create();
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#events-by-persistent-id-refresh
final RefreshInterval refresh = RefreshInterval.create(1, TimeUnit.SECONDS);
readJournal.query(EventsByPersistenceId.create("user-us-1337"), refresh);
//#events-by-persistent-id-refresh
}
void demonstrateEventsByTag() {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#events-by-tag
// assuming journal is able to work with numeric offsets we can:
final Source<EventEnvelope, BoxedUnit> blueThings =
readJournal.query(EventsByTag.create("blue"));
// find top 10 blue things:
final Future<List<Object>> top10BlueThings =
(Future<List<Object>>) blueThings
.map(t -> t.event())
.take(10) // cancels the query stream after pulling 10 elements
.<List<Object>>runFold(new ArrayList<>(10), (acc, e) -> {
acc.add(e);
return acc;
}, mat);
// start another query, from the known offset
Source<EventEnvelope, BoxedUnit> blue = readJournal.query(EventsByTag.create("blue", 10));
//#events-by-tag
}
//#materialized-query-metadata-classes
// a plugin can provide:
//#materialized-query-metadata-classes
static
//#materialized-query-metadata-classes
final class QueryMetadata {
public final boolean deterministicOrder;
public final boolean infinite;
public QueryMetadata(Boolean deterministicOrder, Boolean infinite) {
this.deterministicOrder = deterministicOrder;
this.infinite = infinite;
}
}
//#materialized-query-metadata-classes
static
//#materialized-query-metadata-classes
final class AllEvents implements Query<Object, QueryMetadata> {
private AllEvents() {}
private static AllEvents INSTANCE = new AllEvents();
}
//#materialized-query-metadata-classes
void demonstrateMaterializedQueryValues() {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#materialized-query-metadata
final Source<Object, QueryMetadata> events = readJournal.query(AllEvents.INSTANCE);
events.mapMaterializedValue(meta -> {
System.out.println("The query is: " +
"ordered deterministically: " + meta.deterministicOrder + " " +
"infinite: " + meta.infinite);
return meta;
});
//#materialized-query-metadata
}
class ReactiveStreamsCompatibleDBDriver {
Subscriber<List<Object>> batchWriter() {
return null;
}
}
void demonstrateWritingIntoDifferentStore() {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#projection-into-different-store-rs
final ReactiveStreamsCompatibleDBDriver driver = new ReactiveStreamsCompatibleDBDriver();
final Subscriber<List<Object>> dbBatchWriter = driver.batchWriter();
// Using an example (Reactive Streams) Database driver
readJournal
.query(EventsByPersistenceId.create("user-1337"))
.grouped(20) // batch inserts into groups of 20
.runWith(Sink.create(dbBatchWriter), mat); // write batches to read-side database
//#projection-into-different-store-rs
}
//#projection-into-different-store-simple-classes
class ExampleStore {
Future<Void> save(Object any) {
// ...
//#projection-into-different-store-simple-classes
return null;
//#projection-into-different-store-simple-classes
}
}
//#projection-into-different-store-simple-classes
void demonstrateWritingIntoDifferentStoreWithMapAsync() {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#projection-into-different-store-simple
final ExampleStore store = new ExampleStore();
readJournal
.query(EventsByTag.create("bid"))
.mapAsync(1, store::save)
.runWith(Sink.ignore(), mat);
//#projection-into-different-store-simple
}
//#projection-into-different-store
class MyResumableProjection {
private final String name;
public MyResumableProjection(String name) {
this.name = name;
}
public Future<Long> saveProgress(long offset) {
// ...
//#projection-into-different-store
return null;
//#projection-into-different-store
}
public Future<Long> latestOffset() {
// ...
//#projection-into-different-store
return null;
//#projection-into-different-store
}
}
//#projection-into-different-store
void demonstrateWritingIntoDifferentStoreWithResumableProjections() throws Exception {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final ReadJournal readJournal =
PersistenceQuery.get(system)
.getReadJournalFor("akka.persistence.query.noop-read-journal");
//#projection-into-different-store-actor-run
final Timeout timeout = Timeout.apply(3, TimeUnit.SECONDS);
final MyResumableProjection bidProjection = new MyResumableProjection("bid");
final Props writerProps = Props.create(TheOneWhoWritesToQueryJournal.class, "bid");
final ActorRef writer = system.actorOf(writerProps, "bid-projection-writer");
long startFromOffset = Await.result(bidProjection.latestOffset(), timeout.duration());
readJournal
.query(EventsByTag.create("bid", startFromOffset))
.<Long>mapAsync(8, envelope -> {
final Future<Object> f = ask(writer, envelope.event(), timeout);
return f.<Long>map(new Mapper<Object, Long>() {
@Override public Long apply(Object in) {
return envelope.offset();
}
}, system.dispatcher());
})
.mapAsync(1, offset -> bidProjection.saveProgress(offset))
.runWith(Sink.ignore(), mat);
}
//#projection-into-different-store-actor-run
class ComplexState {
boolean readyToSave() {
return false;
}
}
static class Record {
static Record of(Object any) {
return new Record();
}
}
//#projection-into-different-store-actor
final class TheOneWhoWritesToQueryJournal extends AbstractActor {
private final ExampleStore store;
private ComplexState state = new ComplexState();
public TheOneWhoWritesToQueryJournal() {
store = new ExampleStore();
receive(ReceiveBuilder.matchAny(message -> {
state = updateState(state, message);
// example saving logic that requires state to become ready:
if (state.readyToSave())
store.save(Record.of(state));
}).build());
}
ComplexState updateState(ComplexState state, Object msg) {
// some complicated aggregation logic here ...
return state;
}
}
//#projection-into-different-store-actor
}

View file

@ -5,6 +5,7 @@
package docs.persistence.query;
import akka.actor.Cancellable;
import akka.actor.Scheduler;
import akka.japi.Pair;
import akka.japi.pf.ReceiveBuilder;
import akka.persistence.PersistentRepr;
@ -23,6 +24,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import static java.util.stream.Collectors.toList;
@ -39,21 +41,28 @@ class MyEventsByTagJavaPublisher extends AbstractActorPublisher<EventEnvelope> {
private final String CONTINUE = "CONTINUE";
private final int LIMIT = 1000;
private long currentOffset;
private List<EventEnvelope> buf = new ArrayList<>();
private List<EventEnvelope> buf = new LinkedList<>();
private Cancellable continueTask;
public MyEventsByTagJavaPublisher(Connection connection, String tag, Long offset, FiniteDuration refreshInterval) {
public MyEventsByTagJavaPublisher(Connection connection,
String tag,
Long offset,
FiniteDuration refreshInterval) {
this.connection = connection;
this.tag = tag;
this.currentOffset = offset;
this.continueTask = context().system().scheduler().schedule(refreshInterval, refreshInterval, self(), CONTINUE, context().dispatcher(), self());
final Scheduler scheduler = context().system().scheduler();
this.continueTask = scheduler
.schedule(refreshInterval, refreshInterval, self(), CONTINUE,
context().dispatcher(), self());
receive(ReceiveBuilder
.matchEquals(CONTINUE, (in) -> {
query();
deliverBuf();
})
.matchEquals(CONTINUE, (in) -> {
query();
deliverBuf();
})
.match(Cancel.class, (in) -> {
context().stop(self());
})
@ -71,33 +80,33 @@ class MyEventsByTagJavaPublisher extends AbstractActorPublisher<EventEnvelope> {
private void query() {
if (buf.isEmpty()) {
try {
PreparedStatement s = connection.prepareStatement(
"SELECT id, persistent_repr " +
"FROM journal WHERE tag = ? AND id >= ? " +
"ORDER BY id LIMIT ?");
final String query = "SELECT id, persistent_repr " +
"FROM journal WHERE tag = ? AND id >= ? " +
"ORDER BY id LIMIT ?";
try (PreparedStatement s = connection.prepareStatement(query)) {
s.setString(1, tag);
s.setLong(2, currentOffset);
s.setLong(3, LIMIT);
final ResultSet rs = s.executeQuery();
try (ResultSet rs = s.executeQuery()) {
final List<Pair<Long, byte[]>> res = new ArrayList<>(LIMIT);
while (rs.next())
res.add(Pair.create(rs.getLong(1), rs.getBytes(2)));
final List<Pair<Long, byte[]>> res = new ArrayList<>(LIMIT);
while (rs.next())
res.add(Pair.create(rs.getLong(1), rs.getBytes(2)));
if (!res.isEmpty()) {
currentOffset = res.get(res.size() - 1).first();
if (!res.isEmpty()) {
currentOffset = res.get(res.size() - 1).first();
}
buf = res.stream().map(in -> {
final Long id = in.first();
final byte[] bytes = in.second();
final PersistentRepr p = serialization.deserialize(bytes, PersistentRepr.class).get();
return new EventEnvelope(id, p.persistenceId(), p.sequenceNr(), p.payload());
}).collect(toList());
}
buf = res.stream().map(in -> {
final Long id = in.first();
final byte[] bytes = in.second();
final PersistentRepr p = serialization.deserialize(bytes, PersistentRepr.class).get();
return new EventEnvelope(id, p.persistenceId(), p.sequenceNr(), p.payload());
}).collect(toList());
} catch(Exception e) {
onErrorThenStop(e);
}

View file

@ -14,12 +14,6 @@ side of an application, however it can help to migrate data from the write side
simple scenarios Persistence Query may be powerful enough to fulful the query needs of your app, however we highly
recommend (in the spirit of CQRS) of splitting up the write/read sides into separate datastores as the need arrises.
While queries can be performed directly on the same datastore, it is also a very common pattern to use the queries
to create *projections* of the write-side's events and store them into a separate datastore which is optimised for more
complex queries. This architectural pattern of projecting the data into a query optimised datastore, with possibly some
transformation or canculations along the way is the core use-case and recommended style of using Akka Persistence Query
- pulling out of one Journal and storing into another one.
.. warning::
This module is marked as **“experimental”** as of its introduction in Akka 2.4.0. We will continue to
@ -58,7 +52,7 @@ journal is as simple as:
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#basic-usage
Journal implementers are encouraged to put this identified in a variable known to the user, such that one can access it via
Journal implementers are encouraged to put this identifier in a variable known to the user, such that one can access it via
``getJournalFor(NoopJournal.identifier)``, however this is not enforced.
Read journal implementations are available as `Community plugins`_.
@ -90,7 +84,7 @@ If your usage does not require a live stream, you can disable refreshing by usin
``EventsByPersistenceId`` is a query equivalent to replaying a :ref:`PersistentActor <event-sourcing>`,
however, since it is a stream it is possible to keep it alive and watch for additional incoming events persisted by the
persistent actor identified by the given ``persistenceId``. Most journal will have to revert to polling in order to achieve
persistent actor identified by the given ``persistenceId``. Most journals will have to revert to polling in order to achieve
this, which can be configured using the ``RefreshInterval`` query hint:
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#events-by-persistent-id-refresh
@ -120,7 +114,6 @@ including for example taking the first 10 and cancelling the stream. It is worth
query has an optionally supported offset parameter (of type ``Long``) which the journals can use to implement resumable-streams.
For example a journal may be able to use a WHERE clause to begin the read starting from a specific row, or in a datastore
that is able to order events by insertion time it could treat the Long as a timestamp and select only older events.
Again, specific capabilities are specific to the journal you are using, so you have to
Materialized values of queries
@ -133,6 +126,7 @@ stream, for example if it's finite or infinite, strictly ordered or not ordered
is defined as the ``M`` type parameter of a query (``Query[T,M]``), which allows journals to provide users with their
specialised query object, as demonstrated in the sample below:
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#materialized-query-metadata-classes
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#materialized-query-metadata
.. _materialized values: http://doc.akka.io/docs/akka-stream-and-http-experimental/1.0/java/stream-quickstart.html#Materialized_values
@ -152,18 +146,18 @@ means that data stores which are able to scale to accomodate these requirements
On the other hand the same application may have some complex statistics view or we may have analists working with the data
to figure out best bidding strategies and trends this often requires some kind of expressive query capabilities like
for example SQL or writing Spark jobs to analyse the data. Trefore the data stored in the write-side needs to be
for example SQL or writing Spark jobs to analyse the data. Therefore the data stored in the write-side needs to be
projected into the other read-optimised datastore.
.. note::
When refering to **Materialized Views** in Akka Persistence think of it as "some persistent storage of the result of a Query".
In other words, it means that the view is created once, in order to be afterwards queries multiple times, as in this format
In other words, it means that the view is created once, in order to be afterwards queried multiple times, as in this format
it may be more efficient or interesting to query it (instead of the source events directly).
Materialize view to Reactive Streams compatible datastore
---------------------------------------------------------
If the read datastore exposes it an `Reactive Streams`_ interface then implementing a simple projection
If the read datastore exposes an `Reactive Streams`_ interface then implementing a simple projection
is as simple as, using the read-journal and feeding it into the databases driver interface, for example like so:
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#projection-into-different-store-rs
@ -179,6 +173,7 @@ you may have to implement the write logic using plain functions or Actors instea
In case your write logic is state-less and you just need to convert the events from one data data type to another
before writing into the alternative datastore, then the projection is as simple as:
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#projection-into-different-store-simple-classes
.. includecode:: code/docs/persistence/PersistenceQueryDocTest.java#projection-into-different-store-simple
Resumable projections

View file

@ -11,7 +11,6 @@ import akka.serialization.SerializationExtension
import akka.stream.actor.ActorPublisher
import akka.stream.actor.ActorPublisherMessage.{ Cancel, Request }
import scala.annotation.tailrec
import scala.concurrent.duration.FiniteDuration
object MyEventsByTagPublisher {
@ -90,17 +89,15 @@ class MyEventsByTagPublisher(tag: String, offset: Long, refreshInterval: FiniteD
}
}
@tailrec final def deliverBuf(): Unit =
final def deliverBuf(): Unit =
if (totalDemand > 0 && buf.nonEmpty) {
if (totalDemand <= Int.MaxValue) {
val (use, keep) = buf.splitAt(totalDemand.toInt)
buf = keep
use foreach onNext
} else {
val (use, keep) = buf.splitAt(Int.MaxValue)
buf = keep
use foreach onNext
deliverBuf()
buf foreach onNext
buf = Vector.empty
}
}
}

View file

@ -14,12 +14,6 @@ side of an application, however it can help to migrate data from the write side
simple scenarios Persistence Query may be powerful enough to fulful the query needs of your app, however we highly
recommend (in the spirit of CQRS) of splitting up the write/read sides into separate datastores as the need arrises.
While queries can be performed directly on the same datastore, it is also a very common pattern to use the queries
to create *projections* of the write-side's events and store them into a separate datastore which is optimised for more
complex queries. This architectural pattern of projecting the data into a query optimised datastore, with possibly some
transformation or canculations along the way is the core use-case and recommended style of using Akka Persistence Query
- pulling out of one Journal and storing into another one.
.. warning::
This module is marked as **“experimental”** as of its introduction in Akka 2.4.0. We will continue to
@ -58,7 +52,7 @@ journal is as simple as:
.. includecode:: code/docs/persistence/query/PersistenceQueryDocSpec.scala#basic-usage
Journal implementers are encouraged to put this identified in a variable known to the user, such that one can access it via
Journal implementers are encouraged to put this identifier in a variable known to the user, such that one can access it via
``journalFor(NoopJournal.identifier)``, however this is not enforced.
Read journal implementations are available as `Community plugins`_.
@ -90,7 +84,7 @@ If your usage does not require a live stream, you can disable refreshing by usin
``EventsByPersistenceId`` is a query equivalent to replaying a :ref:`PersistentActor <event-sourcing>`,
however, since it is a stream it is possible to keep it alive and watch for additional incoming events persisted by the
persistent actor identified by the given ``persistenceId``. Most journal will have to revert to polling in order to achieve
persistent actor identified by the given ``persistenceId``. Most journals will have to revert to polling in order to achieve
this, which can be configured using the ``RefreshInterval`` query hint:
.. includecode:: code/docs/persistence/query/PersistenceQueryDocSpec.scala#events-by-persistent-id-refresh
@ -120,7 +114,6 @@ including for example taking the first 10 and cancelling the stream. It is worth
query has an optionally supported offset parameter (of type ``Long``) which the journals can use to implement resumable-streams.
For example a journal may be able to use a WHERE clause to begin the read starting from a specific row, or in a datastore
that is able to order events by insertion time it could treat the Long as a timestamp and select only older events.
Again, specific capabilities are specific to the journal you are using, so you have to
Materialized values of queries
@ -152,18 +145,18 @@ means that data stores which are able to scale to accomodate these requirements
On the other hand the same application may have some complex statistics view or we may have analists working with the data
to figure out best bidding strategies and trends this often requires some kind of expressive query capabilities like
for example SQL or writing Spark jobs to analyse the data. Trefore the data stored in the write-side needs to be
for example SQL or writing Spark jobs to analyse the data. Therefore the data stored in the write-side needs to be
projected into the other read-optimised datastore.
.. note::
When refering to **Materialized Views** in Akka Persistence think of it as "some persistent storage of the result of a Query".
In other words, it means that the view is created once, in order to be afterwards queries multiple times, as in this format
In other words, it means that the view is created once, in order to be afterwards queried multiple times, as in this format
it may be more efficient or interesting to query it (instead of the source events directly).
Materialize view to Reactive Streams compatible datastore
---------------------------------------------------------
If the read datastore exposes it an `Reactive Streams`_ interface then implementing a simple projection
If the read datastore exposes an `Reactive Streams`_ interface then implementing a simple projection
is as simple as, using the read-journal and feeding it into the databases driver interface, for example like so:
.. includecode:: code/docs/persistence/query/PersistenceQueryDocSpec.scala#projection-into-different-store-rs

View file

@ -26,7 +26,7 @@ import scala.annotation.varargs;
*
* final Source&lt;EventEnvelope, ?&gt; events =
* journal.query(new EventsByTag("mytag", 0L));
* </pre></code>
* </code></pre>
*/
public interface ReadJournal {

View file

@ -3,6 +3,8 @@
*/
package akka.persistence.query
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.FiniteDuration
/**
@ -21,6 +23,12 @@ trait Hint
* A plugin may optionally support this [[Hint]] for defining such a refresh interval.
*/
final case class RefreshInterval(interval: FiniteDuration) extends Hint
object RefreshInterval {
/** Java API */
def create(length: Long, unit: TimeUnit): RefreshInterval = new RefreshInterval(FiniteDuration(length, unit))
/** Java API */
def create(interval: FiniteDuration): RefreshInterval = new RefreshInterval(interval)
}
/**
* Indicates that the event stream is supposed to be completed immediately when it

View file

@ -67,10 +67,9 @@ class PersistenceQuery(system: ExtendedActorSystem) extends Extension {
private def createPlugin(configPath: String): scaladsl.ReadJournal = {
require(!isEmpty(configPath) && system.settings.config.hasPath(configPath),
s"'reference.conf' is missing persistence read journal plugin config path: '${configPath}'")
val pluginActorName = configPath
val pluginConfig = system.settings.config.getConfig(configPath)
val pluginClassName = pluginConfig.getString("class")
log.debug(s"Create plugin: ${pluginActorName} ${pluginClassName}")
log.debug(s"Create plugin: ${configPath} ${pluginClassName}")
val pluginClass = system.dynamicAccess.getClassFor[AnyRef](pluginClassName).get
// TODO remove duplication

View file

@ -20,7 +20,11 @@ trait Query[T, M]
*
* A plugin may optionally support this [[Query]].
*/
final case object AllPersistenceIds extends Query[String, Unit]
final case object AllPersistenceIds extends AllPersistenceIds {
/** Java API */
final def getInstance: AllPersistenceIds = this
}
abstract class AllPersistenceIds extends Query[String, Unit]
/**
* Query events for a specific `PersistentActor` identified by `persistenceId`.
@ -34,7 +38,19 @@ final case object AllPersistenceIds extends Query[String, Unit]
*/
final case class EventsByPersistenceId(persistenceId: String, fromSequenceNr: Long = 0L, toSequenceNr: Long = Long.MaxValue)
extends Query[Any, Unit]
object EventsByPersistenceId {
/** Java API */
def create(persistenceId: String, fromSequenceNr: Long, toSequenceNr: Long): EventsByPersistenceId =
EventsByPersistenceId(persistenceId, fromSequenceNr, toSequenceNr)
/** Java API */
def create(persistenceId: String, fromSequenceNr: Long): EventsByPersistenceId =
EventsByPersistenceId(persistenceId, fromSequenceNr)
/** Java API */
def create(persistenceId: String): EventsByPersistenceId =
EventsByPersistenceId(persistenceId)
}
/**
* Query events that have a specific tag. A tag can for example correspond to an
* aggregate root type (in DDD terminology).
@ -56,6 +72,12 @@ final case class EventsByPersistenceId(persistenceId: String, fromSequenceNr: Lo
* A plugin may optionally support this [[Query]].
*/
final case class EventsByTag(tag: String, offset: Long = 0L) extends Query[EventEnvelope, Unit]
object EventsByTag {
/** Java API */
def create(tag: String): EventsByTag = EventsByTag(tag)
/** Java API */
def create(tag: String, offset: Long): EventsByTag = EventsByTag(tag)
}
/**
* Event wrapper adding meta data for the events in the result stream of

172
lol Normal file
View file

@ -0,0 +1,172 @@
adoc-api/akka/persistence/query/scaladsl/ReadJournal.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/scaladsl/ReadJournal.java:31: warning: no @param for <T>
[error] public abstract <T extends java.lang.Object, M extends java.lang.Object> akka.stream.scaladsl.Source<T, M> query (akka.persistence.query.Query<T, M> q, scala.collection.Seq<akka.persistence.query.Hint> hints) ;
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/scaladsl/ReadJournal.java:31: warning: no @param for <M>
[error] public abstract <T extends java.lang.Object, M extends java.lang.Object> akka.stream.scaladsl.Source<T, M> query (akka.persistence.query.Query<T, M> q, scala.collection.Seq<akka.persistence.query.Hint> hints) ;
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/scaladsl/ReadJournalAdapter.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/javadsl/ReadJournal.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:43: warning: no @param for <T>
[error] <T, M> Source<T, M> query(Query<T, M> q, Hint... hints);
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:43: warning: no @param for <M>
[error] <T, M> Source<T, M> query(Query<T, M> q, Hint... hints);
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:43: warning: no @param for q
[error] <T, M> Source<T, M> query(Query<T, M> q, Hint... hints);
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:43: warning: no @param for hints
[error] <T, M> Source<T, M> query(Query<T, M> q, Hint... hints);
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:43: warning: no @return
[error] <T, M> Source<T, M> query(Query<T, M> q, Hint... hints);
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:23: error: end tag missing: </code>
[error] * <pre><code>
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/src/main/java/akka/persistence/query/javadsl/ReadJournal.java:29: error: unexpected end tag: </code>
[error] * </pre></code>
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/javadsl/ReadJournalAdapter.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/AllPersistenceIds.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/AllPersistenceIds.java:4: warning: no @return
[error] static public final akka.persistence.query.AllPersistenceIds getInstance () { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/AllPersistenceIds$.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/EventEnvelope.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/EventEnvelope$.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/EventsByPersistenceId.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:14: warning: no @param for persistenceId
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:14: warning: no @param for fromSequenceNr
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:14: warning: no @param for toSequenceNr
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:14: warning: no @return
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:16: warning: no @param for persistenceId
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:16: warning: no @param for fromSequenceNr
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:16: warning: no @return
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:18: warning: no @param for persistenceId
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId.java:18: warning: no @return
[error] static public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId) { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/EventsByPersistenceId$.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:9: warning: no @param for persistenceId
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:9: warning: no @param for fromSequenceNr
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:9: warning: no @param for toSequenceNr
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:9: warning: no @return
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr, long toSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:11: warning: no @param for persistenceId
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:11: warning: no @param for fromSequenceNr
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:11: warning: no @return
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId, long fromSequenceNr) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:13: warning: no @param for persistenceId
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByPersistenceId$.java:13: warning: no @return
[error] public akka.persistence.query.EventsByPersistenceId create (java.lang.String persistenceId) { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/EventsByTag.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag.java:24: warning: no @param for tag
[error] static public akka.persistence.query.EventsByTag create (java.lang.String tag) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag.java:24: warning: no @return
[error] static public akka.persistence.query.EventsByTag create (java.lang.String tag) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag.java:26: warning: no @param for tag
[error] static public akka.persistence.query.EventsByTag create (java.lang.String tag, long offset) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag.java:26: warning: no @param for offset
[error] static public akka.persistence.query.EventsByTag create (java.lang.String tag, long offset) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag.java:26: warning: no @return
[error] static public akka.persistence.query.EventsByTag create (java.lang.String tag, long offset) { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/EventsByTag$.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag$.java:9: warning: no @param for tag
[error] public akka.persistence.query.EventsByTag create (java.lang.String tag) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag$.java:9: warning: no @return
[error] public akka.persistence.query.EventsByTag create (java.lang.String tag) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag$.java:11: warning: no @param for tag
[error] public akka.persistence.query.EventsByTag create (java.lang.String tag, long offset) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag$.java:11: warning: no @param for offset
[error] public akka.persistence.query.EventsByTag create (java.lang.String tag, long offset) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/EventsByTag$.java:11: warning: no @return
[error] public akka.persistence.query.EventsByTag create (java.lang.String tag, long offset) { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/Hint.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/NoRefresh.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/NoRefresh.java:4: warning: no @return
[error] static public akka.persistence.query.NoRefresh getInstance () { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/NoRefresh$.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/NoRefresh$.java:5: warning: empty <p> tag
[error] * <p>
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/PersistenceQuery.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/PersistenceQuery.PluginHolder.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/PersistenceQuery.PluginHolder$.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/PersistenceQuery$.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/Query.html...
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/RefreshInterval.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval.java:11: warning: no @param for length
[error] static public akka.persistence.query.RefreshInterval create (long length, java.util.concurrent.TimeUnit unit) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval.java:11: warning: no @param for unit
[error] static public akka.persistence.query.RefreshInterval create (long length, java.util.concurrent.TimeUnit unit) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval.java:11: warning: no @return
[error] static public akka.persistence.query.RefreshInterval create (long length, java.util.concurrent.TimeUnit unit) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval.java:13: warning: no @param for interval
[error] static public akka.persistence.query.RefreshInterval create (scala.concurrent.duration.FiniteDuration interval) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval.java:13: warning: no @return
[error] static public akka.persistence.query.RefreshInterval create (scala.concurrent.duration.FiniteDuration interval) { throw new RuntimeException(); }
[error] ^
[info] Generating /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/genjavadoc-api/akka/persistence/query/RefreshInterval$.html...
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval$.java:9: warning: no @param for length
[error] public akka.persistence.query.RefreshInterval create (long length, java.util.concurrent.TimeUnit unit) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval$.java:9: warning: no @param for unit
[error] public akka.persistence.query.RefreshInterval create (long length, java.util.concurrent.TimeUnit unit) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval$.java:9: warning: no @return
[error] public akka.persistence.query.RefreshInterval create (long length, java.util.concurrent.TimeUnit unit) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval$.java:11: warning: no @param for interval
[error] public akka.persistence.query.RefreshInterval create (scala.concurrent.duration.FiniteDuration interval) { throw new RuntimeException(); }
[error] ^
[error] /mnt/akka/jenkinsakka/localhome-a0/workspace/pr-validator-per-commit-jenkins/akka-persistence-query/target/java/akka/persistence/query/RefreshInterval$.java:11: warning: no @return
[error] public akka.persistence.query.RefreshInterval create (scala.concurrent.duration.FiniteDuration interval) { throw new RuntimeException(); }
[error] ^