[Spring '24] 気になるリリースをピックアップ ~Apex関連~
はじめに
こんにちは、荒武です。
Spring '24のリリースノートから気になるリリースをピックアップするシリーズ記事となります。
この記事では自分がSpring '24のリリースノートの中からApex関連で気になったトピックをピックアップして紹介します。
今回私がピックアップしたのは以下の5つになります。
Null 合体演算子の使用
ランダムに生成される UUID v4 のサポート
Apex での Zip ファイルの圧縮および抽出 (開発者プレビュー)
Apex での動的な数式の評価 (開発者プレビュー)
DML のロールバックとセーブポイントの解放後のコールアウトの実行
Null 合体演算子の使用
null合体演算子(??)が使えるようになりました。
?? 演算子では、左側の引数が null でない場合に左側の引数が返されます。null の場合は、右側の引数が返されます。
// 三項演算子
Integer notNullReturnValue = (anInteger == null) ? anInteger : 100;
// null合体演算子
Integer notNullReturnValue = anInteger ?? 100;
SOQLでレコードが返ってこなかった場合のデフォルト値指定にも利用することができます。(便利ですね)
Account defaultAccount = new Account(name = 'Acme');
// null合体演算子でdefaultAccountを指定していると例外が発生しない
Account a = [SELECT Id FROM Account
WHERE Id = '001000000FAKEID'] ?? defaultAccount;
ランダムに生成される UUID v4 のサポート
新しい UUID クラスを使用して、バージョン 4 のユニバーサル一意識別子 (UUID) を生成することができるようになりました。
UUID randomUuid = UUID.randomUUID();
Apex での Zip ファイルの圧縮および抽出 (開発者プレビュー)
Compression 名前空間のメソッドを使用して、圧縮された zip ファイルを簡単に生成および抽出できるようになりました。
(この機能が使用でできるのはApexZipSupport 機能が有効になっているスクラッチ組織となっています。)
ZipWriter writer = new ZipWriter();
List<id> contentDocumentIds = new List<id>();
// 圧縮したいドキュメントのidをcontentDocumentIdsに詰め込む
for ( ContentVersion cv : [SELECT PathOnClient, Versiondata
FROM ContentVersion
WHERE ContentDocumentId IN :contentDocumentIds]) {
writer.addEntry(cv.PathOnClient, cv.versiondata);
}
blob zipAttachment = writer.getArchive();
blob zipAttachment = writer.getArchive();
Messaging.EmailFileAttachment efa1 = new Messaging.EmailFileAttachment();
efa.setFileName('attachments.zip');
efa.setBody(zipAttachment);
fileAttachments.add(efa);
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
// アドレスや件名等をセットする
email.setEntityAttachments(fileAttachments);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
Apex での動的な数式の評価 (開発者プレビュー)
新しい FormulaEval 名前空間のクラスを使用して、Apex オブジェクトおよび sObject のユーザー定義数式を評価できるようになりました。
(この機能が使用できるのは、FormulaEvalInApex 機能が有効になっているスクラッチ組織となっています。)
global class MotorYacht {
global Integer lengthInYards;
global Integer numOfGuestCabins;
global String name;
global Account owner;
}
MotorYacht aBoat = new MotorYacht();
aBoat.lengthInYards = 52;
aBoat.numOfGuestCabins = 4;
aBoat.name = 'RV Foo';
FormulaEval.FormulaInstance isItSuper = FormulaEval.FormulaBuilder.builder()
.withReturnType(FormulaEval.FormulaReturnType.STRING)
.withType(MotorYacht.class)
.withFormula('IF(lengthInYards < 100, "Not Super", "Super")')
.build();
isItSuper.evaluate(aBoat); //=> "Not Super"
aBoat.owner = new Account(Name='Acme Watercraft', Site='New York');
FormulaEval.FormulaInstance ownerDetails = FormulaEval.FormulaBuilder.builder()
.withReturnType(FormulaEval.FormulaReturnType.STRING)
.withType(MotorYacht.class)
.withFormula('owner.Name & " (" & owner.Site & ")"')
.build();
ownerDetails.evaluate(aBoat); //=> "Acme Watercraft (New York)"
DML のロールバックとセーブポイントの解放後のコールアウトの実行
これまで、セーブポイントの作成後にコールアウトを実行すると、コミットされていない DML があるかどうか、または変更がセーブポイントにロールバックされているかどうかに関係なくCalloutException が発生していましたが、ロールバック後にDatabase.releaseSavepoint メソッドを使用するとコールアウトが実行できるようになりました。
Savepoint sp = Database.setSavepoint();
try {
// Try a database operation
insert new Account(name='Foo');
integer bang = 1 / 0;
} catch (Exception ex) {
Database.rollback(sp);
Database.releaseSavepoint(sp); // 'sp'以降に作成されたすべてのセーブポイントも開放する必要がある。
makeACallout(); // ロールバックし、セーブポイントを開放しているのでコールアウト可能
}
おわりに
以上がピックアップになります。null合体演算子なんかは便利なのですぐに使えそうですね。数式の評価やロールバック後のコールアウトの実行も色々実装の幅を広げてくれそうです🙏