Developer training - Day one
This day covers:
Quick review of the platform
The Genesis low-code platform is the only low-code platform designed to build and run mission-critical systems for the financial markets, based on event-driven and microservice architecture.
The platform enables your application to handle events and distribute data in real time from the start by using its building blocks, such as Data Servers, Request Servers and Event Handlers. These resources are powered by Genesis Platform Abstraction Language (GPAL), which plugs into IntelliJ, allowing for code autocompletion, compilation and syntax highlighting as you code.
Genesis Low-Code PlatformAt the heart of the server is the data persistence layer and the data model. You model your data by defining fields, then tables, then views.
Once you have a data model defined, you can start bringing your application to life by creating events in an Event Handler process, which have access to the data layer importing auto-generated data repositories, to handle the business logic with code written in languages such as Kotlin and/or Java.
When it comes to displaying the data, you can configure a Data Server to distribute the data to the front end. The Data Server is a GPAL component that streams the data in real time to subscribers, such as a data grid component in the front end. You can also bind a button in the UI to an event (action) defined in your Event Handler.
All of this is managed by the Genesis low-code platform. You don't need to worry about inter-process communication or even how to connect the front end to the back end, as the Platform handles a web socket connection between the browser and the data server for you. Even defining something as simple as the example below will get you a data grid showing all trades in real time:
Back end
dataServer {
query("ALL_TRADES", TRADE)
}
Front end
<zero-grid-pro rowHeight="45">
<grid-pro-genesis-datasource resourceName="ALL_TRADES" orderBy="TRADE_DATETIME" />
</zero-grid-pro>
Now let's take a closer look at the server architecture.
Server ArchitectureSurrounding the core, operational tools enable you to run and monitor the application, while cluster services enable you to run across multiple nodes. Auth and permissions enable you control access and build sophisticated and granular access to data and functions.
You will get familiar with all these concepts in the next lessons.
Developing your first application
This will enable you to see the basics of the Genesis low-code platform by starting with a very simple application. It is designed simply to get from start to finish as quickly as possible. It is in five main steps:
- Create a new project.
- Define the data model.
- Add business logic.
- Prepare the server.
- Build and Deploy process.
What you will build
The very simple application you will build will look like this:
- a simple table with 5 fields
- two front-end components: one to display data and one to insert data
Once you finish this lesson, you will extend this initial simple application into a full Trades & Positions app!
With a lack of imagination we hope you will find trustworthy, we are going to call this example application alpha. You will see this reflected in the file names throughout.
1. Create a new project
To create a new project, you can use the genx
CLI tool, which enables you to seed projects. Further details can be found here.
In our case, we just want to extend a blank full-stack application project, so we are using the training seed. Hopefully, you have followed the Environment set-up and done the step Start the project baseline, where you cloned the repository locally.
Here's a quick overview of the repository that you cloned:
Above, we have expanded the client folder. This contains all the UI-related projects.
The server folder has the following structure:
- cfg: stores all configuration files such as tables definition, views, processes...
- data: stores all data that has to be loaded to the database. It includes the credential data.
- scripts: stores all scripts such as queries, events...
2. Define the data model
Now you are ready to define the fields and tables that make up your data model. This model structures information in a simple way that can be viewed by users and processed by the application.
Open IntelliJ and open the alpha project (the devtraining-seed you cloned). After importing and indexing, you should see the files and project structure ready.
You define your fields and tables in the file alpha-tables-dictionary.kts under the cfg folder.
Once the project is open, there are two easy ways to find this file quickly in Intellij:
- Press the Shift key twice, then type the name of the file you are looking for.
- Press Shift + Ctrl + N, then type the name of the file you are looking for.
For our simple example, we will add five fields inside one table called trades:
tables {
table (name = "TRADE", id = 2000) {
field("TRADE_ID",STRING).sequence("TR").primaryKey()
field("QUANTITY",INT)
field("PRICE",DOUBLE).notNull()
field("SYMBOL",STRING)
field("DIRECTION", ENUM("BUY","SELL")).default("BUY")
}
}
After you have saved this file, run genesis-generated-dao as will be explained next.
generateDao
After you have saved this file, run genesis-generated-dao from the Gradle menu, this is:
genesisproduct-alpha/alpha-dictionary-cache/genesis-generated-dao/Tasks/genesis/generateDao
After running this, you have the DAOs (i.e. data repos) automatically generated from the tables and available to be imported in your code.
You are editing a kts file that needs to be compiled and built to be used from other places. In this case, we want the fields to be available to the tables (and with intellisense support from the IDE).
As we go, you'll see we have different Gradle tasks, depending on the artifact we want to build.
3. Add business logic
We have a table; now we want to be able to see its contents and create new entries.
Data Server
A Data Server enables data to be read in real time. You must define the Data Server in the file alpha-dataserver.kts.
dataServer {
query("ALL_TRADES", TRADE)
}
Event Handler
Next, we want to be able to insert rows into our table. For this, you need to define an Event Handler in the file alpha-eventhandler.kts.
eventHandler {
eventHandler<Trade>(name = "TRADE_INSERT") {
schemaValidation = false
onCommit { event ->
entityDb.insert(event.details)
ack()
}
}
}
The entityDb enables you to interact with the database layer. It's part of the Genesis Database API and we'll get into more details soon. For now, understand that this is the common way to access data from code. Feel free to use the intellisense of your IDE to explore the methods available from entityDb.
4. Prepare the server
So far we have created an Event Handler and Data Server - just their definitions, but there's nothing on the runtime configuration yet. Each microservice, such as Event Handler and Data Server, must run on their own process. To do that, we have to change the processes and the service definition files:
- alpha-processes.xml
- alpha-service-definitions.xml
At present, these files are empty. You need to insert the details of the Data Server and Event Handler that you have just created.
Add the following content to the alpha-processes.xml file.
<processes>
<process name="ALPHA_DATASERVER">
<groupId>ALPHA</groupId>
<start>true</start>
<options>-Xmx1024m -DXSD_VALIDATE=false</options>
<module>genesis-pal-dataserver</module>
<package>global.genesis.dataserver.pal</package>
<script>alpha-dataserver.kts</script>
<description>Displays real-time details</description>
<language>pal</language>
<loggingLevel>DEBUG,DATADUMP_ON</loggingLevel>
</process>
<process name="ALPHA_EVENT_HANDLER">
<groupId>ALPHA</groupId>
<start>true</start>
<options>-Xmx256m -DRedirectStreamsToLog=true -DXSD_VALIDATE=false</options>
<module>genesis-pal-eventhandler</module>
<package>global.genesis.eventhandler.pal</package>
<script>alpha-eventhandler.kts</script>
<description>Handles events</description>
<classpath>alpha-app*</classpath>
<language>pal</language>
</process>
</processes>
Add the following content to the alpha-service-definitions.xml file.
<configuration>
<service host="localhost" name="ALPHA_DATASERVER" port="11000"/>
<service host="localhost" name="ALPHA_EVENT_HANDLER" port="11001"/>
</configuration>
Please see here for a detailed description of the processes configuration.
5. The build process
Finally, you can build and deploy the server.
Build
In the Genesis plugin menu on the right of IntelliJ, select:
Prepare Local Genesis Application
This runs a full Gradle build and a genesisInstall
Credentials to login
Before you proceed, make sure you have selected java 17 as your SDK. Check File > Project Structure.
By default, the following will be your login details:
- Username: admin
- Password: genesis (This is encrypted in the user.csv file.)
However, after the first Build and Deploy, you need to send the login information so that you can access the application you have just created.
Remap
Before you can run your application, you need to create the tables of your database. Run the remap
script.
After that, you will be asked to confirm the tables that you want to insert in your database, you should return y
.
WARNING: are you sure you want to commit changes to the database? (y/n)
After remapping is complete, you will see the following prompt:
=========Starting Data Load=======
This will load reference data needed to user all of the Genesis components utilised by the application,
and anything you've added to your project's /data folder, overwriting any data that has changed.
WARNING: If you have test data in your application's data folder and this is not a development environment it will still be loaded in
Are you sure you want to proceed? (y/n)
This means that all data stored in the data folder will be loaded. For this exercise, there is only credentials data. Once you confirm, it will be loaded into the database, and you will be able to log in.
Details
Want to check if your data has been sent?
To check your database, Genesis Intellij plugin has the following scripttype table USER
and then search 1
you will be displayed the following:
==================================
Genesis Database Monitor
Enter 'help' for a list of commands
==================================
DbMon>table USER
DbMon:USER>search 1
==================================
USER
==================================
Field Name Value Type
===========================================================================================
TIMESTAMP 2024-05-16 10:55:00.729(n:0,s:84) NANO_TIMESTAMP
COMPANY_ID STRING
COMPANY_NAME GENESIS STRING
DOMAIN STRING
EMAIL_ADDRESS admin.global@genesis.global STRING
FIRST_NAME admin STRING
LAST_LOGIN 2016-04-28T00:00:00.000Z DATE
LAST_NAME global STRING
ONLINE false BOOLEAN
PASSWORD 775d545a8f34a8bf6c3f9d9c6381fbc8d3d76... STRING
PASSWORD_EXPIRY_DATETIME DATETIME
STATUS ENABLED STRING
USER_NAME admin STRING
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
Total Results: 1
DbMon:USER>
Now you are ready to start your application.
Starting the server
Now we need to start the server. To do that, click on the Start Server button. This starts all the processes:
And that's all you have to do to get your server up and running.
Testing the back end
There are multiple ways you can test the back end of your application. Most resources, such as Event Handlers and Data Servers, are exposed as HTTP endpoints automatically by the Genesis low-code platform - without any additional code. This enables you to test those resources from HTTP clients, such as Postman.
Alternatively, you can use Genesis Console, which gives you a simple way of testing components from a nice web UI.
Genesis Console
Some browsers automatically change http to https - which will cause a fail. Make sure the url starts with http before submitting. If you still have problems, open a new incognito/private browser (this avoids any cache issues).
- Enter the IP address of your server, in this case localhost port 9064, as we are using GENESIS_ROUTER locally through the Genesis plugin. So, the value to be entered here is
localhost:9064
- Log in with your user name and password as defined previously. This starts Genesis Console, and you will see a list of tabs along the top of the screen.
- Click on the RESOURCES tab.
- Filter the Resource type to show only Event Handlers.
For example:
As well as the Event Handlers that you have defined yourself, you will also see other Event Handlers that have been generated automatically by the platform: anything that is a GENESIS_CLUSTER service, for example.
If you click on any Event Handler in the list, the fields relevant to the event are displayed to the right.
Now you need to pick the Event Handler you want to test. So, let's look up EVENT_TRADE_INSERT.
- Find the Event Handler in the list, then click on the arrow beside it. On the right, this displays the relevant input fields for the event. Some are mandatory, while others are optional - depending on how the Event Handler was set up.
- Enter the details of the new trade in the fields then click on COMMIT:
If the Event Handler is working correctly, you will receive an ACK.
Checking the insertion
You can go to check the TRADE table to see if your insert is there.
-
Filter the list of services to show only Data Servers (these are the components that distribute the data).
-
Search for the relevant resource - in our case TRADE.
- Click on the arrow beside the relevant resource. You should now see the new trade in the list displayed on the right.
Exercise 1.1: Data Servers
30 mins
Look at the Data Server documentation and see if you are able to modify the Data Server that we defined previously:
- add a new query called "ALL_PRICES" on the TRADE table
- make ALL_PRICES display only SYMBOL and PRICE fields
- add a
filter
clause so it displays only trades whose PRICE are higher than 10.0
Remember to insert a few trades using Genesis Console so you can test the Data Server.
Exercise 1.2: Event Handlers
20 mins
Look at the Event Handler documentation and see if you are able to modify our Event Handler defined previously:
- return
nack("Quantity must be positive")
if the quantity is lower than 0.
Test it with Genesis Console.