Speedment is a library which makes it possible to write database enabled Java applications without knowing anything about database. Ok, this may be a bit of a stretch, but Speedment manages to get very close. To make this possible, Speedment uses code generation based on the structure of an existing database. This generated code makes heavy use of the Java Streams introduced in Java8. As a result, all you need to know really is how to program with Streams and you’re good to go.
This is the first tutorial in the series on how to use Speedment with Springboot to build a REST microservice. The resulting microservice will contain an item catalogue with a REST interface enabling the full set of features needed for a catalogue. For instance, adding items, removing items, updating items and requesting items.
To get to that point, a few things need to happen first though. This tutorial explains how to set things up in such a way that it is possible to generate the code needed to use Speedment as part of you actual application code. There will be follow-up tutorials on what comes after that. But first, lets see how you go from having an existing database to have generated code you can use from your application. And the term existing database is used loosely here, since it could just as easily be a new database for a new application. It just means Speedment uses the database as a starting point, unlike most other Java ORM frameworks which generate the database from the Java code.
The database
For the purpose of this tutorial you are going to need a database. This is going to be a very simpel database with just one table for now. In later tutorials this database will be extended with more a complex structure, but this is just a Speedment basics tutorial so we’ll keep it simple
This and any following Speedment tutorials, use a mysql database. Each tutorial will come with a script that will help to setup the database so it is ready for that specific tutorial.
The database has one user, aside from root, with the following credentials.
- Username: mycatalogue
- Password: MyCatalogue.
It is possible to use other databases or users. Which databases are supported can be found in the official documentation.
For this tutorial, the database will have just one table, ITEMS. This table will contain the items in the catalogue. As such it will need three fields:
- ID, this is a UUID. This is also the primary key of the table.
- NAME, this is the name of the item. The name should be unique.
- LEAD, this is a short description of the item.
All three fields are strings and all three are mandatory.
This results in the following SQL script.
CREATE DATABASE my_catalogue; CREATE TABLE my_catalogue.item ( id char(36) NOT NULL, name varchar(45) NOT NULL, lead varchar(140) NOT NULL, PRIMARY KEY (id), UNIQUE KEY name_UNIQUE (name) );
While it is off course possible to create the table through database tooling, having the SQL script will be useful in later tutorials when unit testing the database layer of the application.
Maven
As the purpose of this tutorial is to show how automate the entire code generation process, we need to use a tool that can handle this for us. The tool of choice in this case is Maven. Maven is a tool often used in Java projects to handle dependencies as well as the entire build process. This tutorial is not about Maven itself though, so we’ll only focus on the parts of Maven needed for the purpose of this tutorial.
After creating the database, we can start working on the Maven pom. We will be adding the following functionalities to the pom:
- Generate the JSON definition file for the database
- Generate the Java code to the database from the application
JSON Definition file
Speedment uses a JSON file to represent the database structure. The layout of this JSON file is failry complex. This mean writing it completely by hand is hard and error prone. The good news is that Speedment has several methods in which it can create this JSON file for you. You can either use their GUI based tool to click through a series of options and create the file that way, or you can use their Maven plugin to do it as part of your build process. While using the GUI based tool is a very good way of doing it, it does require a lot of manual actions. So for this tutorial we are going to use the Maven plugin option.
Plugin Definition
To be able to use the plugin we need to add it to the pom. This is done in the build section.
Example
<plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.1.15</version> </plugin>
This example adds the speedment-maven-plugin to the plugin section of the Maven pom.
After adding the plugin, it needs to be configured. The first thing that needs to happen is to add a dependency on the database driver. The plugin needs to be able to connect to the database, for that it needs a driver.
This is done by adding a dependency section to the plugin in the same way as you would add dependencies to the main part of the pom.
Example
<plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>${speedment.version}</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.17</version> </dependency> </dependencies> </plugin>
This example shows the same plugin but now with an added dependency on the database library for mysql, the mysql-connector-java.
The next thing the plugin needs is some general configuration information. This is configuration information not specific to one of the goals of the plugin.
Example
<plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>${speedment.version}</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies> <configuration> <dbmsUsername>mycatalogue</dbmsUsername> <dbmsPassword>MyCatalogue</dbmsPassword> <dbmsPort>9876</dbmsPort> <dbmsSchemas>my_catalogue</dbmsSchemas> <companyName>ractoc.com</companyName> <configFile>${project.basedir}/src/main/resources/json/speedment.json</configFile> </configuration> </plugin>
This example shows the same plugin but now with an added configuration section. This is the general configuration section which will be used in all executions. The specific configuration items are detailed below. There are a lot more items that can be used as part of the configuration. A full list can be found on the official Speedment website.
dbmsUsername | This is the username used to connect to the database |
dbmsPassword | This is the password used to connect to the database |
dbmsPort | This is the port used to connect to the database |
dbmsSchema | This is the schema containing our table |
companyName | This is the name of the company. |
configFile | This is the location where the plugin places the generated config file |
Execution blocks
Generating an entirely new configuration file or updating an existing one need different goals. Generating an entirely new configuration file uses the goal “init” while updating an existing configuration file uses the goal “reload”. When using Maven to manage your configuration file it is always a good idea to configure both goals. That way, when all goes wrong, it is possible to just remove the entire configuration file and start over without any additional actions needed down the line.
init
The first execution block is the init block. This execution creates an entirely new configuration file if one is not already present at the location specified in the general configuration information.
Example
For simplicity’s sake only the execution block is displayed here.
<execution> <id>re-initialize</id> <goals> <goal>init</goal> </goals> </execution>
This example shows the absolute minimum of information needed to generate the new configuration file. Using this setup, a lot of information is inferred from other parts of the pom like the groupId and the artifactId.
reload
The second execution block is the reload block. This execution refreshes both the meta data and the schema data in an existing configuration file. When running the maven pom for the first time, this means the configuration is actually created, and the immediately reloaded. Since this is only done for a completely new configuration file, this is acceptable.
Example
For simplicity’s sake only the execution block is displayed here.
<execution> <id>update json for Mysql</id> <goals> <goal>reload</goal> </goals> </execution>
This example shows the absolute minimum of information needed to reload an existing configuration file. Using this setup, a lot of information is inferred from other parts of the pom like the groupId and the artifactId.
Profile
Since the maven plugin needs access to an actual database in order to generate the JSON definition file, it is a good idea to put this plugin definition in a maven profile block. This way, it is not executed by default, but can be activated by a command line trigger. This is also very useful when running the Maven pom as part of a build pipeline, since typically a database is not present then. This is also the main reason the JSON definition file is placed in the src folder and not in the target folder.
Code generation
Based on the JSON Definition file, Speedment can generate Java code. It does this using the same Maven plugin which was used to generate the JSON Definition file.
Plugin Definition
Now that the JSON definition file has been generated, another goal can be implemented to generate the actual code. Since the JSON definition file has been generated from a profile, the entire main part of the plugin definition needs to be put into the main build section of the Maven pom as well.
Example
<plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>${speedment.version}</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies> <configuration> <dbmsPassword>MyCatalogue</dbmsPassword> <configFile>${project.basedir}/src/main/resources/json/speedment.json</configFile> <packageLocation>target/generated-sources/java</packageLocation> </configuration> </plugin>
This example is almost a repeat from the example provided earlier in the Plugin definition for the JSON Definition file. Just the configuration block is slightly different. A lot of the configuration items are no longer needed since they have been added to the JSON Definition file. Just the password and the location of the config file remain. The Maven plugin will never add the password to the generated JSON Definition file, for safety reasons.
A new addition is the packageLocation. By default, Speedment generates the Java sources in the “src/main/java folder”. Since Maven is being used as a build manager, there is a better location to place them. The default Maven location to store generated source files is “target/generated-sources”. In this case, the generated sources are java source files, so they should be placed in “target/generated-sources/java”.
Execution Block
Generating the code from the JSON Definition file is done by a single goal, “generate”.
Example
For simplicity’s sake only the execution block is displayed here .
<execution> <id>Generate code for Mysql</id> <phase>generate-sources</phase> <goals> <goal>generate</goal> </goals> </execution>
This example shows the plugin execution block used to generate Java code based on the JSON Definition file generated earlier. This execution block is a bit more extensive then the ones for the JSON Definition file. Since we are generating sources with this goal, it needs to be executed in the correct lifecycle phase, “generate-sources”.
Links
The main Speedment website can be found at https://www.speedment.com
The main documentation for Speedment can be found at https://speedment.github.io/speedment-doc/index.html
The source code for the tutorial series examples can be found at https://github.com/ractoc-tutorials/speedment