Tekunda
طريقة عملنا
الوظائفانضم إلى فريق يبني ذكاءً اصطناعيًا وكيليًا جاهزًا للإنتاج.المدوّنةملاحظات عملية عن الذكاء الاصطناعي وSalesforce والإنتاج.
حلولنا
ضع وكلاء الذكاء الاصطناعي في عملياتكوكلاء يتصرفون، يستشهدون بالمصادر، ويعترضون عند الحاجة.حسّن تجربة العملاء بالذكاء الاصطناعيوكلاء يحلّون ويوجّهون، عبر كل القنوات، بالعربية والإنجليزية.اربط أنظمتكتكامل وMCP: أكثر من 70 نظام مؤسسي، خاضع للحوكمة وقابل للتراجع.ابنِ منتج أو تطبيقمنتجات full-stack وSaaS وتطبيقات جوال أصيلة، بأيدي مهندسين خبراء.اخدم عملاءك بالعربيةوكلاء واعون باللهجات، RTL كامل، Agentforce Voice، WhatsApp.
عمق Salesforce: على بعد نقرة
Agentforceستة وكلاء، رحلة عميل واحدة، مرتكزة على بياناتك.Service Cloudحالات ذاتية حيث ينجز Agentforce العمل.Data 360مصدر حقيقة واحد على Salesforce Data Cloud.Tekunda IoT Cloudمن أحداث الأجهزة إلى فرز ذاتي للحالات.AI Decision Supportإجابات استباقية مرتكزة تعترض حين تختلف البيانات.شريك Salesforceاعتمادات SI وISV وPDO وAgentforce.
مثبتة في الإنتاج
الأجهزة المتصلةASSA ABLOY وFocusCura وPhoniro: أساطيل أجهزة تدير نفسها.الرعاية الصحية والمنزليةأكثر من 12 مؤسسة رعاية تعمل في الإنتاج في هولندا.العقاراترحلة الوكلاء الستة، من مطابقة العرض إلى الرد الأول.
الإثبات
دراسة حالة ASSA ABLOYمن 3,000 حالة كل أسبوع إلى 350.Cerebroمنتج Salesforce أصيل للتسويق والمبيعات، مثبت في الإنتاج.دراسة حالة Syntilioمنصة رعاية بمستوى PDO على AppExchange.كل القطاعاتبنية واحدة تُعايَر حسب قطاعك.
محفظة المنتجاتمن بناء Tekunda

المنصات والمحركات التي نبنيها ونشغّلها: Service Circle وTekunda IoT Cloud والIntegration Hub وTekunda AI.

استكشف المحفظة
احجز اجتماع
AR
EnglishENNederlandsNLالعربيةARFrançaisFRDeutschDE
SalesforcepartnerClaudeClaude partner
AR
EnglishENNederlandsNLالعربيةARFrançaisFRDeutschDE
احجز اجتماع
Tekunda

Shed to grow. نبسّط عمليات الأعمال ليتفرغ فريقك لما يهم بالفعل.

شريك Salesforce معتمد: SI · ISV · PDO · Agentforce
حلولنا
وكلاء الذكاء الاصطناعيوكلاء تجربة العملاءالتكامل وMCPتطوير المنتجاتوكلاء بالعربية
Salesforce
AgentforceService CloudData 360Tekunda IoT CloudAI Decision SupportCerebroاعتمادات الشريك
الشركة
المنتجاتالقطاعاتمقالاتطريقة عملنامن نحنتواصل معنا
© 2026 Tekunda L.L.C-FZ
EnglishNederlandsالعربيةFrançaisDeutsch
الخصوصيةالشروط
العودة إلى المقالات
Andrew Hanna

Andrew Hanna

تم التحديث قبل 3 أشهر

2026-04-07T03:50:41.998Z

أسرار Salesforce Second Generation Managed Package

أسرار Salesforce Second Generation Managed Package

سنتناول عدة موضوعات تجعل عملك أسهل، سواء كنت تستخدم بالفعل second generation managed packages أو كنت جديدا على هذا الموضوع.

عندما تنشئ إصدارا جديدا، قد يستغرق ذلك الكثير من الوقت والجهد، وعند فشله لا يقدم أحيانا رسائل خطأ مفيدة بما يكفي لمساعدتك على حل المشكلة. كنت أتمنى حقا أن يقدم رسائل خطأ أكثر تفصيلا مثل أمر sfdx deploy. ومع ذلك، فهذا ليس الجزء الأصعب بعد. يصبح الأمر أكثر تعقيدا عندما تكون الحزمة قد أُنشئت وأصبحت جاهزة للاستخدام، لكن عند محاولة تثبيتها في test org تكتشف أن الكثير من الميزات لا تعمل كما هو متوقع.

إذا كنت تريد تجنب هذا الارتباك أو تواجهه بالفعل، فأنت في المكان الصحيح لتتعلم من تحدياتنا وأخطائنا وتوفر على نفسك صداعا غير ضروري.

معدلات الوصول في Apex

لنبدأ بالتعرف إلى معدلات الوصول المختلفة في كلاسات Apex حتى تساعدك على اختيار طريقة تنفيذ الكود:

Private

هذا هو معدل الوصول الافتراضي، ويعني أن method أو variable متاح فقط داخل كلاس Apex الذي تم تعريفه فيه. إذا لم تحدد معدل وصول، فستكون method أو variable خاصة.

Protected

يعني ذلك أن method أو variable مرئي لأي inner classes داخل كلاس Apex المعرِّف، وكذلك للكلاسات التي ترث من ذلك الكلاس. يمكنك استخدام معدل الوصول هذا فقط مع instance methods وmember variables. هذا الإعداد أكثر سماحية من الإعداد الافتراضي private، تماما كما في Java.

Public

يعني ذلك أن method أو variable متاح لكل Apex داخل package محددة.

في Apex، لا يعمل معدل الوصول public بالطريقة نفسها التي يعمل بها في Java. تم ذلك لتقليل ربط التطبيقات ببعضها وإبقاء كود كل تطبيق منفصلا. في Apex، إذا أردت جعل شيء ما عاما كما في Java، فيجب استخدام معدل الوصول global.

@NamespaceAccessible annotation

لإتاحة الوصول لكل second-generation (2GP) managed packages التي تشترك في namespace، استخدم public مع annotation @NamespaceAccessible. استخدام معدل الوصول public في packages من دون namespace يجعل كود Apex ضمنيا @NamespaceAccessible.

Global

يعني ذلك أن method أو variable يمكن أن يستخدمه أي كود Apex لديه وصول إلى الكلاس، وليس فقط كود Apex داخل التطبيق نفسه. يجب استخدام معدل الوصول هذا لأي method يجب الرجوع إليها من خارج التطبيق، سواء عبر SOAP API أو بواسطة كود Apex آخر. إذا أعلنت method أو variable كـ global، فيجب أيضا إعلان الكلاس الذي يحتويها كـ global.

نوصي باستخدام معدل الوصول global نادرا، إن كان لا بد من استخدامه. فالاعتماديات بين التطبيقات صعبة الصيانة.

AuraEnabled Annotation

تمكّن annotation @AuraEnabled الوصول من جهة العميل وجهة الخادم إلى Apex controller method. إضافة هذه annotation تجعل methods لديك متاحة لمكونات Lightning، سواء Lightning web components أو Aura components. لا يتم كشف إلا methods التي تحمل هذه annotation.

في API version 44.0 وما بعده، يمكنك تحسين أداء runtime عبر تخزين نتائج method على العميل باستخدام annotation @AuraEnabled(cacheable=true). يمكنك تخزين نتائج methods فقط للـ methods التي تسترجع البيانات ولا تعدلها. استخدام هذه annotation يلغي الحاجة إلى استدعاء setStorable() في JavaScript code عند كل action يستدعي Apex method.

في API version 55.0 وما بعده، يمكنك استخدام annotation @AuraEnabled(cacheable=true scope='global') لتمكين تخزين Apex methods في global cache.

إذا كان لديك كلاس Apex في base package لديك 

global with sharing class TestClass{ 
@AuraEnabled global static void testMethod{} }
يمكنك الرجوع إلى هذه method من package مختلفة داخل Lightning Web Component بهذه الطريقة

import logExceptionLWC from "@salesforce/apex/TestClass.testMethod";
معدل الوصول global هو الحيلة التي تمكّنك من الرجوع إليه من package أخرى. لكن إذا كنت ترجع إلى Lightning Web Component من Apex Class داخل package نفسها، فسيكون معدل الوصول Public مناسبا في هذه الحالة.

JSON Access Annotation

من أهم الحيل أنه عندما تنشئ model مخصصا في كود Apex وقد تحتاج لاحقا إلى serialize أو deserialize له، فستحتاج بالتأكيد إلى إضافة Json Access annotation للـ custom model. تلميح: تأكد من إضافة annotation إلى child objects أيضا ;)

إذن ما Json Access annotation؟ وما خيارات واعتبارات serialization و deserialization الخاصة بها؟

تتحكم annotation @JsonAccess المعرفة على مستوى Apex class فيما إذا كان يمكن serialize أو deserialize لنسخ الكلاس. إذا قيدت annotation عمليات JSON serialization وdeserialization، فسيتم رمي runtime JSONException.

تفرض المعلمتان serializable وdeserializable في annotation @JsonAccess السياقات التي يسمح فيها Apex بعمليات serialization وdeserialization.

يمكنك تحديد معلمة واحدة أو كلتيهما، لكن لا يمكنك تحديد annotation دون معلمات. القيم الصالحة للمعلمات التي تحدد ما إذا كانت serialization و deserialization مسموحتين:

  • never: غير مسموح أبدا
  • sameNamespace: مسموح فقط لكود Apex داخل namespace نفسها
  • samePackage: مسموح فقط لكود Apex داخل package نفسها، ويؤثر فقط في second-generation packages
  • always: مسموح دائما لأي كود Apex

اعتبارات JSON Access

إذا تم توسيع Apex class يحمل JsonAccess، فلن يرث الكلاس الموسع هذه الخاصية. إذا طُبقت method toString على objects يجب ألا يتم serialize لها، فقد يتم كشف بيانات خاصة. يجب عليك override للـ toString method على objects التي يجب حماية بياناتها. مثلا، عند serialize لكائن مخزن كمفتاح في Map، يتم استدعاء toString method. تتضمن الخريطة الناتجة entries من key (string) وvalue، وبذلك تكشف كل حقول الكائن.

@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;} 
  }
}

الرجوع إلى Apex Classes من Managed Package

ماذا لو كنت تنشئ بعض apex classes غير المعبأة داخل مشروعك، وقد تحتاج إلى الرجوع إلى apex class آخر أو interface يمثل جزءا من managed package؟ تأكد فقط من تعيين هذه الكلاسات كـ global والرجوع إلى الكلاس عبر <Namespace>.<ClassName>

Named Credentials

عادة ما يكون مرجع callout هو callout:<NamedCredentialsApiName>، لكن إذا كنت تستخدم named credentials كجزء من package لكلاسات callout، فستحتاج إلى تحديثه إلى callout:<NampeSpace>__<NamedCredentialsApiName>

Connected App

إذا كنت تضيف مكون connected app إلى package لديك، فهذه هي الخطوات الدقيقة للقيام بذلك وتجنب بعض الأخطاء الشائعة.

  1. أنشئ developer org
  2. انتقل إلى package manager
  3. تحقق من توفر namespace ثم أضفها
  4. اربط namespace developer org بـ DevHub لديك. إذا فشل الاتصال بعد نافذة allow access، فانتظر من 10 إلى 15 دقيقة ثم حاول مرة أخرى.
  5. انتقل إلى app manager وأنشئ connected app جديدة
  6. عيّن إما full permissions أو api وweb وrefresh permissions
  7. بعد إنشاء connected app، يمكنك إضافة metadata داخل مشروع dx
<?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>

إذا اتبعت الخطوات نفسها بالضبط، وفشلت أثناء إنشاء package version مع الخطأ التالي

ERROR running force:package:version:create: <ConnectedAppName>: Installing an app (<ConnectedAppName>) that has been deleted.

صدقني، مررنا بذلك. ستحتاج إلى إنشاء package جديدة أولا، ثم إنشاء package version جديدة. للتحقق من ذلك قبل البدء، أنشئ مشروع dx تجريبيا جديدا وأنشئ package جديدة، وأضف connected app نفسها التي أنشأتها مسبقا، ثم أنشئ package version وأخبرني هل نجح الأمر معك.

بقية مكونات Salesforce

أخيرا، تحتاج إلى مراجعة كل الحقول والكائنات وtriggers وpermission sets وcustom metadata وغيرها، وإضافة <Namespace>__

تحديات وحيل تثبيت Managed Package

إذا وجدت خطأ مشابها يؤدي إلى فشل تثبيت package في أي بيئة، فبدلا من قضاء ساعات وأيام في محاولة فهمه، أزل Quick Actions القياسية من layout ثم أعد إضافتها بعد تثبيت package بنجاح.

(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]

هناك أمر آخر يجب التفكير فيه: إذا كان source code لديك يعتمد على Salesforce built-in Components، فتأكد من منح الوصول إلى تلك المكونات كجزء من خطوات pre-deployment قبل تثبيت package version. مثل هنا، تفعيل omni channel.

Your org doesn't have access to component runtime_service_omnichannel:omniWidget.

أخيرا، إذا كانت لديك standardValueSets في source code وكان metadata الخاص بـ package version يعتمد عليها، فتأكد من نشر تلك value sets كخطوة pre-deployment قبل تثبيت package version. مثل هنا، نشر قيمة pick-list مخصصة باسم TestValue.

Component [lst:dynamicRelatedList] attribute [adminFilters]: TestValue isn't a valid picklist value.

يمكنك الرجوع إلى Metadata Coverage Documentation لمعرفة أي المكونات يمكن تضمينها في package.

يسعدنا مشاركة أي معلومات مفيدة ونوصيك بمعرفة المزيد عن تأثيرنا في دورة الإصدارات في Salesforce

احجز عرضا توضيحيا لمعرفة المزيد عن كيفية تمكين Serpent لاستراتيجية Salesforce DevOps لديك اليوم. Serpent من Tekunda يقدم أدوات ممتازة لمساعدة فرق DevOps لديك، بما في ذلك التحكم المدمج في الإصدارات، وأنظمة النشر المستمر والإصدارات، وأدوات الدمج، والعديد من أدوات الاختبار المختلفة.

مقالات أخرى

Web Summit Qatar 2026: نمو مركز وزخم تجاري حقيقي
Andrew Hanna

Andrew Hanna

·تم التحديث 8 يونيو 2026

2026-06-08T14:08:14.367Z

Web Summit Qatar 2026: نمو مركز وزخم تجاري حقيقي

دليل: أفضل منصات وأدوات Salesforce DevOps لعام 2026
Serpent Team

Serpent Team

·تم التحديث 26 أبريل 2026

2026-04-26T19:26:24.805Z

دليل: أفضل منصات وأدوات Salesforce DevOps لعام 2026

بذل جهد إضافي: إنشاء تجارب عملاء استثنائية
Tekunda Team

Tekunda Team

·تم التحديث 7 أبريل 2026

2026-04-07T04:07:16.677Z

بذل جهد إضافي: إنشاء تجارب عملاء استثنائية

Freaky Friday: لماذا أحب العمل هنا
Tekunda Team

Tekunda Team

·تم التحديث 7 أبريل 2026

2026-04-07T04:07:04.560Z

Freaky Friday: لماذا أحب العمل هنا

لماذا وكيف تبدأ مسيرة مهنية في Salesforce: المهارات والموارد
Tekunda Team

Tekunda Team

·تم التحديث 7 أبريل 2026

2026-04-07T04:07:00.024Z

لماذا وكيف تبدأ مسيرة مهنية في Salesforce: المهارات والموارد

داخل Web Summit Lisbon 2025: كيف يبدو فعلا
Andrew Hanna

Andrew Hanna

·تم التحديث 7 أبريل 2026

2026-04-07T04:06:47.297Z

داخل Web Summit Lisbon 2025: كيف يبدو فعلا