应用发布
使用的表
- act_app_deployment 应用部署
- act_app_appdef 应用定义
- act_app_deployment_resource 应用zip包中每个资源文件
/**
* 应用发布->流程部署
*/
@PostMapping(value = "/rest/app-definitions/{modelId}/publish", produces = "application/json")
public AppDefinitionUpdateResultRepresentation publishAppDefinition(@PathVariable("modelId") String modelId,
@RequestBody AppDefinitionPublishRepresentation publishModel) {
AppDefinitionUpdateResultRepresentation resultRepresentation = null;
try {
resultRepresentation = appDefinitionImportService.publishAppDefinition(modelId, publishModel);
} catch (Exception ex) {
resultRepresentation = new AppDefinitionUpdateResultRepresentation();
resultRepresentation.setError(true);
resultRepresentation.setErrorDescription(ex.getMessage());
}
return resultRepresentation;
}
1.首先从模型表act_de_model中获取流程定义模型
Model appModel = modelService.getModel(modelId);
public void publishAppDefinition(String comment, Model appDefinitionModel, String userId) {
if (appRepositoryService == null) {
throw new FlowableIllegalStateException("Cannot publish apps from a standalone Modeler application");
}
//todo 版本更新+1
modelService.createNewModelVersion(appDefinitionModel, comment, userId);
AppDefinition appDefinition = null;
try {
// 构建流程定义pojo对象
appDefinition = resolveAppDefinition(appDefinitionModel);
} catch (Exception e) {
LOGGER.error("Error deserializing app {}", appDefinitionModel.getId(), e);
throw new InternalServerErrorException("Could not deserialize app definition");
}
if (appDefinition != null) {
// 1.创建可部署zip流
byte[] deployZipArtifact = createDeployableZipArtifact(appDefinitionModel, appDefinition);
// 2.部署应用,把应用信息和zip存档到act_app_deployment表中
if (deployZipArtifact != null) {
deployZipArtifact(deployZipArtifact, appDefinitionModel.getKey(), appDefinitionModel.getName());
}
}
}
部署应用,插入应用名称、应用key、应用zip到表act_app_deployment中
5.1 创建可部署zip流
protected void createDeployableModels(AbstractModel parentModel, Map<String, byte[]> deployableAssets, ConverterContext converterContext) {
// 使用app_mode主键链表查询act_de_model_relation 和act_de_model关联的model
List<Model> referencedModels = modelRepository.findByParentModelId(parentModel.getId());
for (Model childModel : referencedModels) {
if (Model.MODEL_TYPE_FORM == childModel.getModelType()) {
converterContext.addFormModel(childModel);
} else if (Model.MODEL_TYPE_DECISION_TABLE == childModel.getModelType()) {
converterContext.addDecisionTableModel(childModel);
} else if (Model.MODEL_TYPE_DECISION_SERVICE == childModel.getModelType()) {
converterContext.addDecisionServiceModel(childModel);
List<Model> referencedDecisionTableModels = modelRepository.findByParentModelId(childModel.getId());
referencedDecisionTableModels.stream()
.filter(refModel -> Model.MODEL_TYPE_DECISION_TABLE == refModel.getModelType())
.forEach(converterContext::addReferencedDecisionTableModel);
} else if (Model.MODEL_TYPE_CMMN == childModel.getModelType()) {
converterContext.addCaseModel(childModel);
createDeployableModels(childModel, deployableAssets, converterContext);
} else if (Model.MODEL_TYPE_BPMN == childModel.getModelType()) {
converterContext.addProcessModel(childModel);
// 创建可部署模型
createDeployableModels(childModel, deployableAssets, converterContext);
}
}
Map<String, EventModel> eventModelMap = new HashMap<>();
Map<String, ChannelModel> channelModelMap = new HashMap<>();
if (parentModel.getModelType() == null || parentModel.getModelType() == AbstractModel.MODEL_TYPE_BPMN) {
// BPM流程图每个节点转化为对象
BpmnModel bpmnModel = modelService.getBpmnModel(parentModel, converterContext);
List<FlowElement> eventRegistryElements = new ArrayList<>();
Map<String, StartEvent> noneStartEventMap = new HashMap<>();
// 后置处理流程节点。 处理任务开始节点、发送事件服务任务、子流程
postProcessFlowElements(eventRegistryElements, noneStartEventMap, bpmnModel);
BpmnEventModelUtil.fillEventModelMap(eventRegistryElements, eventModelMap);
BpmnEventModelUtil.fillChannelModelMap(eventRegistryElements, channelModelMap);
// 用户任务节点处理,看processUserTasks方法作用,
// 当前用户任务节点填写为$INITIATOR流程发起人, 查找起始节点并把userTask设置为初始节点....
// userTask.setAssignee("${" + startEventMap.get(process.getId()).getInitiator() + "}");
for (Process process : bpmnModel.getProcesses()) {
processUserTasks(process.getFlowElements(), process, noneStartEventMap);
}
// 生成xml文件
byte[] modelXML = modelService.getBpmnXML(bpmnModel);
deployableAssets.put(parentModel.getKey().replaceAll(" ", "") + ".bpmn", modelXML);
} else {
CmmnModel cmmnModel = modelService.getCmmnModel(parentModel, converterContext);
List<BaseElement> eventRegistryElements = new ArrayList<>();
postProcessPlanItemDefinitions(eventRegistryElements, cmmnModel);
CmmnEventModelUtil.fillEventModelMap(eventRegistryElements, eventModelMap);
CmmnEventModelUtil.fillChannelModelMap(eventRegistryElements, channelModelMap);
byte[] modelXML = modelService.getCmmnXML(cmmnModel);
deployableAssets.put(parentModel.getKey().replaceAll(" ", "") + ".cmmn", modelXML);
}
if (eventModelMap.size() > 0) {
for (EventModel eventModel : eventModelMap.values()) {
String eventJson = eventJsonConverter.convertToJson(eventModel);
deployableAssets.put("event-" + eventModel.getKey() + ".event", eventJson.getBytes(StandardCharsets.UTF_8));
}
if (channelModelMap.size() > 0) {
for (ChannelModel channelModel : channelModelMap.values()) {
String channelJson = channelJsonConverter.convertToJson(channelModel);
deployableAssets.put("channel-" + channelModel.getKey() + ".channel", channelJson.getBytes(StandardCharsets.UTF_8));
}
}
}
}
5.2 部署应用
/**
* 应用部署,sql执行。act_app_deployment、 act_app_deployment_resource
*/
protected void deployZipArtifact(byte[] zipArtifact, String deploymentKey, String deploymentName) {
// 构建sql
AppDeploymentBuilder deploymentBuilder = appRepositoryService.createDeployment()
.key(deploymentKey)
.name(deploymentName);
String tenantId = tenantProvider.getTenantId();
if (tenantId != null) {
deploymentBuilder.tenantId(tenantId);
}
try (InputStream bytesStream = new ByteArrayInputStream(zipArtifact);
ZipInputStream zipStream = new ZipInputStream(bytesStream)) {
// zip包中每个资源文件流(表单、bpnm)存档
deploymentBuilder.addZipInputStream(zipStream);
} catch (IOException ex) {
throw new UncheckedIOException("Failed to read bytes", ex);
}
//执行sql
deploymentBuilder.deploy();
}
5.4 应用资源文件存档
@Override
public AppDeploymentBuilder addZipInputStream(ZipInputStream zipInputStream) {
try {
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
if (!entry.isDirectory()) {
String entryName = entry.getName();
byte[] bytes = IoUtil.readInputStream(zipInputStream, entryName);
AppResourceEntity resource = resourceEntityManager.create();
resource.setName(entryName);
resource.setBytes(bytes);
deployment.addResource(resource);
}
entry = zipInputStream.getNextEntry();
}
} catch (Exception e) {
throw new FlowableException("problem reading zip input stream", e);
}
return this;
}
@Override
public AppDeploymentBuilder addZipInputStream(ZipInputStream zipInputStream) {
try {
ZipEntry entry = zipInputStream.getNextEntry();
//循环存储资源
while (entry != null) {
if (!entry.isDirectory()) {
String entryName = entry.getName();
byte[] bytes = IoUtil.readInputStream(zipInputStream, entryName);
AppResourceEntity resource = resourceEntityManager.create();
resource.setName(entryName);
resource.setBytes(bytes);
deployment.addResource(resource);
}
entry = zipInputStream.getNextEntry();
}
} catch (Exception e) {
throw new FlowableException("problem reading zip input stream", e);
}
return this;
}
6. 发布应用查询
涉及表
- act_app_appdef
@GetMapping(value = "/rest/runtime/app-definitions")
public ResultListDataRepresentation getAppDefinitions() {
return appDefinitionService.getAppDefinitions();
}
找到逻辑代码,查询act_app_appdef表中版本最高的应用
protected List<AppDefinitionRepresentation> getTaskAppList(SecurityScope currentUser) {
List<AppDefinitionRepresentation> resultList = new ArrayList<>();
// 查询
List<AppDefinition> appDefinitions = appRepositoryService.createAppDefinitionQuery().latestVersion().list();
return resultList;
}