Maven
Maven is a build tool that automates the building process, including compiling, testing, packaging, and deploying applications. Maven also helps manage project dependencies and provides a structured way to organize projects, making them easier to understand and maintain. An alternative is gradle.
Let's make a small project using maven.
Getting Started
You will need:
- PostgreSQL - A Relational database
- JDBI - Lets you connect to a database
- Docker - Used to run postgres in a container
- Wildfly - Server alternative to tomcat that comes with JTA out of the box.
- Flyway DB - Used for data migrations. Liquibase or Bytebase are alternatives.
Folder Structure
This is how a Maven project is structured:
└───maven-project
├───pom.xml
├───README.txt
├───NOTICE.txt
├───LICENSE.txt
└───src
├───main
│ ├───java
│ ├───resources
│ ├───filters
│ └───webapp
├───test
│ ├───java
│ ├───resources
│ └───filters
├───it
├───site
└───assembly
pom.xml : this file contains dependencies and information about the application. Similar to Ruby on Rails' Gemfile
and Node's package.json
files.
src/main/java : contains package and source code.
src/test/java : contains test code
Configuration
mvn archetype:generate \
-DgroupId=com.mycompany.app \
-DartifactId=my-app \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5 \
-DinteractiveMode=false
version : "3.8"
services:
db:
image: postgres:14-alpine
container_name: user_db
ports:
- "5433:5432"
environment:
- "POSTGRES_USER=postgres"
- "POSTGRES_PASSWORD=pgadmin"
- "POSTGRES_DB=user_db"
package com.mycompany.app;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.Jdbi;
public class App{
public static void main(String[] args) {
Jdbi jdbi = Jdbi.create("jdbc:postgresql://localhost:5433/user_db","postgres","pgadmin");
try(Handle handle = jdbi.open()) {
System.out.println("Running JDBI stuff");
createUserTables(handle);
createTaskTables(handle);
}
System.out.println("DB Stuff is done!");
}
private static void createUserTables(Handle handle){
handle.execute("CREATE TABLE roles (id SERIAL PRIMARY KEY,name VARCHAR(45))");
handle.execute(
"CREATE TABLE user_info" + "(id SERIAL PRIMARY KEY, phone VARCHAR(50), first_name VARCHAR(100), last_name VARCHAR(50), employer VARCHAR(50), university VARCHAR(50), employed_since TIMESTAMP, ip_address VARCHAR(50), bio TEXT, status BOOLEAN, settings json, createdAt TIMESTAMP, updatedAt TIMESTAMP)"
);
handle.execute(
"CREATE TABLE users" + "(id SERIAL PRIMARY KEY, username VARCHAR(50), email VARCHAR(100), password VARCHAR(50), createdAt TIMESTAMP, updatedAt TIMESTAMP, user_info_id INTEGER REFERENCES user_info(id))"
);
handle.execute("CREATE TABLE users_roles (
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
role_id INTEGER REFERENCES roles(id),
CONSTRAINT users_roles_pk PRIMARY KEY(user_id, role_id))"
);
}
private static void createTaskTables(Handle handle){
handle.execute("CREATE TABLE task_types(id SERIAL PRIMARY KEY, name VARCHAR(50))");
handle.execute("CREATE TABLE tasks(id SERIAL PRIMARY KEY, user_id integer references users(id), name VARCHAR(50), description text, type_id integer references task_types(id)");
}
}
<?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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.11.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<!-- Optionally: parameterized tests support -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jdbi/jdbi3-core -->
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-core</artifactId>
<version>3.49.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.wildfly.core/wildfly-server -->
<dependency>
<groupId>org.wildfly.core</groupId>
<artifactId>wildfly-server</artifactId>
<version>28.0.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>11.9.1</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.6.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
You may use other versions of these dependencies. I'm using the latest dependencies available at the time of this writing.
docker-compose up
In the Intelij IDE you will need to click on the database icon to add a new postgres database. You can adjust the port,user, password, and database name to get the URL you will use for your database (these are also set in the docker-compose.yml file). The default port for postgres is 5432 but I mapped it to 5433 to avoid any issues that may come up with using the default.