Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/WASdev/sample.daytrader7/llms.txt

Use this file to discover all available pages before exploring further.

DayTrader 7 uses five JPA 2.1 entities mapped to relational database tables within the daytrader persistence unit (configured in daytrader-ee7-ejb/src/main/resources/META-INF/persistence.xml, using the jdbc/TradeDataSource JTA data source). Every table includes an optLock integer column in the DDL schema; this column is present for schema compatibility but is not mapped to a @Version field in the current entity classes. The DDL for all tables is provided in daytrader-ee7-ejb/src/main/resources/META-INF/daytrader.sql. Primary keys for AccountDataBean, HoldingDataBean, and OrderDataBean are generated using a shared table-based generator (KEYGENEJB), avoiding database-sequence contention.
The JPA shared second-level cache is explicitly disabled (<shared-cache-mode>NONE</shared-cache-mode>) in persistence.xml so that every read goes to the database, producing a more representative benchmark workload.

Entity: AccountDataBean

Table: accountejb
Java class: com.ibm.websphere.samples.daytrader.entities.AccountDataBean
AccountDataBean represents a customer’s brokerage account. It is the root aggregate for orders and holdings. The profile_userid column is a foreign key to accountprofileejb, linking each account to its profile. Login and logout activity increments loginCount and logoutCount directly on the entity, making these counters useful benchmark metrics.
@Entity(name = "accountejb")
@Table(name = "accountejb")
public class AccountDataBean implements Serializable {

    @TableGenerator(name = "accountIdGen", table = "KEYGENEJB",
        pkColumnName = "KEYNAME", valueColumnName = "KEYVAL",
        pkColumnValue = "account", allocationSize = 1000)
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "accountIdGen")
    @Column(name = "ACCOUNTID", nullable = false)
    private Integer accountID;

    @NotNull
    @Column(name = "LOGINCOUNT", nullable = false)
    private int loginCount;

    @NotNull
    @Column(name = "LOGOUTCOUNT", nullable = false)
    private int logoutCount;

    @Column(name = "LASTLOGIN")
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastLogin;

    @Column(name = "CREATIONDATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;

    @Column(name = "BALANCE")
    private BigDecimal balance;

    @Column(name = "OPENBALANCE")
    private BigDecimal openBalance;

    @OneToMany(mappedBy = "account", fetch = FetchType.LAZY)
    private Collection<OrderDataBean> orders;

    @OneToMany(mappedBy = "account", fetch = FetchType.LAZY)
    private Collection<HoldingDataBean> holdings;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PROFILE_USERID")
    private AccountProfileDataBean profile;
}
SQL DDL:
create table accountejb
  (creationdate timestamp,
   openbalance decimal(10, 2),
   logoutcount integer not null,
   balance decimal(10, 2),
   accountid integer not null,
   lastlogin timestamp,
   logincount integer not null,
   PROFILE_USERID VARCHAR(250),
   optLock integer);

alter table accountejb
  add constraint pk_accountejb primary key (accountid);

create index profile_userid on accountejb(profile_userid);
ColumnTypeNotes
ACCOUNTIDintegerPrimary key; generated via KEYGENEJB table
LOGINCOUNTinteger NOT NULLIncremented on every successful login
LOGOUTCOUNTinteger NOT NULLIncremented on every logout
LASTLOGINtimestampUpdated to NOW() on each login
CREATIONDATEtimestampSet at account registration
BALANCEdecimal(10,2)Current cash balance; debited on buy, credited on sell
OPENBALANCEdecimal(10,2)Initial deposit balance; never modified after registration
PROFILE_USERIDvarchar(250)FK → accountprofileejb.userid
optLockintegerSchema column (not mapped to a @Version field in the entity)
Relationships:
  • @OneToOne (lazy) → AccountProfileDataBean via PROFILE_USERID
  • @OneToMany (lazy, mapped by account) → Collection<OrderDataBean>
  • @OneToMany (lazy, mapped by account) → Collection<HoldingDataBean>

Entity: AccountProfileDataBean

Table: accountprofileejb
Java class: com.ibm.websphere.samples.daytrader.entities.AccountProfileDataBean
AccountProfileDataBean stores the user’s identifying and contact information. The userid field is both the natural primary key and the lookup key used throughout the application (e.g., entityManager.find(AccountProfileDataBean.class, userID)). Passwords are stored in plain text as this is a benchmark application, not a production system.
@Entity(name = "accountprofileejb")
@Table(name = "accountprofileejb")
public class AccountProfileDataBean implements Serializable {

    @Id
    @Column(name = "USERID", nullable = false)
    private String userID;

    @Column(name = "PASSWD")
    private String passwd;

    @Column(name = "FULLNAME")
    private String fullName;

    @Column(name = "ADDRESS")
    private String address;

    @Column(name = "EMAIL")
    private String email;

    @Column(name = "CREDITCARD")
    private String creditCard;

    @OneToOne(mappedBy = "profile", fetch = FetchType.LAZY)
    private AccountDataBean account;
}
SQL DDL:
create table accountprofileejb
  (address varchar(250),
   passwd varchar(250),
   userid varchar(250) not null,
   email varchar(250),
   creditcard varchar(250),
   fullname varchar(250),
   optLock integer);

alter table accountprofileejb
  add constraint pk_accountprofile2 primary key (userid);
ColumnTypeNotes
USERIDvarchar(250) NOT NULLPrimary key; used as the application-level user identity
PASSWDvarchar(250)Password (plain text; benchmark only)
FULLNAMEvarchar(250)Customer’s full name
ADDRESSvarchar(250)Street address
EMAILvarchar(250)Email address
CREDITCARDvarchar(250)Credit card number used during registration
optLockintegerSchema column (not mapped to a @Version field in the entity)
Relationships:
  • @OneToOne (lazy, inverse side, mapped by profile) → AccountDataBean

Entity: QuoteDataBean

Table: quoteejb
Java class: com.ibm.websphere.samples.daytrader.entities.QuoteDataBean
QuoteDataBean represents a publicly traded stock. The symbol (e.g., "s:0" through "s:9999") is the natural primary key. After every buy or sell, TradeSLSBBean.updateQuotePriceVolume() issues a SELECT ... FOR UPDATE (via the named native query quoteejb.quoteForUpdate) and updates price, change1, high, low, and volume atomically. These updates are then published to TradeStreamerTopic for real-time WebSocket delivery.
@Entity(name = "quoteejb")
@Table(name = "quoteejb")
@NamedQueries({
    @NamedQuery(name = "quoteejb.allQuotes", query = "SELECT q FROM quoteejb q")
})
@NamedNativeQueries({
    @NamedNativeQuery(name = "quoteejb.quoteForUpdate",
        query = "select * from quoteejb q where q.symbol=? for update",
        resultClass = QuoteDataBean.class)
})
public class QuoteDataBean implements Serializable {

    @Id
    @Column(name = "SYMBOL", nullable = false)
    private String symbol;

    @Column(name = "COMPANYNAME")
    private String companyName;

    @Column(name = "VOLUME", nullable = false)
    private double volume;

    @Column(name = "PRICE")
    private BigDecimal price;

    @Column(name = "OPEN1")
    private BigDecimal open1;

    @Column(name = "LOW")
    private BigDecimal low;

    @Column(name = "HIGH")
    private BigDecimal high;

    @Column(name = "CHANGE1", nullable = false)
    private double change1;
}
SQL DDL:
create table quoteejb
  (low decimal(10, 2),
   open1 decimal(10, 2),
   volume double not null,
   price decimal(10, 2),
   high decimal(10, 2),
   companyname varchar(250),
   symbol varchar(250) not null,
   change1 double not null,
   optLock integer);

alter table quoteejb
  add constraint pk_quoteejb primary key (symbol);
ColumnTypeNotes
SYMBOLvarchar(250) NOT NULLPrimary key; format "s:N" where N is 0–9999
COMPANYNAMEvarchar(250)Display name of the company
VOLUMEdouble NOT NULLCumulative shares traded; incremented on each buy/sell
PRICEdecimal(10,2)Current market price; updated on each trade
OPEN1decimal(10,2)Price at market open; used to compute change1
LOWdecimal(10,2)Intraday low
HIGHdecimal(10,2)Intraday high
CHANGE1double NOT NULLprice − open1; updated on each trade
optLockintegerSchema column (not mapped to a @Version field in the entity)
Relationships:
Referenced (as the quote side) by @ManyToOne from HoldingDataBean and OrderDataBean. No back-reference is stored in QuoteDataBean itself.

Entity: HoldingDataBean

Table: holdingejb
Java class: com.ibm.websphere.samples.daytrader.entities.HoldingDataBean
HoldingDataBean represents a position in a stock that a customer currently owns. A holding is created by TradeSLSBBean.completeOrder() when a buy order is completed, and is removed (entityManager.remove(holding)) when a sell order is completed. Setting purchaseDate to Timestamp(0) marks a holding as “in-flight” (pending sale).
@Entity(name = "holdingejb")
@Table(name = "holdingejb")
public class HoldingDataBean implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "holdingIdGen")
    @Column(name = "HOLDINGID", nullable = false)
    private Integer holdingID;

    @Column(name = "QUANTITY", nullable = false)
    private double quantity;

    @Column(name = "PURCHASEPRICE")
    private BigDecimal purchasePrice;

    @Column(name = "PURCHASEDATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date purchaseDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ACCOUNT_ACCOUNTID")
    private AccountDataBean account;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "QUOTE_SYMBOL")
    private QuoteDataBean quote;
}
SQL DDL:
create table holdingejb
  (purchaseprice decimal(10, 2),
   holdingid integer not null,
   quantity double not null,
   purchasedate timestamp,
   account_accountid integer,
   quote_symbol varchar(250),
   optLock integer);

alter table holdingejb
  add constraint pk_holdingejb primary key (holdingid);

create index account_accountid on holdingejb(account_accountid);
ColumnTypeNotes
HOLDINGIDinteger NOT NULLPrimary key; generated via KEYGENEJB table
QUANTITYdouble NOT NULLNumber of shares held
PURCHASEPRICEdecimal(10,2)Price per share at time of purchase
PURCHASEDATEtimestampDate/time of purchase; set to Timestamp(0) when inflight for sale
ACCOUNT_ACCOUNTIDintegerFK → accountejb.accountid
QUOTE_SYMBOLvarchar(250)FK → quoteejb.symbol
optLockintegerSchema column (not mapped to a @Version field in the entity)
Relationships:
  • @ManyToOne (lazy) → AccountDataBean via ACCOUNT_ACCOUNTID
  • @ManyToOne (eager) → QuoteDataBean via QUOTE_SYMBOL

Entity: OrderDataBean

Table: orderejb
Java class: com.ibm.websphere.samples.daytrader.entities.OrderDataBean
OrderDataBean is the central transaction record. Every buy or sell creates an order with status "open". The order progresses through "processing""closed" (set by completeOrder) and then to "completed" (set by getClosedOrders when the user views their order history). Long-run benchmarks delete completed orders to prevent unbounded table growth. The entity declares a rich set of @NamedQuery definitions used by the JPQL-based query paths.
@Entity(name = "orderejb")
@Table(name = "orderejb")
public class OrderDataBean implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "orderIdGen")
    @Column(name = "ORDERID", nullable = false)
    private Integer orderID;

    @Column(name = "ORDERTYPE")
    private String orderType;       // "buy" or "sell"

    @Column(name = "ORDERSTATUS")
    private String orderStatus;     // "open", "processing", "closed", "completed", "cancelled"

    @Column(name = "OPENDATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date openDate;

    @Column(name = "COMPLETIONDATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date completionDate;

    @Column(name = "QUANTITY", nullable = false)
    private double quantity;

    @Column(name = "PRICE")
    private BigDecimal price;

    @Column(name = "ORDERFEE")
    private BigDecimal orderFee;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ACCOUNT_ACCOUNTID")
    private AccountDataBean account;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "QUOTE_SYMBOL")
    private QuoteDataBean quote;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "HOLDING_HOLDINGID")
    private HoldingDataBean holding;
}
SQL DDL:
create table orderejb
  (orderfee decimal(10, 2),
   completiondate timestamp,
   ordertype varchar(250),
   orderstatus varchar(250),
   price decimal(10, 2),
   quantity double not null,
   opendate timestamp,
   orderid integer not null,
   account_accountid integer,
   quote_symbol varchar(250),
   holding_holdingid integer,
   optLock integer);

alter table orderejb
  add constraint pk_orderejb primary key (orderid);

create index account_accountidt on orderejb(account_accountid);
create index holding_holdingid  on orderejb(holding_holdingid);
create index orderstatus        on orderejb(orderstatus);
create index ordertype          on orderejb(ordertype);
ColumnTypeNotes
ORDERIDinteger NOT NULLPrimary key; generated via KEYGENEJB table
ORDERTYPEvarchar(250)"buy" or "sell"
ORDERSTATUSvarchar(250)"open", "processing", "closed", "completed", or "cancelled"
OPENDATEtimestampWhen the order was submitted
COMPLETIONDATEtimestampWhen completeOrder ran; NULL until completion
QUANTITYdouble NOT NULLNumber of shares in the order
PRICEdecimal(10,2)Execution price (quote price at time of order creation)
ORDERFEEdecimal(10,2)Brokerage commission fee
ACCOUNT_ACCOUNTIDintegerFK → accountejb.accountid
QUOTE_SYMBOLvarchar(250)FK → quoteejb.symbol
HOLDING_HOLDINGIDintegerFK → holdingejb.holdingid; NULL for open orders
optLockintegerSchema column (not mapped to a @Version field in the entity)
Relationships:
  • @ManyToOne (lazy) → AccountDataBean via ACCOUNT_ACCOUNTID
  • @ManyToOne (eager) → QuoteDataBean via QUOTE_SYMBOL
  • @OneToOne (lazy) → HoldingDataBean via HOLDING_HOLDINGID

Entity-Relationship Summary

AccountProfileDataBean (1) ──── (1) AccountDataBean

                         ┌────────────┴────────────┐
                         │                         │
              (many) OrderDataBean        (many) HoldingDataBean
                         │                         │
                         └──── (many→1) ───────────┘
                                    QuoteDataBean

Scale Parameters

DayTrader 7 is pre-populated at benchmark time according to three constants defined in TradeConfig:
ParameterDefaultMeaning
MAX_USERS15,000Number of user accounts (uid:0 through uid:14999) pre-seeded in accountejb and accountprofileejb
MAX_QUOTES10,000Number of stock symbols (s:0 through s:9999) pre-seeded in quoteejb
MAX_HOLDINGS10Maximum number of open holdings per user; scenario servlet avoids buying beyond this limit
These defaults are tunable through the DayTrader configuration page (/daytrader/config) at runtime without restarting the server. Larger values stress the database tier more aggressively; smaller values keep ramp-up time short for development testing.

Build docs developers (and LLMs) love