[JAVA] So erstellen Sie Ihre eigene kopflose API mit Liferays REST Builder (Teil 4)

Einführung

Diese Blog-Serie, die darauf abzielt, mit den REST Builder-Tools von Liferay eine eigene kopflose API zu generieren, ist endlich vorbei!

Erstellen Sie in Teil 1 neue Projekte und Module, ohne Kopf durch eine Beschreibung wiederverwendbarer Komponenten. Wir haben begonnen, die OpenAPI Yaml-Datei zu erstellen, die den Dienst definiert. In Teil 2 finden Sie häufig Probleme beim Hinzufügen von Pfaden und von REST Builder generiertem Code und deren Behebung. Nachdem ich die Problemumgehungen durchlaufen hatte, habe ich die OpenAPI Yaml-Datei fertiggestellt. Überprüfen Sie in Teil 3 den gesamten generierten Code, verstehen Sie den Build und finden Sie den Implementierungscode. Ich habe gelernt, wie man etwas hinzufügt.

In diesem Kapitel, dem letzten in der Reihe, werden wir die für die Werterpersistenz erforderliche "ServiceBuilder" -Schicht (SB) erstellen und den Teilen, die zur Unterstützung der kopflosen API implementiert werden müssen, besondere Aufmerksamkeit widmen.

Erstellen einer Service Builder-Ebene

Verwenden Sie Service Builder für die Persistenzschicht. Ich werde nicht auf alle Details dieses Prozesses eingehen, aber ich werde mich auf das konzentrieren, was ich hinzufügen werde, um den Komfort der kopflosen API zu verbessern.

Der komplexeste Aspekt des Serviceteils ist der Pfad "/ Vitamine", der alle "Vitamine" enthält, die auf den ersten Blick am einfachsten zu spüren sind.

Warum ist es so schwierig? Dies liegt daran, dass wir die folgenden Punkte gemäß dem Liferay-Modell berücksichtigen müssen:

Um all dies zu erreichen, müssen Sie sicherstellen, dass die Entität indiziert ist. Die Bestätigungsmethode finden Sie unter hier.

Der neue Index unterstützt standardmäßig Berechtigungen, daher müssen Sie der Entität Berechtigungen hinzufügen. Referenzartikel: https://portal.liferay.dev/docs/7-2/frameworks/-/knowledge_base/f/defining-application-permissions

Ich habe die Komponente "Vitamin" genannt und mich daher entschieden, Vitamin in Service Builder nicht zu verwenden. Andernfalls müssen Sie das Paket überall einschließen. Ich beschloss, die Entität stattdessen "PersistedVitamin" zu nennen. Auf diese Weise können Sie zwischen der von Headless verwendeten DTO-Klasse und der von Service Builder verwalteten tatsächlich persistierten Entität unterscheiden.

Unterstützung für Listenfilter, Suche und Sortierung

Der Rest dieses Abschnitts beschreibt das Hinzufügen von Unterstützung für das Filtern, Suchen und Sortieren von Listen mithilfe der von Liferay unterstützten Mechanismen. Dieser Abschnitt gilt möglicherweise nicht, wenn Sie das Filtern, Suchen oder Sortieren von Listen nicht unterstützen oder wenn Sie nur Unterstützung für das eine oder andere benötigen und den Liferay-Ansatz nicht verwenden.

Viele der Listenmethoden von Liferay, wie "/ v1.0 / message-board-threads / {messageBoardThreadId} / message-board-messages", verfügen über viele der Listenmethoden von Liferay, um Such-, Filter-, Sortier-, Paging- und Feldeinschränkungen zu unterstützen. Es gibt zusätzliche Attribute, die in der Abfrage bereitgestellt werden können.

Alle Liferay-Dokumentationen zu diesen Details:

Einige Punkte, die im obigen Dokument nicht erwähnt werden, sind Filter, Sortierungen und Suchen, bei denen Sie den Suchindex der Entität verwenden müssen.

Eine Suche wird beispielsweise durchgeführt, indem der Abfrage ein oder mehrere Schlüsselwörter hinzugefügt werden. Diese werden in die Indexabfrage eingegeben, um nach einer Entitätsübereinstimmung zu suchen.

Das Filtern wird auch durch Anpassen von Indexsuchabfragen verwaltet. Um einen Filter auf ein oder mehrere Felder in einer Komponente anzuwenden, müssen sich diese Felder im Suchindex befinden. Darüber hinaus erfordern die in den anderen folgenden Abschnitten beschriebenen Felder "OData Entity Model".

Die Sortierung wird auch durch Anpassen der Indexsuchabfragen verwaltet. Um nach einem oder mehreren Feldern in einer Komponente zu sortieren, müssen sich diese Felder im Suchindex befinden. Darüber hinaus müssen Sie mit der Methode "addKeywordSortable ()" der Schnittstelle "com.liferay.portal.kernel.search.Document" indizieren und der später erwähnten Implementierung "OData EntityModel" sortierbare Felder hinzufügen. müssen es tun.

Vor diesem Hintergrund sollte der Suchdefinition für benutzerdefinierte Entitäten besondere Aufmerksamkeit gewidmet werden:

--Verwenden Sie ModelDocumentContributor, um wichtige Texte und Schlüsselwörter hinzuzufügen, um die richtigen Suchtreffer zu erzielen.

Implementierung der VitaminResourceImpl-Methode

Nachdem Sie die Service Builder-Ebene erstellt und die Abhängigkeit von "Headless-Vitamins-Impl" behoben haben, besteht der nächste Schritt darin, die Methode tatsächlich zu implementieren.

Implementierung von deleteVitamin ()

Beginnen wir mit einer einfachen Methode "deleteVitamin ()". VitaminResourceImpl erweitert die Methode aus der Basisklasse (mit allen Anmerkungen) und ruft die Service-Schicht auf:

@Override
public void deleteVitamin(@NotNull String vitaminId) throws Exception {
  // super easy case, just pass through to the service layer.
  _persistedVitaminService.deletePersistedVitamin(vitaminId);
}

Wir empfehlen, dass Sie nur Remotedienste und keine lokalen Dienste verwenden, um die Persistenz der Entität zu gewährleisten. Warum? Die Überprüfung, ob ein Benutzer die Berechtigung zum Löschen eines "Vitamin" -Datensatzes hat, ist nur Ihre letzte Verteidigungslinie.

Sie können den OAuth2-Bereich verwenden, um Steuerelemente auszuführen und Aktivitäten zu blockieren. Für einen Administrator ist es jedoch schwierig, den OAuth2-Bereich korrekt zu konfigurieren. Selbst wenn ich selbst Administrator bin, kann ich den Bereich jedes Mal korrekt abrufen. Ich glaube nicht

Wenn Sie einen Remotedienst mit Zugriffsberechtigungsprüfung verwenden, müssen Sie sich keine Gedanken über die Konsistenz des Bereichs machen. Selbst wenn der Administrator (I) den OAuth2-Bereich deaktiviert, blockiert der Remotedienst den Vorgang, sofern der Benutzer nicht über die entsprechenden Berechtigungen verfügt.

Umwandlungsprozess

Bevor wir einige der Implementierungsmethoden genauer erläutern, müssen wir die Konvertierung von der Backend-Entität "ServiceBuilder" in die zurückgegebene kopflose Komponente erörtern.

Derzeit hat Liferay keinen Standard für die Verarbeitung von Entitäten-zu-Komponenten-Konvertierungen festgelegt. Das Liferay-Quellmodul "Headless-Delivery-Impl" führt die Konvertierung in eine Richtung durch, während das "Headless-Admin-User-Impl" -Modul die Konvertierung unterschiedlich behandelt.

Der Einfachheit halber ist hier eine Technik, die auf der "Headless-Admin-User-Impl" -Technik basiert. Es kann verschiedene, effektivere Methoden geben, oder Sie bevorzugen die "Headless-Delivery-Impl" -Methode. Liferay bietet möglicherweise auch eine Standardmethode zur Unterstützung von Konvertierungen in der nächsten Version.

Obwohl es besagt, dass es konvertiert werden muss, ist es nicht an eine bestimmte Methode gebunden. Liferay mag besser herauskommen, aber es liegt an Ihnen, sich an die neue Methode anzupassen oder Ihre eigene zu nehmen.

Daher müssen Sie in der Lage sein, von "PersistedVitamin" in eine Vitamin-Komponente umzuwandeln, um diese als Teil einer kopflosen API-Definition zurückzugeben. Erstellen Sie die Methode "_toVitamin ()" in der Klasse "VitaminResourceImpl":

protected Vitamin _toVitamin(PersistedVitamin pv) throws Exception {
  return new Vitamin() {{
    creator = CreatorUtil.toCreator(_portal, _userLocalService.getUser(pv.getUserId()));
    articleId = pv.getArticleId();
    group = pv.getGroupName();
    description = pv.getDescription();
    id = pv.getSurrogateId();
    name = pv.getName();
    type = _toVitaminType(pv.getType());
    attributes = ListUtil.toArray(pv.getAttributes(), VALUE_ACCESSOR);
    chemicalNames = ListUtil.toArray(pv.getChemicalNames(), VALUE_ACCESSOR);
    properties = ListUtil.toArray(pv.getProperties(), VALUE_ACCESSOR);
    risks = ListUtil.toArray(pv.getRisks(), VALUE_ACCESSOR);
    symptoms = ListUtil.toArray(pv.getSymptoms(), VALUE_ACCESSOR);
  }};
}

Zuerst muss ich mich für die Verwendung der Doppelklammer-Instanziierung entschuldigen ... Ich erkenne es auch als Anti-Pattern. Mein Ziel war es jedoch, der "Liferay-Methode" zu folgen, die im "Headless-Admin-User-Impl" -Modul beschrieben ist, das das von Liferay verwendete Muster war. Liferay verwendet das Builder-Muster nicht sehr oft, daher denke ich, dass stattdessen eine doppelte Klammerinstanziierung verwendet wird.

Nach meinem eigenen Geschmack folge ich auch den Mustern Builder und Fluent, um die Erstellung von Objekten zu vereinfachen. Schließlich macht es mir Intellij leicht, eine Builder-Klasse für mich zu erstellen.

Diese Methode wird von der externen Klasse "CreatorUtil" (kopiert aus Liferay-Code), der Methode "_toVitaminType ()", die den internen Ganzzahlcode in einen Aufzählungstyp für Komponenten konvertiert, und der Methode "ListUtil toArray ()" implementiert. Verwenden Sie "VALUE_ACCESSOR", um einige interne Objekte in ein "String" -Array zu verarbeiten.

Kurz gesagt, diese Methode kann die Transformationen verarbeiten, die in der eigentlichen Methodenimplementierung ausgeführt werden müssen.

Implementierung von getVitamin ()

Schauen wir uns eine andere einfache Methode "getVitamin ()" an. Diese Methode gibt eine einzelne Entität mit "vitaminId" zurück.

@Override
public Vitamin getVitamin(@NotNull String vitaminId) throws Exception {
  // fetch the entity class...
  PersistedVitamin pv = _persistedVitaminService.getPersistedVitamin(vitaminId);

  return _toVitamin(pv);
}

Hier erhalten wir die Instanz "PersistedVitamin" von der Serviceschicht, übergeben das erhaltene Objekt jedoch an die Methode "_toVitamin ()", um es zu konvertieren.

Implementierungen von "postVitamin ()", "patchVitamin ()" und "putVitamin ()"

Ich denke, Sie haben es schon satt, die Muster zu sehen, also schauen wir sie uns alle zusammen an.

postVitamin () ist eine POST-Methode für / vitamins und repräsentiert die Schaffung einer neuen Entität.

patchVitamin () ist die PATCH-Methode von / vitamins / {vitaminId}, die das Patchen auf eine vorhandene Entität darstellt (wobei andere vorhandene Eigenschaften übrig bleiben, nur der für das Eingabeobjekt angegebene Wert). Wechseln).

putVitamin () ist die PUT-Methode von / vitamins / {vitaminId}, die das Ersetzen einer vorhandenen Entität darstellt und alle persistenten Werte durch die übergebenen Werte ersetzt, selbst wenn das Feld null oder leer ist.

Da wir die ServiceBuilder-Ebene erstellt und für diese Einstiegspunkte angepasst haben, sieht die Implementierung in der Klasse "VitaminResourceImpl" sehr einfach aus.

@Override
public Vitamin postVitamin(Vitamin v) throws Exception {
  PersistedVitamin pv = _persistedVitaminService.addPersistedVitamin(
      v.getId(), v.getName(), v.getGroup(), v.getDescription(), _toTypeCode(v.getType()), v.getArticleId(), v.getChemicalNames(),
      v.getProperties(), v.getAttributes(), v.getSymptoms(), v.getRisks(), _getServiceContext());

  return _toVitamin(pv);
}

@Override
public Vitamin patchVitamin(@NotNull String vitaminId, Vitamin v) throws Exception {
  PersistedVitamin pv = _persistedVitaminService.patchPersistedVitamin(vitaminId,
      v.getId(), v.getName(), v.getGroup(), v.getDescription(), _toTypeCode(v.getType()), v.getArticleId(), v.getChemicalNames(),
      v.getProperties(), v.getAttributes(), v.getSymptoms(), v.getRisks(), _getServiceContext());

  return _toVitamin(pv);
}

@Override
public Vitamin putVitamin(@NotNull String vitaminId, Vitamin v) throws Exception {
  PersistedVitamin pv = _persistedVitaminService.updatePersistedVitamin(vitaminId,
      v.getId(), v.getName(), v.getGroup(), v.getDescription(), _toTypeCode(v.getType()), v.getArticleId(), v.getChemicalNames(),
      v.getProperties(), v.getAttributes(), v.getSymptoms(), v.getRisks(), _getServiceContext());

  return _toVitamin(pv);
}

Wie Sie sehen können, ist es sehr leicht.

Sie benötigen "ServiceContext", um zur Service-Schicht zu gelangen. Liferay bietet "com.liferay.headless.common.spi.service.context.ServiceContextUtil". Es verfügt nur über die Methoden, die zum Erstellen eines "ServiceContext" erforderlich sind. Dies ist ein Kontextstarter. Fügen Sie einfach zusätzliche Informationen wie die Firmen-ID und die aktuelle Benutzer-ID hinzu. Also habe ich das alles in die Methode "_getServiceContext ()" eingeschlossen. Zukünftige Versionen von REST Builder erhalten neue Kontextvariablen, um das Abrufen eines gültigen "ServiceContext" zu vereinfachen.

Alle meine ServiceBuilder-Methoden übergeben und verwenden erweiterte Parameter, die jeder über ServiceBuilder kennt. Die vom Methodenaufruf zurückgegebene "PersistedValue" -Instanz wird zur Konvertierung an "_toVitamin ()" übergeben und zurückgegeben.

Das Obige ist eine einfache Lösung. Wir müssen auch die Methode "getVitaminsPage ()" erklären, aber vorher müssen wir die "EntityModels" erklären.

EntityModels

Zuvor haben wir darüber gesprochen, wie Liferay Suchindizes verwenden kann, um das Filtern, Suchen und Sortieren von Listen zu unterstützen. Wir haben auch erklärt, dass die Felder, die zum Filtern und Sortieren verwendet werden können, Teil der EntityModel-Definition der Komponente sein müssen. Felder von Komponenten, die nicht Teil von EntityModel sind, können nicht gefiltert oder sortiert werden.

Als zusätzlichen Nebeneffekt macht EntityModel diese Felder aus dem Suchindex zum Filtern und Sortieren verfügbar, sodass Sie diese Felder nicht mit Komponentenfeldern verbinden müssen.

Beispielsweise können Sie in der EntityModel-Definition einen Eintrag für "creatorId" hinzufügen, der die Benutzer-ID des Suchindex filtert. Die Komponentendefinition kann ein "Creator" -Feld anstelle eines "CreatorId" -Felds enthalten. Da die "CreatorId" jedoch Teil des "EntityModel" ist, kann sie sowohl zum Filtern als auch zum Sortieren verwendet werden.

Daher müssen Sie ein EntityModel erstellen, das die Felder definiert, die sowohl das Filtern als auch das Sortieren unterstützen. Verwenden Sie das vorhandene Liferay-Dienstprogramm, um die EntityModel-Klassen zu gruppieren:

public class VitaminEntityModel implements EntityModel {
  public VitaminEntityModel() {
    _entityFieldsMap = Stream.of(
        // chemicalNames is a string array of the chemical names of the vitamins/minerals
        new CollectionEntityField(
            new StringEntityField(
                "chemicalNames", locale -> Field.getSortableFieldName("chemicalNames"))),
        
        // we'll support filtering based upon user creator id.
        new IntegerEntityField("creatorId", locale -> Field.USER_ID),
        
        // sorting/filtering on name is okay too
        new StringEntityField(
            "name", locale -> Field.getSortableFieldName(Field.NAME)),
        
        // as is sorting/filtering on the vitamin group
        new StringEntityField(
            "group", locale -> Field.getSortableFieldName("vitaminGroup")),
        
        // and the type (vitamin, mineral, other).
        new StringEntityField(
            "type", locale -> Field.getSortableFieldName("vType"))
    ).collect(
        Collectors.toMap(EntityField::getName, Function.identity())
    );
  }

  @Override
  public Map<String, EntityField> getEntityFieldsMap() {
    return _entityFieldsMap;
  }

  private final Map<String, EntityField> _entityFieldsMap;
}

Der Feldname stammt von dem Namen, der in der PersistedVitaminModelDocumentContributor-Klasse der Service-Schicht zum Hinzufügen des Feldwerts verwendet wird.

Enthält Definitionen für "chemische Namen", "Field.USER_ID", "Field.NAME", "VitaminGroup" und "vType-Felder" aus dem Suchindex. Von den Definitionen existiert das vom Filter verwendete Feld "creatorId" nicht als Feld in der Definition der Vitaminkomponenten.

Andere Felder, die Teil der Vitaminkomponente sind, müssen den Rest der Sortierung oder Filterung nicht zulassen. Diese Art der Entscheidung wird normalerweise durch Anforderungen bestimmt.

Liferay speichert diese Klassen in einem internen Paket, dem Paket "odata.entity.v1_0". In meinem Fall würde ich also eine Datei mit dem Namen "com.dnebinger.headless.delivery.internal.odata.entity.v1_0" platzieren. Ich warte.

Nachdem die Klasse fertig ist, müssen wir auch die Klasse "VitaminResourceImpl" dekorieren, um sicherzustellen, dass wir das "EntityModel" korrekt bedienen können.

Die erforderlichen Änderungen sind:

Mein VitaminEntityModel ist sehr einfach und nicht sehr dynamisch, daher sieht die Implementierung folgendermaßen aus:

public class VitaminResourceImpl extends BaseVitaminResourceImpl 
    implements EntityModelResource {

  private VitaminEntityModel _vitaminEntityModel = new VitaminEntityModel();

  @Override
  public EntityModel getEntityModel(MultivaluedMap multivaluedMap) throws Exception {
    return _vitaminEntityModel;
  }

Bitte beachten Sie, dass dies keine übliche Implementierung ist. Die Implementierungsklasse für Komponentenressourcen von Liferay weist eine viel komplexere und dynamischere "EntityModel" -Generierung auf, was auf die Komplexität der zugeordneten Entitäten zurückzuführen ist (z. B. "Strukturierter Inhalt" ist "JournalArticle", "DDM-Struktur"). , Eine Sammlung von "Vorlagen").

Kopieren Sie die Methode also nicht einfach und führen Sie sie aus. Es kann in Ihrem Fall funktionieren, aber nicht in anderen Fällen. Weitere Informationen zu komplexeren Szenarien finden Sie in der Liferay-Implementierung der EntityModel-Klasse und in der getEntityModel () -Methode der Komponentenressourcenimplementierung.

Implementierung von getVitaminsPage ()

Dies ist wahrscheinlich die komplizierteste Implementierungsmethode. Es ist an sich nicht schwierig, es hängt von vielen anderen Dingen ab.

Die Liferay-Listenverarbeitungsfunktion stammt hier aus dem Suchindex, nicht aus der Datenbank. Daher muss die Entität indiziert werden.

Dies ist auch eine Methode, die Filter-, Such- und Sortierparameter unterstützt, und die Entität muss indiziert werden. Und wie wir bereits gesehen haben, hängt das Filtern und Sortieren auch von der EntityModel-Klasse ab.

Da wir die Liferay-Methode aufrufen, ist die Implementierung selbst ziemlich undurchsichtig und außer Kontrolle. Das Endergebnis ist:

public Page<Vitamin> getVitaminsPage(String search, Filter filter, Pagination pagination, Sort[] sorts) throws Exception {
  return SearchUtil.search(
    booleanQuery -> {
      // does nothing, we just need the UnsafeConsumer<BooleanQuery, Exception> method
    },
    filter, PersistedVitamin.class, search, pagination,
    queryConfig -> queryConfig.setSelectedFieldNames(
      Field.ENTRY_CLASS_PK),
    searchContext -> searchContext.setCompanyId(contextCompany.getCompanyId()),
    document -> _toVitamin(
      _persistedVitaminService.getPersistedVitamin(
        GetterUtil.getLong(document.get(Field.ENTRY_CLASS_PK)))),
    sorts);
}

Wir verwenden die SearchUtil.search () -Methode, die alle Möglichkeiten kennt.

Das erste Argument ist die Klasse "UnsafeConsumer", die im Wesentlichen für die Feinabstimmung der "booleanQuery" nach Bedarf der Entität verantwortlich ist. Ich brauchte es hier nicht, aber Liferays kopfloses Liefermodul hat ein Beispiel. Die Version von StructuredContent, die nach Artikeln anhand der Site-ID sucht, fügt die Site-ID als Abfrageargument hinzu. Der Parameter "Abflachen" optimiert die Abfrage, um einen bestimmten Filter, einen dieser Typen, zu finden.

Die aus der kopflosen Schicht erhaltenen Filter-, Such- und Pagenierungsargumente werden unverändert übergeben. Die Ergebnisse werden auf die Bourian-Abfrage angewendet, die Ergebnisse werden gefiltert und durchsucht, und die Seitennationen geben die seitenäquivalenten Ergebnisse an.

queryConfig gibt nur den Primärschlüsselwert zurück und fordert keine anderen Felddaten an. Sie benötigen die Entität "ServiceBuilder", da Sie nicht aus dem Suchindex "Dokument" konvertieren.

Das vorletzte Argument ist eine weitere "UnsafeFunction", die die Konvertierung von Dokument zu Komponententyp anwendet. Diese Implementierung ruft eine "PersistedVitamin" -Instanz unter Verwendung des aus dem Dokument extrahierten Primärschlüsselwerts ab und übergibt das "PersistedVitamin" an "_toVitamin ()", um die endgültige Konvertierung durchzuführen.

Verbleibende Arbeit

Sie haben die gesamte Codierung durchgeführt, aber Sie sind noch nicht fertig.

Führen Sie den Befehl buildREST erneut aus. Nachdem wir die Methoden zur VitaminResourceImpl -Methode hinzugefügt haben, möchten wir Testfälle haben, die auf sie angewendet werden können.

Anschließend müssen Sie das Modul erstellen und bereitstellen, um alle offenen Referenzen, Bereitstellungsprobleme usw. zu bereinigen. Stellen Sie die "Vitamine-API" und "Vitamine-Service" auf der ServiceBuilder-Ebene und die "Vitamine-Headless-API" - und "Vitamine-Headless-Impl" -Module auf der Headless-Ebene bereit.

Wenn sie fertig sind, müssen Sie sie in das Modul "Headless-Vitamins-Test" ablegen und alle Testfälle ausführen (wenn Sie fehlen, können Sie sie auch neu erstellen).

Sobald Sie fertig sind, möchten Sie möglicherweise die Headless-API in SwaggerHub veröffentlichen, damit andere sie verwenden können.

Die für REST Builder erstellte Yaml-Datei wird nicht verwendet. Stattdessen in Ihrem Browser [http: // localhost: 8080 / o / kopflose Vitamine / v1.0 / openapi.yaml](http: // localhost: 8080 / o / kopflose Vitamine / v1.0 / openapi.yaml] ) Wird angegeben und die Datei wird zur Übertragung verwendet. Alle erforderlichen Teile werden platziert und zusätzliche Komponenten wie der Typ "PageVitamin" werden hinzugefügt.

Zusammenfassung

Erstellen Sie in Teil 1 einen neuen Arbeitsbereich und ein neues Modul für die kopflose Validierung und verwenden Sie OpenAPI Yaml für REST Builder, um schließlich Code zu generieren Ich habe die Datei gestartet.

In Teil 2 haben wir die Pfaddefinition hinzugefügt und die OpenAPI-Yaml-Datei von REST Builder vervollständigt. Während ich mit REST Builder-Erstellungsfehlern konfrontiert war, verstand ich einige der häufigsten Formatfehler, die Erstellungsfehler verursachen konnten, behebt sie und verwendete REST Builder, um erfolgreich Code zu generieren.

In Teil 3 haben wir den gesamten von allen Modulen generierten Code überprüft und gezeigt, wo die Änderungen vorgenommen werden.

In Teil 4 (dieses Kapitel) erstellen Sie eine Service Builder-Ebene zur Unterstützung von Ressourcenberechtigungen (zum Überprüfen von Berechtigungen für Remotedienste) und zur Entitätsindizierung (Liferays Funktionen zum Filtern / Suchen / Sortieren von kopflosen Infrastrukturlisten von Liferay). Zu tun) enthalten. Als Nächstes erklärte ich, wie die "VitaminResourceImpl" -Methode geleert wird, wie die Konvertierung von Entität in Komponente behandelt wird und welche "EntityModel" -Klasse erforderlich ist, um das Filtern und Sortieren zu erleichtern.

Wir haben alles getestet und wahrscheinlich die API in SwaggerHub veröffentlicht, damit jeder sie genießen kann. Es war ein langer Weg, aber es war wirklich interessant für mich. Ich hoffe du genießt es.

Hier ist noch einmal das Repository für diese Blog-Serie: https://github.com/dnebing/vitamins

Recommended Posts

So erstellen Sie Ihre eigene kopflose API mit Liferays REST Builder (Teil 3)
So erstellen Sie Ihre eigene kopflose API mit Liferays REST Builder (Teil 2)
So erstellen Sie Ihre eigene kopflose API mit Liferays REST Builder (Teil 4)
So erstellen Sie Ihre eigene kopflose API mit Liferays REST Builder (Teil 1)
So erstellen Sie mit Spring Boot einen eigenen Controller, der / error entspricht
So erstellen Sie Ihre eigene Anmerkung in Java und erhalten den Wert
Erstellen wir eine REST-API mit WildFly Swarm.
[Rails] So erstellen Sie ein Diagramm mit lazy_high_charts
So implementieren Sie optimistisches Sperren in der REST-API
So erstellen Sie hierarchische Kategoriedaten mithilfe von Vorfahren
So lesen Sie Ihre eigene YAML-Datei (*****. Yml) in Java
[Forge] So registrieren Sie Ihre eigene Entität und Ihr Entity Render in 1.13.2
So stellen Sie jQuery in Rails-Apps mit Webpacker bereit
So erstellen Sie ein Service Builder-Portlet in Liferay 7 / DXP
So spielen Sie eine MIDI-Datei mit der Java Sound API ab
Verwendung der Ketten-API
Verwendung von @Builder (Lombok)
Erstellen Sie Ihre eigenen Java-Anmerkungen
Einführung in die EHRbase 2-REST-API
So erstellen Sie eine Methode
So autorisieren Sie mit graphql-ruby
So erstellen Sie eine JAR-Datei und eine War-Datei mit dem Befehl jar
[Rails 6] So erstellen Sie mit cocoon einen dynamischen Formular-Eingabebildschirm
Einfache Möglichkeit zum Erstellen einer Zuordnungsklasse bei Verwendung der API