interactief

Jakarta Enterprise Edition 9

1. Starten met Jakarta Enterprise Edition

In dit gedeelte gaan we geavanceerder werken met hetgeen we tot nu toe hebben gedaan. Het gaat om het Jakarta Enterprise Edition 9 framework. Voordat we hiermee beginnen heb je het volgende nodig:

We leggen hier niet meer uit hoe je dit kunt installeren. Zie deel 1.

Maak een nieuw project aan en noem dit cdiweb. We gaan namelijk gebruik maken van CDI wat staat voor Content en Depedency Injection. De naam klinkt moeilijker dan dat het in werkelijkheid is.

Het eerste wat van belang is, zijn de instellingen van je project. Dit doe je in de zogenaamde pom.xml. Deze is te vinden onderin het project.

https://images.computational.nl/galleries/interactief/2022-11-16_14-05-22.png

In de pom file moet je wat instellingen doen. Je kunt hier de pom-file inzien of downloaden. Als je de gehele pomfile kopieert en plakt in je eigen pom-file dan gaat het werken. Pas bovenin de naam aan bij naam aanpassen.

Klik vervolgens op Build Project (het hamertje in Netbeans). Nu moet er nog één ding worden veranderd namelijk de web.xml. Deze vind je in het mapje WEB-INF. In jouw project staat deze echter op version 6 en https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd". Dit moet versie 5 worden. Er moet nog meer worden aangepast. Klik hier voor de juiste web.xml file. 

We hebben een filmpje gemaakt waarin het project niet wil starten.  Dit heeft te maken met de versie van de JDK. Je kunt hierin de foutmelding herkennen.  In een tweede filmpje wordt de versie aangepast in de server en werkt het project.

2. De Payara server geschikt maken voor een connectie met de database

We gaan in deze lessen uit van de Payara server. Deze is te downloaden via Netbeans. Wat we hiermee moeten doen is de mysql connector werkend maken. Dit is een driver en deze is hier te downloaden.

De volgende stap is de driver te installeren in de Payara server. Dit gaat met behulp van het asadmin commando in de command. De command open je met het commando cmd in de zoekfunctie van Windows. Klik vervolgens met de rechtermuisknop op het icoontje en start de applicatie als een administrator (je moet dus ingelogd zijn als admin - vraag aan de docent).

Je ziet in de cmd het volgende:

C:\windows\system32\

Ga nu naar het volgende mapje:

Met het commando cd kun je een mapje verder. Je kunt nu naar een specifiek mapje binnen de Payara server door het volgende te doen:

cd C:\Users\<gebruikersnaam>\Payara_Server\bin

Start nu eerst in Netbeans de server met de rechtermuisknop in het mapje Services.

Kopieer nu met verkenner hierna het bestand mysql-connector-java-9.0.28.jar in het mapje C:\Users\\Payara_Server\glassfish\bin en voer hierna het volgende commando uit:

C:\Users\<gebruikersnaam>asadmin add-library mysql-connector-java-8.0.28.jar

Als het goed is gaat de server reageren met het volgende:

Command add-library executed successfully.

Je hebt nu de driver geïnstalleerd voor een connectie met de database. Start nu in Netbeans met de rechtermuisknop de server opnieuw op.

Om ervoor te zorgen dat je dit niet iedere keer hoeft te doen kun je het mapje van de serverkopiëren naar je Google Drive en zodra je in je account werkt kun je dit mapje weer kopiëren naar je account.

3. Een user met een bijbehorende database aanmaken in MySQL

De volgende stap is het aanmaken van een user account binnen MySQL. Start hiervoor XAMPP en start hiermee de database. Ga vervolgens naar de gebruikersaccount en maak een nieuw account aan door te klikken op Gebruikersaccount toevoegen.

Vul nu de velden als volgt in:

Merk op dat je ook tevens een database met dezelfde naam aanmaakt. Wij laten onze databasenaam beginnen met admin. Dit is niet persé noodzakelijk maar we kunnen op deze manier meerdere databases groeperen.

Zorg er verder voor dat je het wachtwoord ergens opslaat. Merk tevens weer op dat we een ingewikkeld wachtwoord gebruiken. Bijvoorbeeld: &jXc&T9*#yLWc!85bQ

4. Een connectionpool in de Payaraserver maken

Om een connectie te kunnen maken met de database is het nodig om een zogenaamde connetionpool in de Payara server te maken. Klik met de rechtermuisknop op de server en klik op View Domain Admin Console.

De admin console opent in de standaard browser. Dat is geen probleem.

Ga nu naar het tabje JDBC en klik daarbinnen op  JDBC Connection Pools. Klik daarna op New..

Stel nu de volgende parameters in:

De naam van de driver moet dus zijn: com.mysql.cj.jdbc.MysqlDataSource

En in het derde tabje stel je de zogenaamde Addional Properties in. Je mag alle andere eventuele properties verwijderen.

De url in het plaatje is: jdbc:mysql://localhost:3306/admin_inschrijf?zeroDateTimeBehavior=convertToNull waarbij je het vetgemaakte vervangt voor de naam van jouw database. Het wachtwoord is het wachtwoord wat  je hebt aangemaakt in MySQL.

Uiteindelijk kun je de database testen met een ping in het eerte tabje:

5. De resource in de server maken

Een resource in de server is eigenlijk alleen maar een verwijzing naar de connectionpool. Klik in de admin van de server op het knopje JDBC Resources. Klik daarna op New.

Geef de resouce (bron) de naam die begint met jdbc/<naamvanjouwapplicatie> en kies de juiste connectionpool. Dit gaan we hier niet uitgebreid beschrijven.

6. De persistence unit instellen

Om nu een connectie met de database via de Payara server te maken is een zogenaamde persistence unit noodzakelijk. Deze kun je eenvoudig maken door met de rechtermuisknop op je project te klikken, daarna op Other... en dan in het filter het woordje persist te typen.

Klik nu eerst zo snel mogelijk op finish en de file opent automatisch in de design mode. Deze verlaten we door op source te klikken.

In de source kun je het beste de code als volgt instellen:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://java.sun.com/xml/ns/persistence" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <!-- Define Persistence Unit -->
    <persistence-unit name="admin_jouwproject" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/jouwproject</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.logging.level" value="FINE"/>
            <property name="javax.persistence.schema-generation.database.action" value="create"/>
        </properties>
    </persistence-unit>
</persistence>

Hierover nog enige uitleg. De naam van je unit mag je zelf kiezen. Bij ons heet deze admin_jouwproject

<persistence-unit name="admin_jouwproject" transaction-type="JTA">

De jta-data-source is de naam van de jdbc resource die je hebt gemaakt in de Payara server. Dit wordt ook wel de JNDI name genoemd.

Verder is er nog een property (eigenschap) die je in de design mode kunt veranderen met drie keuzes:

  • none: de database wordt niet aangepast
  • create: als de database tabel niet bestaat, wordt deze aangemaakt
  • drop and create: alle tabellen worden met inhoud verwijderd en opnieuw aangemaakt.

7. Beans.xml toevoegen

Op dezelfde manier zoals je een persistence unit hebt gemaakt, dien je ook een beans.xml toe te voegen. Klik hiervoor met de rechtermuisknop op de Web pages.

De code van de beans.xml is iets anders. Er komt namelijk nog een optie bij waarbij de applicatie alle beans ontdekt en meeneemt. Het gaat om de optie bean-discovery-mode="all"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                            http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
       bean-discovery-mode="all">
</beans>

8. Het maken van een entitiy

Je zult nu gaan merken dat de toegepaste techniek veel werk zullen besparen. We gaan namelijk nu een entity maken. De definitie van een entity is "iets wat zelfstandig bestaat". Je zou kunnen stellen dat een entity zoveel mogelijk de werkelijkheid nabootst. In onderstaand voorbeeld maken we de entity registration. Voordat er computers waren was dat natuurlijk een registratieformulier wat we hiermee digitaal hebben gemaakt.

Maak een class genaam Registration  en plaats dat in de package entities. In deze package komen alle entities zoals bijvoorbeeld een student of een parent. We maken een eenvoudige registratie die eventueel later nog uitgebreid kan worden met een id een naam. De methode public boolean equals overschrijft de bestaande methode binnen Java en doet wat extra checks zodat het resultaat betrouwbaarder is. 

Uitendelijk komen we tot de volgende code:

package entities;

import jakarta.enterprise.context.RequestScoped;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "registration")
@RequestScoped
//hier komen te queries
public class Registration implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private int id;

    @Column(name = "lastname")
    private String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Registration other = (Registration) obj;
        return this.id == other.id;
    }

}

Het maken van deze entity heeft als gevolg dat dit ook als tabel wordt aangemaakt in de database. Als je alles goed hebt staan zou dit nu moeten werken. Zorg dat in de persistence unit de optie create aanstaat. De code van persistence.xml ziet er dan als volgt uit:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="admin_coorndijk" transaction-type="JTA">
    <jta-data-source>jdbc/coorndijk</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="eclipselink.logging.level" value="FINE"/>
        <property name="javax.persistence.schema-generation.database.action" value="create"/>
    </properties>
  </persistence-unit>
</persistence>

9. Het maken van een dataservice

Een dataservice is een class die rechtstreeks mag praten met de database. Hierin komen de queries. Voor de entity Content ziet dit er bijvoorbeeld als volgt uit:

package service;

import entities.Content;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class DataServices {

    @PersistenceContext(unitName = "admin_coorndijk")
    EntityManager em;


    public List<Content> getAllContent() {
        return em.createNamedQuery("Content.all", Content.class).getResultList();
    }

}

Je ziet dat zo'n query er een beetje anders uitziet dan dat je gewend bent. Het principe blijft hetzelfde.

10. De entity met een query

Stel nu dat we een applicatie maken die de content haalt uit de database. De entity is als volgt:

@Entity
@Table(name = "content")
@RequestScoped
@NamedQueries({
    @NamedQuery(name = "Content.all", query = "select content from Content content order by content.id")
})
public class Content implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;


    @Column(name = "date")
    private LocalDate date;

    @Column(name = "subject")
    private String subject;

    @Column(name = "header")
    private String header;

    @Column(name = "content")
    private String content;


    @Column(name = "publish")
    private boolean publish;

    private final int maxCharactersHeader = 200;

    public String getHeader() {
        return header;
    }

    public void setHeader(String header) {
            this.header = header;
    }

    public int getId() {
        return id;
    }

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

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public boolean isPublish() {
        return publish;
    }

    public void setPublish(boolean publish) {
        this.publish = publish;
    }


}

Je ziet dat er nu een query is bijgemaakt die erg lijkt op een normale database query.

11. De controller maken

Een controller praat weer met een dataService. Dit gebeurt in eerste instantie door de dataService te importeren met de volgende code:

@Inject
DataServices dataService;

Vervolgens kan er met behulp van het object dataServic een methode worden gemaakt. Hieronder geven we de hele class. Let op! Je kunt dit nu niet meer zomaar kopiëren. Je moet dit toepassen op je eigen project.

package controller;

import entities.Content;
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import service.DataServices;

@SessionScoped
@Named
public class ContentController implements Serializable {

@Inject
DataServices dataService;


    public List<Content> getAllContent() {
        List list = dataService.getAllContent();
        return list;
    }

}

De methode getAllContent verwijst dus naar de dataService class. Verder nog wat uitleg over andere zaken die je ziet:

  • @Sessionscoped: dit gaat over hoelang een object mag blijven leven. In dit geval: zolang je de applicatie draait, verdeeld over meerdere pagina's.
  • @Named: moet erboven staan zodat de xhtml-file weet wat de naam van de class is.

12. De web.xml

Pas de web.xml aan zoals hieronder wordt getoond. We gaan dit verder niet uitleggen.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
 
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>
            javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL
        </param-name>
        <param-value>true</param-value>
    </context-param>
</web-app>

13. De xhtml-file maken

In principe heb je nu alles klaar staan om enige content te kunnen tonen op je website. We gaan dit eerst testen met behulp van een data tabel van Primefaces. De file de je nodig hebt ziet er zo uit:

<!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:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      lang="nl"
      xmlns:p="http://primefaces.org/ui"
      >

    <h:head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <title>Mijn website</title>
        <h:outputStylesheet library="css" name="style.css" />
    </h:head>

Je ziet in het element <html> zogenaamde tag-lbraries staan. Deze heb je nodig om elementen in je website te kunnen maken. Ze zijn erg handig. Zie ook de volgende les over Primefaces.

Hierna wordt de body als volgt opgesteld:

<h:body id="home">      
       <p:dataTable var="content" value="#{contentController.allContent}">
            <p:column headerText="Code">
                <h:outputText value="#{content.date}" />
            </p:column>

            <p:column headerText="onderwerp">
                <h:outputText value="#{content.subject}" />
            </p:column>

            <p:column headerText="inhoud">
                <h:outputText value="#{content.content}" />
            </p:column>
        </p:dataTable>
 </h:body>

Dit is een tabel waarin de inhoud van de database wordt getoond. Als eerste worden twee waarden ingesteld:

<p:dataTable var="content" value="#{contentController.allContent}">

Met de value wordt de contentController aangesproken en de daarin aanwezige methode getAllContent. Merk op dat het niet meer nodig is om get te gebruiken. Dat doet de applicatie al voor je. In var wordt de naam van de variabele gegeven en wordt telkens een object content gemaakt. Hiermee kun je alle variabelen opvragen die horen bij die class.

Uiteraard pas je alle namen aan, aan jouw situatie. Dus als je een entity Registration hebt dan wordt het bijvoorbeeld:

<p:dataTable var="registration" value="#{registrationController.allContent}">

14. Primefaces

Primefaces is een open source user interface bibliotheek en kun je voor ons project gebruiken. Het is ontwikkeld door het Turkse bedrijf Primetek.  Met deze link kun je zien wat er allemaal mogelijk is en kun je de diverse onderdelen voor jouw project gebruiken.