Monday, March 20, 2017

How to Set Up a Secure REST API with Spring

Happy Spring Wishes from Spire and Crew

As you all know, Spring Boot is a toolkit that makes it super easy to quickly develop powerful web services. It is very modular and made to play well with other frameworks and tools. In this tutorial I am going to show you how easy it is to set up a RESTful API towards an existing SQL database by using Speedment as the ORM.

Background

Speedment is an open-source toolkit that connects to a database, analyzes the metadata and uses it to generate entity- and managers classes to model the database in an object-oriented fashion. It also contains a runtime library that turns Java 8 Streams into optimized SQL queries, allowing you to write your code in a very type-safe and modern way. As it turns out, this is perfect for a Spring Application.

Goal of This Tutorial

The goal of this tutorial is to develop a REST API with Spring that grants access to different endpoints depending on the role of the user. If you want to look ahead, you can find all the sources from the guide here.

POST /account Accessible by anyone
GET /account/{id} Accessible by admins, as well as the user in question
GET /account Lists all accounts and is only accessible by admins

Authentication will be made using a MySQL database that we will query using standard Java 8 Streams. In the end, we will have a fully object-oriented solution ready to be expanded with custom business logic!

If you would like to follow along with the finished project, you can clone it at GitHub.

Step 1: The Database

For the sake of simplicity, I am using a custom MySQL database that I created using the following statement. The idea is however that you can use any existing database that you happen to have access to.


create database `securerest`;
use `securerest`;

create table `account` (
    `id` bigint not null auto_increment primary key,
    `username` varchar(30) not null unique,
    `password` char(60) not null,
    `role` enum('USER', 'ADMIN') not null
);

Step 2: Create the Maven Project

To quickly get up a new Spring Project, I recommend the awesome Spring Initializr website. There you can easily enter the dependencies you need for your project.

We need the following Spring dependencies:

  • spring-boot-starter-security
  • spring-boot-starter-web
  • mysql-connector-java

Secondly, we also need to add the Speedment dependency as well as the Speedment plugin to generate our code.


<dependency>
    <groupId>com.speedment</groupId>
    <artifactId>runtime</artifactId>
    <version>${speedment.version}</version>
    <type>pom</type>
</dependency>
...
<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>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</plugin>

Step 3: Generate Domain Model

With the plugin added, we can run the following Maven Goal to launch the Speedment UI.


mvn speedment:tool
Connect to Database using Speedment

This will open up the Speedment Tool. It will ask you for the username, password, schema name, etc. for your database. Enter values for the fields and press “Connect”.

The main window in Speedment

Inside the UI there are many configurations you can do. You can specify the exact location of the generated code, disable tables or columns that are irrelevant for the application and create aliases if you want a field or table to appear as something else in the code.

For this tutorial, it is enough to press “Generate”. You should now see how a number of new java classes and packages are generated into your project!

Step 4: Configure Spring Security

To allow Spring to launch Speedment as a Spring Bean, we need to specify how the instance is created. To do this, we create a class named SpeedmentConfiguration.

SpeedmentConfiguration.java

@Configuration
public class SpeedmentConfiguration {

    private @Value("${dbms.host}") String host;
    private @Value("${dbms.port}") int port;
    private @Value("${dbms.schema}") String schema;
    private @Value("${dbms.username}") String username;
    private @Value("${dbms.password}") String password;
    
    @Bean
    public SpeedmentApplication getSpeedmentApplication() {
        return new SpeedmentApplicationBuilder()
            .withIpAddress(host)
            .withPort(port)
            .withUsername(username)
            .withPassword(password)
            .withSchema(schema)
            .build();
    }
    
    @Bean
    public AccountManager getAccountManager(SpeedmentApplication app) {
        return app.getOrThrow(AccountManager.class);
    }
}

The @Value fields in the top are loaded by default from a file called application.properties. We should therefore specify the values there:

application.properties

# Speedment Settings
dbms.host=localhost
dbms.port=3306
dbms.schema=securerest
dbms.username=root
dbms.password=password

# Server Settings
server.port=9777

Next, we need to create a configuration class for the authentication of users. We call this class AuthenticationConfiguration.

AuthenticationConfiguration.java

@Configuration
public class AuthenticationConfiguration 
extends GlobalAuthenticationConfigurerAdapter {

    private @Autowired AccountManager accounts;
    
    @Bean
    public DaoAuthenticationProvider authProvider() {
        final DaoAuthenticationProvider authProvider = 
            new DaoAuthenticationProvider();

        authProvider.setUserDetailsService(getUserDetailsService());
        authProvider.setPasswordEncoder(getPasswordEncoder());
        return authProvider;
    }

    @Bean
    public UserDetailsService getUserDetailsService() {
        return username -> accounts.stream()
            .filter(Account.USERNAME.equal(username))
            .findAny()
            .orElseThrow(() -> new UsernameNotFoundException(
                "Could not find the user '" + username + "'"
            ));
    }
    
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    public void init(
            AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(getUserDetailsService())
            .passwordEncoder(getPasswordEncoder());
    }
}

Note how we can use @Autowired on the generated AccountManager since it is specified as a Spring Bean in the SpeedmentConfiguration class.

In the method getUserDetailsService(), we use the Stream API with a custom predicate, allowing the stream to be turned into an optimized SQL query. There is one thing we need to do to make this method work, however. We need to make sure the generated Account interface extends UserDetails so that it can be used seamlessly with the Spring API. This is easy to do, since Speedment doesn’t overwrite files that doesn’t begin with the prefix “Generated”.

Account.java

public interface Account extends GeneratedAccount, UserDetails {
    
}

We also need to add a few methods to the implementation class to support the interface.

AccountImpl.java

@JsonIgnoreProperties("password")
public final class AccountImpl extends GeneratedAccountImpl 
implements Account {

    private static final long serialVersionUID = -7552975849070084309L;

    @Override @JsonIgnore
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return createAuthorityList(getRole());
    }

    @Override @JsonIgnore
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override @JsonIgnore
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override @JsonIgnore
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override @JsonIgnore
    public boolean isEnabled() {
        return true;
    }
}

We then create a third configuration file to define what authorities are required to access the various REST endpoints.

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
public class SecurityConfiguration 
extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(POST, "/account").permitAll()
                .antMatchers(GET, "/account").hasAuthority("ROLE_ADMIN")
                .anyRequest().fullyAuthenticated()
            .and().httpBasic()
            .and().csrf().disable();
    }
}

Step 5: Create the Controller

The final step is to create the Controller class where our business logic is located. The class is annotated with @RestController to allow Spring to pick it up automatically. It defines three mappings, one for each REST endpoint.

AccountController.java

@RestController
public class AccountController {

    private @Autowired AccountManager accounts;
    private @Autowired PasswordEncoder passwordEncoder;

    ...

}

The first endpoint is the registration command. It will be located on “POST /account”. We take two parameters, username and password, hash the password and then persist it to the database. The operation will fail if the username already exists since it is defined as UNIQUE in the database.


    @PostMapping("/account")
    long onPostAccount(
            @RequestParam("username") String username,
            @RequestParam("password") String password) {
        
        final Account created = accounts.persist(new AccountImpl()
            .setUsername(username)
            .setPassword(passwordEncoder.encode(password))
            .setRole("USER")
        );
        
        return created.getId();
    }

Next up is the “GET /account” endpoint. It is quite simple. We will initiate a stream using the generated manager class. The stream is then optimized into a SQL query by Speedment.


    @GetMapping("/account")
    List<Account> onGetAllAccounts() {
        return accounts.stream().collect(toList());
    }

The last endpoint is a bit more complicated. We have configured Spring to only allow logged in users to access “GET /account{id}”, but we want to make sure users can only access their own information unless they have the “ADMIN” role.


    @GetMapping("/account/{id}")
    Account onGetAccount(
            @PathVariable("id") long accountId,
            Authentication auth) {
        
        final Account account = (Account) auth.getPrincipal();
        
        if (account.getId() == accountId) {
            return account;
        } else if ("ADMIN".equals(account.getRole())) {
            return accounts.stream()
                .filter(Account.ID.equal(accountId))
                .findAny().orElseThrow(NotFoundException::new);
        } else {
            throw new ForbiddenException();
        }
    }

Done! We now have a REST API that uses a database to store users and Basic Authentication to make sure users can only invoke the commands they have access to!

Trying It Out

To try the REST API we just created, simply fire up a terminal and use the cURL command!

To register an account:


curl -X POST "http://localhost:9777/account
    ?username=my_user
    &password=my_pass"

To see our own information (in this case we are the user with ID 1):


curl -X  GET -u my_user:my_pass "http://localhost:9777/account/1"

To list all users (requires ADMIN role):


curl -X GET -u my_user:my_pass "http://localhost:9777/account"

Summary

In this tutorial we have created a new Spring Boot project to quickly map up a RESTful API with a simple registration system and used Speedment to generate an object-oriented database access layer for this API. We have also configured Spring Security to require users to authenticate themselves to access particular endpoints.

For more guides and tutorials on how to use Speedment, check out the GitHub page! There you can also find some example projects on how to use more of the cool code-generation features available in Speedment!

The full sources for this tutorial can be found here!

Until next time!

Thursday, March 2, 2017

Query Databases Using Streams - Video

Java 8 introduced a completely new way of working with data in Java with the Stream interface. In these quick-start videos I explain how easy it is to write database applications with Streams by using Speedment to generate the necessary entity and field classes.

(Spoiler: In the last video I explain why the performance will be just as good as a normal JDBC query!)

Part 1: Create a New Speedment Project

Part 2: Configuration Options in Speedment

Part 3: How to Query a Database Using Streams

Let me know what you think of the videos in the comment section!

Tuesday, December 20, 2016

Quick Tip To Prevent Your Caches From Exploding

There are many scenarios when you can benefit from caching commonly used objects in your application, especially in web and micro-service oriented environments. The most simple type of caching you can do in Java is probably to introduce a private HashMap that you query before calculating an object to make sure you don't do the job twice.

Here is an example of that:


public class PrimeService {

    private Map<Long, BigInteger> cache = new HashMap<>();
    
    public BigInteger getPrime(long minimum) {
        return cache.computeIfAbsent(minimum, 
            m -> BigInteger.valueOf(m).nextProbablePrime()
        );
    }
    
}

This is a quick solution to the problem, but sadly not very efficient. After a few months of people entering all kinds of crazy numbers into the service, we will have a very large HashMap that might cause us to run out of memory.

Here is a quick trick to solve that. Instead of using a HashMap, you can use a LinkedHashMap and simply override the method removeEldestEntry. That allows you to configure your own limit function to prevent the map from exploding.


public class PrimeService {

    public final static int CACHE_MAX_SIZE = 1_000;

    private Map<Long, BigInteger> cache = new LinkedHashMap<>() {
        @Override
        protected boolean removeEldestEntry(Map.Entry<ID, Boolean> eldest) {
            return size() > PrimeService.CACHE_MAX_SIZE;
        }
    };
    
    public BigInteger getPrime(long minimum) {
        return cache.computeIfAbsent(minimum, 
            m -> BigInteger.valueOf(m).nextProbablePrime()
        );
    }
    
}

We have now successfully limited the cache, preventing it from explosion. Old entries will be removed as new ones are added. It should be noted that this soluton works well in small applications, but for more advanced scenarious you might want to use an external caching solution instead. If you are interested in caching entries in a SQL database without writing tons of SQL code, I would recommend Speedment since it is lightweight and has a very fluent API.

Until next time!

Friday, December 9, 2016

Creating a REST API with Speedment and Spring

Happy Spring Wishes from Speedment and Crew

With the 4th release of Spring Boot, developing enterprise applications for the web have become so much easier. Something that still requires a lot of time on the developer's behalf is modelling an existing database in for an example Hibernate to get an object-oriented view of the data. In this tutorial we are going to explore how to use the open source tool Speedment together with Spring to generate entities, managers and controllers with the press of a button, enabling you to get started with the development so much faster.

About Speedment

Speedment is an open source java toolkit that makes it possible for a developer to rapidly generate all the glue required to communicate with a database. Using a graphical tool, you can connect to a database and generate java sources in seconds. Speedment is built in a modular fashion, just like Spring, making it easy to learn and use only the parts you are interested in. In this article we are going to use a plugin for Speedment to generate Spring controllers in addition to the standard files.

Step 1: Creating a New Spring Boot Project

Spring Boot consists of a number of templates that make it easy to get started with a new application. We are going to use one called “spring-boot-starter-web” to set the stage for our web application.

Begin by creating a new Maven Project and add the following to your “pom.xml”-file:



<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
    </parent>
    
    <groupId>com.github.pyknic</groupId>
    <artifactId>speedment-spring-example</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <properties>
        <java.version>1.8</java.version>
        
        <speedment.version>3.0.1</speedment.version>
        <mysql.version>5.1.39</mysql.version>
    </properties>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            
            <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>
                    
                    <dependency>
                        <groupId>com.speedment.plugins</groupId>
                        <artifactId>spring-generator</artifactId>
                        <version>${speedment.version}</version>
                    </dependency>
                </dependencies>
                
                <configuration>
                    <components>                       
<component>com.speedment.plugins.spring.SpringGeneratorBundle</component>
                    </components>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    <dependencies>
        <dependency>
            <groupId>com.speedment</groupId>
            <artifactId>runtime</artifactId>
            <version>${speedment.version}</version>
            <type>pom</type>
        </dependency>
        
        <dependency>
            <groupId>com.speedment.plugins</groupId>
            <artifactId>spring-generator</artifactId>
            <version>${speedment.version}</version>
        </dependency>
        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

This will configure your project as a Spring Boot application and tell it to use Speedment with the Spring Generator Plugin.

Step 2: Using Speedment to Generate Sources

Once the pom-file has been modified, a number of new Maven goals will be available in the IDE. Speedment can be used both graphically or from the command line. In this tutorial, we are going to use the UI. To start the Speedment Tool, execute the following Maven goal on the project:

mvn speedment:tool

A dialog will open that let you connect to a database. Once connected, you will see a window with an overview of the database on the left and various configuration options in the center. For this tutorial the default settings will suffice, so simply press “Generate” in the toolbar.

Screenshot of the Speedment Open Source Tool

If you switch back to the IDE you will see the new generated sources. You will notice that every class exists in two copies, one of them with the “Generated”-prefix. The reason for this is to allow modifications without the risk of overwriting your changes should you need to regenerate the sources at some point. Files with the “Generated”-prefix will always be overwritten and files without it will only be created once.

Step 3: Create a Main File

Speedment has generated a complete object-oriented model of the database, but we still need to create an entry point for the application. We will put this in the main package and call it Main.java.

Main.java

package com.github.pyknic.spring;

import com.speedment.common.logger.Level;
import com.speedment.common.logger.LoggerManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {
    
    public static void main(String... args) {
        SpringApplication.run(Main.class, args);
    }
}

If we start the application, Spring Boot will setup a self-contained web application with a generated controller for every table in the database. We can try it out by going to the following path in a browser:

http://localhost:8080/hare/

A JSON representation of the “hare” table in my database will now be returned.


[
    {"id":1, "name":"Harry", "color":"Gray", "age":3},
    {"id":2, "name":"Henrietta", "color":"White", "age":2},
    {"id":3, "name":"Henry", "color":"Black", "age":9}
]

Note #1: If you get an exception that says something in style of this...

There was an unexpected error (type=Internal Server Error, status=500). 
Could not write content: No value present (through reference chain: 
java.util.ArrayList[0]...

...it probably means that you have nullable columns in your database that Speedment chooses to implement as OptionalLong, OptionalInt etc. You can turn this feature off in the Speedment Tool by setting the "Nullable Implementation" field to WRAPPER instead of OPTIONAL for those columns.

Note #2: If you get an exception in the style of this...

java.sql.SQLException: Access denied for user 'root'@'localhost' 
(using password: YES)

...you will need to create an application.properties-file in the root of the project and add the authentication details for your database.

application.properties

jdbc.username=root
jdbc.password=password

Summary

In this article we have used Speedment and the Spring Generator plugin to automatically create a complete Spring Boot Application. Speedment has generated entities, managers and REST controllers for communicating with the database. If you want to know more about Speedment and how you can control the generated code, check out the many examples at the Speedment GitHub page!

Monday, November 21, 2016

Hack Speedment into Your Own Personal Code Generator

Spire and Duke dressed as Neo from Matrix

Speedment is an Open Source toolkit that can be used to generate Java entities and managers for communicating with a database. This is great if you need an Object Relational Mapping of the domain model, but in some cases, you might want to generate something completely different using your database as the template. In this article I am going to show you a hack that you can use to take over that code generator in Speedment and use it for your own personal purposes. At the end of the article we will have a completely blank code generator that we can program to do our bidding!

Background

Speedment is designed to operate as a plugin to Maven. By invoking various new Maven goals we can instruct Speedment to connect to a database, generate source code and also remove any generated files from our project. It also contains a graphical user interface that makes it easy to configure the generation job based on metadata collected from our database. Now, imagine all this information that we can collect from analyzing that metadata. We know what tables exist, we know of all the constraints they have and what types the individual columns have. There are probably millions of use-cases where we can benefit from automatically generating stuff from that metadata. Following the steps in this article, we can do all those things.

Screenshot of the Speedment User Interface

Step 1: Set Up a Regular Speedment Project

Create a new Maven Project and add the following to the pom.xml-file:

pom.xml

<properties>
    <speedment.version>3.0.1</speedment.version>
    <mysql.version>5.1.39</mysql.version>
</properties>


<dependencies>
    <dependency>
        <groupId>com.speedment</groupId>
        <artifactId>runtime</artifactId>
        <version>${speedment.version}</version>
        <type>pom</type>
    </dependency>
</dependencies>


<build>
    <plugins>
        <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>
        </plugin>
    </plugins>
</build>

We have added Speedment as a runtime dependency and configured the Maven plugin to use the standard MySQL JDBC driver to connect to our database. Great! You now have access to a number of new Maven goals. For an example, if we wanted to launch the Speedment UI we could do that by running:


mvn speedment:tool

If we did that now, Speedment would launch in normal mode allowing us to connect to a database and from it generate entities and managers for communicating with that database using Java 8 streams. That is not what we want to do this time around. We want to hack it so that it does exactly what we need it to do. We therefore continue to modify the pom.

Step 2: Modify the Plugin Declaration

Speedment is built up in a modular fashion with different artifacts responsible for different tasks. All the pre-existing generator tasks are located in an artifact called "com.speedment.generator:generator-standard". That is where we are going to strike! By removing that artifact from the classpath we can prevent Speedment from generating anything we don’t want it to.

We modify the pom as follows:


...
<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>
       
        <!-- Add this: -->
        <dependency>
            <groupId>com.speedment</groupId>
            <artifactId>tool</artifactId>
             <version>${speedment.version}</version>
             <type>pom</type>
             <exclusions>
                 <exclusion>
                     <groupId>com.speedment.generator</groupId>
                     <artifactId>generator-standard</artifactId>
                 </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</plugin>
...

What is that? We exclude a dependency by adding one? How can that even work? Well, Speedment is designed to include as little code as possible unless it is explicitly needed by the application. The "com.speedment:tool-artifact" is a dependency to the maven plugin already, and by mentioning it in the <dependencies>-section of the maven plugin we can append settings to its configuration. In this case, we say that we want the plugin to have access to the tool except we don’t want the standard generator.

There is a problem here though. If we try and launch the speedment:tool goal, we will get an exception. The reason for this is that Speedment expects the standard translators to be on the classpath.

Here is where the second ugly hack comes in. In our project, we create a new package called com.speedment.generator.standard and in it define a new java file called StandardTranslatorBundle.java. As it turns out, that is the only file that Speedment really needs to work. We give it the following content:

StandardTranslatorBundle.java

package com.speedment.generator.standard;


import com.speedment.common.injector.InjectBundle;
import java.util.stream.Stream;


public final class StandardTranslatorBundle implements InjectBundle {
    @Override
    public Stream<Class<?>> injectables() {
        return Stream.empty();
    }
}

Next, we need to replace the excluded artifact with our own project so that the plugin never realizes that the files are missing. We return to the pom.xml-file and add our own project to the <dependencies>-section of the speedment-maven-plugin. The full pom file looks like this:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.github.pyknic</groupId>
  <artifactId>speedment-general-purpose</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>
    
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <speedment.version>3.0.1</speedment.version>
  </properties>
    
  <dependencies>
    <dependency>
      <groupId>com.speedment</groupId>
      <artifactId>runtime</artifactId>
      <version>${speedment.version}</version>
      <type>pom</type>
    </dependency>
  </dependencies>
    
  <build>
    <plugins>
      <plugin>
        <groupId>com.speedment</groupId>
        <artifactId>speedment-maven-plugin</artifactId>
        <version>${speedment.version}</version>
        <dependencies>
          <dependency>
            <groupId>com.speedment</groupId>
            <artifactId>tool</artifactId>
            <version>${speedment.version}</version>
            <type>pom</type>
            <exclusions>
              <exclusion>
                <groupId>com.speedment.generator</groupId>
                <artifactId>generator-standard</artifactId>
              </exclusion>
            </exclusions>
          </dependency>
          <dependency>
            <groupId>com.github.pyknic</groupId>
            <artifactId>speedment-general-purpose</artifactId>
            <version>1.0.0-SNAPSHOT</version>
          </dependency>   
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

If we now build our project and then run the goal speedment:tool, we should be able to launch the graphical user interface without problem. If we connect to the database and then press "Generate", nothing will happen at all! We have successfully hacked Speedment into doing absolutely nothing!

Step 3: Turn Speedment Into What You Want It To Be

Now when we have a fresh, clean Speedment, we can start turning it into the application we want it to be. We still have a powerful user interface where we can configure the code generation based on a database model. We have an expressive library of utilities and helper classes to work with generated code. And above all, we have a structure for analyzing the database metadata in an object-oriented fashion.

To learn more about how to write your own code generation templates and hook them into the platform, check out this article. You should also check out the Speedment GitHub page to learn how the existing generators work (the ones we just disabled) and maybe get some inspiration on how you can build your own.

Until next time, continue hacking!