Bala B
Bala B

Reputation: 31

Spring State machine - Table Scripts

Am new to Spring state machine.

I have configured the states & transitions in a configuration file, using which am able to orchestrate my micro-services successfully.

Now am planning to persist the states & transitions in an external repository (MYSQL DB)

When i tried to do that using JpaStateMachineRepository, am getting SQL Exception saying state_machine doesn't exists.

So 2 questions 1. Do we have readily available scripts for creating state machine tables. 2. Is it possible to have custom tables.

Upvotes: 3

Views: 2473

Answers (4)

Alexander Biryukov
Alexander Biryukov

Reputation: 345

This is a liquibase version of tables for Spring Statemachine

<changeSet id="00001" author="Alexander Biryukov">
    <comment>Spring State Machine JPA changelog</comment>

    <!-- main tables -->
    <createTable tableName="action">
        <column name="id" type="bigint" autoIncrement="true">
            <constraints primaryKey="true" nullable="false"/>
        </column>

        <column name="name" type="varchar(255)"/>
        <column name="spel" type="varchar(255)"/>
    </createTable>
    <createTable tableName="deferred_events">
        <column name="jpa_repository_state_id" type="bigint">
            <constraints nullable="false"/>
        </column>

        <column name="deferred_events" type="varchar(255)"/>
    </createTable>
    <createTable tableName="guard">
        <column name="id" type="bigint" autoIncrement="true">
            <constraints primaryKey="true" nullable="false"/>
        </column>

        <column name="name" type="varchar(255)"/>
        <column name="spel" type="varchar(255)"/>
    </createTable>
    <createTable tableName="state">
        <column name="id" type="bigint" autoIncrement="true">
            <constraints primaryKey="true" nullable="false"/>
        </column>

        <column name="initial_state" type="boolean"/>
        <column name="kind" type="varchar(255)"/>
        <column name="machine_id" type="varchar(255)"/>
        <column name="region" type="varchar(255)"/>
        <column name="state" type="varchar(255)"/>
        <column name="submachine_id" type="varchar(255)"/>
        <column name="initial_action_id" type="bigint"/>
        <column name="parent_state_id" type="bigint"/>
    </createTable>
    <createTable tableName="state_machine">
        <column name="machine_id" type="varchar(255)">
            <constraints primaryKey="true" nullable="false"/>
        </column>

        <column name="state" type="varchar(255)"/>
        <column name="state_machine_context" type="blob"/>
    </createTable>
    <createTable tableName="transition">
        <column name="id" type="bigint" autoIncrement="true">
            <constraints primaryKey="true" nullable="false"/>
        </column>

        <column name="event" type="varchar(255)"/>
        <column name="kind" type="varchar(255)"/>
        <column name="machine_id" type="varchar(255)"/>

        <column name="guard_id" type="bigint"/>
        <column name="source_id" type="bigint"/>
        <column name="target_id" type="bigint"/>
    </createTable>

    <!-- many to many binding tables -->
    <createTable tableName="state_entry_actions">
        <column name="jpa_repository_state_id" type="bigint">
            <constraints nullable="false"/>
        </column>
        <column name="entry_actions_id" type="bigint">
            <constraints nullable="false"/>
        </column>
    </createTable>
    <addPrimaryKey tableName="state_entry_actions"
                   columnNames="jpa_repository_state_id, entry_actions_id"
                   constraintName="pk_state_entry_actions"/>

    <createTable tableName="state_exit_actions">
        <column name="jpa_repository_state_id" type="bigint">
            <constraints nullable="false"/>
        </column>
        <column name="exit_actions_id" type="bigint">
            <constraints nullable="false"/>
        </column>
    </createTable>
    <addPrimaryKey tableName="state_exit_actions"
                   columnNames="jpa_repository_state_id, exit_actions_id"
                   constraintName="pk_exit_entry_actions"/>

    <createTable tableName="state_state_actions">
        <column name="jpa_repository_state_id" type="bigint">
            <constraints nullable="false"/>
        </column>
        <column name="state_actions_id" type="bigint">
            <constraints nullable="false"/>
        </column>
    </createTable>
    <addPrimaryKey tableName="state_state_actions"
                   columnNames="jpa_repository_state_id, state_actions_id"
                   constraintName="pk_state_state_actions"/>

    <createTable tableName="transition_actions">
        <column name="jpa_repository_transition_id" type="bigint">
            <constraints nullable="false"/>
        </column>
        <column name="actions_id" type="bigint">
            <constraints nullable="false"/>
        </column>
    </createTable>
    <addPrimaryKey tableName="transition_actions"
                   columnNames="jpa_repository_transition_id, actions_id"
                   constraintName="pk_transition_actions"/>

    <!-- foreign keys -->
    <addForeignKeyConstraint baseTableName="deferred_events"
                             baseColumnNames="jpa_repository_state_id"
                             constraintName="fk_state_deferred_events"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state"
                             baseColumnNames="initial_action_id"
                             constraintName="fk_state_initial_action"
                             referencedTableName="action"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state"
                             baseColumnNames="parent_state_id"
                             constraintName="fk_state_parent_state"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="transition"
                             baseColumnNames="guard_id"
                             constraintName="fk_transition_guard"
                             referencedTableName="guard"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="transition"
                             baseColumnNames="source_id"
                             constraintName="fk_transition_source"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="transition"
                             baseColumnNames="target_id"
                             constraintName="fk_transition_target"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state_entry_actions"
                             baseColumnNames="entry_actions_id"
                             constraintName="fk_state_entry_actions_a"
                             referencedTableName="action"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state_entry_actions"
                             baseColumnNames="jpa_repository_state_id"
                             constraintName="fk_state_entry_actions_s"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state_exit_actions"
                             baseColumnNames="exit_actions_id"
                             constraintName="fk_state_exit_actions_a"
                             referencedTableName="action"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state_exit_actions"
                             baseColumnNames="jpa_repository_state_id"
                             constraintName="fk_state_exit_actions_s"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state_state_actions"
                             baseColumnNames="state_actions_id"
                             constraintName="fk_state_state_actions_a"
                             referencedTableName="action"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="state_state_actions"
                             baseColumnNames="jpa_repository_state_id"
                             constraintName="fk_state_state_actions_s"
                             referencedTableName="state"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="transition_actions"
                             baseColumnNames="actions_id"
                             constraintName="fk_transition_actions_a"
                             referencedTableName="action"
                             referencedColumnNames="id"/>
    <addForeignKeyConstraint baseTableName="transition_actions"
                             baseColumnNames="jpa_repository_transition_id"
                             constraintName="fk_transition_actions_t"
                             referencedTableName="transition"
                             referencedColumnNames="id"/>
</changeSet>

or alternatively SQL version:

create sequence hibernate_sequence start with 1 increment by 1
create table action (id bigint not null, name varchar(255), spel varchar(255), primary key (id))
create table deferred_events (jpa_repository_state_id bigint not null, deferred_events varchar(255))
create table guard (id bigint not null, name varchar(255), spel varchar(255), primary key (id))
create table state (id bigint not null, initial_state boolean, kind integer, machine_id varchar(255), region varchar(255), state varchar(255), submachine_id varchar(255), initial_action_id bigint, parent_state_id bigint, primary key (id))
create table state_entry_actions (jpa_repository_state_id bigint not null, entry_actions_id bigint not null, primary key (jpa_repository_state_id, entry_actions_id))
create table state_exit_actions (jpa_repository_state_id bigint not null, exit_actions_id bigint not null, primary key (jpa_repository_state_id, exit_actions_id))
create table state_state_actions (jpa_repository_state_id bigint not null, state_actions_id bigint not null, primary key (jpa_repository_state_id, state_actions_id))
create table state_machine (machine_id varchar(255) not null, state varchar(255), state_machine_context blob, primary key (machine_id))
create table transition (id bigint not null, event varchar(255), kind integer, machine_id varchar(255), guard_id bigint, source_id bigint, target_id bigint, primary key (id))
create table transition_actions (jpa_repository_transition_id bigint not null, actions_id bigint not null, primary key (jpa_repository_transition_id, actions_id))
alter table deferred_events add constraint fk_state_deferred_events foreign key (jpa_repository_state_id) references state
alter table state add constraint fk_state_initial_action foreign key (initial_action_id) references action
alter table state add constraint fk_state_parent_state foreign key (parent_state_id) references state
alter table state_entry_actions add constraint fk_state_entry_actions_a foreign key (entry_actions_id) references action
alter table state_entry_actions add constraint fk_state_entry_actions_s foreign key (jpa_repository_state_id) references state
alter table state_exit_actions add constraint fk_state_exit_actions_a foreign key (exit_actions_id) references action
alter table state_exit_actions add constraint fk_state_exit_actions_s foreign key (jpa_repository_state_id) references state
alter table state_state_actions add constraint fk_state_state_actions_a foreign key (state_actions_id) references action
alter table state_state_actions add constraint fk_state_state_actions_s foreign key (jpa_repository_state_id) references state
alter table transition add constraint fk_transition_guard foreign key (guard_id) references guard
alter table transition add constraint fk_transition_source foreign key (source_id) references state
alter table transition add constraint fk_transition_target foreign key (target_id) references state
alter table transition_actions add constraint fk_transition_actions_a foreign key (actions_id) references action
alter table transition_actions add constraint fk_transition_actions_t foreign key (jpa_repository_transition_id) references transition

Upvotes: 3

hovanessyan
hovanessyan

Reputation: 31463

If you have enabled the Spring state machine JPA auto-configuration (StateMachineJpaRepositoriesAutoConfiguration) this will enable all the default repositories and entities used for persisting states, transitions etc. in a database. A complete list of those entities and repositories can be found here.

For example the JpaRepositoryAction entity will create a table ACTION, as can be seein in the entity definition (@Table(name = "Action").

The default db schema looks like this:

enter image description here

Upvotes: 1

azhar
azhar

Reputation: 167

You just need to create STATE_MACHINE table. After creation the persist feature works like charm.

Following is the mysql script for the said table.

CREATE TABLE `STATE_MACHINE`(
    MACHINE_ID VARCHAR(255) NOT NULL,
    STATE VARCHAR(255),
    STATE_MACHINE_CONTEXT BLOB
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

Upvotes: 1

Bala B
Bala B

Reputation: 31

Found the solution, default JPA entities are available in State Machine libraries. Just create the tables, records can be inserted automatically as expected.

Upvotes: 0

Related Questions