如何在Salesforce中使用匿名块建立每小时执行一次的Scheduler

在Salesforce中建立Scheduler的方式有两种

  1. 在Develop->Apex Classes页面,点击Schedule Apex按钮之后会提供如下的面板。

    这个面板虽然能方便的决定Scheduler执行的频率,但是最高频率也只能是一天一次。
  2. 再有就是使用Apex。在匿名块中使用系统函数设定Scheduler,可以获得更高的频率。

所以,如果想设定一小时执行的Scheduler就必须使用第二种方式。
需要使用的函数为System.schedule();
官方文档对此进行了详细的描述。具体参照下列示例代码。

// Sample 1 hour 1 time
System.schedule('My Scheduler','0 0 0/1 * * ?', new MyScheduler()); 

作为一个成熟的完善的系统,定时器与后台Job是必须的组成部分。
Scheduler就是Linux Cron的强力山寨。
所以System.schedule()中的第二个参数,就等同于Cron表达式(当然,只能算一个子集)。

为什么要把一小时一次单独拎出来,因为,这是Scheduler的最小粒度。
Scheduler表达式的秒位与分位是不支持“/”符号的。

所以,想几分钟执行一次的,放弃吧。

Salesforce使用truncate清空数据库

如果想快速的清空MySQL中的表,可以使用Truncate命令。
Truncate能够快速的,对数据进行无差别的清空。

在Mysql中使用truncate的语法是
TRUNCATE TABLE [Table Name];

在Salesforce中同样提供了Truncate功能。不过只是提供一个按钮,并不提供任何代码及API调用Truncate的方式。
所以正确的应用场景,应该只是用来快速的清空临时数据或者测试数据。毕竟,无论使用Batch还是dataloader来删除全部数据都要花费大量的时间。

在Salesforce中想要看到Truncate按钮的话,需要达成如下条件,参考官方文档:

  1. Profile -> Administrative Permissions -> Customize Application -> True
  2. User Interface -> Setup -> Enable Custom Object Truncate -> True

然后在到Custom Object的详细画面,就能看到在Edit,Delete按钮旁边Truncate按钮出现了。

不过,并不是任何Object任何情况都能进行Truncate,有如下要求,参考官方文档:

  1. 不能被别的Object Lookup,或者处在Master-Detail中的Master地位。
  2. 不能被Report Snapshot参照。
  3. 不能有自定义字段是Index或者是External ID。
  4. 不能开启了skinny table。(关于Skinny Table的事情会另外写一篇)。

为什么会有如上的限制,显而易见,与Salesforce中Truncate的动作有关。
在Salesforce中,虽然Truncate功能与MySQL类似,用来清空表中的数据,但是会导致Custom Object的Id Prefix产生变化。所以所有通过三位Id Prefix引用此Custom Object的功能都会失效。如果Apex/VF/Button中有直接使用3位Id Prefix进行判断的逻辑,就会受到影响。

除此之外,另一点与MySQL不用的是,如果有一个自增字段。MySQL在Truncate后,会重置自增字段的计数器。而Salesforce则不会。没错,虽然ID变了,但自增字段会接着数并不会重新回到起始值。

匿名块中SavePoint的使用技巧

经常要使用匿名块验证代码片段的可用性,尤其是在写测试类的时候。一个很长的测试类,一口气写完,再逐一排查问题是很低效的。

但是,使用匿名块执行代码片段的话,插入数据或者修改数据的动作就会对数据库造成实际的影响。这个时候,我们就可以使用SavePoint来避免这个问题。

如下

Savepoint sp = Database.setSavepoint();

// Place your code here

Database.rollback(sp);

这样,如果DML代码成功了,也不会对数据库造成任何影响。

关于SavePoint和Rollback,参照官方文档

CentOS搭建Java Web环境

题外话:首先痛斥国内“技术”博客圈的拿来风。用汉语搜索到的基本上都是重复的内容,如果最开始的人写错了,那么所有人一起错。或者明明第一篇文章是五年前写出来的,技术环境已经都废弃了,结果到现在还有人转。连最基本的验证都不做。

下面进入正题:
全世界大部分的网站都是PHP做成的。所以各大VPS供应商都提供了一键PHP安装环境。或者各个社区也提供了方便的一键PHP环境安装脚本。相比之下,JAVA就没这么好运了。

之前买了一个搬瓦工的VPS想部署JAVA代码。结果一直被误导。今日虽然已经深夜,仍然打算将此过程记下来。
记住,做成时间2017/01/15。时间太长之后就别参照了。一切都在变。

下面是步骤。

  1. 进入搬瓦工后台,选择系统,CentOS7 64位。 等待重装完毕。
  2. 用Putty进入服务器后台。SSH的端口和密码在重装系统时会自动提供。
  3. 首先安装Java,使用 yum install java即可。一路y,默认安装的应该是OpenJDK(Oracle在Do evil)。
  4. 然后执行java -version查看java版本,以此确认java安装是否正常。现在为OpenJDK1.8。
  5. 之后安装Tomcat。执行yum install tomcat tomcat-webapps tomcat-admin-webapps。网上文章最坑人的地方在于,都是写Tomcat6。其实早就不带版本号了。
  6. 然后一路Y。
  7. 去etc/tomcat路径下面去修改各配置文件。比如Server.xml,tomcat-users.xml,web.xml等。
  8. webapps路径会在/var/lib/tomcat/webapps。根目录是ROOT。
  9. 之后执行service tomcat start会启动服务。
  10. 执行service tomcat stop停止服务。
  11. 执行service tomcat restart重启服务。

//TODO 设置服务自启动。
//TODO 补图。

// Update 1

补充MacOS下使用终端连接SSH的方法。
网上的教程一般指告诉到了使用ssh [userName]@[Host]为止,但是,正常的服务器是不会使用默认端口号的。
那么怎么指定端口号呢,完整版命令是这样的ssh [UserName]:@[Host] -p [Port]

// Update 2

在Win10的最新版本里,可以安装Beta版的Ubuntu Linux,这样不需要Putty等工具,直接在Win10里使用SSH命令了。
具体命令和MacOS里是一样的。

Javascript如何生成Json

最近遇到个想复杂了的问题,就是如何用Javascript生成Json。
因为之前用的都是高级语言,已经封装好了数据结构或者类,直接赋值就好了。
之前想模拟前端向后台呼叫接口,需要POST方式传递JSON进来。然后就懵住了。

咦?我应该不用傻傻的拼接字符串吧。然后开始了脑洞。

脑洞第一版,模仿Salesforce制作List的方式

var dataArray = [];
var data = {};
data["id"] = "0010000000ABCD";
data["name"] = "Account";
dataArray.push(data);
var jsonString = JSON.stringify(dataArray);
var output = eval("(" + jsonString + ")");

感觉很怪。

脑洞第二版,用Javascript的类概念

var Account = new Object();
Account.Id = "0010000000ABCD";
Account.Name = "Account";
var output = JSON.stringify(Account);

感觉好多了,但感觉还是不够简单。毕竟Json是Javascirpt原生支持的啊。

然后查了半天,发现自己真的想复杂了

var output = {Id:"0010000000ABCD", Name:"Account"};

// Update 1
补充一下如何传两条数据

var output = [{Id:"0010000000ABCD", Name:"Account1"}, {Id:"0010000000ABCE", Name:"Account2"}];

Google的人工智能

在围棋领域,Google的Alpha GO与Master已经打败了光荣的人类棋手们。很了不起。

不同与早先的下棋智能程序,Google的AI并没有使用遍历算法。早先红白机上的中国象棋之类的,不过是计算了所有的可能之后回应。围棋的变化太多,计算量超乎目前计算机的承受能力。

Google使用了深度学习系统Tensorflow。(Python,又是Python。。。这个世界要被Python占领了吗)

这里是来自极客学院的翻译教程

关于随机数

在随机数这个问题上,一般程序员总是要经历下面的过程:

  1. 压根没有随机数的概念,想使用随机数的念头往往出于想每次执行自己辛辛苦苦写的小程序时可以有不一样的结果。
  2. 发现有个函数/方法是专门用来生成随机数的,试了一下,确实挺随机的。
  3. 兴高采烈的在自己的小程序里使用了这个函数/方法。结果发现每次结果其实还是一样的(C的话)
  4. 经历了千万次google才发现原来自己没加种子,只有不同的种子才会产生不同的随机数。往往种子都是使用一个恒定在变的东西——–时间。
  5. 当程序被高频访问的时候,问题又来了————-时间在计算里有最小单位,所以高频访问中临近访问的随机数是一样的。
  6. 又学会了一种叫随机数仓库的东西,来应对突然的高频访问。不断的往随机数队列里填充随机数,然后每个访问都是去随机数队列里去取。
  7. 然后,突然有一天,有人告诉你,这些不是随机数,最多只能称为伪随机数。

那么问题来了,什么是伪随机数,维基百科上的解释

伪随机性英语:Pseudorandomness)是指一个过程似乎是随机的,但实际上并不是。例如伪随机数(或称伪乱数),是使用一个确定性的算法计算出来的似乎是随机的数序,因此伪随机数实际上并不随机。在计算伪随机数时假如使用的开始值不变的话,那么伪随机数的数序也不变。伪随机数的随机性可以用它的统计特性来衡量,其主要特征是每个数出现的可能性和它出现时与数序中其它数的关系。伪随机数的优点是它的计算比较简单,而且只使用少数数值很难推算出计算它的算法。一般人们使用一个假的随机数,比如电脑上的时间作为计算伪随机数的开始值。

所以严格来讲,计算机生成的随机数并不是严格意义上的随机。那么我们如果想要真正的随机数怎么办呢。

有一个简便的方法,调用http://random.org的接口。

调用示例等参考此链接

 

Salesforce中的Apex Class Security设定问题

在我以往的印象中,给Profile设定VF和Apex Class的访问权限,都是需要什么就加什么。

比如新建了一个VF叫PageA, 又新建了一个Controller叫ControllerA,然后新建了一个被Controller调用的工具类ToolA。
那么,在此Profile中,PageA,ControllerA和ToolA通通都要加到Profile的访问权限里。

如果只添加了PageA,按理说应该是无法正常执行才对。

但通过实践,发现就算只添加了PageA的权限,整个功能仍然能正常运行。与之前的印象不符。

所以去查了文档,发现官方给出的解释是这样的:

Permission for an Apex class is checked only at the top level. For example, if class A calls class B, and a user profile has access only to class A but not class B, the user can still execute the code in class A. Likewise, if a Visualforce page uses a custom component with an associated controller, security is only checked for the controller associated with the page. The controller associated with the custom component executes regardless of permissions.

就是说如果代码之间存在着依赖链,那么权限判断中,只关注最顶层的那个代码。按照这个逻辑下来,只要拥有了PageA的权限,因为PageA与ControllerA的依赖关系,就自动获取了ControllerA的访问权限,同理ToolA。

知其然,不知其所以然还是不对的。