{{announcement.body}}
{{announcement.title}}

Deploy Quarkus Faster in The Cloud with Platform.sh. Part 2: PostgreSQL with JPA

DZone 's Guide to

Deploy Quarkus Faster in The Cloud with Platform.sh. Part 2: PostgreSQL with JPA

In the second of this seires on deploying Quarkus to the cloud, we take a look at building the Quarkus app in preparation for deployment.

· Java Zone ·
Free Resource

Quarkus is, in its own words, a cloud-native, (Linux) container-first framework for writing Java applications. It has become popular lately because of the amazingly fast boot time, incredibly low RSS memory. In this series of articles about Quarkus, we'll discuss how to deploy a Quarkus application even faster to the cloud with Platform.sh.

The first step is to create the application itself, and Quarkus has proper documentation. You have either a Maven Archetype or the start code link where you can define the dependencies that you need to write your application.

In the Maven project, we either add manually or from the start site the Hibernate ORM,  JDBC driver, and the data source dependency.


XML
 




x
20


 
1
<dependency>
2
    <groupId>io.quarkus</groupId>
3
    <artifactId>quarkus-hibernate-orm</artifactId>
4
</dependency>
5
<dependency>
6
    <groupId>io.quarkus</groupId>
7
    <artifactId>quarkus-agroal</artifactId>
8
</dependency>
9
<dependency>
10
    <groupId>io.quarkus</groupId>
11
    <artifactId>quarkus-resteasy</artifactId>
12
</dependency>
13
<dependency>
14
    <groupId>io.quarkus</groupId>
15
    <artifactId>quarkus-resteasy-jsonb</artifactId>
16
</dependency>
17
<dependency>
18
    <groupId>io.quarkus</groupId>
19
    <artifactId>quarkus-jdbc-postgresql</artifactId>
20
</dependency>



We need to configure the application to run locally to test it.

Properties files
 




xxxxxxxxxx
1
10
9


1
quarkus.datasource.db-kind=postgresql
2
quarkus.datasource.username=quarkus_test
3
quarkus.datasource.password=quarkus_test
4
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost/quarkus_test
5
quarkus.datasource.jdbc.max-size=8
6
quarkus.datasource.jdbc.min-size=2
7
 
          
8
quarkus.hibernate-orm.database.generation=update
9
quarkus.hibernate-orm.log.sql=true



If you want to run a PostgreSQL locally, a good option might be Docker, which you can run with the command below:

Shell
 




x


 
1
docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:10.5



The infrastructure code is ready; the next step is to create the application itself. In this sample, we'll create a small rest-application to store animal names. Therefore, we'll create an Animal entity.

Java
 




x


1
import javax.persistence.Cacheable;
2
import javax.persistence.Column;
3
import javax.persistence.Entity;
4
import javax.persistence.GeneratedValue;
5
import javax.persistence.GenerationType;
6
import javax.persistence.Id;
7
import javax.persistence.NamedQuery;
8
import javax.persistence.QueryHint;
9
import javax.persistence.SequenceGenerator;
10
import javax.persistence.Table;
11
 
          
12
@Entity
13
@Table(name = "animal")
14
@NamedQuery(name = "Animal.findAll", query = "SELECT f FROM Animal f ORDER BY f.name", hints = @QueryHint(name = "org.hibernate.cacheable", value = "true"))
15
@Cacheable
16
public class Animal {
17
 
          
18
    @Id
19
    @SequenceGenerator(name = "animalSequence", sequenceName = "animal_id_seq", allocationSize = 1, initialValue = 10)
20
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "animalSequence")
21
    private Integer id;
22
 
          
23
    @Column(length = 40, unique = true)
24
    private String name;
25
 
          
26
   //getter and setter
27
 
          
28
}
29
 
          



The last step is to create a resource where the client can do the request and then the CRUD.

Java
 




x


 
1
import javax.enterprise.context.ApplicationScoped;
2
import javax.inject.Inject;
3
import javax.json.Json;
4
import javax.json.JsonObjectBuilder;
5
import javax.persistence.EntityManager;
6
import javax.transaction.Transactional;
7
import javax.ws.rs.Consumes;
8
import javax.ws.rs.DELETE;
9
import javax.ws.rs.GET;
10
import javax.ws.rs.POST;
11
import javax.ws.rs.PUT;
12
import javax.ws.rs.Path;
13
import javax.ws.rs.Produces;
14
import javax.ws.rs.WebApplicationException;
15
import javax.ws.rs.core.MediaType;
16
import javax.ws.rs.core.Response;
17
import javax.ws.rs.ext.ExceptionMapper;
18
import javax.ws.rs.ext.Provider;
19
20
import org.jboss.logging.Logger;
21
import org.jboss.resteasy.annotations.jaxrs.PathParam;
22
23
@Path("animals")
24
@ApplicationScoped
25
@Produces(MediaType.APPLICATION_JSON)
26
@Consumes(MediaType.APPLICATION_JSON)
27
public class AnimalResource {
28
29
    @Inject
30
    EntityManager entityManager;
31
32
    @GET
33
    public Animal[] get() {
34
        return entityManager.createNamedQuery("Animal.findAll", Animal.class)
35
                .getResultList().toArray(new Animal[0]);
36
    }
37
38
    @GET
39
    @Path("{id}")
40
    public Animal getSingle(@PathParam Integer id) {
41
        Animal entity = entityManager.find(Animal.class, id);
42
        if (entity == null) {
43
            throw new WebApplicationException("Animal with id of " + id + " does not exist.", 404);
44
        }
45
        return entity;
46
    }
47
48
    @POST
49
    @Transactional
50
    public Response create(Animal animal) {
51
        if (animal.getId() != null) {
52
            throw new WebApplicationException("Id was invalidly set on request.", 422);
53
        }
54
55
        entityManager.persist(animal);
56
        return Response.ok(animal).status(201).build();
57
    }
58
59
    @PUT
60
    @Path("{id}")
61
    @Transactional
62
    public Animal update(@PathParam Integer id, Animal animal) {
63
        if (animal.getName() == null) {
64
            throw new WebApplicationException("Animal Name was not set on request.", 422);
65
        }
66
67
        Animal entity = entityManager.find(Animal.class, id);
68
69
        if (entity == null) {
70
            throw new WebApplicationException("Animal with id of " + id + " does not exist.", 404);
71
        }
72
73
        entity.setName(animal.getName());
74
75
        return entity;
76
    }
77
78
    @DELETE
79
    @Path("{id}")
80
    @Transactional
81
    public Response delete(@PathParam Integer id) {
82
        Animal entity = entityManager.getReference(Animal.class, id);
83
        if (entity == null) {
84
            throw new WebApplicationException("Animal with id of " + id + " does not exist.", 404);
85
        }
86
        entityManager.remove(entity);
87
        return Response.status(204).build();
88
    }
89
}
90



The application is ready to go, and you can run the test the application.  The next step is to move to the cloud with Platform.sh.

  • To move your application to the cloud, briefly, you need three files:
YAML
 




xxxxxxxxxx
1


 
1
"https://{default}/":
2
  type: upstream
3
  upstream: "app:http"
4
 
          
5
"https://www.{default}/":
6
  type: redirect
7
  to: "https://{default}/"



YAML
 




xxxxxxxxxx
1


 
1
db:
2
  type: postgresql:11
3
  disk: 512



  • One containers (.platform.app.yaml). You control your application and the way it will be built and deployed on Platform.sh via a single configuration file. On this application, we allow the relationship between the PostgreSQL database and the application. So, our application container will have access to see the PostgreSQL container. Also, we'll overwrite the local configuration to use in the cloud to Platform.sh.
Java
 




x


 
1
name: app
2
type: "java:11"
3
disk: 1024
4
hooks:
5
    build: ./mvnw package -DskipTests
6
relationships:
7
    database: "db:postgresql"
8
 
          
9
web:
10
    commands:
11
        start: |
12
            export HOST=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".database[0].host"`
13
            export PASSWORD=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".database[0].password"`
14
            export USER=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".database[0].username"`
15
            export DATABASE=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|jq -r ".database[0].path"`
16
            java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError \
17
            -Dquarkus.http.port=$PORT \
18
            -Dquarkus.datasource.username=$USER \
19
            -Dquarkus.datasource.password=$PASSWORD \
20
            -Dquarkus.datasource.jdbc.url=jdbc:postgresql://${HOST}/${DATABASE} \
21
            target/jpa-1.0-SNAPSHOT-runner.jar
22
 
          



The application is now ready, so it’s time to move it to the cloud with Platform.sh using the following steps:

  • Create a new free trial account.
  • Sign up with a new user and password, or login using a current GitHub, Bitbucket, or Google account. If you use a third-party login, you’ll be able to set a password for your Platform.sh account later.
  • Select the region of the world where your site should live.
  • Select the blank template.

You have the option to either integrate to GitHub, GitLab, or Platform.sh will provide to you. Finally, push to the remote repository.


Done! We have a simple and nice Quarkus application ready to go to the cloud.

Topics:
cloud, cloud deployment, java, platform.sh, quarkus

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}