Qualitätsregeln für benutzerspezifischen Code

Diese Seite beschreibt die Qualitätsregeln für benutzerspezifischen Code, die von Cloud Manager im Rahmen der Code-Qualitätstests ausgeführt werden. Sie basieren auf Best Practices von Experience Manager-Engineering.

HINWEIS

Vollständige SonarQube-Regeln stehen aufgrund von Adobe-proprietären Informationen nicht zum Download zur Verfügung. Sie können die vollständige Liste von Regeln über diesen Link herunterladen. Lesen Sie dieses Dokument weiter, um Beschreibungen und Beispiele für die Regeln zu erhalten.

HINWEIS

Die hier bereitgestellten Code-Beispiele dienen nur Veranschaulichungszwecken. In der Dokumentation zu SonarQube-Konzepten finden Sie Informationen zu SonarQube-Konzepten und Qualitätsregeln.

Regeln für SonarQube

Im folgenden Abschnitt werden die SonarQube-Regeln beschrieben, die von Cloud Manager ausgeführt werden.

Verwenden Sie keine potenziell gefährlichen Funktionen

  • Schlüssel: CQRules:CWE-676
  • Typ: Sicherheitslücke
  • Schweregrad: Hoch
  • Seit: Version 2018.4.0

Die Methoden Thread.stop() und Thread.interrupt() können schwer zu reproduzierende Probleme und in einigen Fällen Sicherheitslücken verursachen. Daher sollte deren Verwendung sorgfältig überwacht und validiert werden. Im Allgemeinen ist die Nachrichtenübergabe eine sicherere Möglichkeit, ähnliche Ziele zu erreichen.

Nicht konformer Code

public class DontDoThis implements Runnable {
  private Thread thread;

  public void start() {
    thread = new Thread(this);
    thread.start();
  }

  public void stop() {
    thread.stop();  // UNSAFE!
  }

  public void run() {
    while (true) {
        somethingWhichTakesAWhileToDo();
    }
  }
}

Konformer Code

public class DoThis implements Runnable {
  private Thread thread;
  private boolean keepGoing = true;

  public void start() {
    thread = new Thread(this);
    thread.start();
  }

  public void stop() {
    keepGoing = false;
  }

  public void run() {
    while (this.keepGoing) {
        somethingWhichTakesAWhileToDo();
    }
  }
}

Verwenden Sie keine Formatzeichenfolgen, die extern gesteuert werden können

  • Schlüssel: CQRules:CWE-134
  • Typ: Sicherheitslücke
  • Schweregrad: Hoch
  • Seit: Version 2018.4.0

Durch die Verwendung einer Formatzeichenfolge aus einer externen Quelle (z. B. einem Anbfrageparameter oder benutzergenerierten Inhalten) kann ein Programm für Denial-of-Service-Angriffe anfällig werden. In einigen Situationen wird eine Formatzeichenfolge extern kontrolliert. In diesem Fall darf sie jedoch nur aus vertrauenswürdigen Quellen verwendet werden.

Nicht konformer Code

protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) {
  String messageFormat = request.getParameter("messageFormat");
  request.getResource().getValueMap().put("some property", String.format(messageFormat, "some text"));
  response.sendStatus(HttpServletResponse.SC_OK);
}

HTTP-Anfragen sollten immer Zeitüberschreitungswerte für Sockets und Verbindungen enthalten

  • Schlüssel: CQRules:ConnectionTimeoutMechanism
  • Typ: Fehler
  • Schweregrad: Kritisch
  • Seit: Version 2018.6.0

Beim Ausführen von HTTP-Anfragen über eine Experience Manager-Anwendung muss unbedingt sichergestellt sein, dass korrekte Zeitüberschreitungswerte konfiguriert werden, um unnötige Thread-Nutzung zu vermeiden. Leider sind in Javas™ Standard-HTTP-Client (java.net.HttpUrlConnection) und dem häufig verwendeten Client für Apache-HTTP-Komponenten standardmäßig keine Zeitüberschreitungswerte festgelegt, sodass diese explizit eingestellt werden müssen. Als Best Practice gilt, für diese Zeitüberschreitungswerte maximal 60 Sekunden zu definieren.

Nicht konformer Code

@Reference
private HttpClientBuilderFactory httpClientBuilderFactory;

public void dontDoThis() {
  HttpClientBuilder builder = httpClientBuilderFactory.newBuilder();
  HttpClient httpClient = builder.build();

  // do something with the client
}

public void dontDoThisEither() {
  URL url = new URL("http://www.google.com");
  URLConnection urlConnection = url.openConnection();

  BufferedReader in = new BufferedReader(new InputStreamReader(
    urlConnection.getInputStream()));

  String inputLine;
  while ((inputLine = in.readLine()) != null) {
    logger.info(inputLine);
  }

  in.close();
}

Konformer Code

@Reference
private HttpClientBuilderFactory httpClientBuilderFactory;

public void doThis() {
  HttpClientBuilder builder = httpClientBuilderFactory.newBuilder();
  RequestConfig requestConfig = RequestConfig.custom()
    .setConnectTimeout(5000)
    .setSocketTimeout(5000)
    .build();
  builder.setDefaultRequestConfig(requestConfig);

  HttpClient httpClient = builder.build();

  // do something with the client
}

public void orDoThis() {
  URL url = new URL("http://www.google.com");
  URLConnection urlConnection = url.openConnection();
  urlConnection.setConnectTimeout(5000);
  urlConnection.setReadTimeout(5000);

  BufferedReader in = new BufferedReader(new InputStreamReader(
    urlConnection.getInputStream()));

  String inputLine;
  while ((inputLine = in.readLine()) != null) {
    logger.info(inputLine);
  }

  in.close();
}

ResourceResolver-Objekte immer schließen

  • Schlüssel: CQRules:CQBP-72
  • Typ: Code Smell
  • Schweregrad: Hoch
  • Seit: Version 2018.4.0

ResourceResolver-Objekte, die aus ResourceResolverFactory abgerufen werden, verbrauchen Systemressourcen. Obwohl es Möglichkeiten gibt, diese Ressourcen freizugeben, wenn ein ResourceResolver nicht mehr verwendet wird, ist es effizienter, alle offenen ResourceResolver-Objekte explizit durch Aufruf der Methode close() zu schließen.

Es ist ein weitverbreiteter Irrtum, dass ResourceResolver-Objekte, die mit einer bestehenden JCR-Sitzung erstellt wurden, nicht explizit geschlossen werden sollten oder dass durch ihre Schließung die zugrunde liegende JCR-Sitzung geschlossen wird. Dies ist nicht der Fall. Gleichgültig, wie ein ResourceResolver geöffnet wird, sollte es geschlossen werden, wenn es nicht mehr benötigt wird. Da ResourceResolver die Closeable-Schnittstelle implementiert, kann auch die Syntax try-with-resources statt eines expliziten Aufrufs von close() verwendet werden.

Nicht konformer Code

public void dontDoThis(Session session) throws Exception {
  ResourceResolver resolver = factory.getResourceResolver(Collections.singletonMap("user.jcr.session", (Object)session));
  // do some stuff with the resolver
}

Konformer Code

public void doThis(Session session) throws Exception {
  ResourceResolver resolver = null;
  try {
    resolver = factory.getResourceResolver(Collections.singletonMap("user.jcr.session", (Object)session));
    // do something with the resolver
  } finally {
    if (resolver != null) {
      resolver.close();
    }
  }
}

public void orDoThis(Session session) throws Exception {
  try (ResourceResolver resolver = factory.getResourceResolver(Collections.singletonMap("user.jcr.session", (Object) session))){
    // do something with the resolver
  }
}

Verwenden Sie keine Sling-Servlet-Pfade zum Registrieren von Servlets

  • Schlüssel: CQRules:CQBP-75
  • Typ: Code Smell
  • Schweregrad: Hoch
  • Seit: Version 2018.4.0

Wie in der Sling-Dokumentation beschrieben, sollten Servlets nicht über Pfade verknüpft werden. Pfadgebundene Servlets können keine standardmäßigen JCR-Zugriffssteuerungselemente verwenden, sodass besonders strenge Sicherheitsmaßnahmen erforderlich sind. Statt pfadgebundene Servlets zu verwenden, wird empfohlen, Knoten im Repository zu erstellen und Servlets nach Ressourcentyp zu registrieren.

Nicht konformer Code

@Component(property = {
  "sling.servlet.paths=/apps/myco/endpoint"
})
public class DontDoThis extends SlingAllMethodsServlet {
 // implementation
}

Erfasste Ausnahmen sollten entweder protokolliert oder ausgelöst werden, aber nicht beides

  • Schlüssel: CQRules:CQBP-44—CatchAndEitherLogOrThrow
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Im Allgemeinen sollte eine Ausnahme genau einmal protokolliert werden. Die mehrfache Protokollierung von Ausnahmen kann verwirren, da unklar ist, wie oft eine Ausnahme aufgetreten ist. Dies wird vor allem dadurch verursacht, dass eine erfasste Ausnahme sowohl protokolliert als auch ausgegeben wird.

Nicht konformer Code

public void dontDoThis() throws Exception {
  try {
    someOperation();
  } catch (Exception e) {
    logger.error("something went wrong", e);
    throw e;
  }
}

Konformer Code

public void doThis() {
  try {
    someOperation();
  } catch (Exception e) {
    logger.error("something went wrong", e);
  }
}

public void orDoThis() throws MyCustomException {
  try {
    someOperation();
  } catch (Exception e) {
    throw new MyCustomException(e);
  }
}

Throw-Anweisungen sollten möglichst nicht unmittelbar auf Log-Anweisungen folgen

  • Schlüssel: CQRules:CQBP-44—ConsecutivelyLogAndThrow
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Ein weiteres gängiges Muster, das vermieden werden sollte, ist die Protokollierung einer Nachricht, direkt gefolgt von der Auslösung einer Ausnahme. Dadurch wird die Ausnahmemeldung in Protokolldateien meist doppelt aufgeführt.

Nicht konformer Code

public void dontDoThis() throws Exception {
  logger.error("something went wrong");
  throw new RuntimeException("something went wrong");
}

Konformer Code

public void doThis() throws Exception {
  throw new RuntimeException("something went wrong");
}

Vermeiden Sie beim Verarbeiten von GET- oder HEAD-Anfragen die Protokollierung bei INFO

  • Schlüssel: CQRules:CQBP-44—LogInfoInGetOrHeadRequests
  • Typ: Code Smell
  • Schweregrad: Gering

Allgemein sollten mit der Protokollebene INFO wichtige Aktionen abgegrenzt werden. Standardmäßig ist Experience Manager so konfiguriert, dass auf der INFO-Ebene oder darüber protokolliert wird. GET- und HEAD-Methoden sollten nur schreibgeschützte Vorgänge sein und stellen daher keine wichtigen Aktionen dar. Eine Protokollierung auf INFO-Ebene als Antwort auf GET- oder HEAD-Anfragen füllt das Protokoll wahrscheinlich mit erheblichen Mengen überflüssiger Informationen, sodass es schwieriger wird, nützliche Informationen in Protokolldateien zu finden. Bei der Verarbeitung von GET- oder HEAD-Anfragen sollte bei einem Fehler die Protokollierung entweder auf WARN- oder ERROR-Ebene erfolgen oder auf DEBUG- oder TRACE-Ebene, wenn detailliertere Informationen erforderlich sind.

HINWEIS

Das gilt nicht für die Protokollierung von Ereignissen des Typs access.log einer Anfrage.

Nicht konformer Code

public void doGet() throws Exception {
  logger.info("handling a request from the user");
}

Konformer Code

public void doGet() throws Exception {
  logger.debug("handling a request from the user.");
}

Verwenden Sie nicht Exception.getMessage() als ersten Parameter einer Protokollanweisung

  • Schlüssel: CQRules:CQBP-44—ExceptionGetMessageIsFirstLogParam
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Als Best Practice sollten Protokollmeldungen kontextbezogene Informationen darüber enthalten, wo eine Programmausnahme aufgetreten ist. Obwohl der Kontext auch mit Stacktraces bestimmt werden kann, ist die Protokollmeldung meist besser lesbar und verständlicher. Daher ist es bei der Protokollierung einer Ausnahme nicht empfehlenswert, die Ausnahmemeldung als Protokollmeldung zu verwenden. Die Ausnahmemeldung enthält Informationen zu Fehlern, während die Protokollmeldung verwendet werden sollte, um Protokoll-Lesenden den Status der Anwendung beim Auftreten der Ausnahme mitzuteilen. Die Ausnahmemeldung wird dennoch protokolliert. Durch die Spezifizierung Ihrer eigenen Nachricht sind die Protokolle leichter verständlich.

Nicht konformer Code

public void dontDoThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    logger.error(e.getMessage(), e);
  }
}

Konformer Code

public void doThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    logger.error("Unable to do something", e);
  }
}

Die Protokollierung in Catch-Blöcken sollte auf WARN- oder ERROR-Ebene erfolgen

  • Schlüssel: CQRules:CQBP-44—WrongLogLevelInCatchBlock
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Wie schon der Name sagt, sollten Java™-Ausnahmen immer in Ausnahmefällen verwendet werden. Wenn eine Ausnahme erfasst wird, muss daher sichergestellt sein, dass Protokollmeldungen auf der entsprechenden Ebene – WARN oder ERROR – protokolliert werden. Damit wird sichergestellt, dass diese Meldungen in den Protokollen korrekt angezeigt werden.

Nicht konformer Code

public void dontDoThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    logger.debug(e.getMessage(), e);
  }
}

Konformer Code

public void doThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    logger.error("Unable to do something", e);
  }
}

Drucken Sie keine Stacktraces in der Konsole

  • Schlüssel: CQRules:CQBP-44—ExceptionPrintStackTrace
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Wie bereits erwähnt, ist Kontext beim Verständnis von Protokollmeldungen äußerst wichtig. Durch Verwendung von Exception.printStackTrace() wird nur der Stacktrace an den Standardfehler-Stream ausgegeben, während der gesamte Kontext verloren geht. Außerdem kann es bei mehrprozessgestützten Anwendungen wie Experience Manager beim parallelen Drucken mehrerer Ausnahmen mit dieser Methode zu einer Überlappung der Stacktraces kommen, was erhebliche Verwirrung verursacht. Ausnahmen sollten daher nur über das Protokollierungs-Framework protokolliert werden.

Nicht konformer Code

public void dontDoThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    e.printStackTrace();
  }
}

Konformer Code

public void doThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    logger.error("Unable to do something", e);
  }
}

Nicht an Standardausgabe oder Standardfehler ausgeben

  • Schlüssel: CQRules:CQBP-44—LogLevelConsolePrinters
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Die Anmeldung in Experience Manager sollte immer über das Protokollierungs-Framework (SLF4J) erfolgen. Bei der direkten Ausgabe an die Standardausgabe oder den Standardfehler-Stream gehen die vom Protokollierungs-Framework bereitgestellten Struktur- und Kontextinformationen verloren. Manchmal kann dies zu Leistungsproblemen führen.

Nicht konformer Code

public void dontDoThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    System.err.println("Unable to do something");
  }
}

Konformer Code

public void doThis() {
  try {
    someMethodThrowingAnException();
  } catch (Exception e) {
    logger.error("Unable to do something", e);
  }
}

Hartcodierte /apps- und /libs-Pfade vermeiden

  • Schlüssel: CQRules:CQBP-71
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2018.4.0

Im Allgemeinen sollten Pfade, die mit /libs und /apps beginnen, nicht hartcodiert werden, da die Pfade, auf die sie verweisen, meist als Pfade relativ zum Sling-Suchpfad (der standardmäßig auf /libs,/apps festgelegt ist) gespeichert werden. Durch die Angabe des absoluten Pfads können geringfügige Fehler entstehen, die erst später im Projektlebenszyklus deutlich werden.

Nicht konformer Code

public boolean dontDoThis(Resource resource) {
  return resource.isResourceType("/libs/foundation/components/text");
}

Konformer Code

public void doThis(Resource resource) {
  return resource.isResourceType("foundation/components/text");
}

Sling-Scheduler nicht verwenden

  • Schlüssel: CQRules:AMSCORE-554
  • Typ: Code Smell/Cloud Service-Kompatibilität
  • Schweregrad: Gering
  • Seit: Version 2020.5.0

Verwenden Sie den Sling-Scheduler nicht für Aufgaben, die eine garantierte Ausführung erfordern. Über Sling geplante Vorgänge garantieren die Ausführung und eignen sich besser für Umgebungen mit und ohne Cluster.

Weitere Informationen zum Umgang mit Sling-Vorgängen in Cluster-Umgebungen finden Sie unter Apache Sling Eventing und Job Handling.

Keine nicht mehr unterstützten Experience Manager-APIs verwenden

  • Schlüssel: AMSCORE-553
  • Typ: Code Smell/Cloud Service-Kompatibilität
  • Schweregrad: Gering
  • Seit: Version 2020.5.0

Die Experience Manager-API-Oberfläche wird ständig geprüft, um APIs zu identifizieren, deren Verwendung nicht mehr empfohlen wird und die deshalb als nicht mehr unterstützt gelten.

In vielen Fällen sind diese APIs unter Verwendung der Standard-Java™-Annotation @Deprecated als veraltet eingestuft und durch squid:CallToDeprecatedMethod gekennzeichnet.

Es gibt jedoch auch Fälle, in denen eine API im Experience Manager-Kontext veraltet ist, in anderen Kontexten jedoch nicht. Diese Regel identifiziert diese zweite Gruppe.

Inhaltsregeln für OakPAL

Im folgenden Abschnitt werden die von Cloud Manager durchgeführten OakPAL-Prüfungen vorgestellt.

HINWEIS

OakPAL ist ein Framework, das Inhaltspakete mit einem eigenständigen Oak-Repository validiert. Es wurde von einem Experience Manager-Partner entwickelt, der mit dem 2019 Experience Manager Rockstar North America Award ausgezeichnet wurde.

Produkt-APIs, die mit @ProviderType kommentiert wurden, sollten von Kunden nicht implementiert oder erweitert werden

  • Schlüssel: CQBP-84
  • Typ: Fehler
  • Schweregrad: Kritisch
  • Seit: Version 2018.7.0

Die Experience Manager-API enthält Java™-Schnittstellen und -Klassen, die nur für die Verwendung, aber nicht für die Implementierung durch benutzerdefinierten Code vorgesehen sind. Beispielsweise sollte die Schnittstelle com.day.cq.wcm.api.Page nur durch Experience Manager implementiert werden.

Wenn neue Methoden zu diesen Schnittstellen hinzugefügt werden, wirken sich diese zusätzlichen Methoden nicht auf vorhandenen Code aus, der diese Schnittstellen verwendet. Daher wird das Hinzufügen neuer Methoden zu diesen Schnittstellen als abwärtskompatibel betrachtet. Wenn jedoch benutzerdefinierter Code eine dieser Schnittstellen implementiert, erzeugt dieser benutzerspezifische Code ein Abwärtskompatibilitätsrisiko für den Kunden.

Schnittstellen und Klassen — wie durch Experience Manager implementiert — werden mit org.osgi.annotation.versioning.ProviderType oder manchmal einer ähnliche Legacy-Anmerkung aQute.bnd.annotation.ProviderType gekennzeichnet. Diese Regel identifiziert die Fälle, in denen eine solche Schnittstelle durch benutzerdefinierten Code implementiert wird oder eine Klasse erweitert wird.

Nicht konformer Code

import com.day.cq.wcm.api.Page;

public class DontDoThis implements Page {
// implementation here
}

Benutzerdefinierte Lucene-Oak-Indizes müssen über eine Tika-Konfiguration verfügen

  • Schlüssel: IndexTikaNode
  • Typ: Fehler
  • Schweregrad: Blocker
  • Seit: 2021.8.0

Mehrere vorkonfigurierte Experience Manager Oak-Indizes enthalten eine Tika-Konfiguration und Anpassungen dieser Indizes müssen eine Tika-Konfiguration enthalten. Diese Regel überprüft auf Anpassungen der Indizes damAssetLucene, lucene und graphqlConfig und löst ein Problem aus, wenn entweder der Knoten tika fehlt oder wenn im Knoten tika ein untergeordneter Knoten mit dem Namen config.xml fehlt.

Weitere Informationen zum Anpassen von Indexdefinitionen finden Sie unter Dokumentation zur Indizierung.

Nicht konformer Code

+ oak:index
    + damAssetLucene-1-custom
      - async: [async]
      - evaluatePathRestrictions: true
      - includedPaths: /content/dam
      - reindex: false
      - tags: [visualSimilaritySearch]
      - type: lucene

Konformer Code

+ oak:index
    + damAssetLucene-1-custom-2
      - async: [async]
      - evaluatePathRestrictions: true
      - includedPaths: /content/dam
      - reindex: false
      - tags: [visualSimilaritySearch]
      - type: lucene
      + tika
        + config.xml

Benutzerdefinierte Lucene-Oak-Indizes dürfen nicht synchron sein

  • Schlüssel: IndexAsyncProperty
  • Typ: Fehler
  • Schweregrad: Blocker
  • Seit: 2021.8.0

Oak-Indizes des Typs lucene muss immer asynchron indiziert werden. Andernfalls kann es zu einer Instabilität des Systems kommen. Weitere Informationen zur Struktur von Lucene-Indizes finden Sie in der Oak-Dokumentation.

Nicht konformer Code

+ oak:index
    + damAssetLucene-1-custom
      - evaluatePathRestrictions: true
      - includedPaths: /content/dam
      - reindex: false
      - type: lucene
      - reindex: false
      - tags: [visualSimilaritySearch]
      - type: lucene
      + tika
        + config.xml

Konformer Code

+ oak:index
    + damAssetLucene-1-custom-2
      - async: [async]
      - evaluatePathRestrictions: true
      - includedPaths: /content/dam
      - reindex: false
      - tags: [visualSimilaritySearch]
      - type: lucene
      + tika
        + config.xml

Benutzerdefinierte DAM-Asset-Lucene-Oak-Indizes sind ordnungsgemäß strukturiert

  • Schlüssel: IndexDamAssetLucene
  • Typ: Fehler
  • Schweregrad: Blocker
  • Seit: 2021.6.0

Damit die Asset-Suche in Experience Manager Assets ordnungsgemäß funktioniert, müssen die Einstellungen des damAssetLucene-Oak-Indexes einem Satz von spezifisch für diesen Index geltenden Richtlinien entsprechen. Diese Regel stellt sicher, dass die Indexdefinition über eine Eigenschaft mit mehreren Werten mit dem Namen tags verfügt, die den Wert visualSimilaritySearch enthält.

Nicht konformer Code

+ oak:index
    + damAssetLucene-1-custom
      - async: [async, nrt]
      - evaluatePathRestrictions: true
      - includedPaths: /content/dam
      - reindex: false
      - type: lucene
      + tika
        + config.xml

Konformer Code

+ oak:index
    + damAssetLucene-1-custom-2
      - async: [async, nrt]
      - evaluatePathRestrictions: true
      - includedPaths: /content/dam
      - reindex: false
      - tags: [visualSimilaritySearch]
      - type: lucene
      + tika
        + config.xml

Kundenpakete sollten keine Knoten unter /libs erstellen oder ändern

  • Schlüssel: BannedPath
  • Typ: Fehler
  • Schweregrad: Kritisch
  • Seit: Version 2019.6.0

Gemäß einer bewährten Best Practice sollte die /libs-Inhaltsstruktur im Experience Manager-Content-Repository von Kunden als schreibgeschützt konfiguriert werden. Das Ändern von Knoten und Eigenschaften unter /libs ist bei großen und kleineren Aktualisierungen mit erheblichen Risiken verbunden. Änderungen an /libs müssen durch Adobe über offizielle Kanäle erfolgen.

Pakete sollten keine doppelten OSGi-Konfigurationen enthalten

  • Schlüssel: DuplicateOsgiConfigurations
  • Typ: Fehler
  • Schweregrad: Hoch
  • Seit: Version 2019.6.0

Ein häufig auftretendes Problem bei komplexen Projekten besteht darin, dass dieselbe OSGi-Komponente mehrmals konfiguriert ist. Dadurch ist nicht mehr eindeutig, welche Konfiguration gelten soll. Diese Regel beachtet den jeweiligen Ausführungsmodus, da sie nur Probleme erkennt, bei denen dieselbe Komponente mehrmals im gleichen Ausführungsmodus oder in der gleichen Kombination aus Ausführungsmodi konfiguriert ist.

HINWEIS

Diese Regel führt zu Problemen, wenn dieselbe Konfiguration unter demselben Pfad in mehreren Paketen definiert ist, einschließlich der Fälle, in denen dasselbe Paket in der Gesamtliste der erstellten Pakete dupliziert ist.

Wenn der Build zum Beispiel Pakete mit den Namen com.myco:com.myco.ui.apps und com.myco:com.myco.all erstellt, wobei com.myco:com.myco.ui.apps in com.myco:com.myco.all eingebettet ist, werden alle Konfigurationen innerhalb von com.myco:com.myco.ui.apps als Duplikat gemeldet.

Dies ist im Allgemeinen der Fall, wenn Sie die Richtlinien für die Struktur von Inhaltspaketen nicht befolgen. In diesem speziellen Beispiel fehlt dem Paket com.myco:com.myco.ui.apps die <cloudManagerTarget>none</cloudManagerTarget>-Eigenschaft.

Nicht konformer Code

+ apps
  + projectA
    + config
      + com.day.cq.commons.impl.ExternalizerImpl
  + projectB
    + config
      + com.day.cq.commons.impl.ExternalizerImpl

Konformer Code

+ apps
  + shared-config
    + config
      + com.day.cq.commons.impl.ExternalizerImpl

Konfigurations- und Installationsordner sollten nur OSGi-Knoten enthalten

  • Schlüssel: ConfigAndInstallShouldOnlyContainOsgiNodes
  • Typ: Fehler
  • Schweregrad: Hoch
  • Seit: Version 2019.6.0

Aus Sicherheitsgründen sind Pfade, die /config/ und /install/ enthalten, nur von Benutzenden mit Administratorrechten in Experience Manager lesbar und sollten nur für OSGi-Konfigurationen und OSGi-Bundles verwendet werden. Das Platzieren anderer Inhaltstypen in Pfade mit diesen Segmenten führt dazu, dass sich das Programm abhängig davon anders verhält, ob sie von Administratoren- oder Nicht-Administratoren verwendet wird.

Ein häufig auftretendes Problem ist die Verwendung von Knoten mit der Bezeichnung config in Komponentendialogfeldern oder beim Angeben der Rich-Text-Editor-Konfiguration für die Inline-Bearbeitung. Um dieses Problem zu beheben, sollte der fehlerhafte Knoten umbenannt und mit einem kompatiblen Namen versehen werden. Nutzen Sie bei der Rich-Text-Editor-Konfiguration die Eigenschaft configPath im Knoten cq:inplaceEditing, um den neuen Speicherort anzugeben.

Nicht konformer Code

+ cq:editConfig [cq:EditConfig]
  + cq:inplaceEditing [cq:InplaceEditConfig]
    + config [nt:unstructured]
      + rtePlugins [nt:unstructured]

Konformer Code

+ cq:editConfig [cq:EditConfig]
  + cq:inplaceEditing [cq:InplaceEditConfig]
    ./configPath = inplaceEditingConfig (String)
    + inplaceEditingConfig [nt:unstructured]
      + rtePlugins [nt:unstructured]

Pakete sollten sich nicht überlappen

  • Schlüssel: PackageOverlaps
  • Typ: Fehler
  • Schweregrad: Hoch
  • Seit: Version 2019.6.0

Ähnlich wie bei der Regel Pakete dürfen keine doppelten OSGi-Konfigurationen enthalten ist dies ein häufiges Problem bei komplexen Projekten, bei denen mehrere separate Inhaltspakete in denselben Knotenpfad schreiben. Mit Inhaltspaketabhängigkeiten kann zwar ein konsistentes Ergebnis sichergestellt werden, Überlappungen sollten aber dennoch vermieden werden.

Der standardmäßige Authoring-Modus sollte nicht die klassische Benutzeroberfläche verwenden

  • Schlüssel: ClassicUIAuthoringMode
  • Typ: Code Smell/Cloud Service-Kompatibilität
  • Schweregrad: Gering
  • Seit: Version 2020.5.0

Die OSGi-Konfiguration com.day.cq.wcm.core.impl.AuthoringUIModeServiceImpl definiert den standardmäßigen Authoring-Modus in Experience Manager. Da die klassische Benutzeroberfläche seit Experience Manager 6.4 nicht mehr unterstützt wird, tritt jetzt ein Problem auf, wenn als standardmäßiger Authoring-Modus die klassische Benutzeroberfläche konfiguriert ist.

Komponenten mit Dialogfeldern sollten Dialogfelder für die Touch-Benutzeroberfläche aufweisen

  • Schlüssel: ComponentWithOnlyClassicUIDialog
  • Typ: Code Smell/Cloud Service-Kompatibilität
  • Schweregrad: Gering
  • Seit: Version 2020.5.0

Experience Manager-Komponenten mit einem Dialogfeld für die klassische Benutzeroberfläche sollten immer über ein entsprechendes Dialogfeld für die Touch-Benutzeroberfläche verfügen. Beide bieten ein optimales Authoring-Erlebnis und sind mit dem Cloud Service-Bereitstellungsmodell kompatibel, in dem die klassische Benutzeroberfläche nicht unterstützt wird. Diese Regel überprüft die folgenden Szenarien:

  • Eine Komponente mit einem Dialogfeld für die klassische Benutzeroberfläche (d. h. einem untergeordneten dialog-Knoten) muss über ein entsprechendes Dialogfeld für die Touch-Benutzeroberfläche verfügen (d. h. über einen untergeordneten cq:dialog-Knoten).
  • Eine Komponente mit einem Design-Dialogfeld für die klassische Benutzeroberfläche (d. h. einem design_dialog-Knoten) muss über ein entsprechendes Design-Dialogfeld für die Touch-Benutzeroberfläche verfügen (d. h. über einen untergeordneten cq:design_dialog-Knoten).
  • Eine Komponente mit einem Dialogfeld für die klassische Benutzeroberfläche und einem Design-Dialogfeld für die klassische Benutzeroberfläche muss sowohl über ein entsprechendes Dialogfeld für die Touch-Benutzeroberfläche als auch über ein entsprechendes Design-Dialogfeld für die Touch-Benutzeroberfläche verfügen.

Die Dokumentation zu den Experience Manager-Modernisierungs-Tools bietet Dokumentation und Tools zum Konvertieren von Komponenten aus der klassischen Benutzeroberfläche in die Touch-Benutzeroberfläche. Weitere Informationen finden Sie in der Dokumentation zu den Experience Manager-Modernisierungs-Tools.

In Paketen sollten veränderliche und unveränderliche Inhalte nicht gemischt werden

  • Schlüssel: ImmutableMutableMixedPackage
  • Typ: Code Smell/Cloud Service-Kompatibilität
  • Schweregrad: Gering
  • Seit: Version 2020.5.0

Um mit dem Cloud Service-Bereitstellungsmodell kompatibel zu sein, müssen einzelne Inhaltspakete entweder Inhalte für die unveränderlichen Bereiche des Repositorys (d. h. /apps und /libs) oder den veränderlichen Bereich (d. h. alles, was nicht in /apps oder /libs ist) enthalten, aber nicht beides. Beispielsweise ist ein Paket, das /apps/myco/components/text und /etc/clientlibs/myco enthält, nicht mit Cloud Service kompatibel und führt dazu, dass ein Problem gemeldet wird.

Weitere Informationen finden Sie unter Experience Manager-Projektstruktur.

Verwenden Sie keine Agenten für Rückwärtsreplikation

  • Schlüssel: ReverseReplication
  • Typ: Code Smell/Cloud Service-Kompatibilität
  • Schweregrad: Gering
  • Seit: Version 2020.5.0

Die Unterstützung für die Rückwärtsreplikation ist in Cloud-Service-Implementierungen nicht verfügbar, wie in den Versionshinweisen zu Experience Manager as a Cloud Service beschrieben.

Kunden, die die Rückwärtsreplikation verwenden, sollten sich für alternative Lösungen an Adobe wenden.

In Proxy-fähigen Client-Bibliotheken enthaltene Ressourcen sollten sich in einem Ordner mit dem Namen „resources“ befinden

  • Schlüssel: ClientlibProxyResource
  • Typ: Fehler
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager-Client-Bibliotheken können statische Ressourcen wie Bilder und Schriftarten enthalten. Wie im Dokument Verwenden von Präprozessoren beschrieben, müssen diese statischen Ressourcen bei der Verwendung von Proxy-fähigen Client-Bibliotheken in einem untergeordneten Ordner namens „resources“ enthalten sein, damit sie in den Veröffentlichungsinstanzen effektiv referenziert werden können.

Nicht konformer Code

+ apps
  + projectA
    + clientlib
      - allowProxy=true
      + images
        + myimage.jpg

Konformer Code

+ apps
  + projectA
    + clientlib
      - allowProxy=true
      + resources
        + myimage.jpg

Verwenden von mit Cloud Service inkompatiblen Workflow-Prozessen

  • Schlüssel: CloudServiceIncompatibleWorkflowProcess
  • Typ: Fehler
  • Schweregrad: Hoch
  • Seit: Version 2021.2.0

Mit der Umstellung auf Asset-Microservices für die Asset-Verarbeitung in Experience Manager as a Cloud Service werden verschiedene Workflow-Prozesse, die in On-Premise- und AMS-Versionen von Experience Manager verwendet wurden, entweder nicht mehr unterstützt oder sind nicht mehr erforderlich.

Mit dem Migrations-Tool im GitHub-Repository für Experience Manager as a Cloud Service-Assets können Workflow-Modelle während der Migration in Experience Manager as a Cloud Service aktualisiert werden.

Es wird empfohlen anstelle von statischen Vorlagen bearbeitbare Vorlagen zu verwenden.

  • Schlüssel: StaticTemplateUsage
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Auch wenn die Verwendung statischer Vorlagen in Experience Manager-Projekten früher üblich war, empfiehlt Adobe bearbeitbare Vorlagen zu verwenden, da sie die beste Flexibilität bieten und zusätzliche Funktionen besitzen, die in statischen Vorlagen nicht vorhanden sind. Weitere Informationen finden Sie im Dokument Seitenvorlagen.

Die Migration von statischen zu bearbeitbaren Vorlagen kann mithilfe des Experience Manager-Modernisierungs-Tools weitgehend automatisiert werden.

Die Verwendung veralteter Foundation-Komponenten wird nicht empfohlen

  • Schlüssel: LegacyFoundationComponentUsage
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Die veralteten Foundation-Komponenten (d. h. Komponenten unter /libs/foundation) werden seit mehreren Experience Manager-Versionen nicht mehr verwendet und wurden durch die Kernkomponenten ersetzt. Von der Verwendung der Foundation-Komponenten als Basis für benutzerdefinierte Komponenten – sei es durch Überlagerung oder Vererbung – wird abgeraten und sie sollten in die entsprechende Kernkomponente konvertiert werden.

Diese Konvertierung mit den Experience Manager-Modernisierungs-Tools vorgenommen werden.

Verwenden Sie nur unterstützte Ausführungsmodusnamen und -reihenfolgen

  • Schlüssel: SupportedRunmode
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager as a Cloud Service erzwingt eine strikte Benennungsrichtlinie für Ausführungsmodusnamen und eine strikte Reihenfolge für diese Ausführungsmodi. Die Liste der unterstützten Ausführungsmodi ist im Dokument Bereitstellung für Experience Manager as a Cloud Service zu finden und jede Abweichung davon erzeugt einen Fehler.

  • Schlüssel: OakIndexLocation
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager as a Cloud Service verlangt, dass benutzerdefinierte Suchindex-Definitionen (d. h. Knoten vom Typ oak:QueryIndexDefinition) direkt untergeordnete Knoten von /oak:index sein müssen. Indizes in anderen Speicherorten müssen so verschoben werden, dass sie mit Experience Manager as a Cloud Service kompatibel sind. Weitere Informationen zu Suchindizes finden Sie im Dokument Inhaltssuche und -indizierung.

Knoten für benutzerdefinierte Suchindex-Definitionen benötigen eine compatVersion von 2

  • Schlüssel: IndexCompatVersion
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager as a Cloud Service erfordert, dass die Eigenschaft compatVersion für benutzerdefinierte Suchindex-Definitionen (wie Knoten vom Typ oak:QueryIndexDefinition) auf 2 festgelegt wird. Andere Werte werden von Experience Manager as a Cloud Service nicht unterstützt. Weitere Informationen zu Suchindizes finden Sie unter Inhaltssuche und -indizierung.

Nachfolgeknoten einer benutzerdefinierten Suchindex-Definition müssen dem Typ nt:unstructured entsprechen

  • Schlüssel: IndexDescendantNodeType
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Schwer behebbare Probleme können auftreten, wenn ein Knoten einer benutzerdefinierten Suchindex-Definition unstrukturierte untergeordnete Knoten enthält. Um diese Situation zu vermeiden, sollten alle untergeordneten Knoten eines oak:QueryIndexDefinition-Knotens dem Typ nt:unstructured sein.

Knoten einer benutzerdefinierten Suchindex-Definition müssen einen untergeordneten Knoten mit dem Namen indexRules enthalten, der wiederum untergeordnete Knoten enthält

  • Schlüssel: IndexRulesNode
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Ein korrekt definierter benutzerdefinierter Suchindex-Definitionsknoten muss einen untergeordneten Knoten namens indexRules enthalten, der wiederum mindestens einen untergeordneten Knoten haben muss. Weitere Informationen finden Sie in der Oak-Dokumentation.

Knoten für benutzerdefinierte Suchindex-Definitionen müssen Benennungskonventionen folgen

  • Schlüssel: IndexName
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager as a Cloud Service erfordert, dass benutzerdefinierte Suchindex-Definitionen (d. h. Knoten des Typs oak:QueryIndexDefinition) nach einem bestimmten Muster benannt werden, das im Dokument Inhaltssuche und -indizierung beschrieben wird.

Knoten für benutzerdefinierte Suchindex-Definitionen müssen den Indextyp Lucene verwenden

  • Schlüssel: IndexType
  • Typ: Fehler
  • Schweregrad: Blocker
  • Seit: Version 2021.2.0 (Änderung von Typ und Schweregrad in 2021.8.0)

Experience Manager as a Cloud Service erfordert, dass benutzerdefinierte Suchindex-Definitionen (d. h. Knoten vom Typ oak:QueryIndexDefinition) eine type-Eigenschaft mit dem definierten Wert lucene aufweisen. Die Indizierung mit veralteten Indextypen muss vor der Migration auf Experience Manager as a Cloud Service aktualisiert werden. Weitere Informationen finden Sie unter Inhaltssuche und -indizierung.

Knoten einer benutzerdefinierten Suchindex-Definition dürfen keine Eigenschaft namens „seed“ enthalten

  • Schlüssel: IndexSeedProperty
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager as a Cloud Service verbietet es, dass benutzerdefinierte Suchindex-Definitionen (d. h. Knoten vom Typ oak:QueryIndexDefinition) eine Eigenschaft mit dem Namen seed enthalten. Die Indizierung mit dieser Eigenschaft muss vor der Migration auf Experience Manager as a Cloud Service aktualisiert werden. Weitere Informationen finden Sie im Dokument Inhaltssuche und -indizierung.

Knoten für die benutzerdefinierte Suchindex-Definition dürfen keine Eigenschaft namens „reindex“ enthalten

  • Schlüssel: IndexReindexProperty
  • Typ: Code Smell
  • Schweregrad: Gering
  • Seit: Version 2021.2.0

Experience Manager as a Cloud Service verbietet es, dass benutzerdefinierte Suchindex-Definitionen (d. h. Knoten vom Typ oak:QueryIndexDefinition) eine Eigenschaft mit dem Namen reindex enthalten. Die Indizierung mit dieser Eigenschaft muss vor der Migration auf Experience Manager as a Cloud Service aktualisiert werden. Weitere Informationen finden Sie im Dokument Inhaltssuche und -indizierung.

Auf dieser Seite