salesforce 零基础学习(五十四)常见异常友好消息提示
异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_concepts_core_data_objects.htm
做项目的时候有很多异常是我们经常遇到的:
1.空指针异常;
2.死锁或者超时;
3.级联删除时无级联表操作权限导致删除失败;
4.一次请求查询超过50000条数据;
5.查询时偏移量超过2000;
6.不满足Validation Rule条件;
7.必填字段为空;
8.unique字段记录添加重复。
上述问题很多可以封装公共方法来捕获异常并且返回友好的提示信息,免得将异常直接抛出,导致用户一头雾水。
此篇针对常见异常进行最基本的封装,方便后期项目有类似需求可以直接使用。
ErrorHelper:此类封装的getUserFriendlyMessage方法用于当程序操作出现异常时,可以返回友好的错误提示信息,第一个参数是errormessage,即error.getMessage(),第二个参数为sObject的API Name。
global with sharing class ErrorHelper {
private static final String NULL_POINTER_EXCEPTION = '空指针错误';
private static final String RECORD_ALREADY_INPROCESS = '记录已经被锁定';
private static final String RECORD_OVER_LIMIT = '查询最多只能50000条,请输入搜索条件重新搜索';
private static final String RECORD_OFFSET_OVER_LIMIT = '数据最多只能查询当前检索条件前2000条,请更改检索条件重试';
private static final String RECORD_ALREADY_IN_PROCESS = '当前记录已经在流程中,如有问题,请与管理员联系';
public static String getUserFriendlyMessage(String msg,String sObjectName) {
String errorMessage;
//空指针错误:System.NullPointerException: Attempt to de-reference a null object
if(msg.contains('NullPointerException')){
errorMessage = NULL_POINTER_EXCEPTION;
}
//死锁或者超时
else if(msg.contains('UNABLE_TO_LOCK')){
errorMessage = RECORD_ALREADY_INPROCESS;
}
//级联删除,没有当前表或者关联表权限导致的错误
else if(msg.contains('DELETE_REQUIRED_ON_CASCADE')) {
}
//查询50001
else if(msg.contains('Too many query rows')) {
errorMessage = RECORD_OVER_LIMIT;
}
//offset 超过2000
else if(msg.contains('Maximum SOQL offset allowed is 2000')) {
errorMessage = RECORD_OFFSET_OVER_LIMIT;
}
//当前记录已经在审批流中
else if(msg.contains('ALREADY_IN_PROCESS')) {
errorMessage = RECORD_ALREADY_IN_PROCESS;
}
//Validation Rule失败
//eg: Update failed. First exception on row 0 with id a052800000BvtqEAAR; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, 商品价格不能为空且必须大于0.: [GoodsPrice__c]
else if (msg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')){
errorMessage = getUserFriendlyMessage4ValidationException(msg,sObjectName);
}
//必填字段
//eg:Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Company_Name__c]: [Company_Name__c]
else if(msg.contains('REQUIRED_FIELD_MISSING')){
errorMessage = getUserFriendlyMessage4RequiredField(msg,sObjectName);
}
//对于unique的字段进行相同值插入会报此种错误:System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, duplicate value found: Company_Code_Unique__c duplicates value on record with id: a032800000KOlEr: []
else if(msg.contains('DUPLICATE_VALUE')) {
errorMessage = getUserFriendlyMessage4DuplicateValue(msg,sObjectName);
}
return errorMessage;
}
/**
*针对unique字段添加重复值的异常获取友好的message
*@param msg : 异常信息 eg : System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, duplicate value found: Company_Code_Unique__c duplicates value on record with id: a032800000KOlEr: []
*@param sObjectName : sObject的API Name
*@return
*/
private static String getUserFriendlyMessage4DuplicateValue(String msg,String sObjectName) {
String errorMessage = msg;
Integer pointer;
String fieldName;
if(!msg.contains('DUPLICATE_VALUE')) {
return errorMessage;
}
pointer = errorMessage.indexOf('DUPLICATE_VALUE') + 16;
if(pointer > -1) {
errorMessage = errorMessage.mid(pointer, errorMessage.length());
}
pointer = errorMessage.indexOf('duplicates');
if(pointer > -1) {
errorMessage = errorMessage.mid(0,pointer);
}
pointer = errorMessage.indexOf(':') + 1;
if(pointer > -1) {
fieldName = errorMessage.mid(pointer,errorMessage.length()).trim();
Schema.DescribeFieldResult fieldResult = getSObjectFieldDescribeResult(sObjectName,fieldName);
if(fieldResult != null) {
fieldName = fieldResult.getLabel();
}
}
errorMessage = errorMessage.mid(0,pointer) + fieldName;
return errorMessage;
}
/**
*针对Validation Rule的异常获取友好的message
*@param msg : 异常消息 eg: Update failed. First exception on row 0 with id a052800000BvtqEAAR; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, 商品价格不能为空且必须大于0.: [GoodsPrice__c]
*@param sObjectName : sObject的API Name
*@return 返回有问题的field labe + : + error message (eg : GoodsPrice : 商品价格不能为空且必须大于0.)
*/
private static String getUserFriendlyMessage4ValidationException(String msg,String sObjectName){
String errorMessage = msg;
Integer pointer;
String fieldName;
if (msg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')){
pointer = errorMessage.indexOf('FIELD_CUSTOM_VALIDATION_EXCEPTION,') + 34;
errorMessage = errorMessage.mid(pointer, errorMessage.length());
} else {
return msg;
}
pointer = errorMessage.indexOf('\n');
if(pointer > -1){
errorMessage = errorMessage.mid(0, pointer);
}
pointer = errorMessage.indexOf(':');
if(pointer > -1){
//去除error message中的 []
fieldName = errorMessage.mid(pointer + 1,errorMessage.length()-1).remove('[').remove(']').trim();
errorMessage = errorMessage.mid(0, pointer);
}
if(fieldName != null) {
Schema.DescribeFieldResult fieldDescribeResult = getSObjectFieldDescribeResult(sObjectName,fieldName);
if(fieldDescribeResult != null) {
errorMessage = fieldDescribeResult.getLabel() + ' : ' + errorMessage;
}
}
return errorMessage;
}
/**
* 针对必填字段获取友好的message
* @param msg : 异常消息 eg: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Company_Name__c]: [Company_Name__c]
* @param sObjectName : sObject的API Name
* @return : 友好消息 eg : Required fields are missing: Company Name (field label name)
*/
private static String getUserFriendlyMessage4RequiredField(String msg,String sObjectName){
String errorMessage = msg;
if(!errorMessage.contains('first error:')) {
return errorMessage;
}
Integer pointer;
String fieldName;
//获取first error 以后的message信息
pointer = errorMessage.indexOf('first error:') + 12;
errorMessage = errorMessage.mid(pointer, errorMessage.length());
if(pointer > -1){
pointer = errorMessage.indexOf(',') + 1;
errorMessage = errorMessage.mid(pointer, errorMessage.length());
}
pointer = errorMessage.indexOf(']:');
if(pointer > -1){
errorMessage = errorMessage.mid(0, pointer + 1);
}
fieldName = errorMessage.mid(errorMessage.indexOf('[') + 1,errorMessage.indexOf(']')-errorMessage.indexOf('[')-1).trim();
if(fieldName != null) {
Schema.DescribeFieldResult fieldResult = getSObjectFieldDescribeResult(sObjectName,fieldName);
if(fieldResult != null) {
fieldName = fieldResult.getLabel();
}
}
pointer = errorMessage.indexOf('[');
if(pointer > -1){
errorMessage = errorMessage.mid(0, pointer);
}
errorMessage += fieldName;
return errorMessage;
}
/*
* 通过sObject名称以及field名称获取field相关describe result信息
* @param sObjectName object的api name
* @param fieldName field的api name
* @return 此field的describe result
*/
private static Schema.DescribeFieldResult getSObjectFieldDescribeResult(String sObjectName,String fieldName) {
List<Schema.DescribeSObjectResult> sObjectResultList = Schema.describeSObjects(new String[]{sObjectName});
if(sObjectResultList == null || sObjectResultList.size() == 0) {
return null;
} else {
Schema.DescribeSObjectResult sObjectResult = sObjectResultList.get(0);
Map<String,SObjectField> maps = sObjectResult.fields.getMap();
Schema.SObjectField sObjectField = maps.get(fieldName);
if(sObjectField == null) {
return null;
} else {
Schema.DescribeFieldResult fieldDescribeResult = sObjectField.getDescribe();
return fieldDescribeResult;
}
}
}
}
使用演示:
1.Unique字段插入重复

2.必填字段为空

3.Validation Rule未通过

总结:此篇主要封装简单的异常的友好显示。当前很多常量都放在了程序里,建议放在custom label中,然后对相关进行translate,这样可以保证国际化使用,否则现在language为英文可以,中文使用会有问题,有用到的可以自行优化。
salesforce 零基础学习(五十四)常见异常友好消息提示的更多相关文章
- salesforce 零基础学习(十六)Validation Rules & Date/time
上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules. 本篇参考PDF: Date/time:https://r ...
- salesforce 零基础学习(十九)Permission sets 讲解及设置
Permission sets以及Profile是常见的设置访问权限的方式. Profile规则为'who see what'.通过Profile可以将一类的用户设置相同的访问权限.对于有着相同Pro ...
- salesforce 零基础学习(十八)WorkFlow介绍及用法
说起workflow大家肯定都不陌生,这里简单介绍一下salesforce中什么情况下使用workflow. 当你分配许多任务,定期发送电子邮件,记录修改时,可以通过自动配置workflow来完成以上 ...
- salesforce零基础学习(九十四)classic下pagelayout引入的vf page弹出内容更新此page layout
我们在classic环境中,有时针对page layout不能实现的地方,可以引入 一个vf page去增强标准的 page layout 功能,有时可能要求这个 vf page的部分修改需要更新此 ...
- salesforce 零基础学习(五十二)Trigger使用篇(二)
第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...
- salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现
项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...
- salesforce零基础学习(八十九)使用 input type=file 以及RemoteAction方式上传附件
在classic环境中,salesforce提供了<apex:inputFile>标签用来实现附件的上传以及内容获取.salesforce 零基础学习(二十四)解析csv格式内容中有类似的 ...
- salesforce零基础学习(一百零五)Change Data Capture
本篇参考: https://developer.salesforce.com/docs/atlas.en-us.232.0.api_streaming.meta/api_streaming/using ...
- salesforce零基础学习(一百一十)list button实现的一些有趣事情
本篇参考: salesforce零基础学习(九十五)lightning out https://developer.salesforce.com/docs/component-library/docu ...
随机推荐
- 【.net 深呼吸】细说CodeDom(5):类型成员
前文中,老周已经厚着脸皮介绍了类型的声明,类型里面包含的自然就是类型成员了,故,顺着这个思路,今天咱们就了解一下如何向类型添加成员. 咱们都知道,常见的类型成员,比如字段.属性.方法.事件.表示代码成 ...
- C# 发送邮件 附件名称为空
示例代码: // 1.创建邮件 MailMessage mailMsg = new MailMessage(); mailMsg.To.Add(new MailAddress("test@ ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- 学习ASP.NET Core, 怎能不了解请求处理管道[6]: 管道是如何随着WebHost的开启被构建出来的?
注册的服务器和中间件共同构成了ASP.NET Core用于处理请求的管道, 这样一个管道是在我们启动作为应用宿主的WebHost时构建出来的.要深刻了解这个管道是如何被构建出来的,我们就必须对WebH ...
- C++中的引用
一,C++中引用的基础知识 1.引用的基本概念 1.所谓的引用其实就是对变量起“别名”.引用和变量对应得是相同的内存,修改引用的值,变量的值也会改变,和指针类似. 2.引用在定义的时候必须要初始化,初 ...
- Node.js:进程、子进程与cluster多核处理模块
1.process对象 process对象就是处理与进程相关信息的全局对象,不需要require引用,且是EventEmitter的实例. 获取进程信息 process对象提供了很多的API来获取当前 ...
- gitHub使用入门和github for windows的安装教程
在看这篇教程之前我想大家也在搜索怎样使用gitHub托管自己的项目,在使用gitHub之前我也遇到过各种问题,在网上我也搜索了很多,但总觉得网上搜索到的东西很多很杂,有的根本不知道是在表达什么.在这过 ...
- Android 几种消息推送方案总结
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6241354.html 首先看一张国内Top500 Android应用中它们用到的第三方推送以及所占数量: 现 ...
- ZKWeb网页框架1.3正式发布
本次更新的内容有 更新引用包版本 Microsoft.AspNetCore.Hosting.Abstractions 1.1.0 Microsoft.AspNetCore.Http.Abstracti ...
- Newtonsoft.Json设置类的属性不序列化
参考页面: http://www.yuanjiaocheng.net/webapi/parameter-binding.html http://www.yuanjiaocheng.net/webapi ...