
Salesforce platformu üzerinde geliştirme yapıyorsanız, konfigürasyon değişikliklerini yönetmek ve dağıtmak günlük işlerinizin önemli bir parçasıdır. Bu süreçleri manuel olarak gerçekleştirmek, özellikle karmaşık projelerde, ciddi zaman kaybı yaratabilir. İşte tam bu noktada Salesforce Metadata API devreye giriyor. Bu güçlü API, Salesforce konfigürasyonlarınızı programatik olarak yönetmenize olanak tanıyarak geliştirme süreçlerinizi otomatikleştirmenize ve hızlandırmanıza imkan sağlar.
Bu yazımızda, Salesforce Metadata API’nin temellerinden ileri düzey kullanımına kadar kapsamlı bir rehber sunuyoruz. Hem yeni başlayan geliştiricilerin hem de deneyimli Salesforce uzmanlarının faydalanabileceği pratik bilgiler ve kod örnekleri ile bu güçlü aracı projelerinizde nasıl etkili şekilde kullanabileceğinizi öğreneceksiniz.
Metadata API Nedir?
Salesforce Metadata API, platform üzerindeki meta verileri (metadata) programatik olarak oluşturmanıza, güncelemenize ve yönetmenize olanak tanıyan güçlü bir web servisidir. Meta veri, Salesforce organizasyonunuzdaki yapılandırma bilgilerini temsil eder – özel nesneler, alanlar, sayfa düzenleri, Apex sınıfları, Lightning bileşenleri ve daha fazlası.
Bu API, SOAP (Simple Object Access Protocol) tabanlıdır ve XML mesajları aracılığıyla iletişim kurar. Salesforce’un diğer API’leri genellikle veri manipülasyonuna odaklanırken (örn. REST API ve SOAP API), Metadata API özellikle konfigürasyon bileşenlerinin yönetimi için tasarlanmıştır.
Metadata API, Salesforce platformundaki diğer geliştirme araçlarının temelini oluşturur. Örneğin, Salesforce CLI, Visual Studio Code için Salesforce Uzantısı ve Change Set’ler gibi araçlar arka planda Metadata API’yi kullanır.
Metadata API’nin Kullanım Alanları
Metadata API’nin sağladığı programatik erişim, birçok güçlü kullanım senaryosunu mümkün kılar:
Konfigürasyon Yönetimi
- Organizasyonlar arasında (sandbox’tan üretime veya bir müşteri ortamından diğerine) konfigürasyon değişikliklerini aktarma
- Mevcut organizasyon yapılandırmalarının yedeklerini alıp saklama
- Organizasyon konfigürasyonlarını kod olarak (Configuration as Code) yönetme
Deployment Otomasyonu
- Sürekli Entegrasyon/Sürekli Dağıtım (CI/CD) pipeline’larında otomatik build ve deployment işlemleri
- Planlı release’ler için otomatikleştirilmiş deployment süreçleri oluşturma
- Çoklu ortamlara paralel deploymentlar gerçekleştirme
DevOps Entegrasyonu
- Git gibi versiyon kontrol sistemleriyle entegrasyon
- Jenkins, GitHub Actions veya Azure DevOps gibi CI/CD araçlarıyla entegre çalışma
- Deployment süreçlerini izleme ve raporlama
Metadata API ile Çalışmaya Başlama
Metadata API ile çalışmaya başlamadan önce, aşağıdaki gereksinimleri sağladığınızdan emin olmalısınız:
- API Erişimi Olan Salesforce Hesabı: Organizasyonunuzda API erişiminizin etkinleştirilmiş olması gerekir.
- Kimlik Doğrulama Bilgileri: Kullanıcı adı, şifre ve güvenlik token’ı veya OAuth 2.0 kimlik doğrulaması.
- WSDL Dosyası: Metadata API’ye erişmek için Enterprise WSDL veya Partner WSDL dosyasına ihtiyacınız var.
Bağlantı Kurma
Metadata API’ye bağlanmak için öncelikle bir kimlik doğrulama yöntemi seçmelisiniz. En yaygın yöntemler şunlardır:
Kullanıcı Adı-Şifre Kimlik Doğrulaması:
// Java örneği
ConnectorConfig config = new ConnectorConfig();
config.setUsername(“[email protected]“);
config.setPassword(“sifre+guvenlikToken“);
config.setAuthEndpoint(“https://login.salesforce.com/services/Soap/c/55.0“);
MetadataConnection metadataConnection = com.sforce.soap.metadata.Connector.newConnection(config);
OAuth 2.0 Kimlik Doğrulaması:
// Node.js örneği (JSForce kullanarak)
const jsforce = require(‘jsforce‘);
const conn = new jsforce.Connection({
oauth2: {
clientId: ‘CONNECTED_APP_CLIENT_ID’,
clientSecret: ‘CONNECTED_APP_CLIENT_SECRET’,
redirectUri: ‘CALLBACK_URL’
}
});
conn.login(‘[email protected]’, ‘sifre+guvenlikToken’, (err, userInfo) => {
if (err) { return console.error(err); }
// Metadata API’ye erişim
conn.metadata.list([{type: ‘CustomObject’}], function(err, results) {
if (err) { return console.error(err); }
console.log(‘metadata list: ‘, results);
});
});
API Sürümü Seçimi
Metadata API’nin hangi sürümünü kullanacağınızı belirtmek önemlidir. Genellikle, organizasyonunuzun desteklediği en son sürümü kullanmanız önerilir, ancak bazı durumlarda belirli bir sürümü kullanmanız gerekebilir.
<!– SOAP isteği örneği –>
<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/”
xmlns:met=”http://soap.sforce.com/2006/04/metadata”>
<soapenv:Header>
<met:SessionHeader>
<met:sessionId>SESSION_ID</met:sessionId>
</met:SessionHeader>
</soapenv:Header>
<!– API çağrıları burada –>
</soapenv:Envelope>
Temel Metadata Operasyonları
Metadata API ile gerçekleştirebileceğiniz temel işlemler şunlardır:
1. Metadata Bileşenlerini Okuma (Retrieve)
Mevcut bir organizasyondaki belirli metadata bileşenlerini almak için retrieve işlemi kullanılır:
// Java örneği
RetrieveRequest retrieveRequest = new RetrieveRequest();
retrieveRequest.setApiVersion(55.0);
// Belirli bir paket içeriğini alma
retrieveRequest.setPackageNames(new String[] { “MyPackage” });
// Veya belirli metadata türlerini alma
retrieveRequest.setSpecificFiles(new String[] { “objects/Account.object” });
AsyncResult asyncResult = metadataConnection.retrieve(retrieveRequest);
RetrieveResult result = metadataConnection.checkRetrieveStatus(asyncResult.getId());
// Sonuçları işleme
if (result.getStatus() == RetrieveStatus.Succeeded) {
// Metadata zip dosyasını kullanma
byte[] zipBytes = result.getZipFile();
// Zip’ten dosyaları çıkarma ve işleme…
}
2. Metadata Bileşenlerini Yazma (Deploy)
Organizasyona yeni metadata bileşenleri eklemek veya mevcut olanları güncellemek için deploy işlemi kullanılır:
// Node.js örneği (JSForce kullanarak)
// Metadata dosyaları zip dosyasında paketlenir
const zipBuffer = fs.readFileSync(‘metadata.zip’);
conn.metadata.deploy(zipBuffer, { rollbackOnError: true })
.on(‘progress’, (result) => {
console.log(`Deploy ID: ${result.id}`);
console.log(`Status: ${result.status}`);
console.log(`Tamamlanan: ${result.numberComponentsDeployed}/${result.numberComponentsTotal}`);
})
.complete((err, result) => {
if (err) { return console.error(err); }
console.log(`Deployment ${result.status}`);
if (result.status === ‘Failed’) {
// Hata detaylarını işleme
console.error(result.details.componentFailures);
}
});
3. Metadata Bileşenlerini Silme
Organizasyondan metadata bileşenlerini kaldırmak için:
// Java örneği
DeleteMetadata deleteMetadata = new DeleteMetadata();
deleteMetadata.setType(“CustomObject”);
deleteMetadata.setFullNames(new String[] { “CustomObject__c” });
AsyncResult[] results = metadataConnection.deleteMetadata(deleteMetadata);
for (AsyncResult result : results) {
if (result.isSuccess()) {
System.out.println(“Bileşen başarıyla silindi.”);
} else {
System.out.println(“Hata: “ + result.getStatusCode() + ” – “ + result.getMessage());
}
}
İleri Seviye Kullanım
Batch İşlemleri
Metadata API’nin çağrı limitleri bulunmaktadır. Bu limitleri aşmamak ve büyük miktarda metadata ile çalışmak için batch işlemleri kullanabilirsiniz:
// Node.js örneği – Batch işlemi
const metadataTypes = [
{ type: ‘CustomObject‘, folder: null },
{ type: ‘Layout’, folder: null },
{ type: ‘ApexClass’, folder: null }
]
// Her tür için ayrı ayrı list çağrısı yapma
Promise.all(metadataTypes.map(type => {
return new Promise((resolve, reject) => {
conn.metadata.list([type], (err, results) => {
if (err) { return reject(err); }
resolve(results);
});
});
}))
.then(results => {
// Tüm sonuçları birleştirme
const allMetadata = [].concat(…results);
console.log(`Toplam ${allMetadata.length} metadata bileşeni bulundu.`);
})
.catch(err => {
console.error(‘Hata:’, err);
});
Async Operasyonlar
Büyük metadata işlemleri zaman alabilir. Asenkron işlemlerle, uzun süren işlemleri başlatabilir ve daha sonra durumlarını kontrol edebilirsiniz:
// Java örneği – Asenkron deployment
DeployOptions deployOptions = new DeployOptions();
deployOptions.setPerformRetrieve(false);
deployOptions.setRollbackOnError(true);
deployOptions.setTestLevel(TestLevel.RunLocalTests);
AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
String deployId = asyncResult.getId();
// Deployment durumunu kontrol etme
boolean isDone = false;
DeployResult deployResult = null;
while (!isDone) {
Thread.sleep(5000); // 5 saniye bekle
deployResult = metadataConnection.checkDeployStatus(deployId, true);
isDone = deployResult.isDone();
System.out.println(“Deploy durumu: “ + deployResult.getStatus() +
“, Tamamlanan: “ + deployResult.getNumberComponentsDeployed() +
“/” + deployResult.getNumberComponentsTotal());
}
if (deployResult.getStatus() == DeployStatus.Succeeded) {
System.out.println(“Deployment başarılı!”);
} else {
// Hataları işleme
DeployMessage[] msgs = deployResult.getMessages();
for (DeployMessage msg : msgs) {
if (msg.getProblem() != null) {
System.out.println(“Hata: “ + msg.getFileName() + ” – “ + msg.getProblem());
}
}
}
Büyük Ölçekli Deploymentlar İçin Stratejiler
Büyük organizasyonlarda çalışırken, deployment stratejinizi optimize etmek önemlidir:
- Seçici Deployment: Sadece değişen bileşenleri deploy edin, tüm paketi değil.
- Paralel İşlemler: Bağımsız bileşenleri paralel olarak deploy edin.
- Test Stratejisi: Deployment sırasında çalıştırılacak testleri akıllıca seçin (TestLevel kullanımı).
- Validasyon: Gerçek deployment öncesinde validateOnly=true ile doğrulama yapın.
// Node.js örneği – Validasyon sonra deployment
// Önce validasyon
conn.metadata.deploy(zipBuffer, {
validateOnly: true,
testLevel: ‘RunLocalTests’
})
.complete((err, result) => {
if (err) { return console.error(err); }
if (result.success) {
console.log(‘Validasyon başarılı, gerçek deployment başlatılıyor…’);
// Validasyon başarılıysa, gerçek deployment
conn.metadata.deploy(zipBuffer, {
rollbackOnError: true,
testLevel: ‘RunLocalTests’
})
.complete((err, finalResult) => {
if (err) { return console.error(err); }
console.log(`Deployment ${finalResult.status}`);
});
} else {
console.error(‘Validasyon başarısız:’, result.details.componentFailures);
}
});
En İyi Uygulama Örnekleri
Performans Optimizasyonu
- Küçük Paketler: Büyük tek bir deployment yerine, küçük mantıksal paketlerle çalışın.
- Öncelik Sırası: Bağımlılıklara sahip bileşenleri doğru sırada deploy edin.
- Paketleme Stratejisi: İlişkili bileşenleri birlikte paketleyin (örn. özel nesneler ve ilgili alanları).
Güvenlik En İyi Uygulamaları
- Kimlik Bilgileri Yönetimi: API anahtarları ve kimlik bilgilerini asla kod içinde saklamamalısınız.
- En Az Ayrıcalık İlkesi: Deployment kullanıcılarına sadece gerekli minimum izinleri verin.
- IP Kısıtlamaları: Mümkünse, API erişimlerini belirli IP adresleriyle sınırlandırın.
// Node.js örneği – Güvenli bağlantı yönetimi
require(‘dotenv’).config(); // .env dosyasından çevre değişkenlerini yükleme
const conn = new jsforce.Connection({
oauth2: {
clientId: process.env.SF_CLIENT_ID,
clientSecret: process.env.SF_CLIENT_SECRET,
redirectUri: process.env.SF_REDIRECT_URI
},
instanceUrl: process.env.SF_INSTANCE_URL,
accessToken: process.env.SF_ACCESS_TOKEN,
refreshToken: process.env.SF_REFRESH_TOKEN
});
// Refresh token kullanarak token yenileme
conn.on(‘refresh’, function(accessToken, res) {
// Yeni token’ı güvenli bir şekilde saklama
console.log(‘Access token yenilendi’);
});
CI/CD Pipeline’larında Metadata API Kullanımı
Metadata API, Jenkins, GitHub Actions veya GitLab CI gibi CI/CD araçlarıyla entegre edilebilir:
# GitHub Actions workflow örneği
name: Salesforce Deployment
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v2
– name: ‘Node.js kurulumu’
uses: actions/setup-node@v2
with:
node-version: ’14’
– name: ‘Bağımlılıkları yükleme’
run: npm install jsforce
– name: ‘Salesforce Deployment’
env:
SF_USERNAME: ${{ secrets.SF_USERNAME }}
SF_PASSWORD: ${{ secrets.SF_PASSWORD }}
SF_TOKEN: ${{ secrets.SF_TOKEN }}
SF_LOGIN_URL: ${{ secrets.SF_LOGIN_URL }}
run: |
node ./scripts/deploy-metadata.js
Örnek Kullanım Senaryoları
Senaryo 1: Çoklu Ortam Yönetimi
Birçok organizasyon, geliştirme, test, kalite kontrol ve üretim gibi çoklu ortamlara sahiptir. Bu ortamlar arasında konfigürasyon değişikliklerini yönetmek için Metadata API kullanabilirsiniz:
// Node.js örneği – Ortam bazlı deployment scripti
const environments = {
dev: {
username: process.env.DEV_USERNAME,
password: process.env.DEV_PASSWORD,
loginUrl: ‘https://test.salesforce.com’
},
qa: {
username: process.env.QA_USERNAME,
password: process.env.QA_PASSWORD,
loginUrl: ‘https://test.salesforce.com’
},
prod: {
username: process.env.PROD_USERNAME,
password: process.env.PROD_PASSWORD,
loginUrl: ‘https://login.salesforce.com’
}
};
const targetEnv = process.argv[2] || ‘dev’;
const env = environments[targetEnv];
if (!env) {
console.error(`Hata: ‘${targetEnv}‘ ortamı bulunamadı.`);
process.exit(1);
}
// Seçilen ortama bağlanma ve deployment yapma
const conn = new jsforce.Connection({
loginUrl: env.loginUrl
});
conn.login(env.username, env.password + env.securityToken, (err, userInfo) => {
if (err) { return console.error(err); }
console.log(`${targetEnv} ortamına bağlandı: ${userInfo.organizationId}`);
// Deployment işlemleri…
});
Senaryo 2: Otomatik Konfigürasyon Yönetimi
Standart bir ortam oluşturmak veya tekrarlayan konfigürasyon değişikliklerini otomatikleştirmek için Metadata API kullanabilirsiniz:
// Java örneği – Standart profil konfigürasyonu
public void configureStandardProfiles() {
Profile adminProfile = new Profile();
adminProfile.setFullName(“Admin”);
ProfileObjectPermissions accountPerms = new ProfileObjectPermissions();
accountPerms.setObject(“Account”);
accountPerms.setAllowCreate(true);
accountPerms.setAllowRead(true);
accountPerms.setAllowEdit(true);
accountPerms.setAllowDelete(true);
accountPerms.setViewAllRecords(true);
accountPerms.setModifyAllRecords(true);
adminProfile.setObjectPermissions(new ProfileObjectPermissions[] { accountPerms });
Metadata[] metadata = new Metadata[] { adminProfile };
SaveResult[] results = metadataConnection.updateMetadata(metadata);
for (SaveResult result : results) {
if (result.isSuccess()) {
System.out.println(“Profil güncellendi.”);
} else {
System.out.println(“Hata: “ + result.getErrors()[0].getMessage());
}
}
}
Senaryo 3: Organizasyon Analizi ve Dökümantasyonu
Metadata API, mevcut bir organizasyonun kapsamlı bir envanterini çıkarmak için kullanılabilir:
// Node.js örneği – Organizasyon envanteri oluşturma
async function createOrgInventory() {
const metadataTypes = [
‘ApexClass’, ‘ApexTrigger’, ‘CustomObject’, ‘CustomField’,
‘Layout’, ‘Profile’, ‘PermissionSet’, ‘Flow’, ‘Dashboard’
];
const inventory = {};
for (const type of metadataTypes) {
try {
const results = await conn.metadata.list([{ type: type }]);
inventory[type] = Array.isArray(results) ? results : [results];
console.log(`${type}: ${inventory[type].length} bileşen bulundu.`);
} catch (err) {
console.error(`${type} listelenirken hata oluştu:`, err);
inventory[type] = [];
}
}
// Envanter raporunu oluşturma ve kaydetme
const report = JSON.stringify(inventory, null, 2);
fs.writeFileSync(‘org-inventory.json’, report);
console.log(‘Organizasyon envanteri oluşturuldu: org-inventory.json’);
}
Salesforce Otomasyonunuzun Gücünü Artırın
Salesforce Metadata API, geliştirme süreçlerinizi otomatikleştirmek, organizasyonlar arası değişiklikleri yönetmek ve DevOps uygulamalarınızı entegre etmek için güçlü bir araçtır. Bu rehberde temel kavramlardan ileri düzey tekniklere kadar Metadata API’nin nasıl kullanılacağını inceledik.
API’yi etkili bir şekilde kullanarak, manuel konfigürasyon değişikliklerinden kaynaklanan hataları azaltabilir, deployment süreçlerinizi hızlandırabilir ve geliştirme ekibinizin verimliliğini artırabilirsiniz.
Salesforce geliştirme yolculuğunuzda bir sonraki adım olarak, projelerinizde Salesforce DX araçlarını keşfedebilir veya Metadata API’yi kullanarak kendi özel CI/CD pipeline’ınızı oluşturabilirsiniz.