Skip to content

Commit

Permalink
Documentation update
Browse files Browse the repository at this point in the history
  • Loading branch information
abuijze committed May 7, 2014
1 parent 54677aa commit 2c70398
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 65 deletions.
Expand Up @@ -61,10 +61,17 @@
variable length column of 255 characters, you could use a fixed length column of 36
characters for the aggregate identifier.</para>
<para>The 'timestamp' column in the DomainEventEntry table only stores ISO 8601
timestamps. If all times are stored in the UTZ timezone, they need a column length
timestamps. If all times are stored in the UTC timezone, they need a column length
of 24 characters. If you use another timezone, this may be up to 28. Using variable
length columns is generally not necessary, since time stamps always have the same
length.</para>
length columns is generally not necessary, since time stamps always have the same length.<warning>
<title>Timezones and Event Stores</title>
<para>It is highly recommended to store all timestamps in UTC format. In
countries with Daylight Savings Time, storing timestamps in local time may
result in sorting errors for events generated around and during the timezone
switch. This does not occur when UTC is used. Some servers are configured to
always use UTC. Alternatively, you should configure the Event Store to
convert timestamps to UTC before storing them.</para>
</warning></para>
<para>The 'type' column in the DomainEventEntry stores the Type Identifiers of
aggregates. Generally, these are the 'simple name' of the aggregate. Event the
infamous 'AbstractDependencyInjectionSpringContextTests' in spring only counts 45
Expand Down Expand Up @@ -187,36 +194,38 @@
</sect1>
<sect1>
<title>Event Serializer tuning</title>
<para>XStream is very configurable and extensible. If you just use a plain
<code>XStreamSerializer</code>, there are some quick wins ready to pick up. XStream
allows you to configure aliases for package names and event class names. Aliases are
typically much shorter (especially if you have long package names), making the
serialized form of an event smaller. And since we're talking XML, each character removed
from XML is twice the profit (one for the start tag, and one for the end tag). </para>
<para>A more advanced topic in XStream is creating custom converters. The default reflection
based converters are simple, but do not generate the most compact XML. Always look
carefully at the generated XML and see if all the information there is really needed to
reconstruct the original instance.
</para>
<para>Avoid the use of upcasters when possible. XStream allows aliases to be used for
fields, when they have changed name. Imagine revision 0 of an event, that used a field
called "clientId". The business prefers the term "customer", so revision 1 was created
with a field called "customerId". This can be configured completely in XStream, using
field aliases. You need to configure two aliases, in the following order: alias
"customerId" to "clientId" and then alias "customerId" to "customerId". This will tell
XStream that if it encounters a field called "customerId", it will call the
corresponding XML element "customerId" (the second alias overrides the first). But if
XStream encounters an XML element called "clientId", it is a known alias and will be
resolved to field name "customerId". Check out the XStream documentation for more
information.
</para>
<para>For ultimate performance, you're probably better off without reflection based
mechanisms alltogether. In that case, it is probably wisest to create a custom
serialization mechanism. The <code>DataInputStream</code> and
<code>DataOutputStream</code> allow you to easilly write the contents of the Events
to an output stream. The <code>ByteArrayOutputStream</code> and
<code>ByteArrayInputStream</code> allow writing to and reading from byte
arrays.</para>
<sect2>
<title>XStream Serializer</title>
<para>XStream is very configurable and extensible. If you just use a plain
<code>XStreamSerializer</code>, there are some quick wins ready to pick up.
XStream allows you to configure aliases for package names and event class names.
Aliases are typically much shorter (especially if you have long package names),
making the serialized form of an event smaller. And since we're talking XML, each
character removed from XML is twice the profit (one for the start tag, and one for
the end tag). </para>
<para>A more advanced topic in XStream is creating custom converters. The default
reflection based converters are simple, but do not generate the most compact XML.
Always look carefully at the generated XML and see if all the information there is
really needed to reconstruct the original instance. </para>
<para>Avoid the use of upcasters when possible. XStream allows aliases to be used for
fields, when they have changed name. Imagine revision 0 of an event, that used a
field called "clientId". The business prefers the term "customer", so revision 1 was
created with a field called "customerId". This can be configured completely in
XStream, using field aliases. You need to configure two aliases, in the following
order: alias "customerId" to "clientId" and then alias "customerId" to "customerId".
This will tell XStream that if it encounters a field called "customerId", it will
call the corresponding XML element "customerId" (the second alias overrides the
first). But if XStream encounters an XML element called "clientId", it is a known
alias and will be resolved to field name "customerId". Check out the XStream
documentation for more information. </para>
<para>For ultimate performance, you're probably better off without reflection based
mechanisms alltogether. In that case, it is probably wisest to create a custom
serialization mechanism. The <code>DataInputStream</code> and
<code>DataOutputStream</code> allow you to easilly write the contents of the
Events to an output stream. The <code>ByteArrayOutputStream</code> and
<code>ByteArrayInputStream</code> allow writing to and reading from byte
arrays.</para>
</sect2>
<sect2>
<title>Preventing duplicate serialization</title>
<para>Especially in distributed systems, Event Messages need to be serialized in
Expand Down
Expand Up @@ -400,31 +400,30 @@
<code>EventEntryStore</code> in the JPA Event Store's constructor. You will
need to provide implementations of methods that load and store serialized
events. Check the API Documentation of the <code>EventEntryStore</code> class
for implementation requirements. <warning>
<title>Memory consumption warning</title>
<para>Note that persistence providers, such as Hibernate, use a first-level
cache on their EntityManager implementation. Typically, this means that
all entities used or returned in queries are attached to the
EntityManager. They are only cleared when the surrounding transaction is
committed or an explicit "clear" in performed inside the transaction.
This is especially the case when the Queries are executed in the context
of a transaction. </para>
<para>To work around this issue, make sure to exclusively query for
non-entity objects. You can use JPA's "SELECT new SomeClass(parameters)
FROM ..." style queries to work around this issue. Alternatively, call
<code>EntityManager.flush()</code> and
<code>EntityManager.clear()</code> after fetching a batch of events.
Failure to do so might result in <code>OutOfMemoryException</code>s when
loading large streams of events. </para>
</warning><note>
<title>Hibernate support</title>
<para>The <code>EventEntryStore</code> implementation used by Axon
automatically detects whether Hibernate is used as JPA implementation.
If that is the case, it will use some Hiberante-specific features to
optimize performance while reducing memory consumption. To prevent
Hibernate specific logic, configure the JPA Event Store to use the
<code>DefaultEventEntryStore</code> instead.</para>
</note></para>
for implementation requirements. </para>
<para>If you only want to change the table name or want to add some extra fields to
the table, you can also create a class that extends from
DefaultEventEntryStrore, and override the <code>createDomainEventEntry</code>
and/or <code>createSnapshotEventEntrymethod</code>. This method must return a
<code>DomainEventEntry</code> and <code>SnapshotEventEntry</code> instance,
respectively. By returning your own subclass of these, you can store different
events in different tables, or add extra information in separate columns.</para>
<warning>
<title>Memory consumption warning</title>
<para>Note that persistence providers, such as Hibernate, use a first-level
cache on their EntityManager implementation. Typically, this means that all
entities used or returned in queries are attached to the EntityManager. They
are only cleared when the surrounding transaction is committed or an
explicit "clear" in performed inside the transaction. This is especially the
case when the Queries are executed in the context of a transaction. </para>
<para>To work around this issue, make sure to exclusively query for non-entity
objects. You can use JPA's "SELECT new SomeClass(parameters) FROM ..." style
queries to work around this issue. Alternatively, call
<code>EntityManager.flush()</code> and
<code>EntityManager.clear()</code> after fetching a batch of events.
Failure to do so might result in <code>OutOfMemoryException</code>s when
loading large streams of events. </para>
</warning>
</simplesect>
</sect2>
<sect2>
Expand Down Expand Up @@ -528,25 +527,30 @@
<sect2>
<title>Influencing the serialization process</title>
<para>Event Stores need a way to serialize the Event to prepare it for storage. By
default, Axon provides the <code>XStreamSerializer</code>, which uses <link
default, Axon uses the <code>XStreamSerializer</code>, which uses <link
xmlns:ns1="http://www.w3.org/1999/xlink" ns1:href="http://xstream.codehaus.org/"
>XStream</link> to serialize Events into XML and vice versa. XStream is
reasonably fast and is more flexible than Java Serialization. Furthermore, the
result of XStream serialization is human readable. Quite useful for logging and
debugging purposes. </para>
>XStream</link> to serialize Events into XML. XStream is reasonably fast and is
more flexible than Java Serialization. Furthermore, the result of XStream
serialization is human readable. Quite useful for logging and debugging purposes. </para>
<para>The XStreamSerializer can be configured. You can define aliases it should use for
certain packages, classes or even fields. Besides being a nice way to shorten
potentially long names, aliases can also be used when class definitions of event
change. For more information about aliases, visit the <link
xmlns:ns1="http://www.w3.org/1999/xlink" ns1:href="http://xstream.codehaus.org/"
>XStream website</link>. </para>
>XStream website</link>.</para>
<para>Alternatively, Axon also provides the <code>JacksonSerializer</code>, which uses
<link xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="https://github.com/FasterXML/jackson">Jackson</link> to serialize
Events into JSON. While it produces more a compact serialized form, it does require
that classes stick to the conventions (or configuration) required by Jackson.</para>
<note>
<title>Spring XML Configuration and Serializer Customization</title>
<para>Configuring the serializer using Java code (or other JVM languages) is easy.
However, configuring it in a Spring XML Application Context is not so trivial,
due to its limitations to invoke methods. One of the options is to create a
<code>FactoryBean</code> that creates an instance of an XStreamSerializer
and configures it in code. Check the Spring Reference </para>
and configures it in code. Check the Spring Reference for more
information.</para>
</note>
<para>You may also implement your own Serializer, simply by creating a class that
implements <code>Serializer</code>, and configuring the Event Store to use that
Expand Down Expand Up @@ -770,6 +774,9 @@ public class AdministrativeDetailsUpdatedUpcaster implements Upcaster&lt;Documen
<para>If the content type conversion that you need is not provided by Axon you can
always write one yourself using the <code>ContentTypeConverter</code> interface.
</para>
<para>The <code>XStreamSerializer</code> supports Dom4J as well as XOM as XML document
representations. The <code>JacksonSerializer</code> supports Jackson's
<code>JsonNode</code>.</para>
</sect2>
</sect1>
<sect1 xml:id="using-snapshot-events">
Expand Down
24 changes: 24 additions & 0 deletions documentation/src/main/docbook/en-US/reference-guide/7-sagas.xml
Expand Up @@ -472,6 +472,30 @@
operation. This will ensure that data is sent to the database, even before a
transaction is committed. the default is to use explicit flushes.</para>
</simplesect>
<simplesect>
<title><code>JdbcSagaRepository</code></title>
<para>The <code>JdbcSagaRepository</code> uses plain JDBC to store stage instances
and their association values. Similar to the <code>JpaSagaRepository</code>,
Saga instances don't need to be aware of how they are stored. They are
serialized using a Serializer.</para>
<para>The <code>JdbcSagaRepository</code> is configured with a
<code>ConnectionProvider</code>, which can simply be a
<code>DataSource</code> wrapped in a
<code>DataSourceConnectionProvider</code>, a <code>ResourceInjector</code>
and a <code>Serializer</code>. While not required, it is recommended to use a
<code>UnitOfWorkAwareConnectionProviderWrapper</code>. It will check the
current Unit of Work for an already open database connection. This will ensure
that all activity within a unit of work is done on a single connection.</para>
<para>Unlike JPA, the JdbcSagaRepository uses plain SQL statement to store and
retrieve information. This may mean that some operations depend on the Database
specific SQL dialect. It may also be the case that certain Database vendors
provide non-standard features that you would like to use. To allow for this, you
can provide your own <code>SagaSqlSchema</code>. The <code>SagaSqlSchema</code>
is an interface that defines all the operations the repository needs to perform
on the underlying database. It allows you to customize the SQL statement
executed for each one of them. The default is the
<code>GenericSagaSqlSchema</code>.</para>
</simplesect>
<simplesect>
<title><code>MongoSagaRepository</code></title>
<para>Similar to the <code>JpaSagaRepository</code>, the
Expand Down

0 comments on commit 2c70398

Please sign in to comment.