- Microservices
- Microprofile
- Environment:
- java 11 openjdk
- graalvm
- extension of jvm
- supports several languages
- creates native binaries
- static analysis to find reachable code
- ahread-of-time (aot) compilation
- editors
- intellij
- eclipse
- vscode
- maven, gradle
# graalvm
wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.2.0/graalvm-ce-java11-linux-amd64-21.2.0.tar.gz
tar xzvf graalvm-ce-java11-linux-amd64-21.2.0.tar.gz
mv graalvm-ce-java11-21.2.0 /opt/
export GRAALVM_HOME=/opt/graalvm-ce-java11-21.2.0/
echo 'export GRAALVM_HOME=/opt/graalvm-ce-java11-21.2.0/' >> ~/.bashrc
# maven
wget https://www-us.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz -P /tmp
wget https://ftp.unicamp.br/pub/apache/maven/maven-3/3.8.2/binaries/apache-maven-3.8.2-bin.tar.gz
tar xzvf apache-maven-3.8.2-bin.tar.gz
mv apache-maven-3.8.2 /opt/
export M2_HOME=/opt/apache-maven-3.8.2/
export MAVEN_HOME=/opt/apache-maven-3.8.2/
export PATH="$MAVEN_HOME/bin:${PATH}"
mvn -version
java -version
history
mvn -U io.quarkus:quarkus-maven-plugin:create \
-DprojectGroupId=org.agoncal.quarkus.microservices \
-DprojectArtifactId=rest-book \
-DclassName="org.agoncal.quarkus.microservices.book.BookResource" \
-Dpath="/api/books" \
-Dextensions="resteasy-jsonb, smallrye-openapi"
mvn -U io.quarkus:quarkus-maven-plugin:create \
-DprojectGroupId=org.agoncal.quarkus.microservices \
-DprojectArtifactId=rest-number \
-DclassName="org.agoncal.quarkus.microservices.number.NumberResource" \
-Dpath="/api/numbers" \
-Dextensions="resteasy-jsonb, smallrye-openapi"
NumberResource.java
package org.agoncal.quarkus.microservices.number;
import org.jboss.logging.Logger;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.time.Instant;
import java.util.Random;
@Path("/api/numbers")
public class NumberResource {
@Inject
Logger logger;
@GET
@Produces(MediaType.APPLICATION_JSON)
public IsbnNumbers generateIsbnNumbers(){
IsbnNumbers isbnNumbers = new IsbnNumbers();
isbnNumbers.isbn13 = "13-" + new Random().nextInt(100_000_000);
isbnNumbers.isbn10 = "10-" + new Random().nextInt(100_000);
isbnNumbers.generationDate = Instant.now();
logger.info("Numbers generated " + isbnNumbers);
return isbnNumbers;
}
}
IsbnNumbers.java
package org.agoncal.quarkus.microservices.number;
import java.time.Instant;
public class IsbnNumbers {
public String isbn13;
public String isbn10;
public Instant generationDate;
@Override
public String toString() {
return "IsbnNumbers{" +
"isbn13='" + isbn13 + '\'' +
", isbn10='" + isbn10 + '\'' +
", generationDate=" + generationDate +
'}';
}
}
- /q/openapi
- /q/openapi -H “accept: application/json”
- /q/swagger-ui
mvn quarkus:dev
mvn quarkus:add-extension -Dextensions="rest-client"
mvn quarkus:add-extension -Dextensions="smallrye-fault-tolerance"
mvn package -Dmaven.test.skip=true
-
mvn package -Dquarkus.package.type=native \ -Dmaven.test.skip=true \ -Dquarkus.native.container-build=true
mvn quarkus:add-extension -Dextensions="docker"
-
mvn package -Dquarkus.package.type=native \ -Dmaven.test.skip=true \ -Dquarkus.native.container-build=true \ -Dquarkus.container-image.build=true
- test
curl -X POST http://localhost:8702/api/books -d "title=Quarkus&author=Antonio&year=2021&genre=IT"
curl http://localhost:8701/api/numbers
- references
- https://quarkus.io/community
- https://quarkus.io/guides
- https://github.com/quarkusio
- https://github.com/quarkiverse
- https://microprofile.io
- https://smallrye.io
native build
BookResource.java
package org.agoncal.quarkus.microservices.book;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;
import javax.inject.Inject;
import javax.json.bind.JsonbBuilder;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.time.Instant;
@Path("/api/books")
@Tag(name = "Book REST Endpoint")
public class BookResource {
@Inject
@RestClient
NumberProxy proxy;
@Inject
@RestClient
DjangoProxy django_proxy;
@Inject
Logger logger;
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Operation(
summary = "Creates a Book",
description = "Creates a Book with an ISBN number"
)
@Retry(maxRetries = 3, delay=3000)
@Fallback(fallbackMethod = "fallingbackCreateABook")
public Response createABook(@FormParam("title") String title,
@FormParam("author") String author,
@FormParam("year") int yearOfPublication,
@FormParam("genre") String genre){
Book book = new Book();
//book.isbn13 = "13-We will get this later from number microservice";
book.isbn13 = proxy.generateIsbnNumbers().isbn13;
book.price = django_proxy.generateNumber().django_number;
book.title = title;
book.author = author;
book.yearOfPublication = yearOfPublication;
book.genre = genre;
book.creationDate = Instant.now();
//logger.info("Book created : " + book);
return Response.status(201).entity(book).build();
}
public Response fallingbackCreateABook(String title,
String author,
int yearOfPublication,
String genre){
Book book = new Book();
//book.isbn13 = "13-We will get this later from number microservice";
book.isbn13 = "Will be set later";
book.title = title;
book.author = author;
book.yearOfPublication = yearOfPublication;
book.genre = genre;
book.creationDate = Instant.now();
saveBookOnDisk(book);
//logger.warn("Book saved on disk : " + book);
return Response.status(206).entity(book).build();
}
private void saveBookOnDisk(Book book){
String bookJson = JsonbBuilder.create().toJson(book);
try (PrintWriter out = new PrintWriter("book-" + Instant.now().toEpochMilli() + ".json")) {
out.println(bookJson);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
DjangoProxy.java
package org.agoncal.quarkus.microservices.book;
import org.agoncal.quarkus.microservices.book.djangoNumber;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import javax.print.attribute.standard.Media;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@RegisterRestClient(configKey = "django.proxy")
@Path("/challenges/proxy")
public interface DjangoProxy {
@GET
@Produces(MediaType.APPLICATION_JSON)
djangoNumber generateNumber();
}
DjangoNumber.java
package org.agoncal.quarkus.microservices.book;
import javax.json.bind.annotation.JsonbProperty;
public class djangoNumber {
@JsonbProperty("django_number")
public String django_number;
}
application.properties
quarkus.http.host=0.0.0.0
quarkus.http.port=8080
django.proxy/mp-rest/uri=http://pod-quarkus2-lab:8000
Caveats
bind 0.0.0.0
https://stackoverflow.com/questions/55043764/how-to-make-quarkus-to-listen-on-all-network-interfaces-instead-of-localhost