Clone repository from GitHub:
$ git clone https://github.com/piomin/openshift-quickstart.git
$ cd openshift-quickstart/basic-with-db
Run your development IDE (Eclipse/IntelliJ). Import Maven project.
There are two applications person-app
and insurance-app
. We will start with person-app
:
$ cd person-app
Build the application and start it in the dev mode:
$ mvn quarkus:dev
Does the application start successfully?
Let's fix some problems. Add the configuration properties for database connection only for a development mode:
%dev.quarkus.datasource.db-kind=h2
%dev.quarkus.datasource.username=sa
%dev.quarkus.datasource.password=password
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb
The additional dependency need to be included into Maven pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2</artifactId>
</dependency>
Your application is available at localhost:8080
.
In your web browser run open the following URL: http://localhost:8080
, then click /q/dev
context path. You will be redirected to the Quarkus Dev UI Console.
Let's call example endpoint:
$ curl http://localhost:8080/persons
There is not tables created in H2 database. In src/main/resources
create db
directory. Then create the changeLog.sql
file with the following content:
--liquibase formatted sql
--changeset piomin:1
create table person (
id serial primary key,
name varchar(255),
gender varchar(255),
age int,
externalId int
);
insert into person(name, age, gender) values('John Smith', 25, 'MALE');
insert into person(name, age, gender) values('Paul Walker', 65, 'MALE');
insert into person(name, age, gender) values('Lewis Hamilton', 35, 'MALE');
insert into person(name, age, gender) values('Veronica Jones', 20, 'FEMALE');
insert into person(name, age, gender) values('Anne Brown', 60, 'FEMALE');
insert into person(name, age, gender) values('Felicia Scott', 45, 'FEMALE');
We will use the Liquibase tool for creating tables with test data. In order to use it, we also need to include the following dependency to the Maven pom.xml
, which is responsible for integration between Liquibase and Quarkus:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-liquibase</artifactId>
</dependency>
Let's call example endpoint once again:
$ curl http://localhost:8080/persons
Then, we will finish the implementation of PersonResource
:
@POST
@Transactional
public Person addPerson(Person person) {
personRepository.persist(person);
return person;
}
@GET
@Path("/name/{name}")
public List<Person> getPersonsByName(@PathParam("name") String name) {
return personRepository.findByName(name);
}
@GET
@Path("/{id}")
public Person getPersonById(@PathParam("id") Long id) {
return personRepository.findById(id);
}
@GET
@Path("/age-greater-than/{age}")
public List<Person> getPersonsByName(@PathParam("age") int age) {
return personRepository.findByAgeGreaterThan(age);
}
Go to the implementation of the Panache repository PersonRepository
and change it to the following:
@ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
public List<Person> findByName(String name) {
return find("name", name).list();
}
public List<Person> findByAgeGreaterThan(int age) {
return find("age > ?1", age).list();
}
}
Then call the following endpoints:
$ curl http://localhost:8080/persons/name/<value-from-changelog>
$ curl http://localhost:8080/persons/age-greater-than/30
Let's kill the mvn quarkus:dev
command for a moment. Add the following dependencies to the Maven pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
Then create a package pl.redhat.samples.quarkus.person
and the class PersonResourceTests
inside that package:
@QuarkusTest
public class PersonResourceTests {
@Test
void getPersons() {
List<Person> persons = given().when().get("/persons")
.then()
.statusCode(200)
.extract()
.body()
.jsonPath().getList(".", Person.class);
assertEquals(persons.size(), 6);
}
@Test
void getPersonById() {
Person person = given()
.pathParam("id", 1)
.when().get("/persons/{id}")
.then()
.statusCode(200)
.extract()
.body().as(Person.class);
assertNotNull(person);
assertEquals(1L, person.id);
}
@Test
void newPersonAdd() {
Person newPerson = new Person();
newPerson.age = 22;
newPerson.name = "TestNew";
newPerson.gender = Gender.FEMALE;
Person person = given()
.body(newPerson)
.when().post("/persons")
.then()
.statusCode(200)
.extract()
.body().as(Person.class);
assertNotNull(person);
assertNotNull(person.id);
}
}
Run the command mvn quarkus:dev
once again. You should see:
Tests paused
Press [r] to resume testing, [o] Toggle test output, [h] for more options>
Type r
. You should have 2 (or 1)/3 tests succeeded. Go to the dev UI console. Find Test results
icon and click it. See the output for the failed tests. Try to fix them.
Especially verify the newPersonAdd
test. Maybe you should add something after the .body(newPerson)
line? Then type r
once again.
Kill the mvn quarkus:dev
command.
Navigate to the insurance-app
:
$ cd ../insurance-app
Add the dependency with the REST client:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client</artifactId>
</dependency>
Create a declarative client responsible for calling the GET /persons/{id}
endpoint:
@Path("/persons")
@ApplicationScoped
@RegisterRestClient
public interface PersonService {
@GET
@Path("/{id}")
Person getPersonById(@PathParam("id") Long id);
}
Go to the pl/redhat/samples/quarkus/insurance/resource/InsuranceResource.java
. Find the following method:
@GET
@Path("/{id}/details")
public InsuranceDetails getInsuranceDetailsById(@PathParam("id") Long id) {
return null; // TODO - finish implementation
}
Replace it with the following implementation:
@GET
@Path("/{id}/details")
public InsuranceDetails getInsuranceDetailsById(@PathParam("id") Long id) {
Insurance insurance = insuranceRepository.findById(id);
InsuranceDetails insuranceDetails = new InsuranceDetails();
insuranceDetails.personId = insurance.personId;
insuranceDetails.amount = insurance.amount;
insuranceDetails.type = insurance.type;
insuranceDetails.expiry = insurance.expiry;
insuranceDetails.setPerson(personService.getPersonById(insurance.personId));
return insuranceDetails;
}
Run application in the dev mode. Then run tests using command line. Not all the tests were passed.
Go to the pl/redhat/samples/quarkus/insurance/InsuranceResourceTests.java
. Find newInsuranceAdd()
. This test fails. \
Go to the Maven pom.xml
and add the following dependency:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
Back to the pl/redhat/samples/quarkus/insurance/InsuranceResourceTests.java
. You need to inject PersonService
into the
@QuarkusTest
public class InsuranceResourceTests {
@InjectMock
@RestClient
PersonService personService;
// ... tests
}
Go to the getInsuranceDetailsById()
method inside JUnit test class. Mock communication with person-app
by adding the following Mockito rule at the beginning of the method:
Mockito.when(personService.getPersonById(Mockito.anyLong())).thenAnswer(invocationOnMock -> {
Long id = invocationOnMock.getArgument(1, Long.class);
Person person = new Person();
person.setId(id);
person.setAge(33);
person.setName("Test" + id);
person.setGender(Gender.FEMALE);
return person;
});
Re-run the tests. All should be passed. Then you can kill the command mvn quarkus:dev
.
First, login to the cluster using the oc
client:
$ oc login -u $USER -p $PASSWORD --server=https://api.ocp1.example.lab:6443
Go to: https://console-openshift-console.apps.ocp1.example.lab.
Switch do the Developer perspective. Click +Add
-> Database
. Choose PostgreSQL
. Set person-db
as a Database Service Name
, and leave default values for the rest of fields.
Do the same for insurance-app
.
Go to the person-app
directory in the source code:
$ cd ../person-app
Add the following dependency into Maven pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-openshift</artifactId>
</dependency>
Open the file src/main/resources/application.properties
. Verify quarkus.datasource.*
properties.
Enable automatic deployment on OpenShift:
quarkus.container-image.build=true
quarkus.kubernetes.deploy=true
quarkus.kubernetes.deployment-target=openshift
quarkus.kubernetes-client.trust-certs=true
Configure a connection with a database. Before, go the OpenShift Web Console and view the person-db
secret. Then add the following properties:
quarkus.openshift.env.mapping.postgres_user.from-secret=person-db
quarkus.openshift.env.mapping.postgres_user.with-key=database-user
quarkus.openshift.env.mapping.postgres_password.from-secret=person-db
quarkus.openshift.env.mapping.postgres_password.with-key=database-password
quarkus.openshift.env.mapping.postgres_db.from-secret=person-db
quarkus.openshift.env.mapping.postgres_db.with-key=database-name
Then add some optional fields:
quarkus.openshift.name=person-app
quarkus.openshift.version=${quarkus.application.version}
quarkus.openshift.expose=true
quarkus.openshift.replicas=2
The same configuration should be added for insurance-app
. Just change the name of app and secret.
Run person-app
application in the dev mode. Go to the Dev UI console. Click Deploy
on the OpenShift
tile, then Deploy
on the next window. Wait and watch on the logs, the build is in progress.
Go to the OpenShift Web Console. Click Builds
, choose person-app
BuildConfig
. Switch to the Builds
tab. Choose the latest build. In the Details
verify Output to
.
Then switch to the Logs
tab.
Then with oc
client display a list of routes:
$ oc get route
Copy the path of your person-app
route. Then call the endpoint e.g.:
$ curl http://<your_route>/persons
Then go back to the code. In your IDE open the file target/kubernetes/openshift.yml
.
Switch to the insurance-app
directory:
$ cd ../insurance-app
Execute the following oc
command to display a list of Kubernetes Services:
$ oc get svc
In the application.properties
file add the following line:
pl.redhat.samples.quarkus.insurance.client.PersonService/mp-rest/url=http://person-app:8080
Then deploy the app using Maven command:
$ mvn clean package
Once again display a list of routes. Copy the URL of the insurance-app
route. Call the endpoints:
$ curl http://<your_route>/insurances
$ curl http://<your_route>/insurances/{id}/details
Do for both applications. Add the following dependencies into Maven pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics</artifactId>
</dependency>
Then add the following lines into the application.properties
file:
quarkus.swagger-ui.always-include=true
quarkus.smallrye-health.ui.always-include=true
Redeploy the applications. Verify new versions (e.g. liveness and readiness probes). Then in your web browser view the URLs:
http://<your_route>/q/swagger-ui
http://<your_route>/q/health
http://<your_route>/q/health-ui
http://<your_route>/q/health/live
http://<your_route>/q/health/ready
http://<your_route>/q/metrics
In Openshift Web Console switch to the Topology
view. Add the following properties for person-app
in the application.properties
file. Then redeploy the app:
quarkus.openshift.annotation."app.openshift.io/connects-to"=person-db
quarkus.openshift.labels."app.kubernetes.io/part-of"=persons
Do the same thing for the insurance-app
. Move back to the Topology
view. Add the label app.kubernetes.io/part-of=persons
for person-db
DC and app.kubernetes.io/part-of=insurances
for insurance-db
.
First, list all available components with odo
.
$ odo catalog list components
We choose S2I with Java.
$ odo create java-quarkus person-odo
Set environment variables for odo
.
$ odo config set --env DATABASE_NAME=<your-value> --env DATABASE_USER=<your-value> --env DATABASE_PASSWORD=<your-value>
Finally, deploy the application to OpenShift.
$ odo push
Go to the console -> Topology
. Verify if person-odo-app
deployment exists.
Go to Project
-> Routes
. Call the route with port 8080
. Call the following endpoint.
$ curl http://http-8080-person-odo-app-<your_project>.apps.ocp1.example.lab/persons
[]
Then, start development. Run the following command in the person-app
directory.
$ odo watch
Finally, you can add a new endpoint and call it via e.g. swagger-ui. Also call your route and verify the result.