{"id":17738,"date":"2021-11-12T17:36:53","date_gmt":"2021-11-12T16:36:53","guid":{"rendered":"http:\/\/blog.wenzlaff.de\/?p=17738"},"modified":"2023-08-20T14:55:19","modified_gmt":"2023-08-20T12:55:19","slug":"twrestmindmap-mit-react-patternfly-resteasy-swagger-ui-quarkus-panache-orm-jpa-hibernate-docker-und-postgresql","status":"publish","type":"post","link":"http:\/\/blog.wenzlaff.de\/?p=17738","title":{"rendered":"TWRestMindmap mit React, Patternfly, RESTEasy, Swagger-UI, Quarkus, Panache, ORM, JPA, Hibernate, Docker und PostgreSQL"},"content":{"rendered":"<p>TWRestMindmap mit React, Patternfly, RESTEasy, Swagger-UI, Quarkus, Panache, ORM, JPA, Hibernate, Docker und PostgreSQL DB verwenden. Um nicht JUnit 5 zu vergessen.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-scaled.jpg\" alt=\"\" width=\"2560\" height=\"1919\" class=\"aligncenter size-full wp-image-17739\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-scaled.jpg 2560w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-300x225.jpg 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-1024x768.jpg 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-768x576.jpg 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-1536x1151.jpg 1536w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/Twrestmindmap-2048x1535.jpg 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>Wir bauen nun mit Quarkus eine React Anwendung die Titel und das Datum von Mindmaps anzeigt und per REST bedient werden kann. Die GUI im Browser sieht dann so aus: <!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/twrestmindmap.png\" alt=\"\" width=\"1764\" height=\"908\" class=\"aligncenter size-full wp-image-17745\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/twrestmindmap.png 1764w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/twrestmindmap-300x154.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/twrestmindmap-1024x527.png 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/twrestmindmap-768x395.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/twrestmindmap-1536x791.png 1536w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>Aufteilung in einem Projekt nach Frontend und Backend. Das Backend l\u00e4uft ua. in einem Docker mit einer PostreSQL Datenbank. Das Backend wird mit Maven und Java zusammengebaut und das Frontend verwendet NPM und Node.js bzw. JavaScript.<\/p>\n<p>Das ganze Projekt kann von <a href=\"https:\/\/gitlab.com\/IT-Berater\/twrestmindmap\" rel=\"noopener\" target=\"_blank\">GitLab<\/a> heruntergeladen werden. Hier beschreibe ich einige wichtige Dinge zu den verwendeten Technologien angefangen beim Backend bis zum Frontend. <\/p>\n\n<h1>Automatischer JUnit-Test<\/h1>\n<p>Fangen wir an mit <strong>JUnit<\/strong> Test, also TDD. Das geht mit Quarkus ganz gut, es werden automatisch beim speichern alle JUnit-Tests ausgef\u00fchrt und im Browser das Ergebnis mit Log anzgezeigt. Das alles l\u00e4uft, wenn das Projekt im <strong>mvn quakus:dev<\/strong> Modus l\u00e4uft, hier z.B. die Ansicht der GUI, die im Browser \u00fcber diese URL aufgerufen werden kann: <\/p>\n<p><a href=\"http:\/\/localhost:8080\/q\/dev\/io.quarkus.quarkus-vertx-http\/tests\" rel=\"noopener\" target=\"_blank\">http:\/\/localhost:8080\/q\/dev\/io.quarkus.quarkus-vertx-http\/tests<\/a><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test.png\" alt=\"\" width=\"3540\" height=\"1294\" class=\"aligncenter size-full wp-image-17750\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test.png 3540w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test-300x110.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test-1024x374.png 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test-768x281.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test-1536x561.png 1536w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/tdd-quarkus-test-2048x749.png 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>Folgende Eintr\u00e4ge sind in der pom.xml f\u00fcr das Testen mind. n\u00f6tig:<\/p>\n<pre class=\"minimize:true lang:xhtml decode:true \" > &lt;dependency&gt;\r\n      &lt;groupId&gt;io.quarkus&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;quarkus-junit5&lt;\/artifactId&gt;\r\n      &lt;scope&gt;test&lt;\/scope&gt;\r\n    &lt;\/dependency&gt;\r\n    &lt;dependency&gt;\r\n      &lt;groupId&gt;io.rest-assured&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;rest-assured&lt;\/artifactId&gt;\r\n      &lt;scope&gt;test&lt;\/scope&gt;\r\n    &lt;\/dependency&gt;<\/pre>\n<p>Ok, alles GR\u00dcN. <\/p>\n<h1>Datenbank in Docker Container<\/h1>\n<p>Dann ein paar Worte zur verwendeten Datenbank. In diesem Beispiel verwenden wir in einem Docker Container eine PostgreSQL DB. Wir brauchen dazu nur diese beiden Eintr\u00e4ge in der <strong>\/src\/main\/resources\/application.properties<\/strong> Datei:<\/p>\n<pre class=\"lang:default decode:true \" >quarkus.datasource.db-kind=postgresql\r\nquarkus.hibernate-orm.database.generation=drop-and-create<\/pre>\n<p>In einer  <strong>\/src\/main\/resources\/import.sql<\/strong> Datei, wird die Erstladung der DB eingetragen, wir nehmen mal vier Mindmaps:<\/p>\n<pre class=\"lang:default decode:true \" >INSERT INTO mindmap(id, name, erstellung) VALUES (nextval('hibernate_sequence'), 'Reverse Proxy',                          '2021-11-08T20:48:09.999796');\r\nINSERT INTO mindmap(id, name, erstellung) VALUES (nextval('hibernate_sequence'), '2. Mindmap',                             '2021-10-08T20:48:09.999796');\r\nINSERT INTO mindmap(id, name, erstellung) VALUES (nextval('hibernate_sequence'), '6 Best Point to Protecting your Crypto', '2021-01-08T20:48:09.999796');\r\nINSERT INTO mindmap(id, name, erstellung) VALUES (nextval('hibernate_sequence'), 'Letzte 4. Mindmap Beschreibung Titel',   '2020-08-08T<\/pre>\n<p>Und da wir auch Hibernate mit Panache verwenden brauchen wir f\u00fcr jedes BE eine <strong>@Entity<\/strong> Annotation und die Klasse muss von <strong>PanacheEntity<\/strong> erben. Die Mindmap.java Klasse:<\/p>\n<pre class=\"minimize:true lang:java decode:true \" >package de.wenzlaff.mindmap.be;\r\n\r\nimport java.time.LocalDateTime;\r\n\r\nimport javax.persistence.Cacheable;\r\nimport javax.persistence.Column;\r\nimport javax.persistence.Entity;\r\n\r\nimport io.quarkus.hibernate.reactive.panache.PanacheEntity;\r\n\r\n\/**\r\n * BE einer Mindmap\r\n * \r\n * @author Thomas Wenzlaff\r\n *\/\r\n@Entity\r\n@Cacheable\r\npublic class Mindmap extends PanacheEntity {\r\n\r\n\t@Column(length = 120, unique = true)\r\n\tpublic String name;\r\n\r\n\t\/**\r\n\t * Zeitpunkt der Erstellung der Mindmap.\r\n\t *\/\r\n\t@Column()\r\n\tpublic LocalDateTime erstellung;\r\n}<\/pre>\n<p>In der pom.xml muss noch<\/p>\n<pre class=\"minimize:true lang:xhtml decode:true \" > &lt;dependency&gt;\r\n      &lt;groupId&gt;io.quarkus&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;quarkus-hibernate-reactive-panache&lt;\/artifactId&gt;\r\n    &lt;\/dependency&gt;<\/pre>\n<p>erg\u00e4nzt werden. Das ist schon alles, um eine DB in einem Docker-Container laufen zu lassen.<\/p>\n<h1>REST und Swagger<\/h1>\n<p>Da wir auch einen REST-Service anbieten wollen, auf den das Frontend zugreifft, erstellen wir eine <strong>MindmapResource.java<\/strong> Klasse mit <strong>@Path(&#8222;\/mindmaps&#8220;)<\/strong> und<br \/>\n<strong>@ApplicationScoped<\/strong> Annotationen:<\/p>\n<pre class=\"minimize:true lang:java decode:true \" >package de.wenzlaff.mindmap;\r\n\r\nimport java.net.URI;\r\nimport java.time.LocalDateTime;\r\nimport java.util.List;\r\n\r\nimport javax.enterprise.context.ApplicationScoped;\r\nimport javax.ws.rs.GET;\r\nimport javax.ws.rs.POST;\r\nimport javax.ws.rs.Path;\r\nimport javax.ws.rs.core.Response;\r\n\r\nimport org.jboss.logging.Logger;\r\n\r\nimport de.wenzlaff.mindmap.be.Mindmap;\r\nimport io.quarkus.hibernate.reactive.panache.Panache;\r\nimport io.quarkus.panache.common.Sort;\r\nimport io.smallrye.mutiny.Uni;\r\n\r\n\/**\r\n * http:\/\/localhost:8080\/q\/swagger-ui\/\r\n * \r\n * @author Thomas Wenzlaff\r\n *\/\r\n@Path(\"\/mindmaps\")\r\n@ApplicationScoped\r\npublic class MindmapResource {\r\n\r\n\tprivate static final Logger LOG = Logger.getLogger(MindmapResource.class);\r\n\r\n\t@GET\r\n\tpublic Uni&lt;List&lt;Mindmap&gt;&gt; get() {\r\n\t\treturn Mindmap.listAll(Sort.by(\"name\"));\r\n\t}\r\n\r\n\t\/**\r\n\t * Liefert die Anzahl der Mindmaps.\r\n\t * \r\n\t * @return Anzahl der Mindmaps.\r\n\t *\/\r\n\t@Path(\"\/anzahl\")\r\n\t@GET\r\n\tpublic Uni&lt;Long&gt; count() {\r\n\t\treturn Mindmap.count();\r\n\t}\r\n\r\n\t@GET\r\n\t@Path(\"\/{id}\")\r\n\tpublic Uni&lt;Mindmap&gt; getSingle(Long id) {\r\n\t\treturn Mindmap.findById(id);\r\n\t}\r\n\r\n\t@POST\r\n\tpublic Uni&lt;Response&gt; create(Mindmap mindmap) {\r\n\t\tLOG.info(\"Erzeuge Mindmap\");\r\n\t\tmindmap.erstellung = LocalDateTime.now();\r\n\t\treturn Panache.&lt;Mindmap&gt;withTransaction(mindmap::persist).onItem().transform(inserted -&gt; Response.created(URI.create(\"\/mindmaps\/\" + inserted.id)).build());\r\n\t}\r\n}<\/pre>\n<p>Der REST-Service ist dann \u00fcber eine <strong>Swagger-UI<\/strong> mit dieser URL <a href=\"http:\/\/localhost:8080\/q\/swagger-ui\/\" rel=\"noopener\" target=\"_blank\">http:\/\/localhost:8080\/q\/swagger-ui\/<\/a> aufrufbar:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10.png\" alt=\"\" width=\"3022\" height=\"1466\" class=\"aligncenter size-full wp-image-17759\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10.png 3022w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10-300x146.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10-1024x497.png 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10-768x373.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10-1536x745.png 1536w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.46.10-2048x994.png 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>Und hier mal ein Service ausgef\u00fchrt, es werden die vier Mindmaps sortiert nach Namen mit <strong>Mindmap.listAll(Sort.by(&#8222;name&#8220;))<\/strong>; als Json geliefert:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03.png\" alt=\"\" width=\"2638\" height=\"2426\" class=\"aligncenter size-full wp-image-17760\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03.png 2638w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03-300x276.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03-1024x942.png 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03-768x706.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03-1536x1413.png 1536w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-16.47.03-2048x1883.png 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>Auch gibt es einige Infos \u00fcber RESTEasy \u00fcber die URL <a href=\"http:\/\/localhost:8080\/q\/dev\/io.quarkus.quarkus-resteasy-reactive\/scores\" rel=\"noopener\" target=\"_blank\">http:\/\/localhost:8080\/q\/dev\/io.quarkus.quarkus-resteasy-reactive\/scores<\/a> z.B.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy.png\" alt=\"\" width=\"2326\" height=\"1498\" class=\"aligncenter size-full wp-image-17766\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy.png 2326w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy-300x193.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy-1024x659.png 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy-768x495.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy-1536x989.png 1536w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/resteasy-2048x1319.png 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h1>OpenApi<\/h1>\n<p>Die OpenApi kann auch \u00fcber die Swagger-UI abgefragt werden:<\/p>\n<pre class=\"minimize:true lang:default decode:true \" >---\r\nopenapi: 3.0.3\r\ninfo:\r\n  title: de.wenzlaff.twrestmindmap API\r\n  version: 1.0.0-SNAPSHOT\r\npaths:\r\n  \/info:\r\n    get:\r\n      tags:\r\n      - Version Resource\r\n      responses:\r\n        \"200\":\r\n          description: OK\r\n          content:\r\n            text\/plain:\r\n              schema:\r\n                type: string\r\n  \/mindmaps:\r\n    get:\r\n      tags:\r\n      - Mindmap Resource\r\n      responses:\r\n        \"200\":\r\n          description: OK\r\n          content:\r\n            application\/json:\r\n              schema:\r\n                type: array\r\n                items:\r\n                  $ref: '#\/components\/schemas\/Mindmap'\r\n    post:\r\n      tags:\r\n      - Mindmap Resource\r\n      requestBody:\r\n        content:\r\n          application\/json:\r\n            schema:\r\n              $ref: '#\/components\/schemas\/Mindmap'\r\n      responses:\r\n        \"200\":\r\n          description: OK\r\n          content:\r\n            application\/json: {}\r\n  \/mindmaps\/anzahl:\r\n    get:\r\n      tags:\r\n      - Mindmap Resource\r\n      responses:\r\n        \"200\":\r\n          description: OK\r\n          content:\r\n            application\/json:\r\n              schema:\r\n                format: int64\r\n                type: integer\r\n  \/mindmaps\/{id}:\r\n    get:\r\n      tags:\r\n      - Mindmap Resource\r\n      parameters:\r\n      - name: id\r\n        in: path\r\n        required: true\r\n        schema:\r\n          format: int64\r\n          type: integer\r\n      responses:\r\n        \"200\":\r\n          description: OK\r\n          content:\r\n            application\/json:\r\n              schema:\r\n                $ref: '#\/components\/schemas\/Mindmap'\r\ncomponents:\r\n  schemas:\r\n    Mindmap:\r\n      type: object\r\n      properties:\r\n        id:\r\n          format: int64\r\n          type: integer\r\n        name:\r\n          type: string\r\n        erstellung:\r\n          format: date-time\r\n          type: string\r\n<\/pre>\n<h1>Start Backend<\/h1>\n<p>Nachdem der Docker Desktop gestartet wurde kann die <strong>pom.xml<\/strong> aus dem TWRestMindmap Verzeichnis mit <strong>mvn quarkus:dev<\/strong> gestartet werden. Dann kann das Backend schon \u00fcber die Swagger-Ui oder auch \u00fcber ein einfaches curl abgefragt werden. Z.B.  <strong>curl &#8218;http:\/\/localhost:8080\/mindmaps&#8216; | jq<\/strong> liefert:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.05.57.png\" alt=\"\" width=\"1788\" height=\"1308\" class=\"aligncenter size-full wp-image-17764\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.05.57.png 1788w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.05.57-300x219.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.05.57-1024x749.png 1024w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.05.57-768x562.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.05.57-1536x1124.png 1536w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>Oder auch nur den Namen der 1.Mindmap mit<br \/>\n<strong>curl &#8218;http:\/\/localhost:8080\/mindmaps&#8216; | jq &#8218;.[1].name<\/strong><\/p>\n<h1>Struktur Frontend und Backend<\/h1>\n<p>Das Frontend ist in dem Verzeichnis <strong>src\/main\/webapp<\/strong> in dem TWRestMindmap Projekt zu finden:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.18.40-319x1024.png\" alt=\"\" width=\"319\" height=\"1024\" class=\"aligncenter size-large wp-image-17770\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.18.40-319x1024.png 319w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.18.40-93x300.png 93w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.18.40-478x1536.png 478w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/11\/wenzlaff.de-2021-11-12-um-17.18.40.png 630w\" sizes=\"auto, (max-width: 319px) 100vw, 319px\" \/><\/p>\n<h1>React Frontend<\/h1>\n<p>Die <a href=\"https:\/\/react.dev\/\" rel=\"noopener\" target=\"_blank\">React<\/a> Componente ist in der <strong>mindmaps.js<\/strong> Datei zu finden:<\/p>\n<pre class=\"minimize:true lang:js decode:true \" >import React from 'react'\r\n\r\nconst Mindmaps = ({ mindmaps }) =&gt; {\r\n\treturn (\r\n\t\t&lt;div&gt;\r\n\t\t\t&lt;center&gt;&lt;h1&gt;Mindmaps&lt;\/h1&gt;&lt;\/center&gt;\r\n\t\t\t&lt;table class=\"pf-c-table pf-m-grid-md\" role=\"grid\" id=\"table-basic\"&gt;\r\n\t\t\t\t&lt;caption&gt;{mindmaps.length} von kleinhirn.eu&lt;\/caption&gt;\r\n\t\t\t\t&lt;thead&gt;\r\n\t\t\t\t\t&lt;tr role=\"row\"&gt;\r\n\t\t\t\t\t\t&lt;th role=\"columnheader\" scope=\"col\"&gt;Erstellung&lt;\/th&gt;\r\n\t\t\t\t\t\t&lt;th role=\"columnheader\" scope=\"col\"&gt;Titel&lt;\/th&gt;\r\n\t\t\t\t\t&lt;\/tr&gt;\r\n\t\t\t\t&lt;\/thead&gt;\r\n\t\t\t\t{mindmaps.map((mindmap) =&gt; (\r\n\t\t\t\t\t&lt;tbody role=\"rowgroup\"&gt;\r\n\t\t\t\t\t\t&lt;tr role=\"row\"&gt;\r\n\t\t\t\t\t\t\t&lt;td role=\"cell\" data-label=\"\"&gt;{mindmap.erstellung}&lt;\/td&gt;\r\n\t\t\t\t\t\t\t&lt;td role=\"cell\" data-label=\"\"&gt;{mindmap.name}&lt;\/td&gt;\r\n\t\t\t\t\t\t&lt;\/tr&gt;\r\n\t\t\t\t\t&lt;\/tbody&gt;\r\n\t\t\t\t))}\r\n\t\t\t&lt;\/table&gt;\r\n\t\t&lt;\/div&gt;\r\n\t)\r\n};\r\n\r\nexport default Mindmaps<\/pre>\n<p> und die ganze Application in der <strong>App.js<\/strong> Datei:<\/p>\n<pre class=\"minimize:true lang:js decode:true \" >\r\n\r\nimport React, {Component} from 'react';\r\nimport Mindmaps from '.\/components\/mindmaps'\r\n\r\nclass App extends Component {\r\n  state = {\r\n    mindmaps: []\r\n  }\r\n\r\n  componentDidMount() {\r\n    fetch('\/mindmaps')\r\n    .then(res =&gt; res.json())\r\n    .then((data) =&gt; {\r\n      this.setState({ mindmaps: data })\r\n    })\r\n    .catch(console.log)\r\n  }\r\n\r\n  render () {\r\n    return (\r\n      &lt;Mindmaps mindmaps={this.state.mindmaps} \/&gt;\r\n    );\r\n  }\r\n}\r\n\r\nexport default App;<\/pre>\n<h1>Starten des React Frontend<\/h1>\n<p>In einer neue Konsole in dem <strong>\/TWRestMindmap\/src\/main\/webapp<\/strong> Verzeichnis die <a href=\"https:\/\/react.dev\/\" rel=\"noopener\" target=\"_blank\">React Gui<\/a> starten mit: <strong>npm start<\/strong> und schon \u00f6ffnet sich im Browser die <a href=\"http:\/\/localhost:3000\/\" rel=\"noopener\" target=\"_blank\">http:\/\/localhost:3000\/<\/a> wo die Gui l\u00e4uft und alle Mindmaps wie ganz oben angezeigt wird.<br \/>\nEvl. ist ein einmaliges installieren der React und Patternfly Abh\u00e4ngigkeiten n\u00f6tig:<\/p>\n<pre class=\"lang:default decode:true \" >\r\n# im \/TWRestMindmap\/src\/main\/webapp einmal die beiden Befehler ausf\u00fchren:\r\nnpx create-react-app . \r\nnpm install @patternfly\/patternfly --save<\/pre>\n<p>Am schnellsten einfach das ganze Projekt mit einem <\/p>\n<p><strong>git clone https:\/\/gitlab.com\/IT-Berater\/twrestmindmap.git <\/strong><\/p>\n<p>holen und die oben genannten Schritte nachverfolgen. Fehlt was? &#8230; Gern Merge Repuest https:\/\/gitlab.com\/IT-Berater\/twrestmindmap\/-\/merge_requests oder EMail &#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TWRestMindmap mit React, Patternfly, RESTEasy, Swagger-UI, Quarkus, Panache, ORM, JPA, Hibernate, Docker und PostgreSQL DB verwenden. Um nicht JUnit 5 zu vergessen. Wir bauen nun mit Quarkus eine React Anwendung die Titel und das Datum von Mindmaps anzeigt und per REST bedient werden kann. Die GUI im Browser sieht dann so aus:<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[220,4,5,3897,3137,3163,79,3769,4960],"tags":[5091,2150,2060,4110,5090,5089,4943,3764,5088,3767,3768,5087],"class_list":["post-17738","post","type-post","status-publish","format-standard","hentry","category-anleitung","category-eclipse","category-java","category-java-programmierung","category-javascript","category-maven","category-programmierung","category-quarkus-framework","category-react","tag-docker-und-postgresql","tag-hibernate","tag-jpa","tag-openapi","tag-orm","tag-panache","tag-patternfly","tag-quarkus","tag-resteasy","tag-swagger","tag-swagger-ui","tag-twrestmindmap-mit-react"],"_links":{"self":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/17738","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=17738"}],"version-history":[{"count":0,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/17738\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=17738"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=17738"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=17738"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}