Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Documentation update

  • Loading branch information...
commit 2c7039839c496c4eb15700d76763cb22a829df11 1 parent 54677aa
@abuijze abuijze authored
View
75 documentation/src/main/docbook/en-US/reference-guide/10-performance-tuning.xml
@@ -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
@@ -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
View
71 documentation/src/main/docbook/en-US/reference-guide/5-repositories-and-event-stores.xml
@@ -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>
@@ -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
@@ -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">
View
24 documentation/src/main/docbook/en-US/reference-guide/7-sagas.xml
@@ -473,6 +473,30 @@
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
<code>MongoSagaRepository</code> stores the Saga instances and their
Please sign in to comment.
Something went wrong with that request. Please try again.