Skip to content

Commit

Permalink
Spring Boot AOT - add cmmn/dmn resources
Browse files Browse the repository at this point in the history
  • Loading branch information
jbarrez committed Jan 7, 2024
1 parent 4888a78 commit 28d7ed6
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public boolean shouldCreateDiagram(CaseDefinitionEntity caseDefinition, EngineDe
&& CommandContextUtil.getCmmnEngineConfiguration().isCreateDiagramOnDeploy()) {

// If the 'getProcessDiagramResourceNameFromDeployment' call returns null, it means
// no diagram image for the process definition was provided in the deployment resources.
// no diagram image for the case definition was provided in the deployment resources.
return ResourceNameUtil.getCaseDiagramResourceNameFromDeployment(caseDefinition, deployment.getResources()) == null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.ImplementationType;
import org.flowable.bpmn.model.ServiceTask;
import org.flowable.cmmn.converter.CmmnXmlConverter;
import org.flowable.common.engine.api.query.Query;
import org.flowable.common.engine.impl.db.ListQueryParameterObject;
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl;
Expand All @@ -41,6 +42,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeReference;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
Expand Down Expand Up @@ -68,14 +70,25 @@ class FlowableBeanFactoryInitializationAotProcessor implements BeanFactoryInitia


private Set<Resource> processResources() {
return resources("processes/**/*.bpmn20.xml");
return resources("processes/**/*.bpmn20.xml", "processes/**/*.bpmn20");
}

private Set<Resource> caseResources() {
return resources("cases/**/*.cmmn", "cases/**/*.cmmn.xml");
}

private Set<Resource> ruleResources() {
return resources("dmn/**/*.dmn", "cases/**/*.dmn.xml");
}

private Set<Resource> flowablePersistenceResources() throws Exception {

var resources = new HashSet<Resource>();
resources.addAll(resources("org/flowable/**/*.sql", "org/flowable/**/*.xml", "org/flowable/**/*.txt", "org/flowable/**/*.xsd", "org/flowable/**/*.properties"));

resources.addAll(processResources());
resources.addAll(caseResources());
resources.addAll(ruleResources());

for (var e : "xml,yaml,yml".split(","))
resources.add(new ClassPathResource("flowable-default." + e));
Expand Down Expand Up @@ -158,39 +171,8 @@ public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableL
}


// here lay dragons; we're going to attempt to proactively register aot hints for beans referenced within a process definition
var processDefinitions = this.processResources();
for (var processDefinitionXmlResource : processDefinitions) {
Assert.state(processDefinitionXmlResource.exists(), "the process definition file [" + processDefinitionXmlResource.getFilename() +
"] does not exist");

hints.resources().registerResource(processDefinitionXmlResource);
try (var in = processDefinitionXmlResource.getInputStream()) {

var bpmnXMLConverter = new BpmnXMLConverter();
var bpmnModel = bpmnXMLConverter.convertToBpmnModel(() -> in, false, false);
var serviceTasks = bpmnModel.getMainProcess().findFlowElementsOfType(ServiceTask.class);
for (var st : serviceTasks) {
if (st.getImplementationType().equals(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION)) {
var expression = st.getImplementation();
var expressionWithoutDelimiters = expression.substring(2);
expressionWithoutDelimiters = expressionWithoutDelimiters.substring(0, expressionWithoutDelimiters.length() - 1);
var beanName = expressionWithoutDelimiters;
try {
var beanDefinition = beanFactory.getBeanDefinition(beanName);
hints.reflection().registerType(TypeReference.of(beanDefinition.getBeanClassName()), MemberCategory.values());

log.debug("registering hint for bean name [" + beanName + "]");
}//
catch (Throwable throwable) {
log.error("couldn't find bean named [" + beanName + "]");
}

}
}
}
}

// here lay dragons; we're going to attempt to proactively register aot hints for beans referenced within definitions
registerAotHintsForReferencedBeans(beanFactory, hints);

}//
catch (Throwable throwable) {
Expand All @@ -199,6 +181,78 @@ public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableL
};
}

private void registerAotHintsForReferencedBeans(ConfigurableListableBeanFactory beanFactory, RuntimeHints hints) throws IOException {
registerAotHintForProcessDefinitionBeans(beanFactory, hints);
registerAotHintForCaseDefinitionBeans(beanFactory, hints);
}

protected void registerAotHintForProcessDefinitionBeans(ConfigurableListableBeanFactory beanFactory, RuntimeHints hints) throws IOException {
var processDefinitions = this.processResources();
for (var processDefinitionXmlResource : processDefinitions) {
Assert.state(processDefinitionXmlResource.exists(), "the process definition file [" + processDefinitionXmlResource.getFilename() +
"] does not exist");

hints.resources().registerResource(processDefinitionXmlResource);
try (var in = processDefinitionXmlResource.getInputStream()) {

var bpmnXMLConverter = new BpmnXMLConverter();
var bpmnModel = bpmnXMLConverter.convertToBpmnModel(() -> in, false, false);
var serviceTasks = bpmnModel.getMainProcess().findFlowElementsOfType(ServiceTask.class);
for (var serviceTask : serviceTasks) {
if (serviceTask.getImplementationType().equals(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION)) {
var expression = serviceTask.getImplementation();
var expressionWithoutDelimiters = expression.substring(2);
expressionWithoutDelimiters = expressionWithoutDelimiters.substring(0, expressionWithoutDelimiters.length() - 1);
var beanName = expressionWithoutDelimiters;
try {
var beanDefinition = beanFactory.getBeanDefinition(beanName);
hints.reflection().registerType(TypeReference.of(beanDefinition.getBeanClassName()), MemberCategory.values());

log.debug("registering hint for bean name [" + beanName + "]");
}
catch (Throwable throwable) {
log.error("couldn't find bean named [" + beanName + "]");
}

}
}
}
}
}

protected void registerAotHintForCaseDefinitionBeans(ConfigurableListableBeanFactory beanFactory, RuntimeHints hints) throws IOException {
var caseDefinitions = this.caseResources();
for (var caseDefinitionXmlResource : caseDefinitions) {
Assert.state(caseDefinitionXmlResource.exists(), "the case definition file [" + caseDefinitionXmlResource.getFilename() +
"] does not exist");

hints.resources().registerResource(caseDefinitionXmlResource);
try (var in = caseDefinitionXmlResource.getInputStream()) {

var cmmXmlConverter = new CmmnXmlConverter();
var cmmnModel = cmmXmlConverter.convertToCmmnModel(() -> in, false, false);
var serviceTasks = cmmnModel.getPrimaryCase().findPlanItemDefinitionsOfType(org.flowable.cmmn.model.ServiceTask.class);
for (var serviceTask : serviceTasks) {
if (serviceTask.getImplementationType().equals(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION)) {
var expression = serviceTask.getImplementation();
var expressionWithoutDelimiters = expression.substring(2);
expressionWithoutDelimiters = expressionWithoutDelimiters.substring(0, expressionWithoutDelimiters.length() - 1);
var beanName = expressionWithoutDelimiters;
try {
var beanDefinition = beanFactory.getBeanDefinition(beanName);
hints.reflection().registerType(TypeReference.of(beanDefinition.getBeanClassName()), MemberCategory.values());

log.debug("registering hint for bean name [" + beanName + "]");
}
catch (Throwable throwable) {
log.error("couldn't find bean named [" + beanName + "]");
}

}
}
}
}
}

private static <T> Set<T> from(T[] t) {
return new HashSet<>(Arrays.asList(t));
Expand Down

0 comments on commit 28d7ed6

Please sign in to comment.