DEV Community

Andrecbrito
Andrecbrito

Posted on • Updated on

Azure Functions with supersonic Java

Intro

Serverless is becoming an alternative way of creating and deploying some types of services due to the fast delivery and cost-efficient project management [1]. The way that serverless applications work allows for high availability with a cost-efficient delivery by “turning ON“ our application only when it is being requested and thus saving resources on “dead“ hours.

Java, as it was until recently, wasn’t adequately fit to handle fast boot-ups (needed to wake up the application) and low resource consumption (yes, serverless doesn’t mean there is no server. There is a server and one must pay for it and the resources it uses).

This is where Quarkus and Microprofile [3;4] come to the rescue allowing for a serverless service fully built on Java.

Function as a Service (FaaS) “is an event-driven computing execution model where developers write logic that is deployed in containers fully managed by a platform, then executed on demand.” [5]

Prerequisites

  1. Azure subscription and The Azure CLI
  2. Java JDK 7, 8, 11, 13, 15
  3. Maven v3
  4. A pinch of programming skills

Sample Application

We start off by having to have a service to deploy that fits the need for it to be FaaS [1;5]. For the sake of simplicity, this example will be a basic service where there is a 1-minute timer that reads an in-memory database (DB) and increments a row with the current timestamp. It should also provide a way of getting this information so it will have a microservice with an HTTP GET operation.

Time to replicate

Assuming you already have an Azure subscription it is expected to replicate this example in less than one hour.

Download Code Base

Access https://code.quarkus.io/ and start selecting the options and dependencies needed.

Alt Text

Group | com.example

Artifact | quarkus-functions-sample

Build Tool | Maven

Version | 1.0.0-Snapshot

Then we choose what dependencies we will need, do not worry if you miss dependencies here because you can always add them later.

So, for now, we know that we want azure functions, and we will need to create a REST service. Let’s also check if there is something for the timer as well. Let's start typing in the dependencies:

For REST, we choose RESTeasy JAX-rs

Alt Text

For Azure functions, we type “functions” and select the “Azure functions HTTP“

Alt Text

And let's try the scheduler for the timer

Alt Text

Last we also select the dependencies for the in-memory database.

Alt Text

Finally, we download the application (notice that they provide articles for you to read based on the selected dependencies )

Alt Text
Alt Text

We can see that there are many things configured therefore our job will be to code mostly

Alt Text

Hands-On

We start off by configuring the database, and the entities to access the data.

in the file:

src\main\resources\application.properties

add the following code:

quarkus.http.root-path=/api
quarkus.package.type=uber-jar
quarkus.datasource.db-kind=h2
quarkus.datasource.username=sa
quarkus.datasource.password=sa
quarkus.datasource.jdbc.url=jdbc:h2:mem:public;MODE=PostgreSQL
quarkus.hibernate-orm.database.generation=drop-and-create
Enter fullscreen mode Exit fullscreen mode

And create a file [src/main/resources/import.sql] with the initial data:

INSERT INTO quafun
(id, current)
VALUES(1, '1615195937');
Enter fullscreen mode Exit fullscreen mode

Check that you have all of these dependencies:

pom.xml

<dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-azure-functions-http</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jsonb</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-scheduler</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-arc</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-junit5</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Hibernate ORM specific dependencies -->
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm-panache</artifactId>
        </dependency>

        <!-- JDBC driver dependencies -->
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-jdbc-h2</artifactId>
        </dependency>
    </dependencies>
Enter fullscreen mode Exit fullscreen mode

On the java side we need a JPA entity and a repository to manage the data and an API class:

Quafun.java

@Entity(name = "quafun")
public class Quafun {

  @Id
  private long id;
  private String current;

  public Quafun() {
  }

  public Quafun(long nextLong, long currentTimeMillis) {
    this.id = nextLong;
    this.current = "" + currentTimeMillis;

  }

  public long getId() {
    return id;
  }

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

  public String getCurrent() {
    return current;
  }

  public void setCurrent(String current) {
    this.current = current;
  }

}
Enter fullscreen mode Exit fullscreen mode

QuafunRepo.java

@ApplicationScoped
public class QuafunRepo implements PanacheRepository<Quafun> {

}
Enter fullscreen mode Exit fullscreen mode

A controller for the REST interface

QuafunController.java

@Path("/quarkus-function")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class QuafunController {
  private static final Logger LOGGER = Logger.getLogger(QuafunController.class.getName());

  @Inject
  QuafunRepo repo;

  @GET
  public List<Quafun> getAll() {
    LOGGER.info("[RETRIEVE-OPERATION] Get All Data");

    return repo.findAll().list();

  }
}
Enter fullscreen mode Exit fullscreen mode

And a Scheduler to do an operation regularly.

QuafunScheduler.java

@ApplicationScoped
public class QuafunScheduler {
  private static final Logger LOGGER = Logger.getLogger(QuafunScheduler.class.getName());

  @Inject
  QuafunRepo repo;

  @Scheduled(every = "1m")
  @Transactional
  void updateRepo() {
    LOGGER.info("[AUTO-OPERATION] Scheduller called");
    Quafun quafun = new Quafun(new Random().nextLong(), System.currentTimeMillis());
    repo.persist(quafun);

  }

}
Enter fullscreen mode Exit fullscreen mode

Beam me Up

The next step is to deliver our application to the cloud. There are several ways of achieving this, like terraform for example here [6], but for the sake of simplicity, this example will use Maven to deploy to Azure.

Link Maven to Azure

As we selected “Azure Functions HTTP“ for dependencies much of the needed information will be already placed in our pom.xml :

...
<properties>
        <azure.functions.maven.plugin.version>1.3.2</azure.functions.maven.plugin.version>
        <compiler-plugin.version>3.8.1</compiler-plugin.version>
        <function>greeting</function>
        <functionAppName>${artifactId}-<####INSERT-UUID_HERE####></functionAppName>
        <functionAppRegion>westus</functionAppRegion>
        <functionResourceGroup>java-functions-group</functionResourceGroup>
...
Enter fullscreen mode Exit fullscreen mode

Deploy

Deploying is the easy part! We need to be logged in! Past this into a command line:

az login

and then we just tell our application to deploy itself:

mvn clean install azure-functions:deploy

if everything went fine we have :

Alt Text

And we may test it by calling the URL:

Alt Text

And watching the metrics and check our logging messages:

Alt Text

2021-03-31T11:04:04.514 [Information] INFO: [RETRIEVE-OPERATION] Get All Data
...
2021-03-31T11:04:33.017 [Information] INFO: [AUTO-OPERATION] Scheduller called
Enter fullscreen mode Exit fullscreen mode

Happy coding!

From here on we are able to create and deploy functions with the full potential of Java.

Another topic to consider for functions and Java is the Funqy HTTP [7] which provides less overhead for functions.

#Koerber

Refs

[1] https://www.thoughtworks.com/radar/techniques/serverless-architecture

[2] https://docs.microsoft.com/en-us/azure/developer/java/eclipse-microprofile/deploy-microprofile-quarkus-java-app-with-maven-plugin

[3] https://quarkus.io/

[4] https://microprofile.io/

[5] https://www.redhat.com/en/topics/cloud-native-apps/what-is-serverless?sc_cid=7013a0000026GRyAAM&gclid=CjwKCAiA65iBBhB-EiwAW253W-6QT-UZ2rkqC5FPUVKxXR3Xr4FOrTAi_KYt8ROWySeb9JshOvEm6hoCTJQQAvD_BwE&gclsrc=aw.ds.

[6] https://www.maxivanov.io/deploy-azure-functions-with-terraform/

[7] https://quarkus.io/guides/funqy-http

Top comments (0)