背景

做过oracle bpm开发的同学都知道,在调用oracle bpm相关api时,需要引入大量的jar包,导致应用包体积过大,部署一次需要大量的时间,本文介绍一种方案可以避免该问题。

实现

我觉得做开发都要有一个思维习惯,那就是,你觉得不合理的肯定有人已经解决了,能开发出oracle bpm这种重量级产品的都是大牛,我们都能发现的问题他们不可能没有发现,那他们是怎么解决的?oracle bpm自带一个workspace的应用,用户可以登录该应用进行流程的审批操作,我们可以看看官方是怎么处理jar包的,我们可以在console上找到该应用的位置

Read the rest of this entry

背景

在开发bpm流程,流程流转到平行审批节点时报错,流程如下:

报错信息如下:

Caused By: java.lang.NullPointerException
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.addTaskAttributesToXml(MIUserTaskRequest.java:568)
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.processInputData(MIUserTaskRequest.java:319)
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.handleTaskServiceInvoke(MIUserTaskRequest.java:158)
        at oracle.bpm.bpmn.engine.model.runtime.microinstructions.MIUserTaskRequest.doExecute(MIUserTaskRequest.java:128)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MISequenceBlock.doExecute(MISequenceBlock.java:68)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MicroInstructionContext.callMicroInstruction(MicroInstructionContext.java:203)
        at oracle.bpm.bpmn.engine.microkernel.MICall.doExecute(MICall.java:38)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MISequenceBlock.doExecute(MISequenceBlock.java:68)
        at oracle.bpm.bpmn.engine.microkernel.MIBase.execute(MIBase.java:34)
        at oracle.bpm.bpmn.engine.microkernel.MicroInstructionContext.callMicroInstruction(MicroInstructionContext.java:203)
        at oracle.bpm.bpmn.engine.microkernel.MicroInstructionContext.callProcedure(MicroInstructionContext.java:210)
.......

Read the rest of this entry

背景

某项目需要对生产环境数据库进行数据迁移,需要迁移的数据库版本为12.2.0.1.0RAC双节点,目标数据库为单实例数据库,版本一样。简单一句话就是,需要将数据从rac迁移到单机。

方案

本次尝试过以下三种方案

  • 通过rman进行备份迁移,但因为rac数据库和单机数据库控制文件spfile存在差异,需要手动修改的地方较多,在迁移过程中并不顺利,考虑到数据的一致性,最后放弃该方案。方案可以参考Steps to restore from RAC to Single Instance (RMAN)
  • 通过expdp和impdp数据泵方式进行迁移,方案可以参考Oracle 12c pdb使用expdp/impdp导入导出,impdp导入时出现较多错误,错误都集中其中一个schema上,最后单独对该schema进行导入,但因为错误太多不排除其他schema出现错误,也是考虑到数据的完整性,最后虽然成功导入但还是放弃该方案。
  • 通过oracle 12c新特性克隆远程数据库的方案对数据进行迁移,cdb和pdb是oracle 12c的一个新特性,允许oracle数据库以多租户多实例方式运行,每个用户可以分配一个cdb(相当于一台数据库主机),每个cdb可以创建多个pdb(pluggable database,可插拔数据库),不同数据库之间pdb可以克隆。

Read the rest of this entry

,

背景

你是否和我一样一直有个疑问,如何查看系统执行过的所有sql,之前做oracle中间件实施的时候,由于oracle产品不开放源代码,也不公开表结构设计,因此一个功能涉及到哪些表,具体表里存的数据代表什么除了oracle没人知道,如果了解哪些功能涉及到哪些表,表里的数据都分表对应哪些功能更有助于我们对产品的理解和对问题的解决。

之前曾经想过通过oracle系统表v$sql进行监控,但效果并不理想,如果用过druid连接池应该知道,druid主打的功能就是sql监控(一个数据库连接池竟然干监控的活,有点不务正业),druid的原理是提供了一套jdbc的接口,自然所有的sql都要通过它来执行,这个也给了我们一个思路,如果可以监控jdbc相关方法的执行,不就可以实现以上目的,有了arthas之后,这个事就变得很简单。

jdbc

我们知道,jdbc中负责执行sql的是PreparedStatementStatement,PreparedStatement用于参数绑定,有防注入,避免硬解析等好处,Statement执行纯sql,因此正式环境一般推荐使用PreparedStatement进行sql操作,PreparedStatement通过Connection.prepareStatement(String sql)方法创建,所以我们监控该方法就能得到sql,arthas中watch命令可以监控方法的执行,那问题来了,Connection只是jdbc的接口,并非最终的实现类,我们需要监控的是实现类,并非接口,通过查看oracle jdbc驱动包不难发现,oracle jdbc对于Connection的实现类是oracle.jdbc.OracleConnectionWrapper,执行下面命令开始监控。

Read the rest of this entry

背景

今天开始新的系列,这个系列也是我一直想写的,有几个原因迟迟没开始,一个是担心自己学艺不精,误人子弟,另一个是没有积累较多的使用案例,目前这两个问题已经不是问题,arthas大部分命令也都使用过,并且也积累了较多案例,是时候开始动笔。

要写什么内容,这个也是我一直思考的问题,官网的文档已经很详细,我觉得没有必要再写一份介绍如何使用的教程,arthas的魅力在于线上调试java的黑科技,这一点官网的几个简单示例是不足以展现的,因此我绝对本系列着重讲实战,通过具体的例子展现arthas神奇的黑科技。

既然要写实战,那为什么还要写入门篇,入门是让你知道arthas是个什么东西,怎么安装,知道这两点就够了,足以让你学习接下来的内容,入门还是很有必要的,就像你追一个妹子,再喜欢也要先了解对方的基本信息,投其所好,磨刀不误砍柴工。

Read the rest of this entry

背景

某项目OIM修改密码异常的慢,修改一次密码需要耗费15分钟时间,该功能基本已不可用,通过curl工具调用OIM rest api进行修改密码也需要十几分钟的时间

curl -X PUT \
http://10.10.10.10:14000/iam/governance/selfservice/api/v1/users/61729/password \
-H 'accept-language: zh-CN,en-US;q=0.8,zh;q=0.7,zh-TW;q=0.5,zh-HK;q=0.3,en;q=0.2' \
-H 'authorization: Basic xxxxxxxxxxxxxxxxxxxxx' \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-H 'postman-token: e86578e5-6c12-6bd0-3304-7588cae0f60a' \
-H 'x-requested-by: xx' \
-d '{
"oldPassword": "welcome@2020",
"newPassword": "welcome@2020238",
"confirmPassword": "welcome@2020238"
}'

排查

获取源码

后台并无报错,也没相关有价值的日志,因此考虑从源码入手,api源码位于oim这个应用中,你可以登录console查看ear包路径

Read the rest of this entry