Initial commit
This commit is contained in:
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
Generated
+31
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<annotationProcessing>
|
||||||
|
<profile name="Maven default annotation processors profile" enabled="true">
|
||||||
|
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||||
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
|
<outputRelativeToContentRoot value="true" />
|
||||||
|
<module name="customer-control" />
|
||||||
|
<module name="customer-design" />
|
||||||
|
<module name="customer-work" />
|
||||||
|
</profile>
|
||||||
|
</annotationProcessing>
|
||||||
|
<bytecodeTargetLevel>
|
||||||
|
<module name="flowable-control" target="21" />
|
||||||
|
<module name="flowable-design" target="21" />
|
||||||
|
<module name="flowable-work" target="21" />
|
||||||
|
<module name="work" target="21" />
|
||||||
|
</bytecodeTargetLevel>
|
||||||
|
</component>
|
||||||
|
<component name="JavacSettings">
|
||||||
|
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||||
|
<module name="customer-control" options="-parameters" />
|
||||||
|
<module name="customer-design" options="-parameters" />
|
||||||
|
<module name="customer-work" options="-parameters" />
|
||||||
|
<module name="flowable-control" options="-parameters" />
|
||||||
|
<module name="flowable-design" options="-parameters" />
|
||||||
|
<module name="flowable-work" options="-parameters" />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+19
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="flowable@localhost" uuid="831e70f0-ae1c-40e9-8e8d-b6b93936ea15">
|
||||||
|
<driver-ref>postgresql</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<imported>true</imported>
|
||||||
|
<remarks>$PROJECT_DIR$/customer-control/src/main/resources/application.properties</remarks>
|
||||||
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:postgresql://localhost:5435/flowable</jdbc-url>
|
||||||
|
<jdbc-additional-properties>
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
|
</jdbc-additional-properties>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/customer-control/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/customer-design/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/customer-work/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RemoteRepositoriesConfiguration">
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Central Repository" />
|
||||||
|
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="flowable-repo" />
|
||||||
|
<option name="name" value="flowable-repo" />
|
||||||
|
<option name="url" value="https://repo.flowable.com/artifactory/flowable-maven-all" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Maven Central repository" />
|
||||||
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jboss.community" />
|
||||||
|
<option name="name" value="JBoss Community repository" />
|
||||||
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="homebrew-25" project-jdk-type="JavaSDK" />
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/work/work.iml" filepath="$PROJECT_DIR$/work/work.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,82 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.customer</groupId>
|
||||||
|
<artifactId>customer-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>customer-control</artifactId>
|
||||||
|
<name>customer-control</name>
|
||||||
|
<description>customer-control</description>
|
||||||
|
<url/>
|
||||||
|
<licenses>
|
||||||
|
<license/>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer/>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection/>
|
||||||
|
<developerConnection/>
|
||||||
|
<tag/>
|
||||||
|
<url/>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Flowable Control -->
|
||||||
|
<!-- ================ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.control</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter-control</artifactId>
|
||||||
|
<version>${com.flowable.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Boot -->
|
||||||
|
<!-- =========== -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Testing -->
|
||||||
|
<!-- ======= -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.customer.control;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class ControlApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ControlApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
server.port=8107
|
||||||
|
server.servlet.context-path=/
|
||||||
|
|
||||||
|
#spring.datasource.driver-class-name=org.postgresql.Driver
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5435/flowable
|
||||||
|
spring.datasource.username=flowable
|
||||||
|
spring.datasource.password=flowable
|
||||||
|
|
||||||
|
# In order for hot swapping to work for the custom.js and custom.css
|
||||||
|
spring.thymeleaf.cache=false
|
||||||
|
spring.web.resources.chain.cache=false
|
||||||
|
|
||||||
|
# Enable all endpoints over HTTP
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
management.endpoint.health.show-details=ALWAYS
|
||||||
|
# Pretty-print JSON responses
|
||||||
|
spring.jackson.serialization.indent_output=true
|
||||||
|
|
||||||
|
# TODO Change these to an other random string with a length of 16 characters
|
||||||
|
# Used to encrypt your passwords. After a change existing password become invalid!
|
||||||
|
flowable.control.app.security.encryption.credentials-i-v-spec=fh39chqoxjDF3fhb
|
||||||
|
flowable.control.app.security.encryption.credentials-secret-spec=lw91VtkPq84nGqiJ
|
||||||
|
|
||||||
|
flowable.control.app.cluster-config.name=Default Cluster
|
||||||
|
flowable.control.app.cluster-config.description=Default Flowable Cluster
|
||||||
|
flowable.control.app.cluster-config.server-address=http://localhost
|
||||||
|
flowable.control.app.cluster-config.port=8105
|
||||||
|
flowable.control.app.cluster-config.context-root=/
|
||||||
|
flowable.control.app.cluster-config.user-name=admin
|
||||||
|
flowable.control.app.cluster-config.password=test
|
||||||
|
|
||||||
|
flowable.control.app.db-store-enabled=false
|
||||||
|
flowable.control.app.cluster-type=work
|
||||||
|
flowable.control.app.user-store.password=test
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
server.port=8107
|
||||||
|
server.servlet.context-path=/
|
||||||
|
|
||||||
|
#spring.datasource.driver-class-name=org.postgresql.Driver
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5435/flowable
|
||||||
|
spring.datasource.username=flowable
|
||||||
|
spring.datasource.password=flowable
|
||||||
|
|
||||||
|
# In order for hot swapping to work for the custom.js and custom.css
|
||||||
|
spring.thymeleaf.cache=false
|
||||||
|
spring.web.resources.chain.cache=false
|
||||||
|
|
||||||
|
# Enable all endpoints over HTTP
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
management.endpoint.health.show-details=ALWAYS
|
||||||
|
# Pretty-print JSON responses
|
||||||
|
spring.jackson.serialization.indent_output=true
|
||||||
|
|
||||||
|
# TODO Change these to an other random string with a length of 16 characters
|
||||||
|
# Used to encrypt your passwords. After a change existing password become invalid!
|
||||||
|
flowable.control.app.security.encryption.credentials-i-v-spec=fh39chqoxjDF3fhb
|
||||||
|
flowable.control.app.security.encryption.credentials-secret-spec=lw91VtkPq84nGqiJ
|
||||||
|
|
||||||
|
flowable.control.app.cluster-config.name=Default Cluster
|
||||||
|
flowable.control.app.cluster-config.description=Default Flowable Cluster
|
||||||
|
flowable.control.app.cluster-config.server-address=http://localhost
|
||||||
|
flowable.control.app.cluster-config.port=8105
|
||||||
|
flowable.control.app.cluster-config.context-root=/
|
||||||
|
flowable.control.app.cluster-config.user-name=admin
|
||||||
|
flowable.control.app.cluster-config.password=test
|
||||||
|
|
||||||
|
flowable.control.app.db-store-enabled=false
|
||||||
|
flowable.control.app.cluster-type=work
|
||||||
|
flowable.control.app.user-store.password=test
|
||||||
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.customer</groupId>
|
||||||
|
<artifactId>customer-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>customer-design</artifactId>
|
||||||
|
<name>customer-design</name>
|
||||||
|
<description>customer-design</description>
|
||||||
|
<url/>
|
||||||
|
<licenses>
|
||||||
|
<license/>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer/>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection/>
|
||||||
|
<developerConnection/>
|
||||||
|
<tag/>
|
||||||
|
<url/>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Flowable Design -->
|
||||||
|
<!-- ================= -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.design</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter-design</artifactId>
|
||||||
|
<version>${com.flowable.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.platform</groupId>
|
||||||
|
<artifactId>flowable-platform-palette</artifactId>
|
||||||
|
<version>${com.flowable.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Testing -->
|
||||||
|
<!-- ======= -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,13 @@
|
|||||||
|
package com.customer.design;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class DesignApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(DesignApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.customer.design;
|
||||||
|
|
||||||
|
import jakarta.servlet.DispatcherType;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
||||||
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
|
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||||
|
|
||||||
|
import com.flowable.autoconfigure.design.security.DesignHttpSecurityCustomizer;
|
||||||
|
import com.flowable.autoconfigure.design.security.servlet.DesignPathRequest;
|
||||||
|
import com.flowable.design.security.spring.web.authentication.AjaxAuthenticationFailureHandler;
|
||||||
|
import com.flowable.design.security.spring.web.authentication.AjaxAuthenticationSuccessHandler;
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnProperty(prefix = "application.design.security", name = "type", havingValue = "basic", matchIfMissing = true)
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityHttpBasicConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(10)
|
||||||
|
public SecurityFilterChain basicDefaultSecurity(HttpSecurity http, ObjectProvider<DesignHttpSecurityCustomizer> httpSecurityCustomizers) throws Exception {
|
||||||
|
for (DesignHttpSecurityCustomizer customizer : httpSecurityCustomizers.orderedStream().toList()) {
|
||||||
|
customizer.customize(http);
|
||||||
|
}
|
||||||
|
|
||||||
|
http.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||||
|
|
||||||
|
http.logout(logout -> logout.logoutUrl("/auth/logout").logoutSuccessUrl("/"));
|
||||||
|
|
||||||
|
// Non authenticated exception handling. The formLogin and httpBasic configure the exceptionHandling
|
||||||
|
// We have to initialize the exception handling with a default authentication entry point in order to return 401 each time and not have a
|
||||||
|
// forward due to the formLogin or the http basic popup due to the httpBasic
|
||||||
|
http
|
||||||
|
.exceptionHandling(exceptionHandling -> exceptionHandling
|
||||||
|
.defaultAuthenticationEntryPointFor((request, response, authException) -> {}, new DispatcherTypeRequestMatcher(DispatcherType.ERROR))
|
||||||
|
.defaultAuthenticationEntryPointFor(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AnyRequestMatcher.INSTANCE))
|
||||||
|
.formLogin(formLogin -> formLogin
|
||||||
|
.loginProcessingUrl("/auth/login")
|
||||||
|
.successHandler(new AjaxAuthenticationSuccessHandler())
|
||||||
|
.failureHandler(new AjaxAuthenticationFailureHandler())
|
||||||
|
)
|
||||||
|
.authorizeHttpRequests(configurer -> configurer
|
||||||
|
.requestMatchers(DesignPathRequest.toStaticResources().atCommonLocations()).permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.httpBasic(Customizer.withDefaults());
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
server.port=8106
|
||||||
|
#spring.datasource.url=jdbc:h2:~/flowable-design-db/db;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
|
||||||
|
#spring.datasource.username=flowable
|
||||||
|
#spring.datasource.password=flowable
|
||||||
|
|
||||||
|
#Comment out and configure database
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5435/flowable
|
||||||
|
spring.datasource.username=flowable
|
||||||
|
spring.datasource.password=flowable
|
||||||
|
|
||||||
|
|
||||||
|
# Connection to Work
|
||||||
|
flowable.design.remote.idm-url=http://localhost:8105/flowable-work
|
||||||
|
flowable.design.remote.authentication.user=admin
|
||||||
|
flowable.design.remote.authentication.password=test
|
||||||
|
|
||||||
|
#flowable.design.deployment-api-url=http://localhost:8080/flowable-work/app-api
|
||||||
|
#flowable.design.undeployment-api-url=http://localhost:8080/flowable-work/platform-api/app-deployments
|
||||||
|
flowable.design.deployment-api-url=http://localhost:8105/app-api
|
||||||
|
flowable.design.undeployment-api-url=http://localhost:8105/platform-api/app-deployments
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.customer.design;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class DesignApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
server.port=8106
|
||||||
|
#spring.datasource.url=jdbc:h2:~/flowable-design-db/db;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
|
||||||
|
#spring.datasource.username=flowable
|
||||||
|
#spring.datasource.password=flowable
|
||||||
|
|
||||||
|
#Comment out and configure database
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5435/flowable
|
||||||
|
spring.datasource.username=flowable
|
||||||
|
spring.datasource.password=flowable
|
||||||
|
|
||||||
|
|
||||||
|
# Connection to Work
|
||||||
|
flowable.design.remote.idm-url=http://localhost:8105/flowable-work
|
||||||
|
flowable.design.remote.authentication.user=admin
|
||||||
|
flowable.design.remote.authentication.password=test
|
||||||
|
|
||||||
|
#flowable.design.deployment-api-url=http://localhost:8080/flowable-work/app-api
|
||||||
|
#flowable.design.undeployment-api-url=http://localhost:8080/flowable-work/platform-api/app-deployments
|
||||||
|
flowable.design.deployment-api-url=http://localhost:8105/app-api
|
||||||
|
flowable.design.undeployment-api-url=http://localhost:8105/platform-api/app-deployments
|
||||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
|||||||
|
artifactId=customer-design
|
||||||
|
groupId=com.customer
|
||||||
|
version=0.0.1-SNAPSHOT
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
com/customer/design/DesignApplication.class
|
||||||
|
com/customer/design/SecurityHttpBasicConfiguration.class
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
/Users/andi/prj/flowable/2025.2/customer-design/src/main/java/com/customer/design/DesignApplication.java
|
||||||
|
/Users/andi/prj/flowable/2025.2/customer-design/src/main/java/com/customer/design/SecurityHttpBasicConfiguration.java
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
com/customer/design/DesignApplicationTests.class
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/Users/andi/prj/flowable/2025.2/customer-design/src/test/java/com/customer/design/DesignApplicationTests.java
|
||||||
+1776
File diff suppressed because one or more lines are too long
+195
@@ -0,0 +1,195 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Test set: com.customer.design.DesignApplicationTests
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.527 s <<< FAILURE! -- in com.customer.design.DesignApplicationTests
|
||||||
|
com.customer.design.DesignApplicationTests.contextLoads -- Time elapsed: 0.012 s <<< ERROR!
|
||||||
|
java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@4aba7617 testClass = com.customer.design.DesignApplicationTests, locations = [], classes = [com.customer.design.DesignApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.web.server.context.SpringBootTestRandomPortContextCustomizer@30bcf3c1, org.springframework.boot.test.context.PropertyMappingContextCustomizer@0, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7c2b6087, org.springframework.boot.test.http.client.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory$DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer@354fc8f0, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@5b43fbf6, org.springframework.boot.test.autoconfigure.OnFailureConditionReportContextCustomizerFactory$OnFailureConditionReportContextCustomizer@5b07730f, org.springframework.test.context.support.DynamicPropertiesContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@ae57ec99], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.lambda$loadContext$0(DefaultCacheAwareContextLoaderDelegate.java:195)
|
||||||
|
at org.springframework.test.context.cache.DefaultContextCache.put(DefaultContextCache.java:214)
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:160)
|
||||||
|
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:128)
|
||||||
|
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:200)
|
||||||
|
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:139)
|
||||||
|
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
|
||||||
|
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:210)
|
||||||
|
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:186)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:214)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:197)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:214)
|
||||||
|
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1716)
|
||||||
|
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
|
||||||
|
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
|
||||||
|
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:153)
|
||||||
|
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:176)
|
||||||
|
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:632)
|
||||||
|
at java.base/java.util.Optional.orElseGet(Optional.java:364)
|
||||||
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
||||||
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: Error creating bean with name 'basicDefaultSecurity' defined in class path resource [com/customer/design/SecurityHttpBasicConfiguration.class]: Unsatisfied dependency expressed through method 'basicDefaultSecurity' parameter 0: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'designUserDetailsService' defined in class path resource [com/flowable/autoconfigure/design/security/DesignSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designUserDetailsService' parameter 0: Error creating bean with name 'designIdentityQueryService' defined in class path resource [com/flowable/autoconfigure/design/DesignEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designIdentityQueryService' parameter 0: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:872)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:827)
|
||||||
|
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:146)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:493)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1446)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1218)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1184)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1121)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:994)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:621)
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:756)
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:445)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$2(SpringBootContextLoader.java:156)
|
||||||
|
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
|
||||||
|
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
|
||||||
|
at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1465)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:605)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:156)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:115)
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:247)
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.lambda$loadContext$0(DefaultCacheAwareContextLoaderDelegate.java:167)
|
||||||
|
... 21 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'basicDefaultSecurity' defined in class path resource [com/customer/design/SecurityHttpBasicConfiguration.class]: Unsatisfied dependency expressed through method 'basicDefaultSecurity' parameter 0: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'designUserDetailsService' defined in class path resource [com/flowable/autoconfigure/design/security/DesignSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designUserDetailsService' parameter 0: Error creating bean with name 'designIdentityQueryService' defined in class path resource [com/flowable/autoconfigure/design/DesignEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designIdentityQueryService' parameter 0: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:2008)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1971)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeanCollection(DefaultListableBeanFactory.java:1863)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1833)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1711)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:864)
|
||||||
|
... 48 more
|
||||||
|
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'designUserDetailsService' defined in class path resource [com/flowable/autoconfigure/design/security/DesignSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designUserDetailsService' parameter 0: Error creating bean with name 'designIdentityQueryService' defined in class path resource [com/flowable/autoconfigure/design/DesignEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designIdentityQueryService' parameter 0: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:657)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:489)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:351)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 65 more
|
||||||
|
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'designUserDetailsService' defined in class path resource [com/flowable/autoconfigure/design/security/DesignSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designUserDetailsService' parameter 0: Error creating bean with name 'designIdentityQueryService' defined in class path resource [com/flowable/autoconfigure/design/DesignEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designIdentityQueryService' parameter 0: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:183)
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:72)
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:152)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
|
||||||
|
... 77 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'designUserDetailsService' defined in class path resource [com/flowable/autoconfigure/design/security/DesignSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designUserDetailsService' parameter 0: Error creating bean with name 'designIdentityQueryService' defined in class path resource [com/flowable/autoconfigure/design/DesignEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designIdentityQueryService' parameter 0: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1305)
|
||||||
|
at org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer.configure(InitializeUserDetailsBeanManagerConfigurer.java:94)
|
||||||
|
at org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer.configure(InitializeUserDetailsBeanManagerConfigurer.java:63)
|
||||||
|
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.configure(AbstractConfiguredSecurityBuilder.java:386)
|
||||||
|
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:336)
|
||||||
|
at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38)
|
||||||
|
at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationManager(AuthenticationConfiguration.java:121)
|
||||||
|
at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.authenticationManager(HttpSecurityConfiguration.java:152)
|
||||||
|
at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity(HttpSecurityConfiguration.java:119)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:155)
|
||||||
|
... 80 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'designIdentityQueryService' defined in class path resource [com/flowable/autoconfigure/design/DesignEngineAutoConfiguration.class]: Unsatisfied dependency expressed through method 'designIdentityQueryService' parameter 0: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 100 more
|
||||||
|
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'designEngine': FactoryBean threw exception on object creation
|
||||||
|
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:209)
|
||||||
|
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:149)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1879)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1304)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:343)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 114 more
|
||||||
|
Caused by: java.lang.RuntimeException: Exception while initializing Database connection
|
||||||
|
at org.flowable.common.engine.impl.util.DbUtil.determineDatabaseType(DbUtil.java:116)
|
||||||
|
at org.flowable.common.engine.impl.AbstractEngineConfiguration.initDatabaseType(AbstractEngineConfiguration.java:475)
|
||||||
|
at org.flowable.common.engine.impl.AbstractEngineConfiguration.initDataSource(AbstractEngineConfiguration.java:470)
|
||||||
|
at com.flowable.design.engine.DesignEngineConfiguration.init(DesignEngineConfiguration.java:365)
|
||||||
|
at org.flowable.common.engine.impl.AbstractBuildableEngineConfiguration.buildEngine(AbstractBuildableEngineConfiguration.java:28)
|
||||||
|
at com.flowable.design.engine.DesignEngineConfiguration.buildDesignEngine(DesignEngineConfiguration.java:336)
|
||||||
|
at com.flowable.design.engine.spring.DesignEngineFactoryBean.getObject(DesignEngineFactoryBean.java:36)
|
||||||
|
at com.flowable.design.engine.spring.DesignEngineFactoryBean.getObject(DesignEngineFactoryBean.java:20)
|
||||||
|
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:203)
|
||||||
|
... 124 more
|
||||||
|
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5435 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
|
||||||
|
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:373)
|
||||||
|
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:57)
|
||||||
|
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:290)
|
||||||
|
at org.postgresql.Driver.makeConnection(Driver.java:448)
|
||||||
|
at org.postgresql.Driver.connect(Driver.java:298)
|
||||||
|
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:144)
|
||||||
|
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:373)
|
||||||
|
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:210)
|
||||||
|
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:488)
|
||||||
|
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:576)
|
||||||
|
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:97)
|
||||||
|
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
|
||||||
|
at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:160)
|
||||||
|
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:118)
|
||||||
|
at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:256)
|
||||||
|
at jdk.proxy2/jdk.proxy2.$Proxy86.getMetaData(Unknown Source)
|
||||||
|
at org.flowable.common.engine.impl.util.DbUtil.determineDatabaseType(DbUtil.java:89)
|
||||||
|
... 132 more
|
||||||
|
Caused by: java.net.ConnectException: Connection refused
|
||||||
|
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
|
||||||
|
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:639)
|
||||||
|
at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:543)
|
||||||
|
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:594)
|
||||||
|
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:284)
|
||||||
|
at java.base/java.net.Socket.connect(Socket.java:659)
|
||||||
|
at org.postgresql.core.PGStream.createSocket(PGStream.java:261)
|
||||||
|
at org.postgresql.core.PGStream.<init>(PGStream.java:122)
|
||||||
|
at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:146)
|
||||||
|
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:289)
|
||||||
|
... 148 more
|
||||||
|
|
||||||
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,102 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.customer</groupId>
|
||||||
|
<artifactId>customer-parent</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>customer-work</artifactId>
|
||||||
|
<name>customer-work</name>
|
||||||
|
<description>customer-work</description>
|
||||||
|
<url/>
|
||||||
|
<licenses>
|
||||||
|
<license/>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer/>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection/>
|
||||||
|
<developerConnection/>
|
||||||
|
<tag/>
|
||||||
|
<url/>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Flowable Work -->
|
||||||
|
<!-- ================= -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.work</groupId>
|
||||||
|
<artifactId>flowable-work-frontend</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.platform</groupId>
|
||||||
|
<artifactId>flowable-platform-default-models</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.platform</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter-platform-rest</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.platform</groupId>
|
||||||
|
<artifactId>flowable-tenant-setup</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Flowable Inspect -->
|
||||||
|
<!-- ======= -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.flowable.inspect</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter-inspect-rest</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Testing -->
|
||||||
|
<!-- ======= -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wnameless.json</groupId>
|
||||||
|
<artifactId>json-flattener</artifactId>
|
||||||
|
<version>0.16.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.icegreen</groupId>
|
||||||
|
<artifactId>greenmail</artifactId>
|
||||||
|
<version>2.1.8</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,62 @@
|
|||||||
|
package com.customer.work;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import jakarta.servlet.DispatcherType;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
||||||
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
|
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||||
|
|
||||||
|
import com.flowable.autoconfigure.security.FlowableHttpSecurityCustomizer;
|
||||||
|
import com.flowable.autoconfigure.security.servlet.PlatformPathRequest;
|
||||||
|
import com.flowable.core.spring.security.web.authentication.AjaxAuthenticationFailureHandler;
|
||||||
|
import com.flowable.core.spring.security.web.authentication.AjaxAuthenticationSuccessHandler;
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnProperty(prefix = "application.security", name = "type", havingValue = "basic", matchIfMissing = true)
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityHttpBasicConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(10)
|
||||||
|
public SecurityFilterChain basicDefaultSecurity(HttpSecurity http, ObjectProvider<FlowableHttpSecurityCustomizer> httpSecurityCustomizers) throws Exception {
|
||||||
|
for (FlowableHttpSecurityCustomizer customizer : httpSecurityCustomizers.orderedStream()
|
||||||
|
.collect(Collectors.toList())) {
|
||||||
|
customizer.customize(http);
|
||||||
|
}
|
||||||
|
|
||||||
|
http
|
||||||
|
.logout(logout -> logout.logoutUrl("/auth/logout").logoutSuccessUrl("/"));
|
||||||
|
|
||||||
|
// Non authenticated exception handling. The formLogin and httpBasic configure the exceptionHandling
|
||||||
|
// We have to initialize the exception handling with a default authentication entry point in order to return 401 each time and not have a
|
||||||
|
// forward due to the formLogin or the http basic popup due to the httpBasic
|
||||||
|
http
|
||||||
|
.exceptionHandling(exceptionHandling -> exceptionHandling
|
||||||
|
.defaultAuthenticationEntryPointFor((request, response, authException) -> {}, new DispatcherTypeRequestMatcher(DispatcherType.ERROR))
|
||||||
|
.defaultAuthenticationEntryPointFor(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AnyRequestMatcher.INSTANCE))
|
||||||
|
.formLogin(formLogin -> formLogin
|
||||||
|
.loginProcessingUrl("/auth/login")
|
||||||
|
.successHandler(new AjaxAuthenticationSuccessHandler())
|
||||||
|
.failureHandler(new AjaxAuthenticationFailureHandler())
|
||||||
|
)
|
||||||
|
.authorizeHttpRequests(configurer -> configurer
|
||||||
|
.requestMatchers(PlatformPathRequest.toStaticResources().atCommonLocations()).permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.httpBasic(Customizer.withDefaults());
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.customer.work;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.CacheControl;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public class StaticResourceConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
|
registry.setOrder(10)
|
||||||
|
.addResourceHandler("/ext/*.js", "/*/ext/*.js")
|
||||||
|
.addResourceLocations("classpath:/static/ext/", "classpath:/public/ext/")
|
||||||
|
.setCacheControl(CacheControl.noCache());
|
||||||
|
|
||||||
|
registry.setOrder(20)
|
||||||
|
.addResourceHandler("/ext/*.css", "/*/ext/*.css")
|
||||||
|
.addResourceLocations("classpath:/static/ext/", "classpath:/public/ext/")
|
||||||
|
.setCacheControl(CacheControl.noCache());
|
||||||
|
|
||||||
|
registry.setOrder(30)
|
||||||
|
.addResourceHandler("/*.js")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(40)
|
||||||
|
.addResourceHandler("/*.css")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(50)
|
||||||
|
.addResourceHandler("/*.woff")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(60)
|
||||||
|
.addResourceHandler("/*.woff2")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(70)
|
||||||
|
.addResourceHandler("/*.svg")
|
||||||
|
.addResourceLocations("classpath:/public/", "classpath:/public/twemoji/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(80)
|
||||||
|
.addResourceHandler("/*.map")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(90)
|
||||||
|
.addResourceHandler("/*.png")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
|
||||||
|
registry.setOrder(100)
|
||||||
|
.addResourceHandler("/*.ico")
|
||||||
|
.addResourceLocations("classpath:/public/")
|
||||||
|
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.customer.work;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class WorkApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(WorkApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package com.customer.work.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import com.github.wnameless.json.flattener.JsonFlattener;
|
||||||
|
import com.github.wnameless.json.unflattener.JsonUnflattener;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JsonUtils {
|
||||||
|
|
||||||
|
protected static final Logger LOGGER = LoggerFactory.getLogger(JsonUtils.class);
|
||||||
|
protected final ObjectMapper objectMapper;
|
||||||
|
protected final JavaTimeModule javaTimeModule;
|
||||||
|
|
||||||
|
public JsonUtils(ObjectMapper objectMapper) {
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
this.javaTimeModule = new JavaTimeModule();
|
||||||
|
|
||||||
|
// Enable ObjectMapper for handling Instant as string
|
||||||
|
this.objectMapper.registerModule(javaTimeModule);
|
||||||
|
this.objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode convertListToJsonNode(List<Object> list) {
|
||||||
|
return objectMapper.valueToTree(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode convertMapToJsonNode(Map<String, Object> map) {
|
||||||
|
return objectMapper.valueToTree(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> convertJsonNodeToMap(JsonNode jsonNode) {
|
||||||
|
return objectMapper.convertValue(jsonNode, new TypeReference<Map<String, Object>>() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> flatten(Object payload) {
|
||||||
|
try {
|
||||||
|
return JsonFlattener.flattenAsMap(objectMapper.writeValueAsString(payload));
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> unflatten(Map<String, Object> flatVars) {
|
||||||
|
try {
|
||||||
|
return objectMapper.readValue(JsonUnflattener.unflatten(flatVars), Map.class);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode convertJsonStringToJsonNode(String jsonString) {
|
||||||
|
try {
|
||||||
|
return objectMapper.readTree(jsonString);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> convertObjectNodeToMap(ObjectNode objectNode) {
|
||||||
|
return objectMapper.convertValue(objectNode, new TypeReference<Map<String, Object>>() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode getEmptyObjectNode() {
|
||||||
|
return objectMapper.createObjectNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode loadObjectNodeFromFile(String path) {
|
||||||
|
try {
|
||||||
|
return (ObjectNode) this.objectMapper.readTree(new File(path));
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.debug(e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayNode convertObjectToArrayNode(Object object) {
|
||||||
|
if (object == null) {
|
||||||
|
LOGGER.debug("{}: Argument is null", this.getClass().getName());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String obyTypeName = object.getClass().getName();
|
||||||
|
if (obyTypeName.equals("java.util.Collections$EmptyList") || obyTypeName.equals("java.util.ArrayList")) {
|
||||||
|
return objectMapper.convertValue(object, ArrayNode.class);
|
||||||
|
} else if (obyTypeName.equals("com.fasterxml.jackson.databind.node.ArrayNode")) {
|
||||||
|
return (ArrayNode) object;
|
||||||
|
} else {
|
||||||
|
LOGGER.debug("{}: {} is not implemented}", this.getClass().getName(), obyTypeName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,418 @@
|
|||||||
|
package com.customer.work.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import org.flowable.cmmn.api.CmmnRuntimeService;
|
||||||
|
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
|
||||||
|
import org.flowable.cmmn.engine.impl.persistence.entity.CaseInstanceEntity;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
|
||||||
|
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
|
||||||
|
import org.flowable.engine.ProcessEngineConfiguration;
|
||||||
|
import org.flowable.cmmn.api.runtime.CaseInstance;
|
||||||
|
import org.flowable.cmmn.api.runtime.PlanItemInstance;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||||
|
import org.flowable.engine.runtime.Execution;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.flowable.variable.api.delegate.VariableScope;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General-purpose Flowable variable utility bean.
|
||||||
|
* Usable in BPMN process and CMMN case backend expressions without any scope parameter:
|
||||||
|
* ${varUtils.get('order.customer.name')}
|
||||||
|
* ${varUtils.track('order.customer.name,order.total,status')}
|
||||||
|
* Root variables are supported.
|
||||||
|
* How the scope is resolved without a parameter
|
||||||
|
* -----------------------------------------------
|
||||||
|
* The bean registers itself as a Flowable event listener on both engines.
|
||||||
|
* Before a service task expression is evaluated, Flowable fires events on the
|
||||||
|
* same thread that allow us to capture the current variable scope:
|
||||||
|
* BPMN — PROCESS_STARTED fires a FlowableEngineEntityEvent.
|
||||||
|
* The execution is retrieved via event.getEntity().
|
||||||
|
|
||||||
|
* CMMN — CASE_STARTED fires a FlowableEngineEntityEvent.; Instead, when a plan
|
||||||
|
* The case instance is retrieved via event.getEntity().
|
||||||
|
*/
|
||||||
|
@Component("varUtils")
|
||||||
|
public class VarUtils implements FlowableEventListener, SmartInitializingSingleton {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(VarUtils.class);
|
||||||
|
|
||||||
|
private static final ThreadLocal<VariableScope> SCOPE = new ThreadLocal<>();
|
||||||
|
|
||||||
|
private static final ObjectMapper MAPPER;
|
||||||
|
static {
|
||||||
|
MAPPER = new ObjectMapper();
|
||||||
|
MAPPER.registerModule(new JavaTimeModule());
|
||||||
|
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProcessEngineConfiguration processEngineConfiguration;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CmmnEngineConfiguration cmmnEngineConfiguration;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RuntimeService runtimeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CmmnRuntimeService cmmnRuntimeService;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Listener registration — runs after all beans are ready
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
@Override
|
||||||
|
public void afterSingletonsInstantiated() {
|
||||||
|
if (processEngineConfiguration != null) {
|
||||||
|
processEngineConfiguration.getEventDispatcher().addEventListener(this);
|
||||||
|
LOGGER.debug("varUtils registered on BPMN event dispatcher");
|
||||||
|
}
|
||||||
|
if (cmmnEngineConfiguration != null) {
|
||||||
|
cmmnEngineConfiguration.getEventDispatcher().addEventListener(this);
|
||||||
|
LOGGER.debug("varUtils registered on CMMN event dispatcher");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// FlowableEventListener — bind / unbind the scope ThreadLocal
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
@Override
|
||||||
|
public void onEvent(FlowableEvent event) {
|
||||||
|
|
||||||
|
if (event instanceof FlowableEngineEntityEvent entityEvent) {
|
||||||
|
String typeName = event.getType().name();
|
||||||
|
Object entity = entityEvent.getEntity();
|
||||||
|
|
||||||
|
// BPMN execution
|
||||||
|
if (entity instanceof ExecutionEntity execution) {
|
||||||
|
switch (typeName) {
|
||||||
|
case "PROCESS_STARTED"
|
||||||
|
-> SCOPE.set(execution);
|
||||||
|
case "PROCESS_CANCELLED",
|
||||||
|
"PROCESS_COMPLETED",
|
||||||
|
"PROCESS_COMPLETED_WITH_ERROR_END_EVENT",
|
||||||
|
"PROCESS_COMPLETED_WITH_ESCALATION_END_EVENT",
|
||||||
|
"PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT"
|
||||||
|
-> SCOPE.remove();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CMMN case instance itself
|
||||||
|
if (entity instanceof CaseInstanceEntity caseInstance) {
|
||||||
|
if ("CASE_STARTED".equals(typeName))
|
||||||
|
SCOPE.set(caseInstance);
|
||||||
|
else if ("CASE_ENDED".equals(typeName))
|
||||||
|
SCOPE.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean isFailOnException() { return false; }
|
||||||
|
@Override public boolean isFireOnTransactionLifecycleEvent() { return false; }
|
||||||
|
@Override public String getOnTransaction() { return null; }
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Public API — called from Flowable expressions
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks which of the given comma-separated variable paths changed since the
|
||||||
|
* last call and returns a JSON array describing each change.
|
||||||
|
* ${varUtils.trackVars('root.snapshot', 'root.myString, status')}
|
||||||
|
* {@code snapshotPath} is a dot-notation path (supports the {@code root.} prefix)
|
||||||
|
* pointing to where the previous-values snapshot is stored and updated.
|
||||||
|
* Each subsequent call compares against the previous snapshot and updates it.
|
||||||
|
* Example return value:
|
||||||
|
* [{"path":"root.myString","oldValue":"a","newValue":"b"}]
|
||||||
|
*/
|
||||||
|
public ArrayNode trackVars(String snapshotPath, String variablePathsCsv) {
|
||||||
|
|
||||||
|
// Check parameters
|
||||||
|
if (snapshotPath == null || snapshotPath.isBlank() || variablePathsCsv == null || variablePathsCsv.isBlank()) {
|
||||||
|
LOGGER.debug("{}.trackVars: empty parameters", getClass().getName());
|
||||||
|
return MAPPER.createArrayNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current scope
|
||||||
|
VariableScope currentScope = getCurrentScope();
|
||||||
|
if (currentScope == null) {
|
||||||
|
LOGGER.debug("{}.trackVars: currentScope not found", getClass().getName());
|
||||||
|
return MAPPER.createArrayNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create paths list
|
||||||
|
List<String> paths = Arrays.stream(variablePathsCsv.split(","))
|
||||||
|
.map(String::trim).filter(s -> !s.isEmpty()).toList();
|
||||||
|
|
||||||
|
Map<String, JsonNode> oldSnapshot = loadSnapshot(currentScope, snapshotPath);
|
||||||
|
Map<String, JsonNode> newSnapshot = new HashMap<>();
|
||||||
|
ArrayNode changes = MAPPER.createArrayNode();
|
||||||
|
|
||||||
|
// Loop paths list
|
||||||
|
for (String path : paths) {
|
||||||
|
JsonNode newValue = toJson(readVariableFromPath(currentScope, path));
|
||||||
|
newSnapshot.put(path, newValue);
|
||||||
|
|
||||||
|
JsonNode oldValue = oldSnapshot.getOrDefault(path, MAPPER.nullNode());
|
||||||
|
if (!oldValue.equals(newValue)) {
|
||||||
|
ObjectNode change = MAPPER.createObjectNode();
|
||||||
|
change.put("path", path);
|
||||||
|
change.set("oldValue", oldValue);
|
||||||
|
change.set("newValue", newValue);
|
||||||
|
changes.add(change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSnapshot(currentScope, snapshotPath, newSnapshot);
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Path resolution
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private Object readVariableFromPath(VariableScope scope, String path) {
|
||||||
|
String[] segments = path.split("\\.", -1);
|
||||||
|
if (segments.length < 1) return null;
|
||||||
|
|
||||||
|
int startIndex = 0;
|
||||||
|
if ("root".equals(segments[0])) {
|
||||||
|
if (segments.length < 2) return null;
|
||||||
|
startIndex = 1;
|
||||||
|
scope = getRootScope(scope);
|
||||||
|
}
|
||||||
|
if (scope == null) return null;
|
||||||
|
|
||||||
|
Object currentValue = scope.getVariable(segments[startIndex]);
|
||||||
|
for (int i = startIndex + 1; i < segments.length; i++) {
|
||||||
|
if (currentValue == null) return null;
|
||||||
|
currentValue = getNestedVariable(currentValue, segments[i]);
|
||||||
|
}
|
||||||
|
return currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeVariableToPath(VariableScope scope, String path, Object value) {
|
||||||
|
String[] segments = path.split("\\.", -1);
|
||||||
|
if (segments.length < 1) return;
|
||||||
|
|
||||||
|
VariableScope targetScope;
|
||||||
|
String[] varSegments;
|
||||||
|
if ("root".equals(segments[0])) {
|
||||||
|
if (segments.length < 2) return;
|
||||||
|
targetScope = getRootScope(scope);
|
||||||
|
varSegments = Arrays.copyOfRange(segments, 1, segments.length);
|
||||||
|
} else {
|
||||||
|
targetScope = scope;
|
||||||
|
varSegments = segments;
|
||||||
|
}
|
||||||
|
if (targetScope == null) return;
|
||||||
|
|
||||||
|
if (varSegments.length == 1) {
|
||||||
|
targetScope.setVariable(varSegments[0], value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nested path: read the top-level variable, navigate to the parent node,
|
||||||
|
// mutate it in-place, then write the top-level variable back.
|
||||||
|
String topVar = varSegments[0];
|
||||||
|
Object topValue = targetScope.getVariable(topVar);
|
||||||
|
|
||||||
|
Object parent = topValue;
|
||||||
|
for (int i = 1; i < varSegments.length - 1; i++) {
|
||||||
|
if (parent == null) {
|
||||||
|
LOGGER.warn("varUtils.writeVariableToPath: null at '{}' in path '{}'", varSegments[i - 1], path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent = getNestedVariable(parent, varSegments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setNestedValue(parent, varSegments[varSegments.length - 1], value, path)) return;
|
||||||
|
targetScope.setVariable(topVar, topValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private boolean setNestedValue(Object parent, String key, Object value, String path) {
|
||||||
|
if (parent instanceof Map map) {
|
||||||
|
map.put(key, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (parent instanceof ObjectNode on) {
|
||||||
|
on.set(key, toJson(value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOGGER.warn("varUtils.writeVariableToPath: cannot set '{}' on {} in path '{}'",
|
||||||
|
key, parent == null ? "null" : parent.getClass().getName(), path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Scope resolution
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private VariableScope getCurrentScope() {
|
||||||
|
VariableScope scope = SCOPE.get();
|
||||||
|
if (scope == null) {
|
||||||
|
LOGGER.error("{}.getCurrentScope called without an active Flowable scope", getClass().getName());
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VariableScope getRootScope(VariableScope scope) {
|
||||||
|
if (scope instanceof DelegateExecution ex) return findBpmnRootScope(ex.getProcessInstanceId());
|
||||||
|
if (scope instanceof CaseInstance ci) return findCmmnRootScope(ci.getId());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VariableScope findBpmnRootScope(String processInstanceId) {
|
||||||
|
if (processInstanceId == null || runtimeService == null) return null;
|
||||||
|
try {
|
||||||
|
Execution piExec = runtimeService.createExecutionQuery()
|
||||||
|
.executionId(processInstanceId).singleResult();
|
||||||
|
if (piExec != null && piExec.getSuperExecutionId() != null) {
|
||||||
|
Execution superExec = runtimeService.createExecutionQuery()
|
||||||
|
.executionId(piExec.getSuperExecutionId()).singleResult();
|
||||||
|
if (superExec != null)
|
||||||
|
return findBpmnRootScope(superExec.getProcessInstanceId());
|
||||||
|
}
|
||||||
|
ProcessInstance pi = runtimeService.createProcessInstanceQuery()
|
||||||
|
.processInstanceId(processInstanceId).singleResult();
|
||||||
|
if (pi != null && pi.getCallbackType() != null && pi.getCallbackId() != null
|
||||||
|
&& cmmnRuntimeService != null) {
|
||||||
|
PlanItemInstance planItem = cmmnRuntimeService.createPlanItemInstanceQuery()
|
||||||
|
.planItemInstanceId(pi.getCallbackId()).singleResult();
|
||||||
|
if (planItem != null)
|
||||||
|
return findCmmnRootScope(planItem.getCaseInstanceId());
|
||||||
|
}
|
||||||
|
return (ExecutionEntity) piExec; // root: ExecutionEntity implements VariableScope
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.debug("{}.findBpmnRootScope: BPMN root scope climb failed: {}", getClass().getName(), e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VariableScope findCmmnRootScope(String caseInstanceId) {
|
||||||
|
if (caseInstanceId == null || cmmnRuntimeService == null) return null;
|
||||||
|
try {
|
||||||
|
CaseInstance ci = cmmnRuntimeService.createCaseInstanceQuery()
|
||||||
|
.caseInstanceId(caseInstanceId).singleResult();
|
||||||
|
if (ci == null) return null;
|
||||||
|
if (ci.getParentId() != null)
|
||||||
|
return findCmmnRootScope(ci.getParentId());
|
||||||
|
if (ci.getCallbackType() != null && ci.getCallbackId() != null
|
||||||
|
&& runtimeService != null) {
|
||||||
|
Execution callbackExec = runtimeService.createExecutionQuery()
|
||||||
|
.executionId(ci.getCallbackId()).singleResult();
|
||||||
|
if (callbackExec != null)
|
||||||
|
return findBpmnRootScope(callbackExec.getProcessInstanceId());
|
||||||
|
}
|
||||||
|
return (CaseInstanceEntity) ci; // root: CaseInstanceEntity implements VariableScope
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.debug("{}.findCmmnRootScope: CMMN root scope climb failed: {}", getClass().getName(), e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getNestedVariable(Object obj, String segment) {
|
||||||
|
if (obj instanceof List<?> list) {
|
||||||
|
try {
|
||||||
|
int i = Integer.parseInt(segment);
|
||||||
|
return i >= 0 && i < list.size() ? list.get(i) : null;
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}
|
||||||
|
if (obj instanceof Object[] arr) {
|
||||||
|
try {
|
||||||
|
int i = Integer.parseInt(segment);
|
||||||
|
return i >= 0 && i < arr.length ? arr[i] : null;
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}
|
||||||
|
if (obj instanceof Map<?, ?> map) return map.get(segment);
|
||||||
|
if (obj instanceof JsonNode jn) {
|
||||||
|
JsonNode node = jn.get(segment);
|
||||||
|
if (node == null || node.isNull()) return null;
|
||||||
|
if (node.isTextual()) return node.asText();
|
||||||
|
if (node.isBoolean()) return node.asBoolean();
|
||||||
|
if (node.isLong()) return node.asLong();
|
||||||
|
if (node.isInt()) return node.asInt();
|
||||||
|
if (node.isDouble()) return node.asDouble();
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
String cap = Character.toUpperCase(segment.charAt(0)) + segment.substring(1);
|
||||||
|
try {
|
||||||
|
return obj.getClass().getMethod("get" + cap).invoke(obj);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
try {
|
||||||
|
return obj.getClass().getMethod("is" + cap).invoke(obj);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Field f = findField(obj.getClass(), segment);
|
||||||
|
if (f != null) { f.setAccessible(true); return f.get(obj); }
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
LOGGER.warn("varUtils: cannot resolve '{}' on {}", segment, obj.getClass().getName());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static java.lang.reflect.Field findField(Class<?> c, String name) {
|
||||||
|
while (c != null && c != Object.class) {
|
||||||
|
try { return c.getDeclaredField(name); }
|
||||||
|
catch (NoSuchFieldException e) { c = c.getSuperclass(); }
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Snapshot persistence
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private Map<String, JsonNode> loadSnapshot(VariableScope scope, String path) {
|
||||||
|
Object raw = readVariableFromPath(scope, path);
|
||||||
|
if (raw == null) return new HashMap<>();
|
||||||
|
try {
|
||||||
|
String json = raw instanceof String s ? s : MAPPER.writeValueAsString(raw);
|
||||||
|
Map<String, Object> flat = MAPPER.readValue(json,
|
||||||
|
MAPPER.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class));
|
||||||
|
Map<String, JsonNode> result = new HashMap<>();
|
||||||
|
flat.forEach((k, v) -> result.put(k, toJson(v)));
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.warn("varUtils: could not load snapshot at '{}': {}", path, e.getMessage());
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveSnapshot(VariableScope scope, String path, Map<String, JsonNode> snapshot) {
|
||||||
|
try {
|
||||||
|
writeVariableToPath(scope, path, MAPPER.writeValueAsString(snapshot));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("varUtils: could not save snapshot at '{}'", path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private static JsonNode toJson(Object value) {
|
||||||
|
if (value == null) return MAPPER.nullNode();
|
||||||
|
if (value instanceof JsonNode jn) return jn;
|
||||||
|
return MAPPER.valueToTree(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
server.port=8105
|
||||||
|
|
||||||
|
# Enable all endpoints over HTTP
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
management.endpoint.health.show-details=when_authorized
|
||||||
|
|
||||||
|
flowable.frontend.title=flowable-work
|
||||||
|
|
||||||
|
#spring.datasource.url=jdbc:h2:~/flowable-work-db/db;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
|
||||||
|
#spring.datasource.username=flowable
|
||||||
|
#spring.datasource.password=flowable
|
||||||
|
|
||||||
|
#Comment out and configure database
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5435/flowable
|
||||||
|
spring.datasource.username=flowable
|
||||||
|
spring.datasource.password=flowable
|
||||||
|
|
||||||
|
# Local Elasticsearch config
|
||||||
|
spring.elasticsearch.uris=http://localhost:9203
|
||||||
|
|
||||||
|
# spring.data.elasticsearch.repositories.enabled=true
|
||||||
|
# spring.data.elasticsearch.cluster-nodes=localhost:9300
|
||||||
|
# spring.data.elasticsearch.cluster-name=elasticsearch
|
||||||
|
|
||||||
|
flowable.indexing.index-name-prefix=flowable-work-
|
||||||
|
#Disable ElasticSearch Indexing
|
||||||
|
#flowable.indexing.enabled=false
|
||||||
|
|
||||||
|
# Enable Flowable Inspect
|
||||||
|
flowable.inspect.enabled=true
|
||||||
|
|
||||||
|
# Forms will update even if an old process/case/task definition will be used
|
||||||
|
flowable.platform.enable-latest-form-definition-lookup=true
|
||||||
|
|
||||||
|
# Server URL for REST calls
|
||||||
|
baseUrl=http://localhost:8105
|
||||||
|
|
||||||
|
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "all",
|
||||||
|
"labelKey": "contacts.filter.all",
|
||||||
|
"defaultLabel": "All",
|
||||||
|
"parameters": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "internal",
|
||||||
|
"labelKey": "contacts.filter.internal",
|
||||||
|
"defaultLabel": "Internal",
|
||||||
|
"parameters": {
|
||||||
|
"must": {
|
||||||
|
"type": "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "external",
|
||||||
|
"labelKey": "contacts.filter.external",
|
||||||
|
"defaultLabel": "External",
|
||||||
|
"parameters": {
|
||||||
|
"must" : {
|
||||||
|
"type": "external"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "active",
|
||||||
|
"labelKey": "contacts.filter.active",
|
||||||
|
"defaultLabel": "Active",
|
||||||
|
"parameters": {
|
||||||
|
"must" : {
|
||||||
|
"state": "ACTIVE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "inactive",
|
||||||
|
"labelKey": "contacts.filter.inactive",
|
||||||
|
"defaultLabel": "Inactive",
|
||||||
|
"parameters": {
|
||||||
|
"must" : {
|
||||||
|
"state": "INACTIVE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Flowable",
|
||||||
|
|
||||||
|
"groups": [
|
||||||
|
{ "key": "flowableUser", "name": "Flowable User" },
|
||||||
|
{ "key": "flowableAdministrator", "name": "Flowable Administrator" }
|
||||||
|
],
|
||||||
|
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"firstName": "Flowable",
|
||||||
|
"lastName": "Admin",
|
||||||
|
"login": "admin",
|
||||||
|
"email": "test@demo.flowable.io",
|
||||||
|
|
||||||
|
"language": "en",
|
||||||
|
"theme": "flowable",
|
||||||
|
"userDefinitionKey": "user-admin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "user-default",
|
||||||
|
"name": "Default user",
|
||||||
|
"description": "Creates a new, non-specific user where the member groups can be freely chosen.",
|
||||||
|
"initialState": "ACTIVE",
|
||||||
|
"initialSubState": "ACTIVE",
|
||||||
|
"forms": {
|
||||||
|
"init": "F01_userInitFormDefault",
|
||||||
|
"view": "F02_userViewFormDefault",
|
||||||
|
"edit": "F03_userEditFormDefault"
|
||||||
|
},
|
||||||
|
"memberGroups": [
|
||||||
|
"flowableUser"
|
||||||
|
],
|
||||||
|
"lookupGroups":[
|
||||||
|
"flowableUser"
|
||||||
|
],
|
||||||
|
"actionPermissions": {
|
||||||
|
"create": [ "flowableAdministrator" ],
|
||||||
|
"edit": [ "flowableAdministrator" ],
|
||||||
|
"deactivate": [ "flowableAdministrator" ],
|
||||||
|
"activate": [ "flowableAdministrator" ]
|
||||||
|
},
|
||||||
|
"contactFilters": [ "all" ],
|
||||||
|
"allowedFeatures": [ "contacts", "bubbles", "markdownInput", "replyToMessage", "forwardMessage", "reactToMessage", "fileUpload", "work", "createWork",
|
||||||
|
"personalAccessTokens",
|
||||||
|
"tasks", "documents", "changeOwnPassword", "changeOwnTheme", "editOwnAvatar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "user-admin",
|
||||||
|
"name": "Administration User",
|
||||||
|
"description": "Creates a new, administration user.",
|
||||||
|
"initialUserSubType": "admin",
|
||||||
|
"initialState": "ACTIVE",
|
||||||
|
"initialSubState": "ACTIVE",
|
||||||
|
"forms": {
|
||||||
|
"init": "F01_userInitFormDefault",
|
||||||
|
"view": "F02_userViewFormDefault",
|
||||||
|
"edit": "F03_userEditFormDefault"
|
||||||
|
},
|
||||||
|
"memberGroups": [
|
||||||
|
"flowableUser",
|
||||||
|
"flowableAdministrator"
|
||||||
|
],
|
||||||
|
"lookupGroups":[
|
||||||
|
"flowableUser"
|
||||||
|
],
|
||||||
|
"actionPermissions": {
|
||||||
|
"create": [ "flowableAdministrator"],
|
||||||
|
"edit": [ "flowableAdministrator" ],
|
||||||
|
"deactivate": [ "flowableAdministrator" ],
|
||||||
|
"activate": [ "flowableAdministrator" ]
|
||||||
|
},
|
||||||
|
"initialVariables": {
|
||||||
|
"adminUser": true,
|
||||||
|
"description": "Admin"
|
||||||
|
},
|
||||||
|
"contactFilters": [ "all", "internal", "external", "inactive"],
|
||||||
|
"allowedFeatures": [ "contacts", "createUser", "reports",
|
||||||
|
"actuators", "user-mgmt", "search-api", "workobject-api", "templateManagement",
|
||||||
|
"markdownInput", "replyToMessage", "forwardMessage", "reactToMessage", "fileUpload", "work", "createWork", "tasks", "documents",
|
||||||
|
"impersonateUser",
|
||||||
|
"personalAccessTokens",
|
||||||
|
"changeOwnPassword", "changeOwnTheme", "editOwnAvatar", "themeManagement"]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.customer.work;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class WorkApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.customer.work.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class TestConfiguration {
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class EmailDto {
|
||||||
|
private String subject;
|
||||||
|
private List<String> receiverList;
|
||||||
|
private String content;
|
||||||
|
private Object contentRaw;
|
||||||
|
|
||||||
|
public EmailDto(String subject, List<String> receiverList, String content, Object contentRaw) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.receiverList = receiverList;
|
||||||
|
this.content = content;
|
||||||
|
this.contentRaw = contentRaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getReceiverList() {
|
||||||
|
return receiverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReceiverList(List<String> receiverList) {
|
||||||
|
this.receiverList = receiverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getContentRaw() {
|
||||||
|
return contentRaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentRaw(Object contentRaw) {
|
||||||
|
this.contentRaw = contentRaw;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,335 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class FlowableExcelMapper {
|
||||||
|
|
||||||
|
protected static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
protected static JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
|
protected static FlowableExcelParser flowableExcelParser = new FlowableExcelParser();
|
||||||
|
|
||||||
|
public FlowableExcelMapper() {
|
||||||
|
// Enable ObjectMapper for handling Instant as string
|
||||||
|
objectMapper.registerModule(javaTimeModule);
|
||||||
|
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// excelPath defines the location of the Excel file
|
||||||
|
// FlowableExcelParser is used to create an ArrayList from the Excel file
|
||||||
|
// The 1st row of every sheet contains the path of the variables to be created in the JsonNode
|
||||||
|
// Delimiter is "." for an ObjectNode and "*" for an ArrayNode
|
||||||
|
// The 2nd row contains tht type of the variable. Supported types are:
|
||||||
|
// - String
|
||||||
|
// - Boolean
|
||||||
|
// - Integer
|
||||||
|
// - Double
|
||||||
|
// - Date
|
||||||
|
// All sheets are added to an ArrayNode
|
||||||
|
// All rows are added to an ArrayNode in the sheets ArrayNode
|
||||||
|
// All cell values are added to an ObjectNode in the rows ArrayNode
|
||||||
|
public ArrayNode excelBookResourceToJsonNode(String resourcePath) {
|
||||||
|
ArrayList<ArrayList<ArrayList<String>>> book = flowableExcelParser.parseExcelBookFromResource(resourcePath);
|
||||||
|
return bookToJsonNode(book);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayNode bookToJsonNode(ArrayList<ArrayList<ArrayList<String>>> book) {
|
||||||
|
ArrayNode bookNode = objectMapper.createArrayNode();
|
||||||
|
for (ArrayList<ArrayList<String>> sheet : book) {
|
||||||
|
bookNode.add(sheetToJsonNode(sheet));
|
||||||
|
}
|
||||||
|
return bookNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayNode sheetToJsonNode(ArrayList<ArrayList<String>> rows) {
|
||||||
|
ArrayList<String> paths = new ArrayList<>();
|
||||||
|
ArrayList<String> types = new ArrayList<>();
|
||||||
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
||||||
|
for (int rowNum = 0; rowNum < rows.size(); rowNum++) {
|
||||||
|
if (rowNum == 0) {
|
||||||
|
// The 1st row contains the paths
|
||||||
|
paths.addAll(rows.get(rowNum));
|
||||||
|
} else if (rowNum == 1) {
|
||||||
|
// The 2nd row contains the types of the variables
|
||||||
|
types.addAll(rows.get(rowNum));
|
||||||
|
} else {
|
||||||
|
// All other rows contain the values of the variables
|
||||||
|
arrayNode.add(rowToJsonNode(types, paths, rows.get(rowNum), null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arrayNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode rowToJsonNode(ArrayList<String> types, ArrayList<String> paths, ArrayList<String> row, JsonNode jsonNode) {
|
||||||
|
for (int cellNum = 0; cellNum < row.size(); cellNum++) {
|
||||||
|
String cellValue = row.get(cellNum);
|
||||||
|
// Empty cells are not added to node
|
||||||
|
if (cellValue != null && !cellValue.isEmpty()) {
|
||||||
|
String type = types.get(cellNum);
|
||||||
|
Object content;
|
||||||
|
switch (cellValue) {
|
||||||
|
case "__NULL": content = null; break;
|
||||||
|
case "__N_A": content = "__N_A"; break;
|
||||||
|
default:
|
||||||
|
switch (type) {
|
||||||
|
case "String":
|
||||||
|
switch (cellValue) {
|
||||||
|
case "__EMPTY": content = ""; break;
|
||||||
|
case "__BLANK": content = " "; break;
|
||||||
|
default: content = cellValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Boolean": content = Boolean.parseBoolean(cellValue); break;
|
||||||
|
case "Integer": content = Integer.parseInt(cellValue); break;
|
||||||
|
case "Double": content = Double.parseDouble(cellValue); break;
|
||||||
|
case "Long": content = Long.parseLong(cellValue); break;
|
||||||
|
case "Date":
|
||||||
|
// Excel considers dates as local dates, but we want them as UTC
|
||||||
|
Instant instant;
|
||||||
|
try {
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
LocalDate localDate = LocalDate.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
instant = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant();
|
||||||
|
}
|
||||||
|
content = instant.plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Variable type not supported: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jsonNode = addNode(jsonNode, paths.get(cellNum), content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode addNode(JsonNode parent, String path, Object value) {
|
||||||
|
if (parent == null) {
|
||||||
|
parent = objectMapper.createObjectNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
int delimiterPosition = indexOfFirstDelimiter(path, ".*");
|
||||||
|
if (delimiterPosition <= 0) {
|
||||||
|
if (parent instanceof ObjectNode) {
|
||||||
|
// Key of a value in an ObjectNode
|
||||||
|
((ObjectNode) parent).set(path, objectMapper.valueToTree(value));
|
||||||
|
} else {
|
||||||
|
// Index of a value in an ArrayNode
|
||||||
|
int index = Integer.parseInt(path);
|
||||||
|
while (parent.size() <= index) {
|
||||||
|
// Create empty entries to parent ArrayNode
|
||||||
|
((ArrayNode) parent).add(objectMapper.createObjectNode());
|
||||||
|
}
|
||||||
|
((ArrayNode) parent).set(index, objectMapper.valueToTree(value));
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = path.substring(0, delimiterPosition);
|
||||||
|
String newPath = path.substring(delimiterPosition + 1);
|
||||||
|
String delimiter = path.substring(delimiterPosition, delimiterPosition + 1);
|
||||||
|
JsonNode child = null;
|
||||||
|
if (delimiter.equals(".")) {
|
||||||
|
child = objectMapper.createObjectNode();
|
||||||
|
} else if (delimiter.equals("*")) {
|
||||||
|
child = objectMapper.createArrayNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode node;
|
||||||
|
if (parent instanceof ObjectNode) {
|
||||||
|
// Key of a JsonNode in an ObjectNode
|
||||||
|
node = parent.get(key);
|
||||||
|
if (node != null) {
|
||||||
|
// Take the existing ObjectNode as child
|
||||||
|
child = node;
|
||||||
|
}
|
||||||
|
((ObjectNode) parent).set(key, addNode(child, newPath, value));
|
||||||
|
} else {
|
||||||
|
// Index of a JsonNode in an ArrayNode
|
||||||
|
int index = Integer.parseInt(key);
|
||||||
|
node = parent.get(index);
|
||||||
|
if (node != null) {
|
||||||
|
// Take the existing ArrayNode as child
|
||||||
|
child = node;
|
||||||
|
}
|
||||||
|
while (parent.size() <= index) {
|
||||||
|
// Create empty entries to parent ArrayNode
|
||||||
|
((ArrayNode) parent).add(objectMapper.createObjectNode());
|
||||||
|
}
|
||||||
|
((ArrayNode) parent).set(index, addNode(child, newPath, value));
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int indexOfFirstDelimiter(String str, String delimiters) {
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
for (char c : delimiters.toCharArray()) {
|
||||||
|
if (str.charAt(i) == c) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ArrayList<Object>> excelBookResourceToObj(String resourcePath) {
|
||||||
|
ArrayList<ArrayList<ArrayList<String>>> book = flowableExcelParser.parseExcelBookFromResource(resourcePath);
|
||||||
|
return bookToObj(book);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList<ArrayList<Object>> bookToObj(ArrayList<ArrayList<ArrayList<String>>> book) {
|
||||||
|
ArrayList<ArrayList<Object>> bookNode = new ArrayList<>();
|
||||||
|
for (ArrayList<ArrayList<String>> sheet : book) {
|
||||||
|
bookNode.add(sheetToObj(sheet));
|
||||||
|
}
|
||||||
|
return bookNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList<Object> sheetToObj(ArrayList<ArrayList<String>> rows) {
|
||||||
|
ArrayList<String> paths = new ArrayList<>();
|
||||||
|
ArrayList<String> types = new ArrayList<>();
|
||||||
|
ArrayList<Object> arrayNode = new ArrayList<>();
|
||||||
|
for (int rowNum = 0; rowNum < rows.size(); rowNum++) {
|
||||||
|
if (rowNum == 0) {
|
||||||
|
// The 1st row contains the paths
|
||||||
|
paths.addAll(rows.get(rowNum));
|
||||||
|
} else if (rowNum == 1) {
|
||||||
|
// The 2nd row contains the types of the variables
|
||||||
|
types.addAll(rows.get(rowNum));
|
||||||
|
} else {
|
||||||
|
// All other rows contain the values of the variables
|
||||||
|
arrayNode.add(rowToObj(types, paths, rows.get(rowNum), null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arrayNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object rowToObj(ArrayList<String> types, ArrayList<String> paths, ArrayList<String> row, Object node) {
|
||||||
|
for (int cellNum = 0; cellNum < row.size(); cellNum++) {
|
||||||
|
String cellValue = row.get(cellNum);
|
||||||
|
// Empty cells are not added to node
|
||||||
|
if (cellValue != null && !cellValue.isEmpty()) {
|
||||||
|
String type = types.get(cellNum);
|
||||||
|
Object content;
|
||||||
|
switch (cellValue) {
|
||||||
|
case "__NULL": content = null; break;
|
||||||
|
case "__N_A": content = "__N_A"; break;
|
||||||
|
default:
|
||||||
|
switch (type) {
|
||||||
|
case "String":
|
||||||
|
switch (cellValue) {
|
||||||
|
case "__EMPTY": content = ""; break;
|
||||||
|
case "__BLANK": content = " "; break;
|
||||||
|
default: content = cellValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Boolean": content = Boolean.parseBoolean(cellValue); break;
|
||||||
|
case "Integer": content = Integer.parseInt(cellValue); break;
|
||||||
|
case "Double": content = Double.parseDouble(cellValue); break;
|
||||||
|
case "Long": content = Long.parseLong(cellValue); break;
|
||||||
|
case "Date":
|
||||||
|
// Excel considers dates as local dates, but we want them as UTC
|
||||||
|
Instant instant;
|
||||||
|
try {
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
LocalDate localDate = LocalDate.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
instant = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant();
|
||||||
|
}
|
||||||
|
content = instant.plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Variable type not supported: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = addObj(node, paths.get(cellNum), content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected Object addObj(Object parent, String path, Object value) {
|
||||||
|
if (parent == null) {
|
||||||
|
parent = new LinkedHashMap<String, Object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int delimiterPosition = indexOfFirstDelimiter(path, ".*");
|
||||||
|
if (delimiterPosition <= 0) {
|
||||||
|
if (parent instanceof LinkedHashMap) {
|
||||||
|
// Key of a value in an ObjectNode
|
||||||
|
((Map<String, Object>) parent).put(path, value);
|
||||||
|
} else if (parent instanceof ArrayList) {
|
||||||
|
// Index of a value in an ArrayNode
|
||||||
|
int index = Integer.parseInt(path);
|
||||||
|
while (((ArrayList<Object>) parent).size() <= index) {
|
||||||
|
// Create empty entries to parent ArrayNode
|
||||||
|
((ArrayList<Object>) parent).add(new LinkedHashMap<String, Object> ());
|
||||||
|
}
|
||||||
|
((ArrayList<Object>) parent).set(index, value);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Parent type not supported: " + parent.getClass().getName());
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = path.substring(0, delimiterPosition);
|
||||||
|
String newPath = path.substring(delimiterPosition + 1);
|
||||||
|
String delimiter = path.substring(delimiterPosition, delimiterPosition + 1);
|
||||||
|
Object child = null;
|
||||||
|
if (delimiter.equals(".")) {
|
||||||
|
child = new LinkedHashMap<String, Object>();
|
||||||
|
} else if (delimiter.equals("*")) {
|
||||||
|
child = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Object node;
|
||||||
|
if (parent instanceof LinkedHashMap) {
|
||||||
|
// Key of a JsonNode in an ObjectNode
|
||||||
|
node = ((Map<String, Object>) parent).get(key);
|
||||||
|
if (node != null) {
|
||||||
|
// Take the existing ObjectNode as child
|
||||||
|
child = node;
|
||||||
|
}
|
||||||
|
((Map<String, Object>) parent).put(key, addObj(child, newPath, value));
|
||||||
|
} else if (parent instanceof ArrayList) {
|
||||||
|
// Index of a JsonNode in an ArrayNode
|
||||||
|
int index = Integer.parseInt(key);
|
||||||
|
if (((ArrayList<Object>) parent).size() > index) {
|
||||||
|
node = ((ArrayList<Object>) parent).get(index);
|
||||||
|
} else {
|
||||||
|
node = null;
|
||||||
|
}
|
||||||
|
if (node != null) {
|
||||||
|
// Take the existing ArrayNode as child
|
||||||
|
child = node;
|
||||||
|
}
|
||||||
|
while (((ArrayList<Object>) parent).size() <= index) {
|
||||||
|
// Create empty entries to parent ArrayNode
|
||||||
|
((ArrayList<Object>) parent).add(new LinkedHashMap<String, Object> ());
|
||||||
|
}
|
||||||
|
((ArrayList<Object>) parent).set(index, addObj(child, newPath, value));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Parent type not supported: " + parent.getClass().getName());
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class FlowableExcelParser {
|
||||||
|
|
||||||
|
// excelPath defines the location of the Excel file
|
||||||
|
// Return all cells in all sheets with the following restrictions:
|
||||||
|
// - Max column count per sheet is defined in the first row
|
||||||
|
// - Max column count starts with the 1st cell and ends with the 1st empty cell
|
||||||
|
// - Parsing the sheet stops after the 1st empty row
|
||||||
|
// All sheets are added to an ArrayList
|
||||||
|
// All rows are added to an ArrayList in the sheets ArrayList
|
||||||
|
// All cell values are added to an ArrayList in the rows ArrayList
|
||||||
|
// Formulas in cells are evaluated
|
||||||
|
// All values are returned as String
|
||||||
|
public ArrayList<ArrayList<ArrayList<String>>> parseExcelBookFromResource(String excelResourcePath) {
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(getResourcePath(excelResourcePath))) {
|
||||||
|
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
||||||
|
return parseBook(workBook);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getResourcePath(String resourcePath) {
|
||||||
|
ClassLoader classLoader = FlowableExcelParser.class.getClassLoader();
|
||||||
|
URL resourceUrl = classLoader.getResource(resourcePath);
|
||||||
|
if (resourceUrl == null) {
|
||||||
|
throw new RuntimeException("Resource not found: " + resourcePath);
|
||||||
|
}
|
||||||
|
return resourceUrl.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<ArrayList<ArrayList<String>>> parseBook(Workbook workBook ) {
|
||||||
|
ArrayList<ArrayList<ArrayList<String>>> book = new ArrayList<>();
|
||||||
|
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
||||||
|
for (Sheet workSheet : workBook) {
|
||||||
|
book.add(parseSheet(workSheet, formulaEvaluator));
|
||||||
|
}
|
||||||
|
return book;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<ArrayList<String>> parseSheet(Sheet workSheet, FormulaEvaluator formulaEvaluator) {
|
||||||
|
ArrayList<ArrayList<String>> sheet = new ArrayList<>();
|
||||||
|
// Count columns of first row
|
||||||
|
int maxCols = getMaxCols(workSheet.getRow(0));
|
||||||
|
DataFormatter dataFormatter = new DataFormatter();
|
||||||
|
int firstRow = workSheet.getFirstRowNum();
|
||||||
|
int lastRow = workSheet.getLastRowNum();
|
||||||
|
// For (Row workRow : workSheet) sometimes ignores empty rows, then the first empty row as an exit criterion wouldn't work
|
||||||
|
for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
|
||||||
|
ArrayList<String> row = parseRow(workSheet.getRow(rowIndex), maxCols, formulaEvaluator, dataFormatter);
|
||||||
|
if (row == null) {
|
||||||
|
// Take all rows until the first empty row
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sheet.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<String> parseRow(Row workRow, int maxCols, FormulaEvaluator formulaEvaluator, DataFormatter dataFormatter) {
|
||||||
|
if (workRow == null) {
|
||||||
|
// Row is empty
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ArrayList<String> row = new ArrayList<>();
|
||||||
|
boolean allCellsNull = true;
|
||||||
|
for (int colIndex = 0; colIndex < maxCols; colIndex++) {
|
||||||
|
Cell workCell = workRow.getCell(colIndex);
|
||||||
|
formulaEvaluator.evaluate(workCell);
|
||||||
|
String content = dataFormatter.formatCellValue(workCell, formulaEvaluator);
|
||||||
|
if (content != null && !content.isEmpty()) {
|
||||||
|
allCellsNull = false;
|
||||||
|
}
|
||||||
|
row.add(content);
|
||||||
|
}
|
||||||
|
if (allCellsNull) {
|
||||||
|
// Row is empty
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMaxCols(Row workRow) {
|
||||||
|
int maxCol = workRow.getLastCellNum();
|
||||||
|
for (int colIndex = 0; colIndex < maxCol; colIndex++) {
|
||||||
|
Cell workCell = workRow.getCell(colIndex);
|
||||||
|
if (workCell == null || workCell.getCellType() == CellType.BLANK || workCell.getCellType() == CellType._NONE) {
|
||||||
|
// Count cells until the first empty cell
|
||||||
|
return colIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public ArrayList<LinkedHashMap<String, Object>> parseExcelFromResource(String resourcePath) {
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(getResourcePath(resourcePath))) {
|
||||||
|
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
||||||
|
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
||||||
|
ArrayList<ArrayList<String>> sheet = parseSheet(workBook.getSheetAt(0), formulaEvaluator);
|
||||||
|
ArrayList<String> colHeaders = new ArrayList<>();
|
||||||
|
ArrayList<LinkedHashMap<String, Object>> rowList = new ArrayList<>();
|
||||||
|
for (int rowIndex = 0; rowIndex < sheet.size(); rowIndex++) {
|
||||||
|
ArrayList<String> row = sheet.get(rowIndex);
|
||||||
|
if (rowIndex == 0) {
|
||||||
|
// Header row
|
||||||
|
for (Object cell : row) {
|
||||||
|
colHeaders.add(String.valueOf(cell));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LinkedHashMap<String, Object> rowMap = new LinkedHashMap<>();
|
||||||
|
for (int colIndex = 0; colIndex < row.size(); colIndex++) {
|
||||||
|
rowMap.put(colHeaders.get(colIndex), row.get(colIndex));
|
||||||
|
}
|
||||||
|
rowList.add(rowMap);
|
||||||
|
}
|
||||||
|
return rowList;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class FlowableJsonParser {
|
||||||
|
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
private static final JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
|
|
||||||
|
public static final String BOOLEAN = "Boolean";
|
||||||
|
public static final String STRING = "String";
|
||||||
|
public static final String INTEGER = "Integer";
|
||||||
|
public static final String DOUBLE = "Double";
|
||||||
|
public static final String LONG = "Long";
|
||||||
|
public static final String INSTANT = "Instant";
|
||||||
|
public static final String JSON_OBJECT_NODE = "JsonObjectNode";
|
||||||
|
public static final String JSON_ARRAY_NODE = "JsonArrayNode";
|
||||||
|
public static final String MAP = "Map";
|
||||||
|
public static final String ARRAY_LIST = "ArrayList";
|
||||||
|
|
||||||
|
|
||||||
|
public FlowableJsonParser() {
|
||||||
|
objectMapper.registerModule(javaTimeModule);
|
||||||
|
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> parseMap(Object map) throws JsonProcessingException, ClassCastException {
|
||||||
|
return (Map<String, Object>) parseObject(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object parseObject(Object object) throws JsonProcessingException, ClassCastException {
|
||||||
|
if (object instanceof Map) {
|
||||||
|
Map<String, Object> resultMap = new LinkedHashMap<>(Map.of());
|
||||||
|
for (Map.Entry<String, Object> mapEntry : ((Map<String, Object>) object).entrySet()) {
|
||||||
|
String key = mapEntry.getKey();
|
||||||
|
resultMap.put(key, parseMapEntry(key, mapEntry.getValue()));
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
if (object instanceof ArrayList) {
|
||||||
|
ArrayList<Object> resultList = new ArrayList<>();
|
||||||
|
for (Object arrayEntry : (ArrayList<Object>) object) {
|
||||||
|
resultList.add(parseArrayEntry(arrayEntry));
|
||||||
|
}
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object parseMapEntry(String key, Object value) throws JsonProcessingException {
|
||||||
|
if (value instanceof Map) {
|
||||||
|
Map<String, Object> valueMap = (Map<String, Object>) value;
|
||||||
|
if (valueMap.containsKey("__TYPE") && valueMap.containsKey("__VALUE") && valueMap.size() == 2) {
|
||||||
|
// if Map in Map, check if inner Map has explicit type (__TYPE and __VALUE)
|
||||||
|
return convertObjectExplicit(valueMap.get("__VALUE"), (String) valueMap.get("__TYPE"));
|
||||||
|
}
|
||||||
|
if (Arrays.asList("__IN", "__OUT").contains(key)) {
|
||||||
|
// convert __IN and __OUT maps as Map
|
||||||
|
return parseObject(value);
|
||||||
|
}
|
||||||
|
// convert Map to JsonObjectNode (default in models)
|
||||||
|
return convertObjectExplicit(value, JSON_OBJECT_NODE);
|
||||||
|
}
|
||||||
|
if (value instanceof ArrayList) {
|
||||||
|
// convert ArrayList to JsonArrayNode (default in models)
|
||||||
|
return convertObjectExplicit(value, JSON_ARRAY_NODE);
|
||||||
|
}
|
||||||
|
// take json supported type (Boolean, String, Integer, Double)
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object parseArrayEntry(Object value) throws JsonProcessingException {
|
||||||
|
if (value instanceof Map) {
|
||||||
|
// convert Map to JsonObjectNode (default in models)
|
||||||
|
return convertObjectExplicit(value, JSON_OBJECT_NODE);
|
||||||
|
}
|
||||||
|
if (value instanceof ArrayList) {
|
||||||
|
// convert ArrayList to JsonArrayNode (default in models)
|
||||||
|
return convertObjectExplicit(value, JSON_ARRAY_NODE);
|
||||||
|
}
|
||||||
|
// take json supported type (Boolean, String, Integer, Double)
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object convertObjectExplicit(Object value, String explicitType) throws JsonProcessingException {
|
||||||
|
switch (explicitType) {
|
||||||
|
case BOOLEAN: return Boolean.parseBoolean(value.toString());
|
||||||
|
case STRING: return value.toString();
|
||||||
|
case INTEGER: return Integer.parseInt(value.toString());
|
||||||
|
case DOUBLE: return Double.parseDouble(value.toString());
|
||||||
|
case LONG: return Long.parseLong(value.toString());
|
||||||
|
case INSTANT: return Instant.parse(value.toString());
|
||||||
|
case MAP: case ARRAY_LIST: return parseObject(value);
|
||||||
|
case JSON_OBJECT_NODE: case JSON_ARRAY_NODE: return objectMapper.convertValue(parseObject(value), JsonNode.class);
|
||||||
|
default: return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import com.flowable.action.engine.test.ActionExtension;
|
||||||
|
import com.flowable.app.engine.test.FlowableAppExtension;
|
||||||
|
import com.flowable.dataobject.engine.test.DataObjectExtension;
|
||||||
|
import com.flowable.form.spring.impl.test.FlowableFormSpringExtension;
|
||||||
|
import com.flowable.idm.engine.test.PlatformIdmExtension;
|
||||||
|
import com.flowable.platform.tenant.test.TenantSetupExtension;
|
||||||
|
import com.flowable.policy.engine.test.PolicyExtension;
|
||||||
|
import com.flowable.serviceregistry.engine.test.ServiceRegistryExtension;
|
||||||
|
import com.flowable.template.engine.test.TemplateExtension;
|
||||||
|
import org.flowable.cmmn.spring.impl.test.FlowableCmmnSpringExtension;
|
||||||
|
import org.flowable.dmn.spring.impl.test.FlowableDmnSpringExtension;
|
||||||
|
import org.flowable.spring.impl.test.FlowableSpringExtension;
|
||||||
|
import org.junit.jupiter.api.TestInstance;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@ExtendWith(ActionExtension.class)
|
||||||
|
@ExtendWith(DataObjectExtension.class)
|
||||||
|
//@ExtendWith(EngageExtension.class)
|
||||||
|
@ExtendWith(FlowableAppExtension.class)
|
||||||
|
@ExtendWith(FlowableSpringExtension.class)
|
||||||
|
@ExtendWith(FlowableCmmnSpringExtension.class)
|
||||||
|
@ExtendWith(FlowableFormSpringExtension.class)
|
||||||
|
@ExtendWith(FlowableDmnSpringExtension.class)
|
||||||
|
@ExtendWith(PlatformIdmExtension.class)
|
||||||
|
@ExtendWith(PolicyExtension.class)
|
||||||
|
@ExtendWith(ServiceRegistryExtension.class)
|
||||||
|
@ExtendWith(TemplateExtension.class)
|
||||||
|
@ExtendWith(TenantSetupExtension.class)
|
||||||
|
@ExtendWith(TestMailServerExtension.class)
|
||||||
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
|
@Transactional
|
||||||
|
@SpringBootTest
|
||||||
|
public @interface FlowableModelTest {
|
||||||
|
/*
|
||||||
|
@AliasFor(annotation = SpringBootTest.class, attribute = "webEnvironment")
|
||||||
|
SpringBootTest.WebEnvironment webEnvironment() default SpringBootTest.WebEnvironment.MOCK;
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,656 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import com.customer.work.service.JsonUtils;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.flowable.audit.api.AuditService;
|
||||||
|
import com.flowable.audit.api.runtime.AuditInstance;
|
||||||
|
import com.flowable.core.spring.security.SecurityUtils;
|
||||||
|
import com.flowable.platform.service.task.CompleteFormRepresentation;
|
||||||
|
import com.flowable.platform.service.task.PlatformTaskService;
|
||||||
|
import jakarta.mail.Address;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.flowable.bpmn.model.*;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
import org.flowable.cmmn.api.runtime.CaseInstance;
|
||||||
|
import org.flowable.cmmn.engine.CmmnEngine;
|
||||||
|
import org.flowable.common.engine.api.identity.AuthenticationContext;
|
||||||
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
|
import org.flowable.engine.ManagementService;
|
||||||
|
import org.flowable.engine.ProcessEngine;
|
||||||
|
import org.flowable.engine.TaskService;
|
||||||
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
|
||||||
|
import org.flowable.spring.security.SpringSecurityAuthenticationContext;
|
||||||
|
import org.flowable.task.api.Task;
|
||||||
|
import org.flowable.variable.api.history.HistoricVariableInstance;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.platform.commons.util.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class FlowableModelTestUtils {
|
||||||
|
|
||||||
|
protected final ProcessEngine processEngine;
|
||||||
|
protected final CmmnEngine cmmnEngine;
|
||||||
|
protected final TaskService taskService;
|
||||||
|
protected final PlatformTaskService platformTaskService;
|
||||||
|
protected final ManagementService managementService;
|
||||||
|
protected final JsonUtils jsonUtils;
|
||||||
|
protected final FlowableExcelMapper flowableExcelMapper;
|
||||||
|
protected static final Logger logger = LoggerFactory.getLogger(FlowableModelTestUtils.class);
|
||||||
|
protected final TestMailServer testMailServer;
|
||||||
|
protected final AuditService auditService;
|
||||||
|
|
||||||
|
|
||||||
|
public static String TENANT_ID = null;
|
||||||
|
public static String ROOT_PROCESS_ID = "ROOT_PROCESS_ID";
|
||||||
|
public static String TEST_PROCESS_ID = "TEST_PROCESS_ID";
|
||||||
|
|
||||||
|
|
||||||
|
public FlowableModelTestUtils(ProcessEngine processEngine,
|
||||||
|
CmmnEngine cmmnEngine,
|
||||||
|
TaskService taskService,
|
||||||
|
PlatformTaskService platformTaskService,
|
||||||
|
ManagementService managementService,
|
||||||
|
JsonUtils jsonUtils,
|
||||||
|
FlowableExcelMapper flowableExcelMapper,
|
||||||
|
TestMailServer testMailServer,
|
||||||
|
AuditService auditService) {
|
||||||
|
this.processEngine = processEngine;
|
||||||
|
this.cmmnEngine = cmmnEngine;
|
||||||
|
this.taskService = taskService;
|
||||||
|
this.platformTaskService = platformTaskService;
|
||||||
|
this.managementService = managementService;
|
||||||
|
this.jsonUtils = jsonUtils;
|
||||||
|
this.flowableExcelMapper = flowableExcelMapper;
|
||||||
|
this.testMailServer = testMailServer;
|
||||||
|
this.auditService = auditService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkAndAndAssertAuditRecord(Map<String, Object> map, int auditNumber, String hint, String message, String category, String type) {
|
||||||
|
if (map != null) {
|
||||||
|
Object check = map.get("audit");
|
||||||
|
if (check instanceof Integer && (Integer) check > 0) {
|
||||||
|
assertAuditRecord(auditNumber, hint, message, category, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertAuditRecord(int auditNumber, String hint, String message, String category, String type) {
|
||||||
|
List<AuditInstance> auditTrail = getAuditTrail();
|
||||||
|
int auditTrailSize = auditTrail.size();
|
||||||
|
Assertions.assertThat(auditTrailSize).as(hint + ": invalid auditNumber " + auditTrailSize).isGreaterThanOrEqualTo(auditNumber);
|
||||||
|
if (auditTrailSize == 0) return;
|
||||||
|
|
||||||
|
AuditInstance auditInstance = auditTrail.get(auditNumber - 1);
|
||||||
|
Assertions.assertThat(auditInstance.getPayload().get("message")).as(hint).isEqualTo(message);
|
||||||
|
Assertions.assertThat(auditInstance.getPayload().get("category")).as(hint).isEqualTo(category);
|
||||||
|
Assertions.assertThat(auditInstance.getType()).as(hint).isEqualTo(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkAndAssertEmail(Map<String, Object> map, int emailNumber, String hint, String subject, String receivers) {
|
||||||
|
if (map != null) {
|
||||||
|
Object check = map.get("email");
|
||||||
|
if (check instanceof Integer && (Integer) check > 0) {
|
||||||
|
assertEmail(emailNumber, hint, subject, receivers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertEmail(int emailNumber, String hint, String subject, String receivers) {
|
||||||
|
List<EmailDto> emails = getMailList();
|
||||||
|
int emailListSize = emails.size();
|
||||||
|
Assertions.assertThat(emailListSize).as(hint + ": invalid email number " + emailListSize).isGreaterThanOrEqualTo(emailNumber);
|
||||||
|
if (emailNumber == 0) return;
|
||||||
|
|
||||||
|
EmailDto email = emails.get(emailNumber - 1);
|
||||||
|
String emailSubject = email.getSubject();
|
||||||
|
Assertions.assertThat(emailSubject).as(hint + ": invalid subject " + emailSubject).endsWith(subject);
|
||||||
|
|
||||||
|
List<Pair<String, Boolean>> receiverCheckList = new ArrayList<>();
|
||||||
|
for (String receiver : receivers.split("[,\\s]+")) {
|
||||||
|
receiverCheckList.add(Pair.of(receiver, false));
|
||||||
|
}
|
||||||
|
List<String> emailReceiverList = email.getReceiverList();
|
||||||
|
Assertions.assertThat(emailReceiverList.size()).as(hint + ": invalid number of receivers " + emailReceiverList).isEqualTo(receiverCheckList.size());
|
||||||
|
|
||||||
|
for (String emailReceiver : emailReceiverList) {
|
||||||
|
for (int i = 0; i < receiverCheckList.size(); i++) {
|
||||||
|
Pair<String, Boolean> checkReceiver = receiverCheckList.get(i);
|
||||||
|
if (checkReceiver.getLeft().equals(emailReceiver) && !checkReceiver.getRight()) {
|
||||||
|
receiverCheckList.set(i, Pair.of(emailReceiver, true));
|
||||||
|
break;
|
||||||
|
} else if (i == receiverCheckList.size() - 1) {
|
||||||
|
Assertions.fail(hint + ": invalid email receiver " + emailReceiverList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getHistoryCasePayload(String caseInstanceId) {
|
||||||
|
List<HistoricVariableInstance> historicVariableInstanceList = cmmnEngine.getCmmnHistoryService()
|
||||||
|
.createHistoricVariableInstanceQuery()
|
||||||
|
.caseInstanceId(caseInstanceId)
|
||||||
|
.list();
|
||||||
|
return convertHistVariableListToMap(historicVariableInstanceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getRuntimeCasePayload(String caseId) {
|
||||||
|
return cmmnEngine.getCmmnRuntimeService().getVariables(caseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaseInstance startCaseInstance(String key, Map<String, Object> variables) {
|
||||||
|
return cmmnEngine.getCmmnRuntimeService()
|
||||||
|
.createCaseInstanceBuilder()
|
||||||
|
.caseDefinitionKey(key)
|
||||||
|
.tenantId(TENANT_ID) // Must not be "default"
|
||||||
|
.variables(variables)
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessInstance startProcessInstance(String key, Map<String, Object> variables) {
|
||||||
|
return processEngine.getRuntimeService()
|
||||||
|
.createProcessInstanceBuilder()
|
||||||
|
.processDefinitionKey(key)
|
||||||
|
.tenantId(TENANT_ID) // Must not be "default"
|
||||||
|
.variables(variables)
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getOpenTask(String taskKey) {
|
||||||
|
Task task = taskService.createTaskQuery().taskDefinitionKey(taskKey).singleResult();
|
||||||
|
Assertions.assertThat(task).as("No open task with key {} found", taskKey).isNotNull();
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getOpenTaskByName(String taskName) {
|
||||||
|
Task task = taskService.createTaskQuery().taskName(taskName).singleResult();
|
||||||
|
Assertions.assertThat(task).as("No open task with name {} found", taskName).isNotNull();
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void claimOpenTask(String taskKey, String userId) {
|
||||||
|
setTestAuthenticatedUser(userId, TENANT_ID);
|
||||||
|
taskService.claim(getOpenTask(taskKey).getId(), userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AuditInstance> getAuditTrail() {
|
||||||
|
return auditService.createAuditInstanceQuery()
|
||||||
|
//.tenantId(TENANT_ID) TODO: Must not be null, should work with default tenant
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EmailDto> getMailList() {
|
||||||
|
return Arrays.stream(testMailServer.getMessages()).map(mimeMessage -> {
|
||||||
|
try {
|
||||||
|
return new EmailDto(mimeMessage.getSubject(), Arrays.stream(mimeMessage.getAllRecipients())
|
||||||
|
.map(Address::toString).collect(Collectors.toList()), mimeMessage.getContent().toString(), mimeMessage.getContent());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubset(JsonNode root, JsonNode test) {
|
||||||
|
// If test is null, it is always a subset of root
|
||||||
|
if (test == null || test.isNull()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If test is a value node, compare values
|
||||||
|
if (test.isValueNode()) {
|
||||||
|
if (test.isTextual() && "__N_A".equals(test.asText())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (root == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return root.isValueNode() && root.asText().equals(test.asText());
|
||||||
|
}
|
||||||
|
// If test is an array node, check if all elements of test exist in root
|
||||||
|
if(test.isArray()){
|
||||||
|
for (int i = 0; i < test.size(); i++) {
|
||||||
|
JsonNode testElement = test.get(i);
|
||||||
|
JsonNode rootElement = null;
|
||||||
|
if (root != null) {
|
||||||
|
rootElement = root.get(i);
|
||||||
|
}
|
||||||
|
if (testElement.isTextual() && "__N_A".equals(testElement.asText())) {
|
||||||
|
if (rootElement != null && !rootElement.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isSubset(rootElement, testElement)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If test is an object node, check if all fields in test exist in root
|
||||||
|
if (test.isObject()){
|
||||||
|
for (Iterator<String> iterator = test.fieldNames(); iterator.hasNext(); ) {
|
||||||
|
String fieldName = iterator.next();
|
||||||
|
JsonNode testValue = test.get(fieldName);
|
||||||
|
JsonNode rootValue = null;
|
||||||
|
if (root != null) {
|
||||||
|
rootValue = root.get(fieldName);
|
||||||
|
}
|
||||||
|
if (testValue.isTextual() && "__N_A".equals(testValue.asText())) {
|
||||||
|
if (root != null && root.has(fieldName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isSubset(rootValue, testValue)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If none of the above matches, return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Arguments> getJsonArgumentsFromExcel(String path) {
|
||||||
|
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||||
|
JsonNode book = flowableExcelMapper.excelBookResourceToJsonNode(path);
|
||||||
|
for (JsonNode sheet : book) {
|
||||||
|
for (JsonNode row : sheet) {
|
||||||
|
argumentList.add(Arguments.of(path, row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return argumentList.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Arguments> getObjArgumentsFromExcel(String path) {
|
||||||
|
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||||
|
ArrayList<ArrayList<Object>> book = flowableExcelMapper.excelBookResourceToObj(path);
|
||||||
|
for (ArrayList<Object> sheet : book) {
|
||||||
|
for (Object row : sheet) {
|
||||||
|
argumentList.add(Arguments.of(path, row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return argumentList.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode testJsonExcelRow(String path, JsonNode row) {
|
||||||
|
ObjectNode vars = jsonUtils.getEmptyObjectNode();
|
||||||
|
JsonNode rootParam = row.get("root");
|
||||||
|
if (rootParam != null) {
|
||||||
|
Iterator<Map.Entry<String, JsonNode>> rootVars = rootParam.fields();
|
||||||
|
while (rootVars.hasNext()) {
|
||||||
|
Map.Entry<String, JsonNode> rootVar = rootVars.next();
|
||||||
|
String key = rootVar.getKey();
|
||||||
|
JsonNode value = rootVar.getValue();
|
||||||
|
vars.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsonNode inParam = row.get("in");
|
||||||
|
if (inParam != null) {
|
||||||
|
vars.set("__IN", inParam);
|
||||||
|
}
|
||||||
|
JsonNode outParam = row.get("out");
|
||||||
|
if (outParam != null) {
|
||||||
|
vars.set("__OUT", outParam);
|
||||||
|
}
|
||||||
|
JsonNode idParam = row.get("id");
|
||||||
|
JsonNode test = row.get("test");
|
||||||
|
int timerCount = 0;
|
||||||
|
JsonNode timerNode = row.get("timer");
|
||||||
|
if (timerNode != null) timerCount = timerNode.asInt();
|
||||||
|
Integer auditRecordCount = null;
|
||||||
|
JsonNode auditNode = row.get("audit");
|
||||||
|
if (auditNode != null) auditRecordCount = auditNode.asInt();
|
||||||
|
Integer emailCount = null;
|
||||||
|
JsonNode emailNode = row.get("email");
|
||||||
|
if (emailNode != null) emailCount = emailNode.asInt();
|
||||||
|
|
||||||
|
logger.info("TestExcelRow file={} id={} rootParam={} inParam={} outParam={} timer={} test={} audit={} email={} ",
|
||||||
|
path, idParam, rootParam, inParam, outParam, timerCount, test, auditRecordCount, emailCount);
|
||||||
|
ObjectNode processIds = createRootTestProcessInstance(idParam.asText(), jsonUtils.convertJsonNodeToMap(vars));
|
||||||
|
for (int i = 0; i < timerCount; i++) {
|
||||||
|
executeTimer(processIds.get(TEST_PROCESS_ID).asText());
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectNode result = jsonUtils.getEmptyObjectNode();
|
||||||
|
Map<String, Object> rootProcessPayload = getHistProcessPayload(processIds.get(FlowableModelTestUtils.ROOT_PROCESS_ID).asText());
|
||||||
|
JsonNode root = jsonUtils.convertMapToJsonNode(rootProcessPayload);
|
||||||
|
if (root != null) {
|
||||||
|
Assertions.assertThat(isSubset(root, test))
|
||||||
|
.withFailMessage(System.lineSeparator() + "test :" + test + System.lineSeparator() + "root :" + root).isTrue();
|
||||||
|
result.set("root", root);
|
||||||
|
}
|
||||||
|
if (auditRecordCount != null) {
|
||||||
|
// List<AuditInstance> auditTrail = getAuditTrail(processIds.get(ROOT_PROCESS_ID).asText());
|
||||||
|
List<AuditInstance> auditTrail = getAuditTrail();
|
||||||
|
int auditTrailSize = auditTrail.size();
|
||||||
|
Assertions.assertThat(auditTrailSize).as("Invalid audit trail size: {}", auditTrailSize).isEqualTo(auditRecordCount);
|
||||||
|
result.set("auditTrail", jsonUtils.convertListToJsonNode(Collections.singletonList(auditTrail)));
|
||||||
|
}
|
||||||
|
if (emailCount != null) {
|
||||||
|
List<EmailDto> emailList = getMailList();
|
||||||
|
int emailListSize = emailList.size();
|
||||||
|
Assertions.assertThat(emailListSize).as("Invalid number of emails: {}", emailListSize).isEqualTo(emailCount);
|
||||||
|
result.set("emails", jsonUtils.convertListToJsonNode(Collections.singletonList(emailList)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> testObjExcelRow(String path, Map<String, Object> row) {
|
||||||
|
Map<String, Object> vars = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> rootParam = (Map<String, Object>) row.get("root");
|
||||||
|
if (rootParam != null) {
|
||||||
|
for (Map.Entry<String, Object> entry : rootParam.entrySet()) {
|
||||||
|
vars.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<String, Object> inParam = (Map<String, Object>) row.get("in");
|
||||||
|
if (inParam != null) {
|
||||||
|
vars.put("__IN", inParam);
|
||||||
|
}
|
||||||
|
Map<String, Object> outParam = (Map<String, Object>) row.get("out");
|
||||||
|
if (outParam != null) {
|
||||||
|
vars.put("__OUT", outParam);
|
||||||
|
}
|
||||||
|
String idParam = (String) row.get("id");
|
||||||
|
Map<String, Object> test =(Map<String, Object>) row.get("test");
|
||||||
|
int timerCount = 0;
|
||||||
|
Object timerNode = row.get("timer");
|
||||||
|
if (timerNode != null) timerCount = (Integer) timerNode;
|
||||||
|
Integer auditRecordCount = null;
|
||||||
|
Object auditNode = row.get("audit");
|
||||||
|
if (auditNode != null) auditRecordCount = (Integer) auditNode;
|
||||||
|
Integer emailCount = null;
|
||||||
|
Object emailNode = row.get("email");
|
||||||
|
if (emailNode != null) emailCount = (Integer) emailNode;
|
||||||
|
|
||||||
|
logger.info("TestExcelRow file={} id={} rootParam={} inParam={} outParam={} timer={} test={} audit={} email={} ",
|
||||||
|
path, idParam, rootParam, inParam, outParam, timerCount, test, auditRecordCount, emailCount);
|
||||||
|
ObjectNode processIds = createRootTestProcessInstance(idParam, vars);
|
||||||
|
for (int i = 0; i < timerCount; i++) {
|
||||||
|
executeTimer(processIds.get(TEST_PROCESS_ID).asText());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
|
Map<String, Object> rootProcessPayload = getHistProcessPayload(processIds.get(FlowableModelTestUtils.ROOT_PROCESS_ID).asText());
|
||||||
|
JsonNode root = jsonUtils.convertMapToJsonNode(rootProcessPayload);
|
||||||
|
if (root != null) {
|
||||||
|
Assertions.assertThat(isSubset(root, jsonUtils.convertMapToJsonNode(test)))
|
||||||
|
.withFailMessage(System.lineSeparator() + "test :" + test + System.lineSeparator() + "root :" + root).isTrue();
|
||||||
|
result.put("root", rootProcessPayload);
|
||||||
|
}
|
||||||
|
if (auditRecordCount != null) {
|
||||||
|
// List<AuditInstance> auditTrail = getAuditTrail(processIds.get(ROOT_PROCESS_ID).asText());
|
||||||
|
List<AuditInstance> auditTrail = getAuditTrail();
|
||||||
|
int auditTrailSize = auditTrail.size();
|
||||||
|
Assertions.assertThat(auditTrailSize).as("Invalid audit trail size: {}", auditTrailSize).isEqualTo(auditRecordCount);
|
||||||
|
result.put("audit", auditRecordCount);
|
||||||
|
}
|
||||||
|
if (emailCount != null) {
|
||||||
|
List<EmailDto> emailList = getMailList();
|
||||||
|
int emailListSize = emailList.size();
|
||||||
|
Assertions.assertThat(emailListSize).as("Invalid number of emails: {}", emailListSize).isEqualTo(emailCount);
|
||||||
|
result.put("email", emailCount);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportApp(String rootUrl, String appModelKey, String username, String password) {
|
||||||
|
RestClient restClient = RestClient.builder()
|
||||||
|
.baseUrl(rootUrl)
|
||||||
|
.defaultHeaders(h -> h.setBasicAuth(username, password))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ResponseEntity<JsonNode> responseEntity = restClient.post()
|
||||||
|
.uri("/app/authentication?j_username=" + username + "&j_password=" + password + "&spring_security_remember_me=true&submit=Login")
|
||||||
|
.retrieve()
|
||||||
|
.toEntity(JsonNode.class);
|
||||||
|
|
||||||
|
String designCookieRaw = responseEntity.getHeaders().get("Set-Cookie").stream().collect(Collectors.joining(";"));
|
||||||
|
String flowableDesignRememberMeTokenValue = Arrays.stream(designCookieRaw.split(";")).filter(part -> part.contains("FLOWABLE_DESIGN_REMEMBER_ME")).findAny().get();
|
||||||
|
String csrfToken = Arrays.stream(designCookieRaw.split(";")).filter(part -> part.contains("FLOWABLE_DESIGN_CSRF_TOKEN")).findAny().get();
|
||||||
|
|
||||||
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
|
httpHeaders.set("Cookie", flowableDesignRememberMeTokenValue + ";" + csrfToken);
|
||||||
|
|
||||||
|
ArrayNode apps = (ArrayNode) restClient.get()
|
||||||
|
.uri("/app/models?filter=apps&modelType=3&sort=modifiedDesc")
|
||||||
|
.headers(h -> h.addAll(httpHeaders))
|
||||||
|
.retrieve()
|
||||||
|
.body(JsonNode.class)
|
||||||
|
.path("data");
|
||||||
|
String appModelId = StreamSupport.stream(apps.spliterator(), false).filter(app -> app.path("key").asText().equals(appModelKey)).map(app -> app.path("id").asText()).findAny().get();
|
||||||
|
|
||||||
|
File file = new File(Paths.get("src/test/resources/test-auto-deploy-apps", appModelKey + ".zip").toString());
|
||||||
|
restClient.get()
|
||||||
|
.uri("/app/app-definitions/" + appModelId + "/export-bar?includeChildReferences=true")
|
||||||
|
.header("Cookie", flowableDesignRememberMeTokenValue + ";" + csrfToken)
|
||||||
|
.exchange((req, resp) -> {
|
||||||
|
StreamUtils.copy(resp.getBody(), new FileOutputStream(file, false));
|
||||||
|
return file;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode emptyNode() {
|
||||||
|
return jsonUtils.getEmptyObjectNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> emptyMap() {
|
||||||
|
return new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode loadObjectNodeFromResources(String path) {
|
||||||
|
if (path.isEmpty()) return jsonUtils.getEmptyObjectNode();
|
||||||
|
else return jsonUtils.loadObjectNodeFromFile(Paths.get("src","test", "resources", path).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> loadMapFromResources(String path) {
|
||||||
|
return jsonUtils.convertJsonNodeToMap(loadObjectNodeFromResources(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeTimer(String processId) {
|
||||||
|
TimerJobEntity timerJobEntity = (TimerJobEntity) managementService.createTimerJobQuery().processInstanceId(processId).singleResult();
|
||||||
|
Assertions.assertThat(timerJobEntity).withFailMessage("No active timer").isNotNull();
|
||||||
|
managementService.moveTimerToExecutableJob(timerJobEntity.getId());
|
||||||
|
managementService.executeJob(timerJobEntity.getId());
|
||||||
|
}
|
||||||
|
public void setTestAuthenticatedUser(String userId, String tenantId) {
|
||||||
|
if (userId == null) {
|
||||||
|
this.resetTestAuthenticatedUser();
|
||||||
|
} else {
|
||||||
|
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
|
||||||
|
if (StringUtils.isNotBlank(tenantId)) {
|
||||||
|
grantedAuthorities.add(SecurityUtils.createTenantAuthority(tenantId));
|
||||||
|
}
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(userId, "", grantedAuthorities));
|
||||||
|
AuthenticationContext authenticationContext = Authentication.getAuthenticationContext();
|
||||||
|
if (!(authenticationContext instanceof SpringSecurityAuthenticationContext)) {
|
||||||
|
Authentication.setAuthenticatedUserId(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestAuthenticatedUser(String userId, String tenantId, String... groupKeys) {
|
||||||
|
if (userId == null) {
|
||||||
|
this.resetTestAuthenticatedUser();
|
||||||
|
} else {
|
||||||
|
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
|
||||||
|
if (StringUtils.isNotBlank(tenantId)) {
|
||||||
|
grantedAuthorities.add(SecurityUtils.createTenantAuthority(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String groupKey : groupKeys) {
|
||||||
|
grantedAuthorities.add(SecurityUtils.createGroupAuthority(groupKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(userId, "", grantedAuthorities));
|
||||||
|
AuthenticationContext authenticationContext = Authentication.getAuthenticationContext();
|
||||||
|
if (!(authenticationContext instanceof SpringSecurityAuthenticationContext)) {
|
||||||
|
Authentication.setAuthenticatedUserId(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetTestAuthenticatedUser() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(null);
|
||||||
|
AuthenticationContext authenticationContext = Authentication.getAuthenticationContext();
|
||||||
|
if (!(authenticationContext instanceof SpringSecurityAuthenticationContext)) {
|
||||||
|
Authentication.setAuthenticatedUserId(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void completeTaskWithFlatVars(String taskId, Map<String, Object> variables, String outcome) {
|
||||||
|
Map<String, Object> taskVariables = platformTaskService.getTaskVariables(taskId);
|
||||||
|
Map<String, Object> taskVariablesFlat = jsonUtils.flatten(taskVariables);
|
||||||
|
taskVariablesFlat.putAll(variables);
|
||||||
|
Map<String, Object> completionVars = jsonUtils.unflatten(taskVariablesFlat);
|
||||||
|
|
||||||
|
completeTask(taskId, completionVars, outcome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void completeTask(String taskId, Map<String, Object> completionVariables, String outcome) {
|
||||||
|
CompleteFormRepresentation form = new CompleteFormRepresentation();
|
||||||
|
for (String key : completionVariables.keySet()) {
|
||||||
|
form.setValues(key, completionVariables.get(key));
|
||||||
|
}
|
||||||
|
form.setOutcome(outcome);
|
||||||
|
platformTaskService.completeTaskForm(taskId, form);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void completeOpenTask(String taskKey, ObjectNode vars, String outcome) {
|
||||||
|
Task task = getOpenTask(taskKey);
|
||||||
|
Map<String, Object> flatVars = jsonUtils.convertJsonNodeToMap(vars);
|
||||||
|
completeTaskWithFlatVars(task.getId(), flatVars, outcome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getHistProcessPayload(String processInstanceId) {
|
||||||
|
List<HistoricVariableInstance> historicVariableInstanceList = processEngine.getHistoryService()
|
||||||
|
.createHistoricVariableInstanceQuery()
|
||||||
|
.processInstanceId(processInstanceId)
|
||||||
|
.list();
|
||||||
|
return convertHistVariableListToMap(historicVariableInstanceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashMap<String, Object> convertHistVariableListToMap(List<HistoricVariableInstance> historicVariableInstanceList) {
|
||||||
|
HashMap<String, Object> variableMap = new HashMap<>();
|
||||||
|
for (HistoricVariableInstance historicVariableInstance : historicVariableInstanceList) {
|
||||||
|
variableMap.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue());
|
||||||
|
}
|
||||||
|
return variableMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode createRootTestProcessInstance(String testKey, Map<String, Object> variables) {
|
||||||
|
// Create root process with test process as call activity
|
||||||
|
String wrapperProcessKey = testKey + "_T";
|
||||||
|
BpmnModel bpmnModel = createWrapperTestProcessModel(testKey, (ObjectNode) jsonUtils.convertMapToJsonNode(variables));
|
||||||
|
processEngine.getProcessEngineConfiguration()
|
||||||
|
.getRepositoryService()
|
||||||
|
.createDeployment()
|
||||||
|
.addBpmnModel(wrapperProcessKey + ".bpmn20.xml", bpmnModel)
|
||||||
|
.tenantId(TENANT_ID) // Must not be "default"
|
||||||
|
.deploy();
|
||||||
|
|
||||||
|
// Start root process
|
||||||
|
ProcessInstance rootProcessInstance = startProcessInstance(wrapperProcessKey, variables);
|
||||||
|
|
||||||
|
// Store the process IDs for using them in assertions
|
||||||
|
ProcessInstance runtimeTestProcessInstance = processEngine.getRuntimeService()
|
||||||
|
.createProcessInstanceQuery()
|
||||||
|
.superProcessInstanceId(rootProcessInstance.getId())
|
||||||
|
.singleResult();
|
||||||
|
String testProcessId;
|
||||||
|
if (runtimeTestProcessInstance != null) {
|
||||||
|
testProcessId = runtimeTestProcessInstance.getId();
|
||||||
|
} else {
|
||||||
|
HistoricProcessInstance historicTestProcessInstance = processEngine.getHistoryService()
|
||||||
|
.createHistoricProcessInstanceQuery()
|
||||||
|
.superProcessInstanceId(rootProcessInstance.getId())
|
||||||
|
.singleResult();
|
||||||
|
// if history level is none, testProcessId is not available
|
||||||
|
testProcessId = historicTestProcessInstance != null ? historicTestProcessInstance.getId() : null;
|
||||||
|
}
|
||||||
|
ObjectNode rootNode = jsonUtils.getEmptyObjectNode();
|
||||||
|
rootNode.put(ROOT_PROCESS_ID, rootProcessInstance.getProcessInstanceId());
|
||||||
|
rootNode.put(TEST_PROCESS_ID, testProcessId);
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BpmnModel createWrapperTestProcessModel(String testKey, ObjectNode variables) {
|
||||||
|
BpmnModel bpmnModel = new BpmnModel();
|
||||||
|
Process process = new Process();
|
||||||
|
process.setId(testKey + "_T");
|
||||||
|
process.setName(testKey + "_T");
|
||||||
|
|
||||||
|
StartEvent startEvent = new StartEvent();
|
||||||
|
startEvent.setId(testKey + "_Start");
|
||||||
|
startEvent.setName(testKey + "_Start");
|
||||||
|
process.addFlowElement(startEvent);
|
||||||
|
|
||||||
|
CallActivity callActivity = new CallActivity();
|
||||||
|
callActivity.setId(testKey);
|
||||||
|
callActivity.setCalledElement(testKey);
|
||||||
|
JsonNode inNode = variables.get("__IN");
|
||||||
|
if (inNode instanceof ObjectNode) {
|
||||||
|
Map<String, Object> inMap = jsonUtils.convertObjectNodeToMap((ObjectNode) inNode);
|
||||||
|
ArrayList<IOParameter> inParameters = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, Object> entry : inMap.entrySet()) {
|
||||||
|
IOParameter ioParameter = new IOParameter();
|
||||||
|
ioParameter.setSourceExpression("${__IN." + entry.getKey() + "}");
|
||||||
|
ioParameter.setTarget(entry.getKey());
|
||||||
|
inParameters.add(ioParameter);
|
||||||
|
}
|
||||||
|
callActivity.setInParameters(inParameters);
|
||||||
|
}
|
||||||
|
JsonNode outNode = variables.get("__OUT");
|
||||||
|
if (outNode instanceof ObjectNode) {
|
||||||
|
Map<String, String> outMap = (Map) jsonUtils.convertJsonNodeToMap(variables).get("__OUT");
|
||||||
|
ArrayList<IOParameter> outParameters = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> entry : outMap.entrySet()) {
|
||||||
|
IOParameter ioParameter = new IOParameter();
|
||||||
|
ioParameter.setSource(entry.getKey());
|
||||||
|
ioParameter.setTarget(entry.getValue());
|
||||||
|
outParameters.add(ioParameter);
|
||||||
|
}
|
||||||
|
callActivity.setOutParameters(outParameters);
|
||||||
|
}
|
||||||
|
process.addFlowElement(callActivity);
|
||||||
|
|
||||||
|
EndEvent endEvent = new EndEvent();
|
||||||
|
endEvent.setId(testKey + "_End");
|
||||||
|
endEvent.setName(testKey + "_End");
|
||||||
|
process.addFlowElement(endEvent);
|
||||||
|
|
||||||
|
SequenceFlow start = new SequenceFlow(testKey + "_Start", testKey);
|
||||||
|
start.setId("Start_Sequence_Flow");
|
||||||
|
process.addFlowElement(start);
|
||||||
|
|
||||||
|
SequenceFlow end = new SequenceFlow(testKey, testKey + "_End");
|
||||||
|
end.setId("End_Sequence_Flow");
|
||||||
|
process.addFlowElement(end);
|
||||||
|
|
||||||
|
bpmnModel.addProcess(process);
|
||||||
|
return bpmnModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import com.flowable.spring.boot.properties.FlowableMailProperties;
|
||||||
|
import com.icegreen.greenmail.util.GreenMail;
|
||||||
|
import com.icegreen.greenmail.util.ServerSetup;
|
||||||
|
|
||||||
|
import jakarta.mail.internet.MimeMessage;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import static com.icegreen.greenmail.util.ServerSetup.PROTOCOL_SMTP;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TestMailServer {
|
||||||
|
private GreenMail greenMail;
|
||||||
|
|
||||||
|
private final FlowableMailProperties flowableMailProperties;
|
||||||
|
public TestMailServer(FlowableMailProperties flowableMailProperties) {
|
||||||
|
this.flowableMailProperties = flowableMailProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setup() {
|
||||||
|
greenMail = new GreenMail(new ServerSetup(flowableMailProperties.getPort(), flowableMailProperties.getHost(), PROTOCOL_SMTP));
|
||||||
|
greenMail.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
greenMail.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MimeMessage[] getMessages() {
|
||||||
|
return greenMail.getReceivedMessages();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.customer.work.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
public class TestMailServerExtension implements BeforeEachCallback, AfterEachCallback {
|
||||||
|
@Override
|
||||||
|
public void beforeEach(ExtensionContext context) {
|
||||||
|
getTestMailServer(context).setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterEach(ExtensionContext context) {
|
||||||
|
getTestMailServer(context).stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TestMailServer getTestMailServer(ExtensionContext context) {
|
||||||
|
return SpringExtension.getApplicationContext(context).getBean(TestMailServer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package com.customer.work.model.test;
|
||||||
|
|
||||||
|
import com.customer.work.model.EmailDto;
|
||||||
|
import com.customer.work.model.FlowableModelTest;
|
||||||
|
import com.customer.work.model.FlowableModelTestUtils;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.flowable.cmmn.api.runtime.CaseInstance;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@FlowableModelTest
|
||||||
|
public class ModelTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected FlowableModelTestUtils flowableModelTest;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void exportApp() {
|
||||||
|
flowableModelTest.exportApp("http://localhost:8093", "TST_APP", "admin", "test");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void c001Test() {
|
||||||
|
flowableModelTest.setTestAuthenticatedUser("admin", null);
|
||||||
|
CaseInstance caseInstance = flowableModelTest.startCaseInstance("TST_C001", Map.of());
|
||||||
|
String caseInstanceId = caseInstance.getId();
|
||||||
|
flowableModelTest.completeOpenTask("TST_P001_T001", flowableModelTest.loadObjectNodeFromResources("model/test/C001/T001.json"), "COMPLETE");
|
||||||
|
Assertions.assertThat(flowableModelTest.getRuntimeCasePayload(caseInstanceId).get("testText")).isEqualTo("my test text");
|
||||||
|
|
||||||
|
flowableModelTest.completeOpenTask("TST_C001_T002", flowableModelTest.emptyNode(), "COMPLETE");
|
||||||
|
Assertions.assertThat(flowableModelTest.getHistoryCasePayload(caseInstanceId).get("testText")).isEqualTo("my test text");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void p005HappyPathTest() {
|
||||||
|
ObjectNode processIds = flowableModelTest.createRootTestProcessInstance("TST_P005", flowableModelTest.emptyMap());
|
||||||
|
flowableModelTest.claimOpenTask("TST_P005_T001", "admin");
|
||||||
|
flowableModelTest.completeOpenTask("TST_P005_T001", flowableModelTest.loadObjectNodeFromResources("model/test/P005/T001.json"), null);
|
||||||
|
Map<String, Object> rootProcessPayload = flowableModelTest.getHistProcessPayload(processIds.get(FlowableModelTestUtils.ROOT_PROCESS_ID).asText());
|
||||||
|
Assertions.assertThat(rootProcessPayload.get("dataEntry")).isEqualTo("my root text");
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Stream<Arguments> p001TestData() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("admin", "model/test/P001/initiator.json")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("p001TestData")
|
||||||
|
public void p001Test(String initiator, String path) {
|
||||||
|
flowableModelTest.setTestAuthenticatedUser(initiator, null);
|
||||||
|
ObjectNode processIds = flowableModelTest.createRootTestProcessInstance("TST_P001",
|
||||||
|
flowableModelTest.loadMapFromResources(path));
|
||||||
|
flowableModelTest.completeOpenTask("TST_P001_T001", flowableModelTest.emptyNode(), "complete");
|
||||||
|
Map<String, Object> rootProcessPayload = flowableModelTest.getHistProcessPayload(processIds.get(FlowableModelTestUtils.ROOT_PROCESS_ID).asText());
|
||||||
|
|
||||||
|
Assertions.assertThat(rootProcessPayload.get("rootResult")).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Stream<Arguments> p002TestData() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("model/test/P002/boolean1.json", true, false),
|
||||||
|
Arguments.of("model/test/P002/boolean2.json", false, true),
|
||||||
|
Arguments.of("model/test/P002/string1.json", "hello root", "hello"),
|
||||||
|
Arguments.of("model/test/P002/string2.json", "123", "456"),
|
||||||
|
Arguments.of("model/test/P002/string3.json", "123.456,", "456.789"),
|
||||||
|
Arguments.of("model/test/P002/int.json", 123, 456),
|
||||||
|
Arguments.of("model/test/P002/double.json", 123.456, 456.789),
|
||||||
|
Arguments.of("model/test/P002/date.json", "2025-11-12", "2025-11-11")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("p002TestData")
|
||||||
|
public void p002Test(String path, Object result, Object out) {
|
||||||
|
ObjectNode processIds = flowableModelTest.createRootTestProcessInstance("TST_P002",
|
||||||
|
flowableModelTest.loadMapFromResources(path));
|
||||||
|
Map<String, Object> rootProcessPayload = flowableModelTest.getHistProcessPayload(processIds.get(FlowableModelTestUtils.ROOT_PROCESS_ID).asText());
|
||||||
|
|
||||||
|
List<EmailDto> mail = flowableModelTest.getMailList();
|
||||||
|
Assertions.assertThat(mail.size()).isEqualTo(0);
|
||||||
|
|
||||||
|
Assertions.assertThat(rootProcessPayload.get("result")).isEqualTo(result);
|
||||||
|
Assertions.assertThat(rootProcessPayload.get("out")).isEqualTo(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<Arguments> p002ExcelTestData() {
|
||||||
|
return flowableModelTest.getJsonArgumentsFromExcel("model/test/P002/p002Test.xlsx");
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("p002ExcelTestData")
|
||||||
|
public void p002ExcelTest(String path, JsonNode argument) {
|
||||||
|
ObjectNode result = flowableModelTest.testJsonExcelRow(path, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<Arguments> p002ExcelTestData2() {
|
||||||
|
return flowableModelTest.getObjArgumentsFromExcel("model/test/P002/p002Test.xlsx");
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("p002ExcelTestData2")
|
||||||
|
public void p002ExcelTest2(String path, Map<String, Object> argument) {
|
||||||
|
Map<String, Object> result = flowableModelTest.testObjExcelRow(path, argument);
|
||||||
|
flowableModelTest.checkAndAssertEmail(result, 1,
|
||||||
|
"Email", "Test", "test@flowable.com");
|
||||||
|
flowableModelTest.checkAndAndAssertAuditRecord(result, 1,
|
||||||
|
"Audit record", "TST_P002 Audit trail entry", "system", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
spring.datasource.url=jdbc:h2:mem:flowable-work-db;DB_CLOSE_DELAY=1000
|
||||||
|
spring.datasource.username=admin
|
||||||
|
spring.datasource.password=test
|
||||||
|
|
||||||
|
# To make our life easier in tests we are disabling the async executor and elasticsearch
|
||||||
|
flowable.async-executor-activate=false
|
||||||
|
flowable.async-history-executor-activate=false
|
||||||
|
flowable.indexing.enabled=false
|
||||||
|
management.health.elasticsearch.enabled=false
|
||||||
|
management.metrics.export.elastic.enabled=false
|
||||||
|
|
||||||
|
# Set debug level in tests
|
||||||
|
logging.level.com.flowable=INFO
|
||||||
|
logging.level.com.flowable.local.work.model.FlowableModelTestUtils=INFO
|
||||||
|
|
||||||
|
# Disable the timeout process in the tests
|
||||||
|
flowable.external-system.wechat.timeout.process-definition-key=
|
||||||
|
|
||||||
|
# Path to test-auto-deploy-apps
|
||||||
|
flowable.app.resource-location=classpath*:/test-auto-deploy-apps/
|
||||||
|
|
||||||
|
# Email
|
||||||
|
flowable.mail.server.host=localhost
|
||||||
|
flowable.mail.server.port=3025
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"testText": "my test text"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"__IN": {
|
||||||
|
"initiator": "admin"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": true,
|
||||||
|
"__IN": {
|
||||||
|
"param": false
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": false,
|
||||||
|
"__IN": {
|
||||||
|
"param": true
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": "2025-11-12",
|
||||||
|
"__IN": {
|
||||||
|
"param": "2025-11-11"
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": 123.456,
|
||||||
|
"__IN": {
|
||||||
|
"param": 456.789
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": 123,
|
||||||
|
"__IN": {
|
||||||
|
"param": 456
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": "hello root",
|
||||||
|
"__IN": {
|
||||||
|
"param": "hello"
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": "123",
|
||||||
|
"__IN": {
|
||||||
|
"param": "456"
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"param": "123.456,",
|
||||||
|
"__IN": {
|
||||||
|
"param": "456.789"
|
||||||
|
},
|
||||||
|
"__OUT": {
|
||||||
|
"result": "out"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"dataEntry": "my root text"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,38 @@
|
|||||||
|
server.port=8105
|
||||||
|
|
||||||
|
# Enable all endpoints over HTTP
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
management.endpoint.health.show-details=when_authorized
|
||||||
|
|
||||||
|
flowable.frontend.title=flowable-work
|
||||||
|
|
||||||
|
#spring.datasource.url=jdbc:h2:~/flowable-work-db/db;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
|
||||||
|
#spring.datasource.username=flowable
|
||||||
|
#spring.datasource.password=flowable
|
||||||
|
|
||||||
|
#Comment out and configure database
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5435/flowable
|
||||||
|
spring.datasource.username=flowable
|
||||||
|
spring.datasource.password=flowable
|
||||||
|
|
||||||
|
# Local Elasticsearch config
|
||||||
|
spring.elasticsearch.uris=http://localhost:9203
|
||||||
|
|
||||||
|
# spring.data.elasticsearch.repositories.enabled=true
|
||||||
|
# spring.data.elasticsearch.cluster-nodes=localhost:9300
|
||||||
|
# spring.data.elasticsearch.cluster-name=elasticsearch
|
||||||
|
|
||||||
|
flowable.indexing.index-name-prefix=flowable-work-
|
||||||
|
#Disable ElasticSearch Indexing
|
||||||
|
#flowable.indexing.enabled=false
|
||||||
|
|
||||||
|
# Enable Flowable Inspect
|
||||||
|
flowable.inspect.enabled=true
|
||||||
|
|
||||||
|
# Forms will update even if an old process/case/task definition will be used
|
||||||
|
flowable.platform.enable-latest-form-definition-lookup=true
|
||||||
|
|
||||||
|
# Server URL for REST calls
|
||||||
|
baseUrl=http://localhost:8105
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,48 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "all",
|
||||||
|
"labelKey": "contacts.filter.all",
|
||||||
|
"defaultLabel": "All",
|
||||||
|
"parameters": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "internal",
|
||||||
|
"labelKey": "contacts.filter.internal",
|
||||||
|
"defaultLabel": "Internal",
|
||||||
|
"parameters": {
|
||||||
|
"must": {
|
||||||
|
"type": "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "external",
|
||||||
|
"labelKey": "contacts.filter.external",
|
||||||
|
"defaultLabel": "External",
|
||||||
|
"parameters": {
|
||||||
|
"must" : {
|
||||||
|
"type": "external"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "active",
|
||||||
|
"labelKey": "contacts.filter.active",
|
||||||
|
"defaultLabel": "Active",
|
||||||
|
"parameters": {
|
||||||
|
"must" : {
|
||||||
|
"state": "ACTIVE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "inactive",
|
||||||
|
"labelKey": "contacts.filter.inactive",
|
||||||
|
"defaultLabel": "Inactive",
|
||||||
|
"parameters": {
|
||||||
|
"must" : {
|
||||||
|
"state": "INACTIVE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Flowable",
|
||||||
|
|
||||||
|
"groups": [
|
||||||
|
{ "key": "flowableUser", "name": "Flowable User" },
|
||||||
|
{ "key": "flowableAdministrator", "name": "Flowable Administrator" }
|
||||||
|
],
|
||||||
|
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"firstName": "Flowable",
|
||||||
|
"lastName": "Admin",
|
||||||
|
"login": "admin",
|
||||||
|
"email": "test@demo.flowable.io",
|
||||||
|
|
||||||
|
"language": "en",
|
||||||
|
"theme": "flowable",
|
||||||
|
"userDefinitionKey": "user-admin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "user-default",
|
||||||
|
"name": "Default user",
|
||||||
|
"description": "Creates a new, non-specific user where the member groups can be freely chosen.",
|
||||||
|
"initialState": "ACTIVE",
|
||||||
|
"initialSubState": "ACTIVE",
|
||||||
|
"forms": {
|
||||||
|
"init": "F01_userInitFormDefault",
|
||||||
|
"view": "F02_userViewFormDefault",
|
||||||
|
"edit": "F03_userEditFormDefault"
|
||||||
|
},
|
||||||
|
"memberGroups": [
|
||||||
|
"flowableUser"
|
||||||
|
],
|
||||||
|
"lookupGroups":[
|
||||||
|
"flowableUser"
|
||||||
|
],
|
||||||
|
"actionPermissions": {
|
||||||
|
"create": [ "flowableAdministrator" ],
|
||||||
|
"edit": [ "flowableAdministrator" ],
|
||||||
|
"deactivate": [ "flowableAdministrator" ],
|
||||||
|
"activate": [ "flowableAdministrator" ]
|
||||||
|
},
|
||||||
|
"contactFilters": [ "all" ],
|
||||||
|
"allowedFeatures": [ "contacts", "bubbles", "markdownInput", "replyToMessage", "forwardMessage", "reactToMessage", "fileUpload", "work", "createWork",
|
||||||
|
"personalAccessTokens",
|
||||||
|
"tasks", "documents", "changeOwnPassword", "changeOwnTheme", "editOwnAvatar"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "user-admin",
|
||||||
|
"name": "Administration User",
|
||||||
|
"description": "Creates a new, administration user.",
|
||||||
|
"initialUserSubType": "admin",
|
||||||
|
"initialState": "ACTIVE",
|
||||||
|
"initialSubState": "ACTIVE",
|
||||||
|
"forms": {
|
||||||
|
"init": "F01_userInitFormDefault",
|
||||||
|
"view": "F02_userViewFormDefault",
|
||||||
|
"edit": "F03_userEditFormDefault"
|
||||||
|
},
|
||||||
|
"memberGroups": [
|
||||||
|
"flowableUser",
|
||||||
|
"flowableAdministrator"
|
||||||
|
],
|
||||||
|
"lookupGroups":[
|
||||||
|
"flowableUser"
|
||||||
|
],
|
||||||
|
"actionPermissions": {
|
||||||
|
"create": [ "flowableAdministrator"],
|
||||||
|
"edit": [ "flowableAdministrator" ],
|
||||||
|
"deactivate": [ "flowableAdministrator" ],
|
||||||
|
"activate": [ "flowableAdministrator" ]
|
||||||
|
},
|
||||||
|
"initialVariables": {
|
||||||
|
"adminUser": true,
|
||||||
|
"description": "Admin"
|
||||||
|
},
|
||||||
|
"contactFilters": [ "all", "internal", "external", "inactive"],
|
||||||
|
"allowedFeatures": [ "contacts", "createUser", "reports",
|
||||||
|
"actuators", "user-mgmt", "search-api", "workobject-api", "templateManagement",
|
||||||
|
"markdownInput", "replyToMessage", "forwardMessage", "reactToMessage", "fileUpload", "work", "createWork", "tasks", "documents",
|
||||||
|
"impersonateUser",
|
||||||
|
"personalAccessTokens",
|
||||||
|
"changeOwnPassword", "changeOwnTheme", "editOwnAvatar", "themeManagement"]
|
||||||
|
}
|
||||||
|
]
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
com/customer/work/WorkApplication.class
|
||||||
|
com/customer/work/StaticResourceConfiguration.class
|
||||||
|
com/customer/work/SecurityHttpBasicConfiguration.class
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
/Users/andi/prj/flowable/2025.2/customer-work/src/main/java/com/customer/work/SecurityHttpBasicConfiguration.java
|
||||||
|
/Users/andi/prj/flowable/2025.2/customer-work/src/main/java/com/customer/work/StaticResourceConfiguration.java
|
||||||
|
/Users/andi/prj/flowable/2025.2/customer-work/src/main/java/com/customer/work/WorkApplication.java
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
com/customer/work/WorkApplicationTests.class
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/Users/andi/prj/flowable/2025.2/customer-work/src/test/java/com/customer/work/WorkApplicationTests.java
|
||||||
+4850
File diff suppressed because one or more lines are too long
@@ -0,0 +1,292 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Test set: com.customer.work.WorkApplicationTests
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 7.754 s <<< FAILURE! -- in com.customer.work.WorkApplicationTests
|
||||||
|
com.customer.work.WorkApplicationTests.contextLoads -- Time elapsed: 0.013 s <<< ERROR!
|
||||||
|
java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@40e41f88 testClass = com.customer.work.WorkApplicationTests, locations = [], classes = [com.customer.work.WorkApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.web.server.context.SpringBootTestRandomPortContextCustomizer@62e70ea3, org.springframework.boot.test.context.PropertyMappingContextCustomizer@0, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@25ddbbbb, org.springframework.boot.test.http.client.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory$DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer@226642a5, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@625e134e, org.springframework.boot.test.autoconfigure.OnFailureConditionReportContextCustomizerFactory$OnFailureConditionReportContextCustomizer@5dbe30be, org.springframework.test.context.support.DynamicPropertiesContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestAnnotation@dfa5ba73], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.lambda$loadContext$0(DefaultCacheAwareContextLoaderDelegate.java:195)
|
||||||
|
at org.springframework.test.context.cache.DefaultContextCache.put(DefaultContextCache.java:214)
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:160)
|
||||||
|
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:128)
|
||||||
|
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:200)
|
||||||
|
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:139)
|
||||||
|
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
|
||||||
|
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:210)
|
||||||
|
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:186)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:214)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:197)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:214)
|
||||||
|
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1716)
|
||||||
|
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
|
||||||
|
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
|
||||||
|
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:153)
|
||||||
|
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:176)
|
||||||
|
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
|
||||||
|
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:632)
|
||||||
|
at java.base/java.util.Optional.orElseGet(Optional.java:364)
|
||||||
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
||||||
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: Error creating bean with name 'basicDefaultSecurity' defined in class path resource [com/customer/work/SecurityHttpBasicConfiguration.class]: Unsatisfied dependency expressed through method 'basicDefaultSecurity' parameter 0: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'flowableUserDetailsService' defined in class path resource [com/flowable/autoconfigure/security/FlowablePlatformSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableUserDetailsService' parameter 0: Error creating bean with name 'platformIdentityService' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'platformIdentityService' parameter 0: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:872)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:827)
|
||||||
|
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:146)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:493)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1446)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1218)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1184)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1121)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:994)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:621)
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:756)
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:445)
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$2(SpringBootContextLoader.java:156)
|
||||||
|
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
|
||||||
|
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
|
||||||
|
at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1465)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:605)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:156)
|
||||||
|
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:115)
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:247)
|
||||||
|
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.lambda$loadContext$0(DefaultCacheAwareContextLoaderDelegate.java:167)
|
||||||
|
... 21 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'basicDefaultSecurity' defined in class path resource [com/customer/work/SecurityHttpBasicConfiguration.class]: Unsatisfied dependency expressed through method 'basicDefaultSecurity' parameter 0: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'flowableUserDetailsService' defined in class path resource [com/flowable/autoconfigure/security/FlowablePlatformSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableUserDetailsService' parameter 0: Error creating bean with name 'platformIdentityService' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'platformIdentityService' parameter 0: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:2008)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1971)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeanCollection(DefaultListableBeanFactory.java:1863)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1833)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1711)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:864)
|
||||||
|
... 48 more
|
||||||
|
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'flowableUserDetailsService' defined in class path resource [com/flowable/autoconfigure/security/FlowablePlatformSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableUserDetailsService' parameter 0: Error creating bean with name 'platformIdentityService' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'platformIdentityService' parameter 0: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:657)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:489)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:351)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 65 more
|
||||||
|
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'flowableUserDetailsService' defined in class path resource [com/flowable/autoconfigure/security/FlowablePlatformSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableUserDetailsService' parameter 0: Error creating bean with name 'platformIdentityService' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'platformIdentityService' parameter 0: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:183)
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:72)
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:152)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
|
||||||
|
... 77 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'flowableUserDetailsService' defined in class path resource [com/flowable/autoconfigure/security/FlowablePlatformSecurityAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableUserDetailsService' parameter 0: Error creating bean with name 'platformIdentityService' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'platformIdentityService' parameter 0: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1305)
|
||||||
|
at org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer.configure(InitializeUserDetailsBeanManagerConfigurer.java:94)
|
||||||
|
at org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer$InitializeUserDetailsManagerConfigurer.configure(InitializeUserDetailsBeanManagerConfigurer.java:63)
|
||||||
|
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.configure(AbstractConfiguredSecurityBuilder.java:386)
|
||||||
|
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:336)
|
||||||
|
at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38)
|
||||||
|
at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationManager(AuthenticationConfiguration.java:121)
|
||||||
|
at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.authenticationManager(HttpSecurityConfiguration.java:152)
|
||||||
|
at org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity(HttpSecurityConfiguration.java:119)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
|
||||||
|
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:155)
|
||||||
|
... 80 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'platformIdentityService' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'platformIdentityService' parameter 0: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 100 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'coreIdmEngine' defined in class path resource [com/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'coreIdmEngine' parameter 0: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:1225)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1704)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 114 more
|
||||||
|
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.flowable.spring.boot.app.AppEngineServicesAutoConfiguration': Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:610)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:413)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 128 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appIndexingConfigurer' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appIndexingConfigurer' parameter 0: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:2015)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1971)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1792)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1711)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.resolveStream(DefaultListableBeanFactory.java:2685)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.orderedStream(DefaultListableBeanFactory.java:2679)
|
||||||
|
at com.flowable.spring.boot.BaseEngineConfigurationWithConfigurers.setEngineConfigurers(BaseEngineConfigurationWithConfigurers.java:32)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:832)
|
||||||
|
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:146)
|
||||||
|
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:493)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1446)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
|
||||||
|
... 147 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appEngineIndexingConfigurator' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'appEngineIndexingConfigurator' parameter 0: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:1225)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1704)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 170 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'indexManager' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'indexManager' parameter 0: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:1225)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1704)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 184 more
|
||||||
|
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'flowableElasticsearchClient' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Unsatisfied dependency expressed through method 'flowableElasticsearchClient' parameter 1: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1362)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1194)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:229)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1762)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 198 more
|
||||||
|
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchCompatibility' defined in class path resource [com/flowable/autoconfigure/indexing/IndexingAutoConfiguration.class]: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1817)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:1225)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1704)
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
|
||||||
|
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
|
||||||
|
... 212 more
|
||||||
|
Caused by: org.flowable.common.engine.api.FlowableException: Could not retrieve Elasticsearch version information. One possible reason could be that ES is not accessible. See root cause
|
||||||
|
at com.flowable.indexing.ElasticsearchCompatibilityImpl.afterPropertiesSet(ElasticsearchCompatibilityImpl.java:134)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1864)
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1813)
|
||||||
|
... 223 more
|
||||||
|
Caused by: java.net.ConnectException: Connect to http://localhost:9203 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused
|
||||||
|
at co.elastic.clients.transport.rest5_client.low_level.Rest5Client.extractAndWrapCause(Rest5Client.java:945)
|
||||||
|
at co.elastic.clients.transport.rest5_client.low_level.Rest5Client.performRequest(Rest5Client.java:308)
|
||||||
|
at co.elastic.clients.transport.rest5_client.low_level.Rest5Client.performRequest(Rest5Client.java:293)
|
||||||
|
at com.flowable.indexing.ElasticsearchCompatibilityImpl.afterPropertiesSet(ElasticsearchCompatibilityImpl.java:56)
|
||||||
|
... 225 more
|
||||||
|
Caused by: org.apache.hc.client5.http.HttpHostConnectException: Connect to http://localhost:9203 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused
|
||||||
|
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
|
||||||
|
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:639)
|
||||||
|
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:1046)
|
||||||
|
at org.apache.hc.core5.reactor.InternalConnectChannel.onIOEvent(InternalConnectChannel.java:70)
|
||||||
|
at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:51)
|
||||||
|
at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:176)
|
||||||
|
at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:125)
|
||||||
|
at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:92)
|
||||||
|
at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
|
||||||
|
at java.base/java.lang.Thread.run(Thread.java:1474)
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
spring.datasource.url=jdbc:h2:mem:flowable-work-db;DB_CLOSE_DELAY=1000
|
||||||
|
spring.datasource.username=admin
|
||||||
|
spring.datasource.password=test
|
||||||
|
|
||||||
|
# To make our life easier in tests we are disabling the async executor and elasticsearch
|
||||||
|
flowable.async-executor-activate=false
|
||||||
|
flowable.async-history-executor-activate=false
|
||||||
|
flowable.indexing.enabled=false
|
||||||
|
management.health.elasticsearch.enabled=false
|
||||||
|
management.metrics.export.elastic.enabled=false
|
||||||
|
|
||||||
|
# Set debug level in tests
|
||||||
|
logging.level.com.flowable=INFO
|
||||||
|
logging.level.com.flowable.local.work.model.FlowableModelTestUtils=INFO
|
||||||
|
|
||||||
|
# Disable the timeout process in the tests
|
||||||
|
flowable.external-system.wechat.timeout.process-definition-key=
|
||||||
|
|
||||||
|
# Path to test-auto-deploy-apps
|
||||||
|
flowable.app.resource-location=classpath*:/test-auto-deploy-apps/
|
||||||
|
|
||||||
|
# Email
|
||||||
|
flowable.mail.server.host=localhost
|
||||||
|
flowable.mail.server.port=3025
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user