‏ ‏ ‎ ‏ ‏ ‎

1. Create Backend-App and add Dependencies

create quarkus project with gui
Figure 1. create quarkus app with web gui
mit maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.16.3.Final:create \
    -DprojectGroupId=at.htl.leonding.demo \
    -DprojectArtifactId=demo \
    -Dextensions='quarkus-resteasy-jackson,websockets,hibernate-orm-panache,jdbc-postgresql,jib'
cd demo
Troubleshooting
mit maven
/opt/apache-maven-3.8.7/bin/mvn io.quarkus.platform:quarkus-maven-plugin:2.16.3.Final:create \
    -DprojectGroupId=at.htl.leonding.demo \
    -DprojectArtifactId=demo \
    -Dextensions='quarkus-resteasy-jackson,websockets,hibernate-orm-panache,jdbc-postgresql,jib'
cd demo
mit der Quarkus CLI
quarkus create app at.htl.leonding.demo:backend

quarkus ext add quarkus-resteasy-jackson websockets hibernate-orm-panache jdbc-postgresql jib
add assertj to pom.xml and click "Load maven changes"
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.24.2</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-db -->
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-db</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>

2. Configure application.properties

src/main/resources/application.properties
quarkus.datasource.devservices.enabled=false
quarkus.http.root-path=/api

quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=app
quarkus.datasource.password=app
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/db

quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.database.generation.halt-on-error=false
quarkus.hibernate-orm.sql-load-script=db/import.sql

quarkus.hibernate-orm.log.sql=true
quarkus.http.access-log.enabled=true

3. Local Postgres Database

3.1. Install Local Database

output
[+] Running 2/2
 ⠿ Container pgadmin   Started                                                           0.5s
 ⠿ Container postgres  Started                                                           0.5s
directory structure postgres db

3.2. Load Initial Data at Startup

  • create an import.sql-file

insert data folder structure
src/main/resources/db/import.sql
INSERT INTO public.tb_user (name) VALUES('Max Mustermann');
INSERT INTO public.tb_user (name) VALUES('Joe Sixpack');
INSERT INTO public.tb_user (name) VALUES('Jane Roe');
INSERT INTO public.tb_user (name) VALUES('John Doe');

3.3. Start Database Local

Terminal
./postgres-start.sh
output
[+] Running 3/3
 ⠿ Network db-postgres_postgres  Created                               0.0s
 ⠿ Container pgadmin             Started                               0.3s
 ⠿ Container postgres            Started                               0.3s

3.4. Stop Database Local

Terminal
./postgres-stop.sh
output
[+] Running 3/3
 ⠿ Container pgadmin             Removed                                                                       0.8s
 ⠿ Container postgres            Removed                                                                       0.1s
 ⠿ Network db-postgres_postgres  Removed                                                                       0.0s

3.5. Create Datasource for local database

  • When we downloaded and executed the postgres-download-scripts.sh we got a file datasource.txt

  • We open this file

  • Copy the whole content cmd+c / ctrl+c

  • and insert into

datasource create
datasource create settings
Details
datasource change credentials 1
datasource change credentials 2
datasource change test connection
datasource table

4. First REST-request

Endpoint
package at.htl.leonding.demo;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; (1)

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello RESTEasy";
    }
}
1 Achtung auf den korrekten Import
./mvnw clean quarkus:dev
http request create environment file
http request environment
http request folder
Figure 2. folder structure
http request
Figure 3. run request
http request result

5. Erstellen der User-Funktionalität

  • Wir werden nun folgende Struktur erstellen:

package structure by feature

5.1. User

package at.htl.leonding.demo.entity.user;

public class User {

    Long id;
    String name;

}
  • cursor auf Feldnamen setzen

  • encapsulate fields Strg + T

refactor encapsulate fields
  • Generieren der Constructors

    • Alt + Einf / + N

package at.htl.leonding.demo.entity.user;

public class User {

    private Long id;
    private String name;

    //region Constructors
    public User() {
    }

    public User(String name) {
        this.name = name;
    }
    //endregion

    //region getter and setter
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //endregion
}
  • add jpa-annotations

package at.htl.leonding.demo.entity.user;

import javax.persistence.*;

@Entity
@Table(name = "TB_USER")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    //region Constructors
    public User() {
    }

    public User(String name) {
        this.name = name;
    }
    //endregion

    //region getter and setter
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //endregion

    @Override
    public String toString() {
        return String.format("%d: %s", id, name);
    }

}

5.2. UserDto

Dto’s (data transfer objects) werden verwendet, um mehrere Daten (entities) in einem einzigen (teuren) Aufruf zu bündeln. Ein weiterer Vorteil ist, dass ev. vertrauliche Daten der Entities nicht exponiert werden. (siehe auch 1, 2, 3)

package at.htl.leonding.demo.entity.user;

public record UserDto (int id, String name) { }

5.3. UserMapper

package at.htl.leonding.demo.entity.user;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class UserMapper {
    public UserDto toResource(User user) {
        return new UserDto(user.getId(), user.getName());
    }
}

5.4. UserRepository

package at.htl.leonding.demo.entity.user;

import io.quarkus.hibernate.orm.panache.PanacheRepository;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class UserRepository implements PanacheRepository<User> {
}

5.5. UserResource

userresource getusers
Beachte die Anzeige der Rückgabetypen von IntelliJ. Daher sind die Zeilenschaltungen sehr vorteilhaft
package at.htl.leonding.demo.entity.user;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.util.List;
import java.util.stream.Collectors;

@Path("/user")
public class UserResource {
    @Inject
    UserRepository userRepository;

    @Inject
    UserMapper userMapper;

    @GET
    public List<UserDto> getUsers() {
        return userRepository
                .findAll()
                .stream()
                .map(
                        user -> userMapper.toResource(user)
                )
                .collect(Collectors.toList());
    }
}

6. Run App

Terminal
./postgres-start.sh
output
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------< at.htl.leonding.demo:backend >--------------------
[INFO] Building backend 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ backend ---
[INFO] Deleting /Users/stuetz/work/2023-quarkus-ph-seminar/_tag2/backend/target
[INFO]
[INFO] --- quarkus-maven-plugin:2.16.4.Final:dev (default-cli) @ backend ---
[INFO] Invoking org.apache.maven.plugins:maven-resources-plugin:2.6:resources @ backend
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO] Invoking io.quarkus.platform:quarkus-maven-plugin:2.16.4.Final:generate-code @ backend
[INFO] Invoking org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile @ backend
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to /Users/stuetz/work/2023-quarkus-ph-seminar/_tag2/backend/target/classes
[INFO] Invoking org.apache.maven.plugins:maven-resources-plugin:2.6:testResources @ backend
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/stuetz/work/2023-quarkus-ph-seminar/_tag2/backend/src/test/resources
[INFO] Invoking io.quarkus.platform:quarkus-maven-plugin:2.16.4.Final:generate-code-tests @ backend
[INFO] Invoking org.apache.maven.plugins:maven-compiler-plugin:3.10.1:testCompile @ backend
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/stuetz/work/2023-quarkus-ph-seminar/_tag2/backend/target/test-classes
Listening for transport dt_socket at address: 5005
Hibernate:

    drop table if exists TB_USER cascade
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-03-04 13:55:24,750 WARN  [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000

2023-03-04 13:55:24,751 WARN  [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) table "tb_user" does not exist, skipping
Hibernate:

    create table TB_USER (
       id int8 generated by default as identity,
        name varchar(255),
        primary key (id)
    )

Hibernate:
    INSERT INTO public.tb_user (name) VALUES('Max Mustermann')
Hibernate:
    INSERT INTO public.tb_user (name) VALUES('Joe Sixpack')
Hibernate:
    INSERT INTO public.tb_user (name) VALUES('Jane Roe')
Hibernate:
    INSERT INTO public.tb_user (name) VALUES('John Doe')
2023-03-04 13:55:24,870 INFO  [io.quarkus] (Quarkus Main Thread) backend 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.16.4.Final) started in 1.778s. Listening on: http://localhost:8080
2023-03-04 13:55:24,871 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2023-03-04 13:55:24,871 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, vertx, websockets, websockets-client]

--
Tests paused
Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

7. Create Restful Client

http-requests/requests.http
GET {{local}}/user

###
rest client get user

8. Create Frontend-App

node -v
npm -v

# npm install -g npm@9.6.0
npm install -g npm@latest

8.1. Download frontend-scaffolding

curl -# -O http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/nvs/scripts/2023-03-quarkus-sem/frontend.zip

# if unzip is installed ...
unzip frontend.zip

cd frontend/www

npm install

npm update

npm start

8.2. Download k8s-pipeline

download to the project-root and extract
curl -O -# http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/nvs/scripts/2023-03-quarkus-sem/k8s.zip