Class SqlMessageStore
- java.lang.Object
-
- net.sf.eBus.feed.historic.store.SqlMessageStore
-
- All Implemented Interfaces:
IEMessageStore
public final class SqlMessageStore extends Object implements IEMessageStore
This class implementsIEMessageStoreproviding the ability to store events to and retrieve events from aJava SQL connection. An application using this class is responsible for:-
Defining the stored
notification message key. -
Providing an
IInsertGeneratorinstance used to generate SQL statement for storing eBus notification message (as defined by message key) orPublishStatusEventinto target database. -
Providing an
IRetrieveGeneratorinstance used to generate SQL statement for retrieving eBus notification messages orPublishStatusEventfrom target database based on message key andinterval. -
Providing an
IMessageDecoderinstance used to translateResultSetinto eBus notification message (either store's target message key orPublishStatusEvent).
Note: application is responsible for inserting, retrieving, and decoding both the message type defined by the message key and
PublishStatusEventmessages. Also note that the notification message type must be inserted and retrieved using a single SQL statement. Notification types too complex for this requirement cannot useSqlMessageStore.There is a one-to-one mapping between an
SqlMessageStoreand eBus notification message key. But the application developer is free to design SQL tables in any way deemed best. Most likely this means that there will be a single table for a given eBus notification message class containing the message subject. This allows a singleSqlMessageStoreinstance to be shared among multipleEHistoricPublishFeeds. In this case, it is the application's responsibility to provide thread-safe message store and retrieval.Simply put, the application is responsible for interfacing
SqlMessageStorewith the application database, translating eBus notification messages between database and Java.Example
The following code is used to insert and retrieve a
TopOfBookMessagenotification into and from an SQL table. Notification message definition (note: seeENotificationMessageandEMessagefor inherited message fields):public final class TopOfBookMessage extends ENotificationMessage { public final PriceSize bid; public final PriceSize ask; public final PriceType priceType; // enum specifying if this is the opening, closing, low, high, or latest price. // Builder class not shown. }PriceSizedefinition:public final class PriceSize extends EField { public final Decimal6f price; // uses decimal4j for prices. public final int size; public final Trend trend; // enum specifying whether this price is up or down in relation to previous message. // Builder class not shown. }The following SQL data definitions used to store the top-of-book message are in Postgresql:
CREATE TABLE top_of_book ( ticker_symbol varchar(50) NOT NULL, publisher_id bigint NOT NULL, publisher_position integer NOT NULL, bid price_size NULL, ask price_size NULL, price_type price_type NOT NULL, PRIMARY KEY ( message_timestamp, publisher_id, publisher_position ) ); -- Table indices not shown. CREATE TYPE price_Size AS ( price NUMERIC(15, 6), size integer, price_trend trend ); CREATE TYPE price_type AS ENUM ( ... ); CREATE TYPE trend AS ENUM ( ... );The
PublishStatusEventmessages are stored in the table:CREATE TABLE publish_status_event ( subject varchar(500) NOT NULL, message_timestamp timestamp NOT NULL, publisher_id bigint NOT NULL, publisher_position integer NOT NULL, message_key message_key NOT NULL, feed_state feed_state NOT NULL, PRIMARY KEY ( message_timestamp, publisher_id, publisher_position ) ); -- Table indices not shown. CREATE TYPE message_key AS ( message_class varchar(500), message_subject varchar(500) ); CREATE TYPE feed_state AS ENUM ( 'UNKNOWN', 'DOWN', 'UP' );IInsertGenerator.insertStatement(ENotificationMessage)implementation returns the following insert statement for a top-of-book message:INSERT INTO top_of_book VALUES ('ACME', '2024-01-06 07:30:53.113', 2001, 1, ROW (12.076400, 1200, 'NA'::trend), ROW (12.076700, 600, 'NA'::trend), 'LATEST'::price_type)The insert statement for a
PublishStatusEventis:INSERT INTO publish_status_event VALUES ('/marketdata/ACME', '2024-01-06 07:30:54.547', 2001, 15, ROW ('com.lightspeedmd.com', '/marketdata/ACME', 'DOWN'::feed_state)IRetrieveGenerator.retrieveStatement(EMessageKey, EInterval)for top-of-book messages is:SELECT ticker_symbol, message_timestamp, publisher_id, publisher_position, (bid).price, (bid).size, (bid).price_trend, (ask).price, (ask).size, (ask).price_trend, price_type FROM top_of_book WHERE message_timestamp >= '2024-01-06 07:47:43.52010225' AND message_timestamp < '2024-01-06 07:47:44.18792075'The
ResultSetto top-of-book message code is:// Note: result set columns start at index 1. final String tickerSymbol = rs.getString(1); final Instant timestamp = (rs.getTimestamp(2)).toInstant(); final long publisherId = rs.getLong(3); final int position = rs.getInt(4); final Decimal6f bidPrice = Decimal6f.valueOf(rs.getBigDecimal(5)); final int bidSize = rs.getInt(6); final Trend bidTrend = Trend.valueOf(rs.getString(7)); final Decimal6f askPrice = Decimal6f.valueOf(rs.getBigDecimal(8)); final int askSize = rs.getInt(9); final Trend askTrend = Trend.valueOf(rs.getString(10)); final PriceType priceType = PriceType.valueOf(rs.getString(11)); final PriceSize bid = (PriceSize.builder()).price(bidPrice) .size(bidSize) .trend(bidTrend) .build(); final PriceSize ask = (PriceSize.builder()).price(askPrice) .size(askSize) .trend(askTrend) .build(); final TopOfBookMessage.Builder builder = TopOfBookMessage.builder(); builder.subject(tickerSymbol) .timestamp(timestamp) .publisherId(publisherId) .position(position) .bid(bid) .ask(ask) .priceType(priceType) .build());- Author:
- Charles W. Rapp
- See Also:
InMemoryMessageStore
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classSqlMessageStore.BuilderSqlMessageStoreinstances created using aBuilderinstance.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static SqlMessageStore.Builderbuilder(Connection dbConnection)Returns a newSqlMessageStore.Builderinstance for a given data base connection.intinsertCount()Returns number of events inserted into message store since message store opening.booleanisOpen()Returnstrueif this message store is open and ready to store or retrieve notification messages.EMessageKeykey()Returns message key associated with message store.Collection<ENotificationMessage>retrieve(EInterval interval)Retrieves historic messages as defined by given date/time interval.voidstore(ENotificationMessage message)Persists given notification message to store.
-
-
-
Method Detail
-
isOpen
public boolean isOpen()
Description copied from interface:IEMessageStoreReturnstrueif this message store is open and ready to store or retrieve notification messages.- Specified by:
isOpenin interfaceIEMessageStore- Returns:
trueif message store is open.
-
key
public EMessageKey key()
Description copied from interface:IEMessageStoreReturns message key associated with message store.- Specified by:
keyin interfaceIEMessageStore- Returns:
- message store's associated key.
-
store
public void store(ENotificationMessage message)
Description copied from interface:IEMessageStorePersists given notification message to store.- Specified by:
storein interfaceIEMessageStore- Parameters:
message- persist this message.- See Also:
IEMessageStore.retrieve(EInterval)
-
retrieve
public Collection<ENotificationMessage> retrieve(EInterval interval)
Description copied from interface:IEMessageStoreRetrieves historic messages as defined by given date/time interval. Returned collection may be empty but nevernull.Please note that implementation are not required to validate
intervalsince this is performed byEHistoricPublishFeed. That said, such validation is encourage if store is used outside of eBus historic feed framework.- Specified by:
retrievein interfaceIEMessageStore- Parameters:
interval- date/time interval.- Returns:
- iterator over historic messages. Does not
return
nullbut may return iterator whereIterator.hasNext()returnsfalse. - See Also:
IEMessageStore.store(ENotificationMessage)
-
insertCount
public int insertCount()
Returns number of events inserted into message store since message store opening.- Returns:
- return event insertion count.
-
builder
public static SqlMessageStore.Builder builder(Connection dbConnection) throws SQLException
Returns a newSqlMessageStore.Builderinstance for a given data base connection.- Parameters:
dbConnection- database connection encapsulated bySqlMessageStore.- Returns:
- a new
Builderinstance. - Throws:
NullPointerException- ifconnectionisnull.IllegalArgumentException- ifconnectionis closed or read-only.SQLException- if a database access error occurs when attempting to ascertain whether the connection is closed or read-only.
-
-