REST - JAX-RS v Jakarta EE

odkazy na literatúru:
REST-ové webové služby podobne ako SOAP-ové webové služby môžu slúžiť na vzdialené volania metód a používajú sa najmä na prístup frontendu k dátam uloženým na backende, ale môžu slúžiť aj na komunikáciu viacerých aplikácií medzi sebou, napr. v Microservices architektúre. V tejto ukážke si vytvoríme jednoduchú REST-ovú službu, ktorá testuje deliteľnosť dvoch čísel ako Jakarta EE9 aplikáciu v Intellij IDEA 2022.1 a potom druhú aplikáciu, ktorá túto službu bude využívať.

1. Aplikácia s REST-ovým service

Aplikácia má obsahovať jednu triedu, ktorá je podtriedou jakarta.ws.rs.core.Application a ktorá pomocou anotácie @ApplicationPath definuje časť URL adresy, na ktorej budú dostupné služby v tejto aplikácii:
package ee.delenieservice;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("/service")
public class DelApp extends Application {
}

Samotná služba bude poskytovaná triedou anotovanou pomocou @Path, určujúcou časť URL adresy tejto služby a v nej anotáciou @GET označíme metódu, ktorá sa na príslušnom HTTP requeste spustí. V našom prípade bude mať služba aj dva argumenty delenec a delitel, ktoré budú odozvdané cez poslednú časť URL a preto anotácia @Path na tejto metóde upresní poradie argumentov a anotácie @PathParam ich priradia argumentom metódy:
package ee.delenieservice;

import jakarta.ws.rs.*;

@Path("delenie")
public class Delenie {
    @GET
    @Path("{delenec}/{delitel}")
    public boolean jeDelitelne(@PathParam("delenec") int delenec,
                               @PathParam("delitel") int delitel)
    {   
        return (delenec % delitel == 0); 
    }   
}



2. Aplikácia, ktorá REST-ovú službu využíva (klient)

Vybudujme jednoduchú webovú aplikáciu, ktorá bude využívať JSF a CDI a na požiadavku používateľa - po vyplnení argumentov delenec a delitel na webstránke sa aplikácia na servri ako klient obráti na druhú aplikáciu, ktorá službu poskytuje.

Stránka s formulárom (index.xhtml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
    Delitel delenec klient
    <h:form id="formdelenie">
        <h:outputLabel for="delenec">Delenec:</h:outputLabel>
        <h:inputText id="delenec" value="#{delic.delenec}"/>
        <br></br>
        <h:outputLabel for="delitel">Delitel:</h:outputLabel>
        <h:inputText id="delitel" value="#{delic.delitel}"/>
        <br></br>
        <h:commandButton action="vypocet" value="Vydelit"/>
    </h:form>
</f:view>
</html>


výsledná stránka, ktorá zobrazí výstupi (vysledok.xhtml):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
    Vysledok po deleni
    <h:outputText id="delenec" value="${delic.delenec}"/>
    /   
    <h:outputText id="delitel" value="${delic.delitel}"/>
    je delitelne:
    <h:outputText id="vysledok" value="${delic.vysledok}"/>
    <br/>
    <h:outputText id="chyba" value="${delic.err}"/>
    <br/>
    <h:form>
        <h:commandLink action="index">Znovu</h:commandLink>
    </h:form>
</f:view>
</html>


Stránky sa odkazujú na CDI session bean, ktorý prevezme vstupy z formulára, zavolá službu a vráti výstup:

package ee.deleniewebapp;

import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;

import java.io.IOException;
import java.io.Serializable;

@Named
@SessionScoped
public class Delic implements Serializable, ClientRequestFilter {

    public Delic() { }

    @Override
    public void filter(ClientRequestContext ctx) throws IOException
    {
        System.out.println("logujem pristup: " + ctx.getUri());
    }

    private int delenec, delitel;
    private boolean vysledok;
    private String err;

    public int getDelenec() {
        return delenec;
    }

    public void setDelenec(int delenec) {
        this.delenec = delenec;
    }

    public int getDelitel() {
        return delitel;
    }

    public void setDelitel(int delitel) {
        this.delitel = delitel;
    }

    public boolean isVysledok() {
        Client client = ClientBuilder.newClient();
        client.register(Delic.class);
        try {
            vysledok = client
                    .target("http://localhost:8080/DelenieService-1.0-SNAPSHOT/service/delenie")
                    .path("{delenec}/{delitel}")
                    .resolveTemplate("delenec", delenec)
                    .resolveTemplate("delitel", delitel)
                    .request()
                    .get(Boolean.class);
        } catch (Exception e)
        {
            err = "chyba: " + e.toString();
        }
        return vysledok;
    }

    public void setVysledok(boolean vysledok) {
        this.vysledok = vysledok;
    }

    public void setErr(String err) {
        this.err = err;
    }

    public String getErr() {
        return err;
    }
}


Download:

- aplikácia s REST service: DelenieService.zip
- aplikácia, ktorá sa na REST service obracia: DelenieWebApp.zip