[JAVA] Probieren Sie RESTful Web Services mit dem Container-Archetyp von Nablarch aus

What's?

Ich wollte für einen Moment so tun, als wäre ich Nablarch.

Ich möchte ein kleines Thema festlegen und es von Anfang an ausprobieren.

Versuch es

Referenz) Nablarch 5u18 wurde veröffentlicht!

Umgebung

Diese Umgebung ist hier.

$ java --version
openjdk 11.0.9 2020-10-20
OpenJDK Runtime Environment (build 11.0.9+11-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.9+11-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 11.0.9, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-52-generic", arch: "amd64", family: "unix"


$ docker version
Client: Docker Engine - Community
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 17:02:52 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:01:20 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Erstellen Sie ein Projekt

Schauen Sie sich Erste Schritte an.

Getting Started

Wenn Sie eine vollwertige Anwendung erstellen möchten, erstellen Sie sie aus einem leeren Projekt.

Es scheint besser, mit einem leeren Projekt zu beginnen. Machen wir es also zu einem leeren Projekt.

Leeres Projekt

Seit Nablarch 5u18 ist die Unterstützung für Container enthalten. Verwenden Sie diese Option. Sie können ein Docker-Image mit Jib erstellen.

Docker-Containerisierung

Einrichtungsverfahren.

Ersteinrichtung des RESTful-Webdienstprojekts für Container

Ich habe eine Batch-Datei für Windows, aber da diese Umgebung Linux ist, führe ich das Maven-Archetype-Plugin: 2.4: generate direkt aus.

$ mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate \
  -DinteractiveMode=false \
  -DarchetypeGroupId=com.nablarch.archetype \
  -DarchetypeArtifactId=nablarch-container-jaxrs-archetype \
  -DarchetypeVersion=5u18 \
  -DgroupId=com.example \
  -DartifactId=hello-nablarch-restful \
  -Dversion=0.0.1 \
  -Dpackage=com.example

Es ist fertig.

[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: nablarch-container-jaxrs-archetype:5u18
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: hello-nablarch-restful
[INFO] Parameter: version, Value: 0.0.1
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: packageInPathFormat, Value: com/example
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: hello-nablarch-restful
[INFO] Parameter: version, Value: 0.0.1
[INFO] project created from Archetype in dir: /path/to/hello-nablarch-restful
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.583 s
[INFO] Finished at: 2020-11-11T11:10:34+09:00
[INFO] ------------------------------------------------------------------------

In das Projekt eingezogen.

$ cd hello-nablarch-restful

Werfen wir einen kurzen Blick auf die Datei.

$ find -type f
./README.md
./pom.xml
./.gitignore
./h2/bin/h2-1.3.176.jar
./h2/bin/h2w.bat
./h2/bin/h2.sh
./h2/bin/h2.bat
./h2/db/SAMPLE.h2.db
./h2/db/SAMPLE.h2.db.org
./db/ddl/db2/create.sql
./db/ddl/db2/drop.sql
./db/ddl/sqlserver/create.sql
./db/ddl/sqlserver/drop.sql
./db/ddl/oracle/create.sql
./db/ddl/oracle/drop.sql
./db/ddl/postgresql/create.sql
./db/ddl/postgresql/drop.sql
./db/ddl/h2/create.sql
./db/ddl/h2/drop.sql
./db/data/db2/data.sql
./db/data/sqlserver/data.sql
./db/data/oracle/data.sql
./db/data/postgresql/data.sql
./db/data/h2/data.sql
./src/main/webapp/WEB-INF/web.xml
./src/main/resources/entity/data-model_sqlserver.edm
./src/main/resources/entity/data-model.edm
./src/main/resources/entity/data-model_postgresql.edm
./src/main/resources/entity/data-model_db2.edm
./src/main/resources/entity/data-model_oracle.edm
./src/main/resources/rest-boot.xml
./src/main/resources/env.config
./src/main/resources/META-INF/services/nablarch.core.repository.di.config.externalize.ExternalizedComponentDefinitionLoader
./src/main/resources/rest-component-configuration.xml
./src/main/resources/messages.properties
./src/main/resources/data-source.xml
./src/main/resources/log.properties
./src/main/resources/app-log.properties
./src/main/resources/common.config
./src/main/jib/usr/local/tomcat/conf/server.xml
./src/main/jib/usr/local/tomcat/conf/logging.properties
./src/main/java/com/example/entity/package-info.java
./src/main/java/com/example/entity/SampleUser.java
./src/main/java/com/example/package-info.java
./src/main/java/com/example/domain/package-info.java
./src/main/java/com/example/domain/SampleDomainBean.java
./src/main/java/com/example/domain/SampleDomainManager.java
./src/main/java/com/example/SampleAction.java
./src/main/java/com/example/dto/SampleUserListDto.java
./src/test/resources/log.properties
./src/test/resources/unit-test.xml
./src/test/resources/data/SAMPLE_USER.csv
./src/test/java/com/example/SampleApiTest.java
./src/test/java/com/example/SampleActionTest.java

Die Konfiguration wird hier erklärt.

Konfiguration des Maven-Archetyps (https://nablarch.github.io/docs/5u18/doc/application_framework/application_framework/blank_project/MavenModuleStructures/index.html)

Werfen wir einen Blick auf das Profil.

$ mvn help:all-profiles
[INFO] Scanning for projects...
[WARNING] The POM for org.eclipse.m2e:lifecycle-mapping:jar:1.0.0 is missing, no dependency information available
[WARNING] Failed to retrieve plugin descriptor for org.eclipse.m2e:lifecycle-mapping:1.0.0: Plugin org.eclipse.m2e:lifecycle-mapping:1.0.0 or one of its dependencies could not be resolved: Failure to find org.eclipse.m2e:lifecycle-mapping:jar:1.0.0 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced
[INFO] 
[INFO] -----------------< com.example:hello-nablarch-restful >-----------------
[INFO] Building hello-nablarch-restful 0.0.1
[INFO] --------------------------------[ war ]---------------------------------
[WARNING] The POM for org.eclipse.m2e:lifecycle-mapping:jar:1.0.0 is missing, no dependency information available
[WARNING] Failed to retrieve plugin descriptor for org.eclipse.m2e:lifecycle-mapping:1.0.0: Plugin org.eclipse.m2e:lifecycle-mapping:1.0.0 or one of its dependencies could not be resolved: Failure to find org.eclipse.m2e:lifecycle-mapping:jar:1.0.0 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced
[INFO] 
[INFO] --- maven-help-plugin:3.2.0:all-profiles (default-cli) @ hello-nablarch-restful ---
[INFO] Listing Profiles for Project: com.example:hello-nablarch-restful:war:0.0.1
  Profile Id: BACKUP (Active: false , Source: pom)
  Profile Id: gsp (Active: false , Source: pom)
  Profile Id: ossrh (Active: false , Source: pom)

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.106 s
[INFO] Finished at: 2020-11-11T11:06:10+09:00
[INFO] ------------------------------------------------------------------------

Archetypen für Container scheinen nicht das Konzept von Profilen für die Umwelt zu haben.

Einstellungen für die Containerproduktionsumgebung

Es scheint, dass der in "env.config" geschriebene Wert so eingestellt ist, dass er von der Umgebungsvariablen überschrieben wird.

Beim Erstellen eines Projekts sieht es so aus.

$ grep -vE '^$|^#' src/main/resources/env.config 
nablarch.db.jdbcDriver=org.h2.Driver
nablarch.db.url=jdbc:h2:./h2/db/SAMPLE
nablarch.db.user=SAMPLE
nablarch.db.password=SAMPLE
nablarch.db.schema=PUBLIC
nablarch.db.maxPoolSize=5
nablarch.db.minimumIdle=5
nablarch.db.connectionTimeout=30000
nablarch.db.idleTimeout=600000
nablarch.db.maxLifetime=1800000
nablarch.db.validationTimeout=5000
nablarch.codeCache.loadOnStartUp=false

Es scheint auch eine Beispiel-Action-Klasse zu geben

src/main/java/com/example/SampleAction.java

package com.example;

import com.example.dto.SampleUserListDto;
import com.example.entity.SampleUser;
import nablarch.common.dao.EntityList;
import nablarch.common.dao.UniversalDao;
import nablarch.fw.web.HttpRequest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 *Aktionsklasse zur Bestätigung der Kommunikation.
 *
 * @veraltet TODO Dies ist eine Klasse zum Überprüfen der Kommunikation. Bitte löschen Sie es nach Abschluss der Bestätigung.
 */
@Path("/find")
public class SampleAction {

    /**
     *Suchvorgang.
     * <p>
     *Verwenden Sie JSON für die Antwort.
     * </p>
     *
     * @param req HTTP-Anfrage
     * @Benutzerinformationen zurückgeben(JSON)
     */
    @GET
    @Path("/json")
    @Produces(MediaType.APPLICATION_JSON)
    public EntityList<SampleUser> findProducesJson(HttpRequest req) {
        return UniversalDao.findAll(SampleUser.class);
    }

    /**
     *Suchvorgang.
     * <p>
     *Verwenden Sie XML für die Antwort.
     * </p>
     *
     * @param req HTTP-Anfrage
     * @Benutzerinformationen zurückgeben(XML)
     */
    @GET
    @Path("/xml")
    @Produces(MediaType.APPLICATION_XML)
    public SampleUserListDto findProducesXml(HttpRequest req) {
        EntityList<SampleUser> sampleUserList = UniversalDao.findAll(SampleUser.class);
        return new SampleUserListDto(sampleUserList);
    }

}

Befolgen wir vorerst die Methode zur Bestätigung der Kommunikation.

Kommunikationsbestätigung

Erstellen Sie zunächst ein Docker-Image.

$ mvn package jib:dockerBuild -DskipTests=true

Ich konnte es schaffen.

$ docker image ls | grep hello
hello-nablarch-restful             0.0.1               a4b772a979de        50 years ago        448MB
hello-nablarch-restful             latest              a4b772a979de        50 years ago        448MB

Das Standard-Basis-Image stammt von Tomcat.

Erstellen eines Container-Images

Ich werde es starten.

$ docker container run -it --rm -p 8080:8080 -v `pwd`/h2:/usr/local/tomcat/h2 hello-nablarch-restful:0.0.1

Bestätigung. Es scheint vorerst in Ordnung zu sein.

$ curl localhost:8080/find/json
[{"userId":1,"kanjiName":"Rakutaro Nabe","kanaName":"Naburakutaro"},{"userId":2,"kanjiName":"Rakujiro Nabe","kanaName":"Naburakujiro"}]

Übrigens, wenn Sie vergessen, Volume in diesem Verfahren anzugeben, verschwindet die Datenbank und Sie schlagen fehl (ich war süchtig danach, sie zu übersehen).

-v `pwd`/h2:/usr/local/tomcat/h2

Container-Image ausführen

XML-Less DI Configuration

Als nächstes verwenden wir DI leicht. Es scheint, dass DI mit Anmerkungen durchgeführt werden kann, also werde ich dies verwenden.

Erstellen eines Objekts einer mit Anmerkungen versehenen Klasse

Es scheint eine Unterklasse der Klasse "AnnotationComponentDefinitionLoader" zu erstellen.

Was ist der Ort, um es auszudrücken? Ich dachte, beziehen Sie sich also auf das Folgende.

Serviceentwicklungsreferenz für die SPA + REST-API-Konfiguration

https://github.com/Fintan-contents/example-chat/blob/master/backend/src/main/java/com/example/system/nablarch/di/ExampleChatComponentDefinitionLoader.java

Infolgedessen habe ich es einfach gehalten.

src/main/java/com/example/system/HelloRestComponentDefinitionLoader.java

package com.example.system;

import nablarch.core.repository.di.config.externalize.AnnotationComponentDefinitionLoader;

public class HelloRestComponentDefinitionLoader extends AnnotationComponentDefinitionLoader {
    @Override
    protected String getBasePackage() {
        return "com.example";
    }
}

Die Methode "getBasePackage" gibt das zu scannende Paket zurück.

Ich baue dies in das ServiceLoader-Gimmick ein, aber es scheint, dass die Zieldatei bereits vorhanden ist.

src/main/resources/META-INF/services/nablarch.core.repository.di.config.externalize.ExternalizedComponentDefinitionLoader

nablarch.core.repository.di.config.externalize.OsEnvironmentVariableExternalizedLoader
nablarch.core.repository.di.config.externalize.SystemPropertyExternalizedLoader

Hier hinzugefügt.

nablarch.core.repository.di.config.externalize.OsEnvironmentVariableExternalizedLoader
nablarch.core.repository.di.config.externalize.SystemPropertyExternalizedLoader
com.example.system.HelloRestComponentDefinitionLoader

Erstellen Sie eine Klasse, die im Beispiel enthalten war, und übertragen Sie den Datenerfassungsprozess. Fügen Sie die Annotation @ SystemRepositoryComponent hinzu.

src/main/java/com/example/service/UserService.java

package com.example.service;

import com.example.entity.SampleUser;
import nablarch.common.dao.EntityList;
import nablarch.common.dao.UniversalDao;
import nablarch.core.repository.di.config.externalize.annotation.SystemRepositoryComponent;

@SystemRepositoryComponent
public class UserService {
    public EntityList<SampleUser> findUsers() {
        return UniversalDao.findAll(SampleUser.class);
    }
}

Erstellen Sie also eine Aktionsklasse, die dies verwendet.

src/main/java/com/example/HelloAction.java

package com.example;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.example.entity.SampleUser;
import com.example.service.UserService;
import nablarch.common.dao.EntityList;
import nablarch.core.repository.di.config.externalize.annotation.SystemRepositoryComponent;

@SystemRepositoryComponent
@Path("/hello")
public class HelloAction {
    UserService userService;

    public HelloAction(UserService userService) {
        this.userService = userService;
    }

    @GET
    @Path("/json")
    @Produces(MediaType.APPLICATION_JSON)
    public EntityList<SampleUser> users() {
        return userService.findUsers();
    }
}

Lassen Sie uns im Konstruktor die Komponente empfangen.

    public HelloAction(UserService userService) {
        this.userService = userService;
    }

Es scheint, dass zusätzliche Einstellungen erforderlich sind, um die Action-Klasse in einem DI-Container zu verwalten.

Aktionsklasse mit DI-Container verwalten

Dies ist ein Auszug.

src/main/resources/rest-component-configuration.xml

  <!--Einstellungen für die Paketzuordnung-->
  <component name="packageMapping" class="nablarch.integration.router.PathOptionsProviderRoutesMapping">
    <property name="pathOptionsProvider">
      <component class="nablarch.integration.router.jaxrs.JaxRsPathOptionsProvider">
        <property name="applicationPath" value="${nablarch.webApi.applicationPath}"/>
        <property name="basePackage" value="${nablarch.commonProperty.basePackage}"/>
      </component>
    </property>
    <property name="methodBinderFactory">
      <component class="nablarch.fw.jaxrs.JaxRsMethodBinderFactory">
        <property name="handlerList">
          <component class="nablarch.integration.jaxrs.jersey.JerseyJaxRsHandlerListFactory"/>
        </property>
      </component>
    </property>
  </component>

Fügen Sie "SystemRepositoryDelegateFactory" als "delegateFactory" hinzu.

  <!--Einstellungen für die Paketzuordnung-->
  <component name="packageMapping" class="nablarch.integration.router.PathOptionsProviderRoutesMapping">
    <property name="pathOptionsProvider">
      <component class="nablarch.integration.router.jaxrs.JaxRsPathOptionsProvider">
        <property name="applicationPath" value="${nablarch.webApi.applicationPath}"/>
        <property name="basePackage" value="${nablarch.commonProperty.basePackage}"/>
      </component>
    </property>
    <property name="methodBinderFactory">
      <component class="nablarch.fw.jaxrs.JaxRsMethodBinderFactory">
        <property name="handlerList">
          <component class="nablarch.integration.jaxrs.jersey.JerseyJaxRsHandlerListFactory"/>
        </property>
      </component>
    </property>
    <property name="delegateFactory">
        <component class="nablarch.fw.handler.SystemRepositoryDelegateFactory"/>
    </property>
  </component>

Erstellen Sie anschließend das Docker-Image erneut und starten Sie es.

$ mvn package jib:dockerBuild -DskipTests=true
$ docker container run -it --rm -p 8080:8080 -v `pwd`/h2:/usr/local/tomcat/h2 hello-nablarch-restful:0.0.1 

Bestätigung.

$ curl localhost:8080/hello/json
[{"userId":1,"kanjiName":"Rakutaro Nabe","kanaName":"Naburakutaro"},{"userId":2,"kanjiName":"Rakujiro Nabe","kanaName":"Naburakujiro"}]

Es ist in Ordnung.

Ändern Sie die Datenbank in PostgreSQL

Lassen Sie uns abschließend die verwendete Datenbank von H2 auf PostgreSQL ändern.

Verfahren zum Ändern des zu verwendenden RDBMS

In RDBMS wurden der für die Verbindung zu verwendende Benutzer und das Schema bereits erstellt.

Weil es das bedeutet.

PostgreSQL entscheidet sich für das Docker-Image.

postgres

Selbst wenn es 12,2 oder höher ist, wird es in Ordnung sein ...

Betriebsumgebung

In Bezug auf die Struktur des Projekts scheint die SQL-Datei enthalten zu sein

Konfiguration des Maven-Archetyps (https://nablarch.github.io/docs/5u18/doc/application_framework/application_framework/blank_project/MavenModuleStructures/index.html)

In UTF-8 konvertieren (geschrieben in Shift_JIS ...).

$ iconv -f sjis -t utf-8 db/ddl/postgresql/create.sql -o db/ddl/postgresql/create.sql.utf8
$ iconv -f sjis -t utf-8 db/data/postgresql/data.sql -o db/data/postgresql/data.sql.utf8

Starten Sie PostgreSQL.

$ docker container run -it --rm --name postgres \
  -v `pwd`/db:/data/db \
  -e POSTGRES_USER=postgres_user \
  -e POSTGRES_PASSWORD=postgres_password \
  -e POSTGRES_DB=mydatabase \
  postgres:13.0

Geben Sie den Container ein, um DDL auszuführen und Daten zu registrieren.

$ docker container exec -it postgres bash
$ psql -U postgres_user -f /data/db/ddl/postgresql/create.sql.utf8 mydatabase
$ psql -U postgres_user -f /data/db/data/postgresql/data.sql.utf8 mydatabase

Dieses Mal behandeln wir es wie einen anderen Host, ohne es an den Port auf der Hostseite zu binden. Überprüfen Sie die IP-Adresse des Containers.

$ docker container inspect postgres | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

Ersetzte den JDBC-Treiber von H2 zu PostgreSQL

    <!-- TODO:Ändern Sie den JDBC-Treiber so, dass er mit dem im Projekt verwendeten DB-Produkt übereinstimmt.-->
    <!--
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.3.176</version>
      <scope>runtime</scope>
    </dependency>
    -->
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>42.2.18</version>
      <scope>runtime</scope>
    </dependency>

Feste Verbindungseinstellungen. Sie können es mit einer Umgebungsvariablen überschreiben, diesmal jedoch.

src/main/resources/env.config

$ grep nablarch.db src/main/resources/env.config 
#nablarch.db.jdbcDriver=org.h2.Driver
nablarch.db.jdbcDriver=org.postgresql.Driver

#nablarch.db.url=jdbc:h2:./h2/db/SAMPLE
nablarch.db.url=jdbc:postgresql://172.17.0.2:5432/mydatabase

#nablarch.db.user=SAMPLE
nablarch.db.user=postgres_user

#nablarch.db.password=SAMPLE
nablarch.db.password=postgres_password

#nablarch.db.schema=PUBLIC
nablarch.db.schema=public

Erstellen eines Container-Images.

$ mvn clean
$ mvn package jib:dockerBuild -DskipTests=true

Anlaufen.

$ docker container run -it --rm -p 8080:8080 hello-nablarch-restful:0.0.1

Bestätigung.

$ curl localhost:8080/hello/json
][{"userId":1,"kanjiName":"Rakutaro Nabe","kanaName":"Naburakutaro"},{"userId":2,"kanjiName":"Rakujiro Nabe","kanaName":"Naburakujiro"}]

Ich konnte es schaffen.

Recommended Posts

Probieren Sie RESTful Web Services mit dem Container-Archetyp von Nablarch aus
Versuchen Sie es mit der Ressourcenanweisung in der Web-App
Versuchen Sie, einen anderen Servlet-Container-Steg mit Docker zu verwenden
Versuchen Sie es mit einem DI-Container mit Laravel und Spring Boot