
Andrew Hanna

Andrew Hanna

Wir behandeln einige Themen, die Ihnen das Leben erleichtern, egal ob Sie Second Generation Managed Packages bereits nutzen oder neu in diesem Thema sind.
Wenn Sie ein neues Release erstellen, kann das viel Zeit und Aufwand kosten. Wenn es fehlschlägt, liefert es manchmal keine wirklich hilfreichen Fehler, um das Problem zu lösen. Ich wünschte, es gäbe detailliertere Fehlermeldungen wie der Befehl sfdx deploy. Aber das ist noch nicht der unangenehme Teil. Schwieriger wird es, wenn Ihr Package bereits erstellt und einsatzbereit ist, Sie es aber in Ihrer Test-Org installieren und feststellen, dass viele Funktionen nicht wie erwartet laufen.
Wenn Sie dieses Durcheinander vermeiden möchten oder schon mitten darin stecken, sind Sie hier richtig, um aus unseren Herausforderungen und Fehlern zu lernen und sich unnötige Kopfschmerzen zu sparen.
Beginnen wir mit den verschiedenen Access Modifiers in Apex-Klassen, damit Sie besser entscheiden können, wie Sie Ihren Code implementieren:
Dieser Access Modifier ist der Standard und bedeutet, dass die Methode oder Variable nur innerhalb der Apex-Klasse zugänglich ist, in der sie definiert wurde. Wenn Sie keinen Access Modifier angeben, ist die Methode oder Variable private.
Das bedeutet, dass die Methode oder Variable für alle inner classes in der definierenden Apex-Klasse sowie für Klassen sichtbar ist, die diese Klasse erweitern. Sie können diesen Access Modifier nur für Instanzmethoden und Member-Variablen verwenden. Diese Einstellung ist strikter permissiv als die Standardeinstellung private, ähnlich wie in Java.
Das bedeutet, dass die Methode oder Variable für alle Apex-Codebereiche in einem bestimmten Package zugänglich ist.
In Apex ist der public Access Modifier nicht dasselbe wie in Java. Das soll verhindern, dass Anwendungen zu stark verbunden werden, und hält den Code jeder Anwendung getrennt. Wenn Sie in Apex etwas wie in Java public machen möchten, müssen Sie den global Access Modifier verwenden.
Für Zugänglichkeit durch alle Second-Generation (2GP) managed packages mit gemeinsamem Namespace verwenden Sie public mit der @NamespaceAccessible annotation. In Packages ohne Namespace macht der public Access Modifier den Apex-Code implizit @NamespaceAccessible.
Das bedeutet, dass die Methode oder Variable von jedem Apex-Code verwendet werden kann, der Zugriff auf die Klasse hat, nicht nur vom Apex-Code in derselben Anwendung. Dieser Access Modifier muss für jede Methode verwendet werden, die außerhalb der Anwendung referenziert werden muss, entweder in SOAP API oder durch anderen Apex-Code. Wenn Sie eine Methode oder Variable als global deklarieren, müssen Sie auch die Klasse, die sie enthält, als global deklarieren.
Wir empfehlen, den global Access Modifier selten oder gar nicht zu verwenden. Abhängigkeiten zwischen Anwendungen sind schwer zu warten.
Die @AuraEnabled annotation ermöglicht clientseitigen und serverseitigen Zugriff auf eine Apex-Controller-Methode. Mit dieser annotation werden Ihre Methoden für Lightning-Komponenten verfügbar, sowohl Lightning Web Components als auch Aura Components. Nur Methoden mit dieser annotation werden exponiert.
Ab API-Version 44.0 können Sie die Runtime-Performance verbessern, indem Sie Methodenergebnisse auf dem Client mit @AuraEnabled(cacheable=true) cachen. Methodenergebnisse können nur für Methoden gecacht werden, die Daten abrufen, aber nicht ändern. Diese annotation macht es unnötig, setStorable() in JavaScript-Code bei jeder Action aufzurufen, die die Apex-Methode aufruft.
Ab API-Version 55.0 können Sie @AuraEnabled(cacheable=true scope='global') verwenden, um Apex-Methoden in einem globalen Cache zu speichern.
global with sharing class TestClass{
@AuraEnabled
global static void testMethod{}
}
können Sie diese Methode aus einem anderen Package in Ihrer Lightning
Web Component so referenzierenimport logExceptionLWC from "@salesforce/apex/TestClass.testMethod";
Einer der wichtigsten Tricks betrifft Custom Models in Ihrem Apex-Code. Wenn Sie diese später serialisieren oder deserialisieren müssen, sollten Sie die Json Access annotation für Ihr Custom Model hinzufügen. Hinweis: Fügen Sie die annotation auch zu Ihren Child Objects hinzu ;)
Was ist also die Json Access annotation? Und welche Serialisierungs- und Deserialisierungsoptionen und Überlegungen gibt es?
Die @JsonAccess annotation auf Apex-Klassenebene steuert, ob Instanzen der Klasse serialisiert oder deserialisiert werden können. Wenn die annotation JSON-Serialisierung und -Deserialisierung einschränkt, wird zur Laufzeit eine JSONException ausgelöst.
Die Parameter serializable und deserializable der @JsonAccess annotation erzwingen die Kontexte, in denen Apex Serialisierung und Deserialisierung erlaubt.
Sie können einen oder beide Parameter angeben, aber nicht die annotation ohne Parameter. Die gültigen Werte, um anzugeben, ob Serialisierung und Deserialisierung erlaubt sind:
Wenn eine mit JsonAccess annotierte Apex-Klasse erweitert wird, erbt die erweiterte Klasse diese Eigenschaft nicht. Wenn die Methode toString auf Objekte angewendet wird, die nicht serialisiert werden dürfen, können private Daten offengelegt werden. Sie müssen toString auf Objekten überschreiben, deren Daten geschützt werden müssen. Wenn beispielsweise ein als Key in einer Map gespeichertes Objekt serialisiert wird, ruft dies die Methode toString auf. Die erzeugte Map enthält key (string) und value entries und legt dadurch alle Felder des Objekts offen.
@JsonAccess(serializable='always' deserializable='always')
global class FullDetails{
global String fullName {get; set;}
global Address address {get; set;}
@JsonAccess(serializable='always' deserializable='always')
global class Address{
global String streetName {get; set;}
global String postalCode {get; set;}
}
}
Was, wenn Sie einige unpackaged Apex-Klassen in Ihrem Projekt erstellen und eine andere Apex-Klasse oder ein Interface referenzieren möchten, das Teil des Managed Package ist? Stellen Sie einfach sicher, dass diese Klassen als global gesetzt sind, und referenzieren Sie die Klasse mit <Namespace>.<ClassName>
Die übliche Callout-Referenz wäre callout:<NamedCredentialsApiName>. Wenn Sie jedoch Named Credentials als Teil Ihres Package für Ihre Callout-Klassen verwenden, müssen Sie sie auf callout:<NampeSpace>__<NamedCredentialsApiName> aktualisieren.
Wenn Sie die connected app Komponente zu Ihrem Package hinzufügen, finden Sie hier die genauen Schritte und vermeiden einige häufige Fehler.
<?xml version="1.0" encoding="UTF-8"?> <ConnectedApp xmlns="http://soap.sforce.com/2006/04/metadata"> <developerName>YourNamespace__ConnectedAppName</developerName> <contactEmail>ConnectedAppContactEmail</contactEmail> <label>ConnectedAppLabelName</label> <version>ConnectedAppVersion</version> </ConnectedApp>
Wenn Sie genau dieselben Schritte befolgt haben und die Erstellung der Package-Version mit folgendem Fehler scheitert:
ERROR running force:package:version:create: <ConnectedAppName>: Installing an app (<ConnectedAppName>) that has been deleted.
Vertrauen Sie mir, wir waren dort. Sie müssen zuerst ein neues Package erstellen und dann eine neue Package-Version. Um das vor dem Start zu prüfen, erstellen Sie ein neues Dummy-dx-Projekt, erstellen ein neues Package, fügen dieselbe bereits erstellte connected app hinzu und erstellen schließlich Ihre Package-Version. Lassen Sie mich wissen, ob das bei Ihnen funktioniert.
Schließlich müssen Sie alle Felder, Objekte, Trigger, Permission Sets, Custom Metadata usw. durchgehen und <Namespace>__ hinzufügen.
Wenn Sie einen ähnlichen Fehler finden, der die Installation Ihres Package in einer Umgebung verhindert, entfernen Sie statt stunden- oder tagelang zu suchen einfach diese standard Quick Actions aus Ihrem Layout und fügen sie erneut hinzu, nachdem das Package erfolgreich installiert wurde.
(ObjectName-Layout) In field: QuickAction - no QuickAction named NewCase found
(ObjectName-Layout) In field: QuickAction - no QuickAction named NewTask found
(ObjectName-Layout) In field: QuickAction - no QuickAction named LogACall found
Component [flexipage:filterListCard] attribute [filterName]: Error retrieving filter [My_ChatterGroups] for entity [CollaborationGroup]
Noch ein Punkt: Wenn Ihr Source Code von Salesforce built-in Components abhängt, stellen Sie sicher, dass Sie vor der Installation der Package-Version als Pre-Deployment-Schritt Zugriff auf diese Komponenten geben. Wie hier beim Aktivieren von omni channel.
Your org doesn't have access to component runtime_service_omnichannel:omniWidget.
Wenn Sie schließlich standardValueSets in Ihrem Source Code haben und die Metadaten Ihrer Package-Version davon abhängen, deployen Sie diese Value Sets als Pre-Deployment-Schritt vor der Installation der Package-Version. Wie hier beim Deployment eines custom status pick-list value namens TestValue.
Component [lst:dynamicRelatedList] attribute [adminFilters]: TestValue isn't a valid picklist value.
Sie können die Metadata Coverage Documentation nutzen, um zu prüfen, welche Komponenten packageable sind.
Demo planen, um mehr darüber zu erfahren, wie Serpent Ihre Salesforce-DevOps-Strategie schon heute stärken kann. Serpent von Tekunda bietet starke Tools für Ihre DevOps-Teams, darunter integrierte Versionskontrolle, Continuous-Deployment- und Release-Systeme, Merge-Tools und viele verschiedene Testing-Tools.

Andrew Hanna

Serpent Team

Tekunda Team

Tekunda Team

Tekunda Team

Andrew Hanna