diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..8a3d101 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,47 @@ +--- + +name: Bug report +about: Create a report to help us improve +title: '' +labels: 'kind/bug' +assignees: '' + +--- + +**Describe the bug** + + + +**To Reproduce** + + + +**Expected behavior** + + + +**Log/Stacktrace** + + + +
Full Stacktrace +

+ +``` + +``` + +

+
+ +**Environment:** +- OS: +- Deployment: +- Spring-Zeebe Version: +- SpringBoot Version: +- Configuration: diff --git a/.github/ISSUE_TEMPLATE/documentation_issue.md b/.github/ISSUE_TEMPLATE/documentation_issue.md new file mode 100644 index 0000000..d6d22ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation_issue.md @@ -0,0 +1,13 @@ +--- + +name: Documentation issue +about: Changes to the documentation +title: '' +labels: 'kind/documentation' +assignees: '' + +--- + +**Description** + +A clear and concise description of what this issue is about. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..a3fbc02 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +--- + +name: Feature request +about: Suggest an idea for this project +title: '' +labels: 'kind/feature' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml deleted file mode 100644 index bf8cd6d..0000000 --- a/.github/workflows/gradle-publish.yml +++ /dev/null @@ -1,46 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created -# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle - -name: Gradle Package - -on: - release: - types: [created] - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - uses: actions/checkout@v3 - - name: Set up JDK 8 - uses: actions/setup-java@v3 - with: - java-version: '8' - distribution: 'adopt' - server-id: github # Value of the distributionManagement/repository/id field of the pom.xml - settings-path: ${{ github.workspace }} # location for the settings.xml file - - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b - - name: Build with Gradle - uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee - with: - arguments: build - - name: Publish with Gradle - run: ./gradlew -Prelease publishToSonatype closeAndReleaseSonatypeStagingRepository - env: - ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.MAVEN_CENTRAL_DEPLOYMENT_USR }} - ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.MAVEN_CENTRAL_DEPLOYMENT_PSW }} - ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.MAVEN_CENTRAL_GPG_SIGNING_KEY_ID }} - ORG_GRADLE_PROJECT_signingKey: ${{ secrets.MAVEN_CENTRAL_GPG_SIGNING_KEY_SEC }} - ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.MAVEN_CENTRAL_GPG_SIGNING_KEY_PASSPHRASE }} - - diff --git a/.github/workflows/mvn-build.yml b/.github/workflows/mvn-build.yml new file mode 100644 index 0000000..c907003 --- /dev/null +++ b/.github/workflows/mvn-build.yml @@ -0,0 +1,17 @@ +name: Build via Maven and run tests + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Java environment + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'adopt' + cache: maven + - name: Build with Maven + run: mvn verify -PcheckFormat -B diff --git a/.github/workflows/mvn-release.yml b/.github/workflows/mvn-release.yml new file mode 100644 index 0000000..9aac04c --- /dev/null +++ b/.github/workflows/mvn-release.yml @@ -0,0 +1,58 @@ +# If this workflow is triggered by a push to either main or release branches then it +# deploys a SNAPSHOT +# If this workflow is triggered by publishing a Release, it +# deploys a RELEASE with the selected version +# updates the project version by incrementing the patch version +# commits the version update change to the repository's branch that triggered the workflow. +name: Deploy artifacts with Maven + +on: + push: + branches: + - main + - release/** + release: + types: [ published ] +jobs: + publish: + runs-on: ubuntu-22.04 + steps: + + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Java environment + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'adopt' + cache: maven + gpg-private-key: ${{ secrets.MAVEN_CENTRAL_GPG_SIGNING_KEY_SEC }} + gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE + + - name: Deploy SNAPSHOT / Release + uses: camunda-community-hub/community-action-maven-release@v1 + with: + release-version: ${{ github.event.release.tag_name }} + maven-url: s01.oss.sonatype.org + nexus-usr: ${{ secrets.NEXUS_USR }} + nexus-psw: ${{ secrets.NEXUS_PSW }} + maven-usr: ${{ secrets.MAVEN_CENTRAL_DEPLOYMENT_USR }} + maven-psw: ${{ secrets.MAVEN_CENTRAL_DEPLOYMENT_PSW }} + maven-additional-options: -U + maven-gpg-passphrase: ${{ secrets.MAVEN_CENTRAL_GPG_SIGNING_KEY_PASSPHRASE }} + maven-auto-release-after-close: true + github-token: ${{ secrets.GITHUB_TOKEN }} + branch: ${{ github.event.release.target_commitish || github.ref_name }} + id: release + + - if: github.event.release + name: Attach artifacts to GitHub Release (Release only) + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ steps.release.outputs.artifacts_archive_path }} + asset_name: ${{ steps.release.outputs.artifacts_archive_path }} + asset_content_type: application/zip diff --git a/.gitignore b/.gitignore index c2065bc..6d9ba77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ HELP.md .gradle build/ +target !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index ad441c4..34de802 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ -# Code of Conduct +# Code of Conduct -### View the [Camunda Code of Conduct](https://camunda.com/events/code-conduct/) and find ways to report violations. \ No newline at end of file +### View the [Camunda Code of Conduct](https://camunda.com/events/code-conduct/) and find ways to report violations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84e495c..ae0f230 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,4 +59,4 @@ These are roles that are not code-based, but require some knowledge in that you - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) - [GitHub Help](https://help.github.com) -- [CODE_OF_CONDUCT](https://github.com/camunda-community-hub/community/blob/main/CODE_OF_CONDUCT.MD) \ No newline at end of file +- [CODE_OF_CONDUCT](https://github.com/camunda-community-hub/community/blob/main/CODE_OF_CONDUCT.MD) diff --git a/README.md b/README.md index 19f61b6..cafc26b 100644 --- a/README.md +++ b/README.md @@ -2,49 +2,158 @@ ![Compatible with: Camunda Platform 8](https://img.shields.io/badge/Compatible%20with-Camunda%20Platform%208-0072Ce) [![](https://img.shields.io/badge/Lifecycle-Incubating-blue)](https://github.com/Camunda-Community-Hub/community/blob/main/extension-lifecycle.md#incubating-) -# DEPRECATED - -:information_source: **This project is no more maintained** and you should start using the project provided as part of the [Spring Zeebe project](https://github.com/camunda-community-hub/spring-zeebe). If you want to use it outside of the Spring Zeebe client, you can directly use the [java-operate-client](https://github.com/camunda-community-hub/spring-zeebe/tree/main/camunda-sdk-java/java-client-operate). +# Camunda Operate Client This project is designed to simplify communication between a Java backend and the [Operate API of Camunda Platform 8](https://docs.camunda.io/docs/apis-clients/operate-api/). -## How to use the client +## How to build the client -Simply build a CamundaOperateClient that takes an authentication and the Operate URL as parameters. +### Spring Boot -```java -SimpleAuthentication sa = new SimpleAuthentication("demo", "demo", "http://localhost:8081"); -CamundaOperateClient client = new CamundaOperateClient.Builder().operateUrl("http://localhost:8081").authentication(sa).build(); -```` +Add the dependency to your project: + +```xml + + io.camunda.spring + spring-boot-starter-camunda-operate + ${version.operate-client} + +``` + +Configure a Camunda Operate client with simple authentication: + +```yaml +operate: + client: + profile: simple +``` + +To adjust the (meaningful) default properties, you can also override them: + +```yaml +operate: + client: + profile: simple + enabled: true + base-url: http://localhost:8081 + session-timeout: PT10M + username: demo + password: demo +``` -## Authentication -You can use the ***SimpleAuthentication*** to connect to a local Camunda Operate if your setup is "simple": ***without identity and keycloak***. -To connect to the **SaaS** Operate, you need to use the **SaasAuthentication** rather than the SimpleAuthentication. The SaaSAuthentication requires the ClientId and SecretId +Configure a Camunda Operate client with identity authentication: +```yaml +operate: + client: + profile: oidc + client-id: + client-secret: ``` -SaasAuthentication sa = new SaasAuthentication("2~nB1MwkUU45FuXXX", "aBRKtreXQF3uD2MYYY"); -CamundaOperateClient client = new CamundaOperateClient.Builder().authentication(sa) - .operateUrl("https://bru-2.operate.camunda.io/757dbc30-5127-4bed-XXXX-XXXXXXXXXXXX").build(); + +To adjust the (meaningful) default properties, you can also override them: + +```yaml +operate: + client: + profile: oidc + enabled: true + base-url: http://localhost:8081 + auth-url: http://localhost:18080/auth/realms/camunda-platform/openid-connect/token + audience: operate-api + client-id: + client-secret: +``` + +Configure a Camunda Operate client for Saas: + +```yaml +operate: + client: + profile: saas + region: + cluster-id: + client-id: + client-secret: +``` + +```yaml +operate: + client: + profile: saas + enabled: true + base-url: https://${operate.client.region}.operate.camunda.io/${operate.client.cluster-id} + auth-url: https://login.cloud.camunda.io/oauth/token + audience: operate.camunda.io + region: + cluster-id: + client-id: + client-secret: +``` + +### Plain Java + +Add the dependency to your project: + +```xml + + io.camunda.spring + java-client-operate + ${version.operate-client} + ``` -You can also specify the OAuth-URL and audience, for example if you connect to a Camunda TEST system: +Build a Camunda Operate client with simple authentication: +```java +// properties you need to provide +URL operateUrl = URI.create("http://localhost:8081").toURL(); +SimpleCredential credentials = new SimpleCredential("demo", "demo", operateUrl, Duration.ofMinutes(10)); +// bootstrapping +SimpleAuthentication authentication = new SimpleAuthentication(credentials); +ObjectMapper objectMapper = new ObjectMapper(); +CamundaOperateClientConfiguration configuration = new CamundaOperateClientConfiguration(authentication, operateUrl, objectMapper, HttpClients.createDefault()); +CamundaOperateClient client = new CamundaOperateClient(configuration); ``` -SaasAuthentication sa = new SaasAuthentication("https://login.cloud.camunda.io/oauth/token", "operate.camunda.io", 2~nB1MwkUU45FuXXX", "aBRKtreXQF3uD2MYYY"); + +Build a Camunda Operate client with identity authentication: + +```java +// properties you need to provide +String clientId = ""; +String clientSecret = ""; +String audience = "operate-api"; +URL operateUrl = URI.create("http://localhost:8081").toURL(); +URL authUrl = URI.create("http://localhost:18080/auth/realms/camunda-platform/protocol/openid-connect/token"); +// bootstrapping +JwtCredential credentials = new JwtCredential(clientId, clientSecret, audience, authUrl); +ObjectMapper objectMapper = new ObjectMapper(); +JwtAuthentication authentication = new JwtAuthentication(credentials, objectMapper); +CamundaOperateClientConfiguration configuration = new CamundaOperateClientConfiguration(authentication, operateUrl, objectMapper, HttpClients.createDefault()); +CamundaOperateClient client = new CamundaOperateClient(configuration); ``` -To connect to the **Local** Operate with **Identity & Keycloak**, you need to use the **SelfManagedAuthentication**. The SelfManagedAuthentication requires the clientId and clientSecret. You can also change the Keycloak realm and the keycloakUrl depending on your installation. +Build a Camunda Operate client for Saas: ```java -SelfManagedAuthentication sma = new SelfManagedAuthentication().clientId("java").clientSecret("foTPogjlI0hidwbDZcYFWzmU8FOQwLx0").baseUrl("http://localhost:18080").keycloakRealm("camunda-platform"); -CamundaOperateClient client = new CamundaOperateClient.Builder().authentication(sma) - .operateUrl("http://localhost:8081/").build(); +String region = ""; +String clusterId = ""; +String clientId = ""; +String clientSecret = ""; +// bootstrapping +URL operateUrl = URI.create("https://"+ region +".operate.camunda.io/" + clusterId).toURL(); +URL authUrl = URI.create("https://login.cloud.camunda.io/oauth/token"); +JwtCredential credentials = new JwtCredential(clientId, clientSecret, "operate.camunda.io", authUrl); +ObjectMapper objectMapper = new ObjectMapper(); +JwtAuthentication authentication = new JwtAuthentication(credentials, objectMapper); +CamundaOperateClientConfiguration configuration = new CamundaOperateClientConfiguration(authentication, operateUrl, objectMapper, HttpClients.createDefault()); +CamundaOperateClient client = new CamundaOperateClient(configuration); ``` ## Getting and Searching -When you search objects, you can get results as List or as SearchResult. The SearchResult gives you a sortValues that you can use to paginate your results : +When you search objects, you can get results as List or as SearchResult. The SearchResult gives you a sortValues that you can use to paginate your results : ```java SearchQuery query = new SearchQuery.Builder().filter(someFilter).sort(new Sort("name", SortOrder.ASC)).size(20).searchAfter(previousResult.getSortValues()).build(); @@ -75,7 +184,7 @@ SearchQuery instanceQuery = new SearchQuery.Builder().filter(instanceFilter).siz List list = client.searchProcessInstances(instanceQuery); SearchResult result = client.searchProcessInstanceResults(instanceQuery); - + //get a process instance by its key ProcessInstance instance = client.getProcessInstance(instances.get(0).getKey()); ``` @@ -89,7 +198,7 @@ FlownodeInstanceFilter flownodeFilter = new FlownodeInstanceFilter.Builder() SearchQuery flownodeQuery = new SearchQuery.Builder().filter(flownodeFilter).size(20).sort(new Sort("state", SortOrder.ASC)).build(); List flownodes = client.searchFlownodeInstances(flownodeQuery); - + //get a flownode instance by its key FlownodeInstance flownodes = client.getFlownodeInstance(flownodes.get(0).getKey()); ``` @@ -102,50 +211,23 @@ VariableFilter variableFilter = new VariableFilter.Builder().processInstanceKey( SearchQuery varQuery = new SearchQuery.Builder().filter(variableFilter).size(5).sort(new Sort("name", SortOrder.ASC)).build(); List variables = client.searchVariables(varQuery); - + //get a variable by its key Variable var = client.getVariable(variables.get(0).getKey()); ``` ### Incidents -```java +```java //search incidents based on filters IncidentFilter incidentFilter = new IncidentFilter.Builder().creationTime(new DateFilter(new Date(), DateFilterRange.YEAR)).build(); SearchQuery incidentQuery = new SearchQuery.Builder().filter(incidentFilter).size(20).sort(new Sort("state", SortOrder.ASC)).build(); List incidents = client.searchIncidents(incidentQuery); - + //get a incident by its key Incident incident = client.getIncident(incidents.get(0).getKey()); ``` - - -## Use the Beta client -If you're using an older version of Camunda SaaS or you're having a local setup without Keycloak, you could also query the same APIs as Operate UI. In such a case, you might want to use the Beta client : - -```java -SimpleAuthentication sa = new SimpleAuthentication("demo", "demo", "http://localhost:8081"); -CamundaOperateClient client = new CamundaOperateClient.Builder().beta().operateUrl("http://localhost:8081").authentication(sa).build(); - -JsonNode json = ((CamundaOperateBetaClient) client).getFlowNodeStates(2L); - -AuditTrail auditTrail = ((CamundaOperateBetaClient) client).getAuditTrail(2L); -``` - -Obviously, as soon as the exposed APIs will be sufficient, we should get rid of this Beta client. - -# use it in your project -You can import it to your maven or gradle project as a dependency - -```xml - - io.camunda - camunda-operate-client-java - 8.3.0.1 - -``` - -# Note +## Note A similar library is available for the Tasklist API of Camunda Platform 8 here: [camunda-tasklist-client-java](https://github.com/camunda-community-hub/camunda-tasklist-client-java) diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 5000f69..0000000 --- a/build.gradle +++ /dev/null @@ -1,104 +0,0 @@ -plugins { - id 'maven-publish' - id 'java-library' - id 'signing' - id('io.github.gradle-nexus.publish-plugin') version '1.1.0' -} - -group = 'io.camunda' -version = '8.3.0.1' -sourceCompatibility = '8' - -repositories { - mavenCentral() -} - -dependencies { - def httpClientVersion = "5.1.3" - def zeebeBpmnVersion = "8.3.0-rc1" - api "org.apache.httpcomponents.client5:httpclient5:${httpClientVersion}" - api "org.apache.httpcomponents.client5:httpclient5-fluent:${httpClientVersion}" - - api 'com.fasterxml.jackson.core:jackson-databind:2.13.1' - compileOnly "io.camunda:zeebe-bpmn-model:${zeebeBpmnVersion}" - - testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1' -} - -tasks.named('test') { - useJUnitPlatform() -} - -task sourceJar(type: Jar) { - outputs.cacheIf { true } - from sourceSets.main.allJava - archiveClassifier = 'sources' -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - from javadoc.destinationDir - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - archiveClassifier = 'javadoc' -} -java { - withSourcesJar() - withJavadocJar() -} - -nexusPublishing { - transitionCheckOptions { - maxRetries.set(100) - delayBetween.set(Duration.ofSeconds(10)) - } - repositories { - sonatype { - stagingProfileId = "13992b29744076" - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - } - } -} - -signing { - useInMemoryPgpKeys(System.getenv("ORG_GRADLE_PROJECT_signingKey"), System.getenv("ORG_GRADLE_PROJECT_signingPassword")) - sign(publishing.publications) -} - -publishing { - publications { - mavenJava(MavenPublication) { - from(components.java) - versionMapping { - usage('java-api') { - fromResolutionResult() - } - } - pom { - groupId = 'io.camunda' - artifactId = 'camunda-operate-client-java' - packaging = 'jar' - name = 'Camunda 8 Operate Java Client' - description = "Java client for the Operate API of Camunda Platform 8" - url = "https://github.com/camunda-community-hub/camunda-operate-client-java" - licenses { - license { - name = "The Apache License, Version 2.0" - url = "http://www.apache.org/licenses/LICENSE-2.0.txt" - } - } - developers { - developer { - name = "christophe.dame" - email = "christophe.dame@camunda.com" - } - } - scm { - connection = "scm:git:git@github.com:camunda-community-hub/camunda-operate-client-java.git" - developerConnection = "scm:git:git@github.com:camunda-community-hub/camunda-operate-client-java.git" - url = "https://github.com/camunda-community-hub/camunda-operate-client-java" - } - } - } - } -} - diff --git a/examples/operate-example-load-process-instance/README.md b/examples/operate-example-load-process-instance/README.md new file mode 100644 index 0000000..d6d29f7 --- /dev/null +++ b/examples/operate-example-load-process-instance/README.md @@ -0,0 +1,17 @@ +# Example: Load process instances + +This example allows you to load process instances plus dependant data from Operate via REST API. + +## Configuration + +Configure the Operate client as desired. Then, you can run the application and get process instances via + +``` +GET /process-instances +``` + +Also, you can delete process instances using + +``` +DELETE /process-instances/{key} +``` diff --git a/examples/operate-example-load-process-instance/pom.xml b/examples/operate-example-load-process-instance/pom.xml new file mode 100644 index 0000000..0b73905 --- /dev/null +++ b/examples/operate-example-load-process-instance/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + + io.camunda.spring + operate-examples-parent + 8.6.0-alpha1-SNAPSHOT + + + operate-example-load-process-instance + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-autoconfigure + provided + + + org.springframework + spring-web + provided + + + org.springframework + spring-beans + provided + + + org.springframework + spring-context + provided + + + org.springframework.boot + spring-boot + provided + + + io.camunda.spring + spring-boot-starter-camunda-operate + + + io.camunda.spring + java-client-operate + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-test + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.springframework.boot:spring-boot-starter-web + org.springframework.boot:spring-boot-starter-test + io.camunda.spring:spring-boot-starter-camunda-operate + + + + + + + + \ No newline at end of file diff --git a/examples/operate-example-load-process-instance/src/main/java/io/camunda/operate/example/ExampleApp.java b/examples/operate-example-load-process-instance/src/main/java/io/camunda/operate/example/ExampleApp.java new file mode 100644 index 0000000..fa0737c --- /dev/null +++ b/examples/operate-example-load-process-instance/src/main/java/io/camunda/operate/example/ExampleApp.java @@ -0,0 +1,11 @@ +package io.camunda.operate.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ExampleApp { + public static void main(String[] args) { + SpringApplication.run(ExampleApp.class, args); + } +} diff --git a/examples/operate-example-load-process-instance/src/main/java/io/camunda/operate/example/ProcessInstanceController.java b/examples/operate-example-load-process-instance/src/main/java/io/camunda/operate/example/ProcessInstanceController.java new file mode 100644 index 0000000..a8b4130 --- /dev/null +++ b/examples/operate-example-load-process-instance/src/main/java/io/camunda/operate/example/ProcessInstanceController.java @@ -0,0 +1,67 @@ +package io.camunda.operate.example; + +import io.camunda.operate.CamundaOperateClient; +import io.camunda.operate.exception.OperateException; +import io.camunda.operate.model.ChangeStatus; +import io.camunda.operate.model.FlowNodeInstance; +import io.camunda.operate.model.ProcessInstance; +import io.camunda.operate.model.Variable; +import io.camunda.operate.search.FlowNodeInstanceFilter; +import io.camunda.operate.search.SearchQuery; +import io.camunda.operate.search.VariableFilter; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/process-instances") +public class ProcessInstanceController { + private final CamundaOperateClient camundaOperateClient; + + @Autowired + public ProcessInstanceController(CamundaOperateClient camundaOperateClient) { + this.camundaOperateClient = camundaOperateClient; + } + + @GetMapping + public List getProcessInstances() throws OperateException { + return camundaOperateClient.searchProcessInstances(new SearchQuery.Builder().build()).stream() + .map( + pi -> { + try { + return new ProcessInstanceWrapper( + pi, + camundaOperateClient.searchFlowNodeInstances( + new SearchQuery.Builder() + .filter( + FlowNodeInstanceFilter.builder() + .processInstanceKey(pi.getKey()) + .build()) + .build()), + camundaOperateClient.searchVariables( + new SearchQuery.Builder() + .filter( + VariableFilter.builder().processInstanceKey(pi.getKey()).build()) + .build())); + } catch (OperateException e) { + throw new RuntimeException(e); + } + }) + .toList(); + } + + @DeleteMapping("/{key}") + public ChangeStatus deleteProcessInstance(@PathVariable(name = "key") Long key) + throws OperateException { + return camundaOperateClient.deleteProcessInstance(key); + } + + public record ProcessInstanceWrapper( + ProcessInstance processInstance, + List flowNodeInstances, + List variables) {} +} diff --git a/examples/operate-example-load-process-instance/src/main/resources/application.yaml b/examples/operate-example-load-process-instance/src/main/resources/application.yaml new file mode 100644 index 0000000..89ec0fe --- /dev/null +++ b/examples/operate-example-load-process-instance/src/main/resources/application.yaml @@ -0,0 +1,3 @@ +operate: + client: + profile: simple \ No newline at end of file diff --git a/examples/operate-example-load-process-instance/src/test/java/io/camunda/operate/example/ExampleTest.java b/examples/operate-example-load-process-instance/src/test/java/io/camunda/operate/example/ExampleTest.java new file mode 100644 index 0000000..11847f4 --- /dev/null +++ b/examples/operate-example-load-process-instance/src/test/java/io/camunda/operate/example/ExampleTest.java @@ -0,0 +1,14 @@ +package io.camunda.operate.example; + +import io.camunda.operate.CamundaOperateClient; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class ExampleTest { + @Autowired CamundaOperateClient operateClient; + + @Test + void shouldRun() {} +} diff --git a/examples/pom.xml b/examples/pom.xml new file mode 100644 index 0000000..456b210 --- /dev/null +++ b/examples/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + io.camunda.spring + operate-client-root + 8.6.0-alpha1-SNAPSHOT + + + operate-examples-parent + pom + + operate-example-load-process-instance + + + \ No newline at end of file diff --git a/extension/java-client-operate/README.md b/extension/java-client-operate/README.md new file mode 100644 index 0000000..c09ac4e --- /dev/null +++ b/extension/java-client-operate/README.md @@ -0,0 +1,31 @@ +# Java Operate client + +The Spring Boot Starter contains the Operate client which becomes injectable as a bean. + +```java +@Autowired CamundaOperateClient operateClient; +``` + +### List deployed process definitions + +```java + ProcessDefinitionFilter processDefinitionFilter = ProcessDefinitionFilter.builder().build(); + SearchQuery procDefQuery = new SearchQuery.Builder() + .filter(processDefinitionFilter) + .size(1000) + .sort(new Sort("version", SortOrder.DESC)) + .build(); + return camundaOperateClient.searchProcessDefinitions(procDefQuery); +``` + +### Read process definitions content + +```java + camundaOperateClient.getProcessDefinitionXml(ProcessDefinitionKey); +``` + +### List variables + +```java + return camundaOperateClient.searchVariables(new SearchQuery.Builder().filter(new VariableFilter()).size(100).build()); +``` diff --git a/extension/java-client-operate/pom.xml b/extension/java-client-operate/pom.xml new file mode 100644 index 0000000..1cf8461 --- /dev/null +++ b/extension/java-client-operate/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + + io.camunda.spring + operate-client-parent + 8.6.0-alpha1-SNAPSHOT + + + java-client-operate + + + + org.slf4j + slf4j-api + provided + + + io.camunda + zeebe-bpmn-model + + + org.apache.httpcomponents.client5 + httpclient5 + + + org.apache.httpcomponents.core5 + httpcore5 + provided + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + provided + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + io.camunda + spring-boot-starter-camunda-sdk + provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + + UTF-8 + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + io.camunda:spring-boot-starter-camunda-sdk + + + + + + + + diff --git a/extension/java-client-operate/src/main/java/io/camunda/common/auth/Authentication.java b/extension/java-client-operate/src/main/java/io/camunda/common/auth/Authentication.java new file mode 100644 index 0000000..fbd0520 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/common/auth/Authentication.java @@ -0,0 +1,10 @@ +package io.camunda.common.auth; + +import java.util.Map; + +@Deprecated +public interface Authentication { + Map getTokenHeader(Product product); + + void resetToken(Product product); +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/common/auth/JwtConfig.java b/extension/java-client-operate/src/main/java/io/camunda/common/auth/JwtConfig.java new file mode 100644 index 0000000..2b1c89d --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/common/auth/JwtConfig.java @@ -0,0 +1,18 @@ +package io.camunda.common.auth; + +@Deprecated +public class JwtConfig { + private JwtCredential jwtCredential; + + public void addProduct(Product product, JwtCredential credential) { + this.jwtCredential = credential; + } + + public JwtCredential getJwtCredential() { + return jwtCredential; + } + + public JwtCredential getProduct(Product product) { + return jwtCredential; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/common/auth/JwtCredential.java b/extension/java-client-operate/src/main/java/io/camunda/common/auth/JwtCredential.java new file mode 100644 index 0000000..d831cc8 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/common/auth/JwtCredential.java @@ -0,0 +1,21 @@ +package io.camunda.common.auth; + +@Deprecated +public record JwtCredential(String clientId, String clientSecret, String audience, String authUrl) { + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public String getAudience() { + return audience; + } + + public String getAuthUrl() { + return authUrl; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/common/auth/SaaSAuthentication.java b/extension/java-client-operate/src/main/java/io/camunda/common/auth/SaaSAuthentication.java new file mode 100644 index 0000000..0e49667 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/common/auth/SaaSAuthentication.java @@ -0,0 +1,74 @@ +package io.camunda.common.auth; + +import io.camunda.common.json.JsonMapper; +import io.camunda.operate.auth.JwtAuthentication; +import io.camunda.operate.auth.JwtCredential; +import io.camunda.operate.auth.TokenResponse; +import java.net.MalformedURLException; +import java.net.URI; +import java.time.LocalDateTime; +import java.util.Map; + +@Deprecated +public class SaaSAuthentication implements Authentication { + private final JwtAuthentication authentication; + private TokenContext tokenContext; + + public SaaSAuthentication(JwtAuthentication authentication) { + this.authentication = authentication; + } + + public SaaSAuthentication(JwtConfig jwtConfig, JsonMapper jsonMapper) { + this(jwtAuthentication(jwtConfig, jsonMapper)); + } + + private static JwtAuthentication jwtAuthentication(JwtConfig jwtConfig, JsonMapper jsonMapper) { + io.camunda.common.auth.JwtCredential jwtCredential = jwtConfig.getJwtCredential(); + JwtCredential credential; + try { + credential = + new JwtCredential( + jwtCredential.getClientId(), + jwtCredential.getClientSecret(), + jwtCredential.getAudience(), + URI.create(jwtCredential.getAuthUrl()).toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException("Error while mapping jwt credential", e); + } + return new JwtAuthentication( + credential, (token) -> jsonMapper.fromJson(token, TokenResponse.class)); + } + + private JwtConfig jwtConfig() { + JwtConfig jwtConfig = new JwtConfig(); + JwtCredential jwtCredential = authentication.getJwtCredential(); + io.camunda.common.auth.JwtCredential credential = + new io.camunda.common.auth.JwtCredential( + jwtCredential.clientId(), + jwtCredential.clientSecret(), + jwtCredential.audience(), + jwtCredential.authUrl().toString()); + jwtConfig.addProduct(Product.ZEEBE, credential); + return jwtConfig; + } + + @Override + public Map getTokenHeader(Product product) { + return authentication.getTokenHeader(); + } + + @Override + public void resetToken(Product product) { + tokenContext = null; + } + + public JwtConfig getJwtConfig() { + return jwtConfig(); + } + + public JwtAuthentication getJwtAuthentication() { + return authentication; + } + + private record TokenContext(String token, LocalDateTime expiryDate) {} +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/common/auth/SaaSAuthenticationBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/common/auth/SaaSAuthenticationBuilder.java new file mode 100644 index 0000000..b043383 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/common/auth/SaaSAuthenticationBuilder.java @@ -0,0 +1,30 @@ +package io.camunda.common.auth; + +import io.camunda.common.json.JsonMapper; +import io.camunda.common.json.SdkObjectMapper; + +@Deprecated +public class SaaSAuthenticationBuilder { + private JsonMapper jsonMapper; + private JwtConfig jwtConfig; + + public SaaSAuthenticationBuilder withJsonMapper(JsonMapper jsonMapper) { + this.jsonMapper = jsonMapper; + return this; + } + + public SaaSAuthenticationBuilder withJwtConfig(JwtConfig jwtConfig) { + this.jwtConfig = jwtConfig; + return this; + } + + public Authentication build() { + if (jsonMapper == null) { + jsonMapper = new SdkObjectMapper(); + } + if (jwtConfig == null) { + throw new IllegalArgumentException("jwtConfig is required"); + } + return new SaaSAuthentication(jwtConfig, jsonMapper); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClient.java b/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClient.java new file mode 100644 index 0000000..1283133 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClient.java @@ -0,0 +1,229 @@ +package io.camunda.operate; + +import static io.camunda.operate.model.TypeReferences.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.camunda.operate.exception.OperateException; +import io.camunda.operate.http.DefaultHttpClient; +import io.camunda.operate.http.HttpClient; +import io.camunda.operate.model.*; +import io.camunda.operate.search.SearchQuery; +import io.camunda.zeebe.model.bpmn.Bpmn; +import io.camunda.zeebe.model.bpmn.BpmnModelInstance; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CamundaOperateClient { + + private final HttpClient httpClient; + + private CamundaOperateClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public CamundaOperateClient(CamundaOperateClientConfiguration configuration) { + this(buildOperateHttpClient(configuration)); + } + + @Deprecated + public static CamundaOperateClientBuilder builder() { + return new CamundaOperateClientBuilder(); + } + + private static HttpClient buildOperateHttpClient( + CamundaOperateClientConfiguration configuration) { + // load the config map + Map, String> map = new HashMap<>(); + // process definitions + map.put(searchProcessDefinition, "/process-definitions/search"); + map.put(processDefinition, "/process-definitions/{key}"); + map.put(processDefinitionXml, "/process-definitions/{key}/xml"); + // decision definition + map.put(searchDecisionDefinition, "/decision-definitions/search"); + map.put(decisionDefinition, "/decision-definitions/{key}"); + // decision instance + map.put(searchDecisionInstance, "/decision-instances/search"); + map.put(decisionInstance, "/decision-instances/{id}"); + // flownode instance + map.put(searchFlowNodeInstance, "/flownode-instances/search"); + map.put(flowNodeInstance, "/flownode-instances/{key}"); + // variable + map.put(searchVariable, "/variables/search"); + map.put(variable, "/variables/{key}"); + // process instances + map.put(searchProcessInstance, "/process-instances/search"); + map.put(processInstance, "/process-instances/{key}"); + map.put(deleteProcessInstance, "/process-instances/{key}"); + map.put(flownodeStatistics, "/process-instances/{key}/statistics"); + map.put(sequenceFlows, "/process-instances/{key}/sequence-flows"); + // decision requirements + map.put(searchDecisionRequirements, "/drd/search"); + map.put(decisionRequirements, "/drd/{key}"); + map.put(decisionRequirementsXml, "/drd/{key}/xml"); + // incident + map.put(searchIncident, "/incidents/search"); + map.put(incident, "/incidents/{key}"); + + try { + return new DefaultHttpClient( + URI.create(formatUrl(configuration.baseUrl().toString() + "/v1")).toURL(), + configuration.authentication(), + configuration.httpClient(), + configuration.objectMapper(), + map); + } catch (MalformedURLException e) { + throw new RuntimeException("Error while initializing operate http client", e); + } + } + + private static String formatUrl(String url) { + if (url.endsWith("/")) { + return url.substring(0, url.length() - 1); + } + return url; + } + + public ProcessDefinition getProcessDefinition(Long key) throws OperateException { + return httpClient.get(processDefinition, key(key)); + } + + public BpmnModelInstance getProcessDefinitionModel(Long key) throws OperateException { + String xml = getProcessDefinitionXml(key); + try { + InputStream processInputStream = new ByteArrayInputStream(xml.getBytes()); + return Bpmn.readModelFromStream(processInputStream); + } catch (Exception e) { + throw new OperateException(e); + } + } + + public String getProcessDefinitionXml(Long key) throws OperateException { + return httpClient.get(processDefinitionXml, key(key)); + } + + public List searchProcessDefinitions(SearchQuery query) + throws OperateException { + return searchProcessDefinitionResults(query).getItems(); + } + + public SearchResult searchProcessDefinitionResults(SearchQuery query) + throws OperateException { + return httpClient.post(searchProcessDefinition, query); + } + + public List searchDecisionDefinitions(SearchQuery query) + throws OperateException { + return searchDecisionDefinitionResults(query).getItems(); + } + + public SearchResult searchDecisionDefinitionResults(SearchQuery query) + throws OperateException { + return httpClient.post(searchDecisionDefinition, query); + } + + public List searchDecisionInstances(SearchQuery query) throws OperateException { + return searchDecisionInstanceResults(query).getItems(); + } + + public SearchResult searchDecisionInstanceResults(SearchQuery query) + throws OperateException { + return httpClient.post(searchDecisionInstance, query); + } + + public List searchFlowNodeInstances(SearchQuery query) throws OperateException { + return searchFlowNodeInstanceResults(query).getItems(); + } + + public SearchResult searchFlowNodeInstanceResults(SearchQuery query) + throws OperateException { + return httpClient.post(searchFlowNodeInstance, query); + } + + public List searchVariables(SearchQuery query) throws OperateException { + return searchVariableResults(query).getItems(); + } + + public SearchResult searchVariableResults(SearchQuery query) throws OperateException { + return httpClient.post(searchVariable, query); + } + + public List searchProcessInstances(SearchQuery query) throws OperateException { + return searchProcessInstanceResults(query).getItems(); + } + + public SearchResult searchProcessInstanceResults(SearchQuery query) + throws OperateException { + return httpClient.post(searchProcessInstance, query); + } + + public List searchDecisionRequirements(SearchQuery query) + throws OperateException { + return searchDecisionRequirementsResults(query).getItems(); + } + + public SearchResult searchDecisionRequirementsResults(SearchQuery query) + throws OperateException { + return httpClient.post(searchDecisionRequirements, query); + } + + public List searchIncidents(SearchQuery query) throws OperateException { + return searchIncidentResults(query).getItems(); + } + + public SearchResult searchIncidentResults(SearchQuery query) throws OperateException { + return httpClient.post(searchIncident, query); + } + + public ProcessInstance getProcessInstance(Long key) throws OperateException { + return httpClient.get(processInstance, Map.of("key", String.valueOf(key))); + } + + public ChangeStatus deleteProcessInstance(Long key) throws OperateException { + return httpClient.delete(deleteProcessInstance, key(key)); + } + + public List getFlowNodeStatistics(Long key) throws OperateException { + return httpClient.get(flownodeStatistics, key(key)); + } + + public List getSequenceFlows(Long key) throws OperateException { + return httpClient.get(sequenceFlows, key(key)); + } + + public FlowNodeInstance getFlowNodeInstance(Long key) throws OperateException { + return httpClient.get(flowNodeInstance, key(key)); + } + + public Incident getIncident(Long key) throws OperateException { + return httpClient.get(incident, key(key)); + } + + public DecisionDefinition getDecisionDefinition(Long key) throws OperateException { + return httpClient.get(decisionDefinition, key(key)); + } + + public DecisionRequirements getDecisionRequirements(Long key) throws OperateException { + return httpClient.get(decisionRequirements, key(key)); + } + + public String getDecisionRequirementsXml(Long key) throws OperateException { + return httpClient.get(decisionRequirementsXml, key(key)); + } + + public DecisionInstance getDecisionInstance(String id) throws OperateException { + return httpClient.get(decisionInstance, Map.of("id", id)); + } + + public Variable getVariable(Long key) throws OperateException { + return httpClient.get(variable, key(key)); + } + + private Map key(Long key) { + return Map.of("key", String.valueOf(key)); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClientBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClientBuilder.java new file mode 100644 index 0000000..b836d07 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClientBuilder.java @@ -0,0 +1,57 @@ +package io.camunda.operate; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.common.auth.SaaSAuthentication; +import io.camunda.operate.auth.Authentication; +import java.net.MalformedURLException; +import java.net.URI; +import org.apache.hc.client5.http.impl.classic.HttpClients; + +@Deprecated +public class CamundaOperateClientBuilder { + private String operateUrl; + private io.camunda.common.auth.Authentication authentication; + + public CamundaOperateClientBuilder operateUrl(String operateUrl) { + this.operateUrl = operateUrl; + return this; + } + + public CamundaOperateClientBuilder authentication( + io.camunda.common.auth.Authentication authentication) { + this.authentication = authentication; + return this; + } + + public CamundaOperateClientBuilder setup() { + // who needs this at all??? + return this; + } + + public CamundaOperateClient build() { + try { + Authentication auth = mapFromLegacy(); + CamundaOperateClientConfiguration configuration = + new CamundaOperateClientConfiguration( + auth, + URI.create(operateUrl).toURL(), + new ObjectMapper(), + HttpClients.createDefault()); + return new CamundaOperateClient(configuration); + } catch (MalformedURLException e) { + throw new RuntimeException("Error while creating operate client configuration", e); + } + } + + private Authentication mapFromLegacy() { + if (authentication == null) { + throw new IllegalStateException("Authentication not set"); + } + // there is only saas auth which is basically wrapping a jwt auth + if (authentication instanceof SaaSAuthentication saaSAuthentication) { + return saaSAuthentication.getJwtAuthentication(); + } + throw new IllegalStateException( + "Unknown authentication type: " + authentication.getClass().getName()); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClientConfiguration.java b/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClientConfiguration.java new file mode 100644 index 0000000..feaf767 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/CamundaOperateClientConfiguration.java @@ -0,0 +1,12 @@ +package io.camunda.operate; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.operate.auth.Authentication; +import java.net.URL; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; + +public record CamundaOperateClientConfiguration( + Authentication authentication, + URL baseUrl, + ObjectMapper objectMapper, + CloseableHttpClient httpClient) {} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/Authentication.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/Authentication.java new file mode 100644 index 0000000..c2c4aa6 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/Authentication.java @@ -0,0 +1,10 @@ +package io.camunda.operate.auth; + +import java.util.Map; + +public interface Authentication { + + Map getTokenHeader(); + + void resetToken(); +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/DefaultNoopAuthentication.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/DefaultNoopAuthentication.java new file mode 100644 index 0000000..34260cc --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/DefaultNoopAuthentication.java @@ -0,0 +1,33 @@ +package io.camunda.operate.auth; + +import io.camunda.operate.exception.SdkException; +import java.lang.invoke.MethodHandles; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Default implementation for Authentication Typically you will replace this by a proper + * authentication by setting the right properties + */ +public class DefaultNoopAuthentication implements Authentication { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final String errorMessage = + "Unable to determine authentication. Please check your configuration"; + + public DefaultNoopAuthentication() { + LOG.error(errorMessage); + } + + @Override + public void resetToken() { + throw new SdkException(errorMessage); + } + + @Override + public Map getTokenHeader() { + throw new UnsupportedOperationException("Unable to determine authentication"); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/JwtAuthentication.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/JwtAuthentication.java new file mode 100644 index 0000000..1084e07 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/JwtAuthentication.java @@ -0,0 +1,84 @@ +package io.camunda.operate.auth; + +import java.net.URISyntaxException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.message.BasicNameValuePair; + +public class JwtAuthentication implements Authentication { + private final JwtCredential jwtCredential; + private final TokenResponseMapper tokenResponseMapper; + private String token; + private LocalDateTime timeout; + + public JwtAuthentication(JwtCredential jwtCredential, TokenResponseMapper tokenResponseMapper) { + this.jwtCredential = jwtCredential; + this.tokenResponseMapper = tokenResponseMapper; + } + + @Deprecated + public JwtCredential getJwtCredential() { + return jwtCredential; + } + + @Override + public Map getTokenHeader() { + if (token == null || timeout == null || timeout.isBefore(LocalDateTime.now())) { + TokenResponse response = retrieveToken(); + token = response.getAccessToken(); + timeout = LocalDateTime.now().plusSeconds(response.getExpiresIn()).minusSeconds(30); + } + return Map.of("Authorization", "Bearer " + token); + } + + @Override + public void resetToken() { + this.token = null; + this.timeout = null; + } + + private TokenResponse retrieveToken() { + try (CloseableHttpClient client = HttpClients.createDefault()) { + HttpPost request = buildRequest(); + return client.execute( + request, + response -> { + try { + return tokenResponseMapper.readToken(EntityUtils.toString(response.getEntity())); + } catch (Exception e) { + var errorMessage = + String.format( + """ + Token retrieval failed from: %s + Response code: %s + Audience: %s + """, + jwtCredential.authUrl(), response.getCode(), jwtCredential.audience()); + throw new RuntimeException(errorMessage, e); + } + }); + } catch (Exception e) { + throw new RuntimeException("Authenticating for Operate failed due to " + e.getMessage(), e); + } + } + + private HttpPost buildRequest() throws URISyntaxException { + HttpPost httpPost = new HttpPost(jwtCredential.authUrl().toURI()); + httpPost.addHeader("Content-Type", "application/json"); + List formParams = new ArrayList<>(); + formParams.add(new BasicNameValuePair("grant_type", "client_credentials")); + formParams.add(new BasicNameValuePair("client_id", jwtCredential.clientId())); + formParams.add(new BasicNameValuePair("client_secret", jwtCredential.clientSecret())); + formParams.add(new BasicNameValuePair("audience", jwtCredential.audience())); + httpPost.setEntity(new UrlEncodedFormEntity(formParams)); + return httpPost; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/JwtCredential.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/JwtCredential.java new file mode 100644 index 0000000..d094261 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/JwtCredential.java @@ -0,0 +1,5 @@ +package io.camunda.operate.auth; + +import java.net.URL; + +public record JwtCredential(String clientId, String clientSecret, String audience, URL authUrl) {} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/SimpleAuthentication.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/SimpleAuthentication.java new file mode 100644 index 0000000..22ae5ad --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/SimpleAuthentication.java @@ -0,0 +1,98 @@ +package io.camunda.operate.auth; + +import java.lang.invoke.MethodHandles; +import java.time.LocalDateTime; +import java.util.*; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.message.BasicNameValuePair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SimpleAuthentication implements Authentication { + private static final String CSRF_HEADER = "OPERATE-X-CSRF-TOKEN"; + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final SimpleCredential simpleCredential; + private SimpleAuthToken token; + private LocalDateTime sessionTimeout; + + public SimpleAuthentication(SimpleCredential simpleCredential) { + this.simpleCredential = simpleCredential; + } + + private SimpleAuthToken retrieveToken() { + try (CloseableHttpClient client = HttpClients.createDefault()) { + HttpPost request = buildRequest(simpleCredential); + SimpleAuthToken simpleAuthToken = + client.execute( + request, + response -> { + String csrfTokenCandidate = null; + Header csrfTokenHeader = response.getHeader(CSRF_HEADER); + if (csrfTokenHeader != null) { + csrfTokenCandidate = csrfTokenHeader.getValue(); + } + Header[] cookieHeaders = response.getHeaders("Set-Cookie"); + String sessionCookie = null; + String csrfCookie = null; + String sessionCookieName = "OPERATE-SESSION"; + for (Header cookieHeader : cookieHeaders) { + if (cookieHeader.getValue().startsWith(sessionCookieName)) { + sessionCookie = cookieHeader.getValue(); + } + if (cookieHeader.getValue().startsWith(CSRF_HEADER)) { + csrfCookie = cookieHeader.getValue(); + } + } + return new SimpleAuthToken(sessionCookie, csrfCookie, csrfTokenCandidate); + }); + if (simpleAuthToken.sessionCookie() == null) { + throw new RuntimeException( + "Unable to authenticate due to missing Set-Cookie OPERATE-SESSION"); + } + if (simpleAuthToken.csrfToken() == null) { + LOG.info("No CSRF token found"); + } + if (simpleAuthToken.csrfCookie() == null) { + LOG.info("No CSRF cookie found"); + } + sessionTimeout = LocalDateTime.now().plus(simpleCredential.sessionTimeout()); + return simpleAuthToken; + } catch (Exception e) { + throw new RuntimeException("Unable to authenticate", e); + } + } + + private HttpPost buildRequest(SimpleCredential simpleCredential) { + HttpPost httpPost = new HttpPost(simpleCredential.baseUrl().toString() + "/api/login"); + List params = new ArrayList<>(); + params.add(new BasicNameValuePair("username", simpleCredential.username())); + params.add(new BasicNameValuePair("password", simpleCredential.password())); + httpPost.setEntity(new UrlEncodedFormEntity(params)); + return httpPost; + } + + @Override + public Map getTokenHeader() { + if (token == null || sessionTimeout.isBefore(LocalDateTime.now())) { + token = retrieveToken(); + } + return Map.of( + "Cookie", + token.sessionCookie() + "; " + token.csrfCookie(), + CSRF_HEADER, + token.csrfToken()); + } + + @Override + public void resetToken() { + token = null; + } + + private record SimpleAuthToken(String sessionCookie, String csrfCookie, String csrfToken) {} +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/SimpleCredential.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/SimpleCredential.java new file mode 100644 index 0000000..14c5878 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/SimpleCredential.java @@ -0,0 +1,8 @@ +package io.camunda.operate.auth; + +import java.net.URL; +import java.time.Duration; + +/** Contains credential for particular product. Used for Simple authentication. */ +public record SimpleCredential( + String username, String password, URL baseUrl, Duration sessionTimeout) {} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/TokenResponse.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/TokenResponse.java new file mode 100644 index 0000000..a9986b9 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/TokenResponse.java @@ -0,0 +1,51 @@ +package io.camunda.operate.auth; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TokenResponse { + + @JsonProperty("access_token") + private String accessToken; + + private String scope; + + @JsonProperty("expires_in") + private Integer expiresIn; + + @JsonProperty("token_type") + private String tokenType; + + TokenResponse() {} + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public Integer getExpiresIn() { + return expiresIn; + } + + public void setExpiresIn(Integer expiresIn) { + this.expiresIn = expiresIn; + } + + public String getTokenType() { + return tokenType; + } + + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/auth/TokenResponseMapper.java b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/TokenResponseMapper.java new file mode 100644 index 0000000..f2b39a1 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/auth/TokenResponseMapper.java @@ -0,0 +1,25 @@ +package io.camunda.operate.auth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public interface TokenResponseMapper { + TokenResponse readToken(String token); + + public class JacksonTokenResponseMapper implements TokenResponseMapper { + private final ObjectMapper objectMapper; + + public JacksonTokenResponseMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public TokenResponse readToken(String token) { + try { + return objectMapper.readValue(token, TokenResponse.class); + } catch (JsonProcessingException e) { + throw new RuntimeException("Error while reading token " + token, e); + } + } + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/exception/OperateException.java b/extension/java-client-operate/src/main/java/io/camunda/operate/exception/OperateException.java new file mode 100644 index 0000000..2116067 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/exception/OperateException.java @@ -0,0 +1,20 @@ +package io.camunda.operate.exception; + +public class OperateException extends Exception { + + public OperateException() { + super(); + } + + public OperateException(Exception e) { + super(e); + } + + public OperateException(String message) { + super(message); + } + + public OperateException(String message, Exception e) { + super(message, e); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/exception/SdkException.java b/extension/java-client-operate/src/main/java/io/camunda/operate/exception/SdkException.java new file mode 100644 index 0000000..c7ab65a --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/exception/SdkException.java @@ -0,0 +1,18 @@ +package io.camunda.operate.exception; + +public class SdkException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public SdkException(final Throwable cause) { + super(cause); + } + + public SdkException(final String message) { + super(message); + } + + public SdkException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/http/DefaultHttpClient.java b/extension/java-client-operate/src/main/java/io/camunda/operate/http/DefaultHttpClient.java new file mode 100644 index 0000000..9699dac --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/http/DefaultHttpClient.java @@ -0,0 +1,133 @@ +package io.camunda.operate.http; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import io.camunda.operate.auth.Authentication; +import io.camunda.operate.exception.SdkException; +import java.lang.invoke.MethodHandles; +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import org.apache.hc.client5.http.classic.methods.HttpDelete; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.message.BasicHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Default Http Client powered by Apache HttpClient */ +public class DefaultHttpClient implements HttpClient { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private final Map, String> endpointMap; + private final CloseableHttpClient httpClient; + private final Authentication authentication; + private final ObjectMapper objectMapper; + private final String baseUrl; + + public DefaultHttpClient( + URL baseUrl, + Authentication authentication, + CloseableHttpClient httpClient, + ObjectMapper objectMapper, + Map, String> endpointMap) { + this.authentication = authentication; + this.httpClient = httpClient; + this.objectMapper = objectMapper.copy(); + this.endpointMap = endpointMap; + this.objectMapper + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); + this.baseUrl = baseUrl.toString(); + } + + @Override + public T get(TypeReference responseType, Map pathParams) { + String url = baseUrl + retrievePath(responseType, pathParams); + HttpGet httpGet = new HttpGet(url); + retrieveToken().forEach(httpGet::addHeader); + try { + return httpClient.execute(httpGet, handleResponse(responseType)); + } catch (Exception e) { + throw new SdkException(String.format("Failed GET to %s, due to %s", url, e.getMessage()), e); + } + } + + @Override + public T post(TypeReference responseType, U body) { + + String url = baseUrl + retrievePath(responseType, Map.of()); + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("Content-Type", "application/json"); + retrieveToken().forEach(httpPost::addHeader); + String data; + try { + data = objectMapper.writeValueAsString(body); + } catch (JsonProcessingException e) { + throw new RuntimeException("Error while parsing " + body + "of type " + body.getClass(), e); + } + httpPost.setEntity(new StringEntity(data)); + try { + return httpClient.execute(httpPost, handleResponse(responseType)); + } catch (Exception e) { + throw new SdkException( + String.format("Failed POST to %s with body %s, due to %s", url, data, e.getMessage()), e); + } + } + + @Override + public T delete(TypeReference responseType, Map pathParams) { + String resourcePath = retrievePath(responseType, pathParams); + String url = baseUrl + resourcePath; + HttpDelete httpDelete = new HttpDelete(url); + retrieveToken().forEach(httpDelete::addHeader); + try { + return httpClient.execute(httpDelete, handleResponse(responseType)); + } catch (Exception e) { + throw new SdkException( + String.format("Failed DELETE to %s, due to %s", url, e.getMessage()), e); + } + } + + private String retrievePath(TypeReference clazz, Map pathParams) { + AtomicReference path = new AtomicReference<>(); + if (endpointMap.containsKey(clazz)) { + path.set(endpointMap.get(clazz)); + } + for (String pathParam : pathParams.keySet()) { + String pathParamMarker = "{" + pathParam + "}"; + if (path.get().contains(pathParamMarker)) { + path.set(path.get().replace(pathParamMarker, pathParams.get(pathParam))); + } + } + return path.get(); + } + + private List retrieveToken() { + Map header = authentication.getTokenHeader(); + return header.entrySet().stream().map(e -> new BasicHeader(e.getKey(), e.getValue())).toList(); + } + + private HttpClientResponseHandler handleResponse(TypeReference responseType) { + return new TypeReferenceHttpClientResponseHandler<>( + responseType, objectMapper, this::handleErrorResponse); + } + + private SdkException handleErrorResponse(Integer code) { + if (code == HttpStatus.SC_UNAUTHORIZED || code == HttpStatus.SC_FORBIDDEN) { + authentication.resetToken(); + } + return new SdkException("Response not successful: " + code); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/http/HttpClient.java b/extension/java-client-operate/src/main/java/io/camunda/operate/http/HttpClient.java new file mode 100644 index 0000000..c1daec6 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/http/HttpClient.java @@ -0,0 +1,14 @@ +package io.camunda.operate.http; + +import com.fasterxml.jackson.core.type.TypeReference; +import java.util.Map; + +/** Interface to enable swappable http client implementations */ +public interface HttpClient { + + T get(TypeReference responseType, Map pathParams); + + T post(TypeReference responseType, U body); + + T delete(TypeReference responseType, Map pathParams); +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/http/Java8Utils.java b/extension/java-client-operate/src/main/java/io/camunda/operate/http/Java8Utils.java new file mode 100644 index 0000000..074065b --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/http/Java8Utils.java @@ -0,0 +1,37 @@ +package io.camunda.operate.http; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class Java8Utils { + + private Java8Utils() {} + + public static byte[] readAllBytes(InputStream inputStream) throws IOException { + final int bufLen = 4 * 0x400; // 4KB + byte[] buf = new byte[bufLen]; + int readLen; + IOException exception = null; + + try { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + while ((readLen = inputStream.read(buf, 0, bufLen)) != -1) + outputStream.write(buf, 0, readLen); + + return outputStream.toByteArray(); + } + } catch (IOException e) { + exception = e; + throw e; + } finally { + if (exception == null) inputStream.close(); + else + try { + inputStream.close(); + } catch (IOException e) { + exception.addSuppressed(e); + } + } + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/http/TypeReferenceHttpClientResponseHandler.java b/extension/java-client-operate/src/main/java/io/camunda/operate/http/TypeReferenceHttpClientResponseHandler.java new file mode 100644 index 0000000..0b14f62 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/http/TypeReferenceHttpClientResponseHandler.java @@ -0,0 +1,41 @@ +package io.camunda.operate.http; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.function.Function; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.entity.EntityUtils; + +public class TypeReferenceHttpClientResponseHandler implements HttpClientResponseHandler { + private final TypeReference typeReference; + private final ObjectMapper objectMapper; + private final Function errorCodeHandler; + + public TypeReferenceHttpClientResponseHandler( + TypeReference typeReference, + ObjectMapper objectMapper, + Function errorCodeHandler) { + this.typeReference = typeReference; + this.objectMapper = objectMapper; + this.errorCodeHandler = errorCodeHandler; + } + + @Override + public T handleResponse(ClassicHttpResponse response) throws HttpException, IOException { + T resp; + if (200 <= response.getCode() && response.getCode() <= 299) { + HttpEntity entity = response.getEntity(); + String tmp = new String(Java8Utils.readAllBytes(entity.getContent()), StandardCharsets.UTF_8); + resp = objectMapper.readValue(tmp, typeReference); + EntityUtils.consume(entity); + return resp; + } else { + throw errorCodeHandler.apply(response.getCode()); + } + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/ChangeStatus.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ChangeStatus.java new file mode 100644 index 0000000..53a514c --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ChangeStatus.java @@ -0,0 +1,23 @@ +package io.camunda.operate.model; + +public class ChangeStatus { + + private String message; + private Long deleted; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Long getDeleted() { + return deleted; + } + + public void setDeleted(Long deleted) { + this.deleted = deleted; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionDefinition.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionDefinition.java new file mode 100644 index 0000000..2eeb670 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionDefinition.java @@ -0,0 +1,95 @@ +package io.camunda.operate.model; + +public class DecisionDefinition { + + private String id; + private Long key; + private String decisionId; + private String name; + private Long version; + private String decisionRequirementsId; + private Long decisionRequirementsKey; + private String decisionRequirementsName; + private Long decisionRequirementsVersion; + private String tenantId; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public String getDecisionId() { + return decisionId; + } + + public void setDecisionId(String decisionId) { + this.decisionId = decisionId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getDecisionRequirementsId() { + return decisionRequirementsId; + } + + public void setDecisionRequirementsId(String decisionRequirementsId) { + this.decisionRequirementsId = decisionRequirementsId; + } + + public Long getDecisionRequirementsKey() { + return decisionRequirementsKey; + } + + public void setDecisionRequirementsKey(Long decisionRequirementsKey) { + this.decisionRequirementsKey = decisionRequirementsKey; + } + + public String getDecisionRequirementsName() { + return decisionRequirementsName; + } + + public void setDecisionRequirementsName(String decisionRequirementsName) { + this.decisionRequirementsName = decisionRequirementsName; + } + + public Long getDecisionRequirementsVersion() { + return decisionRequirementsVersion; + } + + public void setDecisionRequirementsVersion(Long decisionRequirementsVersion) { + this.decisionRequirementsVersion = decisionRequirementsVersion; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstance.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstance.java new file mode 100644 index 0000000..fa3a895 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstance.java @@ -0,0 +1,151 @@ +package io.camunda.operate.model; + +import java.util.List; + +public class DecisionInstance { + + private String id; + private Long key; + private DecisionState state; + private String evaluationDate; + private String evaluationFailure; + private Long processDefinitionKey; + private Long processInstanceKey; + private String decisionId; + private String decisionDefinitionId; + private String decisionName; + private Long decisionVersion; + private DecisionType decisionType; + private String result; + private List evaluatedInputs; + private List evaluatedOutputs; + private String tenantId; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public DecisionState getState() { + return state; + } + + public void setState(DecisionState state) { + this.state = state; + } + + public String getEvaluationDate() { + return evaluationDate; + } + + public void setEvaluationDate(String evaluationDate) { + this.evaluationDate = evaluationDate; + } + + public String getEvaluationFailure() { + return evaluationFailure; + } + + public void setEvaluationFailure(String evaluationFailure) { + this.evaluationFailure = evaluationFailure; + } + + public Long getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(Long processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public Long getProcessInstanceKey() { + return processInstanceKey; + } + + public void setProcessInstanceKey(Long processInstanceKey) { + this.processInstanceKey = processInstanceKey; + } + + public String getDecisionId() { + return decisionId; + } + + public void setDecisionId(String decisionId) { + this.decisionId = decisionId; + } + + public String getDecisionDefinitionId() { + return decisionDefinitionId; + } + + public void setDecisionDefinitionId(String decisionDefinitionId) { + this.decisionDefinitionId = decisionDefinitionId; + } + + public String getDecisionName() { + return decisionName; + } + + public void setDecisionName(String decisionName) { + this.decisionName = decisionName; + } + + public Long getDecisionVersion() { + return decisionVersion; + } + + public void setDecisionVersion(Long decisionVersion) { + this.decisionVersion = decisionVersion; + } + + public DecisionType getDecisionType() { + return decisionType; + } + + public void setDecisionType(DecisionType decisionType) { + this.decisionType = decisionType; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public List getEvaluatedInputs() { + return evaluatedInputs; + } + + public void setEvaluatedInputs(List evaluatedInputs) { + this.evaluatedInputs = evaluatedInputs; + } + + public List getEvaluatedOutputs() { + return evaluatedOutputs; + } + + public void setEvaluatedOutputs(List evaluatedOutputs) { + this.evaluatedOutputs = evaluatedOutputs; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstanceInput.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstanceInput.java new file mode 100644 index 0000000..a5bf5e6 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstanceInput.java @@ -0,0 +1,32 @@ +package io.camunda.operate.model; + +public class DecisionInstanceInput { + + private String id; + private String name; + private String value; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstanceOutput.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstanceOutput.java new file mode 100644 index 0000000..8939bf7 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionInstanceOutput.java @@ -0,0 +1,50 @@ +package io.camunda.operate.model; + +public class DecisionInstanceOutput { + + private String id; + private String name; + private String value; + private String ruleId; + private Long ruleIndex; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getRuleId() { + return ruleId; + } + + public void setRuleId(String ruleId) { + this.ruleId = ruleId; + } + + public Long getRuleIndex() { + return ruleIndex; + } + + public void setRuleIndex(Long ruleIndex) { + this.ruleIndex = ruleIndex; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionRequirements.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionRequirements.java new file mode 100644 index 0000000..b465371 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionRequirements.java @@ -0,0 +1,68 @@ +package io.camunda.operate.model; + +public class DecisionRequirements { + + private String id; + private Long key; + private String decisionRequirements; + private String name; + private Long version; + private String resourceName; + private String tenantId; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public String getDecisionRequirements() { + return decisionRequirements; + } + + public void setDecisionRequirements(String decisionRequirements) { + this.decisionRequirements = decisionRequirements; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getResourceName() { + return resourceName; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionState.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionState.java new file mode 100644 index 0000000..695eb59 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionState.java @@ -0,0 +1,8 @@ +package io.camunda.operate.model; + +public enum DecisionState { + FAILED, + EVALUATED, + UNKNOWN, + UNSPECIFIED +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionType.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionType.java new file mode 100644 index 0000000..df755b2 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/DecisionType.java @@ -0,0 +1,8 @@ +package io.camunda.operate.model; + +public enum DecisionType { + DECISION_TABLE, + LITERAL_EXPRESSION, + UNSPECIFIED, + UNKNOWN +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeInstance.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeInstance.java new file mode 100644 index 0000000..e3b5f2f --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeInstance.java @@ -0,0 +1,114 @@ +package io.camunda.operate.model; + +import java.util.Date; + +public class FlowNodeInstance { + private Long key; + private Long processInstanceKey; + private Long processDefinitionKey; + private Date startDate; + private Date endDate; + private String flowNodeId; + private String flowNodeName; + private Long incidentKey; + private String type; + private FlowNodeInstanceState state; + private Boolean incident; + private String tenantId; + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public Long getProcessInstanceKey() { + return processInstanceKey; + } + + public void setProcessInstanceKey(Long processInstanceKey) { + this.processInstanceKey = processInstanceKey; + } + + public Long getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(Long processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public String getFlowNodeId() { + return flowNodeId; + } + + public void setFlowNodeId(String flowNodeId) { + this.flowNodeId = flowNodeId; + } + + public String getFlowNodeName() { + return flowNodeName; + } + + public void setFlowNodeName(String flowNodeName) { + this.flowNodeName = flowNodeName; + } + + public Long getIncidentKey() { + return incidentKey; + } + + public void setIncidentKey(Long incidentKey) { + this.incidentKey = incidentKey; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public FlowNodeInstanceState getState() { + return state; + } + + public void setState(FlowNodeInstanceState state) { + this.state = state; + } + + public Boolean getIncident() { + return incident; + } + + public void setIncident(Boolean incident) { + this.incident = incident; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeInstanceState.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeInstanceState.java new file mode 100644 index 0000000..e72de8b --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeInstanceState.java @@ -0,0 +1,8 @@ +package io.camunda.operate.model; + +public enum FlowNodeInstanceState { + ACTIVE, + INCIDENT, + COMPLETED, + TERMINATED; +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeStatistics.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeStatistics.java new file mode 100644 index 0000000..7a89cfb --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/FlowNodeStatistics.java @@ -0,0 +1,50 @@ +package io.camunda.operate.model; + +public class FlowNodeStatistics { + + private String activityId; + private Long active; + private Long canceled; + private Long incidents; + private Long completed; + + public String getActivityId() { + return activityId; + } + + public void setActivityId(String activityId) { + this.activityId = activityId; + } + + public Long getActive() { + return active; + } + + public void setActive(Long active) { + this.active = active; + } + + public Long getCanceled() { + return canceled; + } + + public void setCanceled(Long canceled) { + this.canceled = canceled; + } + + public Long getIncidents() { + return incidents; + } + + public void setIncidents(Long incidents) { + this.incidents = incidents; + } + + public Long getCompleted() { + return completed; + } + + public void setCompleted(Long completed) { + this.completed = completed; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/Incident.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/Incident.java new file mode 100644 index 0000000..4ab7ee2 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/Incident.java @@ -0,0 +1,78 @@ +package io.camunda.operate.model; + +import java.util.Date; + +public class Incident { + private Long key; + private Long processDefinitionKey; + private Long processInstanceKey; + private String type; + private String message; + private Date creationTime; + private String state; + private String tenantId; + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public Long getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(Long processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public Long getProcessInstanceKey() { + return processInstanceKey; + } + + public void setProcessInstanceKey(Long processInstanceKey) { + this.processInstanceKey = processInstanceKey; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Date getCreationTime() { + return creationTime; + } + + public void setCreationTime(Date creationTime) { + this.creationTime = creationTime; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessDefinition.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessDefinition.java new file mode 100644 index 0000000..00f264f --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessDefinition.java @@ -0,0 +1,49 @@ +package io.camunda.operate.model; + +public class ProcessDefinition { + private Long key; + private String name; + private Long version; + private String bpmnProcessId; + private String tenantId; + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getBpmnProcessId() { + return bpmnProcessId; + } + + public void setBpmnProcessId(String bpmnProcessId) { + this.bpmnProcessId = bpmnProcessId; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessInstance.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessInstance.java new file mode 100644 index 0000000..10842f6 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessInstance.java @@ -0,0 +1,96 @@ +package io.camunda.operate.model; + +import java.util.Date; + +public class ProcessInstance { + private Long key; + private Long processVersion; + private String bpmnProcessId; + private Long parentKey; + private Long parentFlowNodeInstanceKey; + private Date startDate; + private Date endDate; + private ProcessInstanceState state; + private Long processDefinitionKey; + private String tenantId; + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public Long getProcessVersion() { + return processVersion; + } + + public void setProcessVersion(Long processVersion) { + this.processVersion = processVersion; + } + + public String getBpmnProcessId() { + return bpmnProcessId; + } + + public void setBpmnProcessId(String bpmnProcessId) { + this.bpmnProcessId = bpmnProcessId; + } + + public Long getParentKey() { + return parentKey; + } + + public void setParentKey(Long parentKey) { + this.parentKey = parentKey; + } + + public Long getParentFlowNodeInstanceKey() { + return parentFlowNodeInstanceKey; + } + + public void setParentFlowNodeInstanceKey(Long parentFlowNodeInstanceKey) { + this.parentFlowNodeInstanceKey = parentFlowNodeInstanceKey; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public ProcessInstanceState getState() { + return state; + } + + public void setState(ProcessInstanceState state) { + this.state = state; + } + + public Long getProcessDefinitionKey() { + return processDefinitionKey; + } + + public void setProcessDefinitionKey(Long processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessInstanceState.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessInstanceState.java new file mode 100644 index 0000000..c93f267 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/ProcessInstanceState.java @@ -0,0 +1,7 @@ +package io.camunda.operate.model; + +public enum ProcessInstanceState { + ACTIVE, + COMPLETED, + CANCELED; +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/SearchResult.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/SearchResult.java new file mode 100644 index 0000000..e809671 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/SearchResult.java @@ -0,0 +1,40 @@ +package io.camunda.operate.model; + +import java.util.Iterator; +import java.util.List; + +public class SearchResult implements Iterable { + private List items; + + private Integer total; + + private List sortValues; + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public List getSortValues() { + return sortValues; + } + + public void setSortValues(List sortValues) { + this.sortValues = sortValues; + } + + public Iterator iterator() { + return this.items.iterator(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/TypeReferences.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/TypeReferences.java new file mode 100644 index 0000000..6e4a203 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/TypeReferences.java @@ -0,0 +1,30 @@ +package io.camunda.operate.model; + +import com.fasterxml.jackson.core.type.TypeReference; +import java.util.List; + +public interface TypeReferences { + TypeReference processInstance = new TypeReference<>() {}; + TypeReference> flownodeStatistics = new TypeReference<>() {}; + TypeReference> sequenceFlows = new TypeReference<>() {}; + TypeReference processDefinition = new TypeReference<>() {}; + TypeReference processDefinitionXml = new TypeReference<>() {}; + TypeReference> searchProcessDefinition = new TypeReference<>() {}; + TypeReference> searchDecisionDefinition = + new TypeReference<>() {}; + TypeReference decisionDefinition = new TypeReference<>() {}; + TypeReference> searchDecisionInstance = new TypeReference<>() {}; + TypeReference decisionInstance = new TypeReference<>() {}; + TypeReference> searchFlowNodeInstance = new TypeReference<>() {}; + TypeReference flowNodeInstance = new TypeReference<>() {}; + TypeReference> searchVariable = new TypeReference<>() {}; + TypeReference variable = new TypeReference<>() {}; + TypeReference> searchProcessInstance = new TypeReference<>() {}; + TypeReference> searchDecisionRequirements = + new TypeReference<>() {}; + TypeReference decisionRequirements = new TypeReference<>() {}; + TypeReference decisionRequirementsXml = new TypeReference<>() {}; + TypeReference> searchIncident = new TypeReference<>() {}; + TypeReference incident = new TypeReference<>() {}; + TypeReference deleteProcessInstance = new TypeReference<>() {}; +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/model/Variable.java b/extension/java-client-operate/src/main/java/io/camunda/operate/model/Variable.java new file mode 100644 index 0000000..b791db9 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/model/Variable.java @@ -0,0 +1,73 @@ +package io.camunda.operate.model; + +public class Variable { + private Long key; + + private Long processInstanceKey; + + private Long scopeKey; + + private String name; + + private String value; + + private Boolean truncated; + + private String tenantId; + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public Long getProcessInstanceKey() { + return processInstanceKey; + } + + public void setProcessInstanceKey(Long processInstanceKey) { + this.processInstanceKey = processInstanceKey; + } + + public Long getScopeKey() { + return scopeKey; + } + + public void setScopeKey(Long scopeKey) { + this.scopeKey = scopeKey; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Boolean getTruncated() { + return truncated; + } + + public void setTruncated(Boolean truncated) { + this.truncated = truncated; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilter.java new file mode 100644 index 0000000..7b951f3 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilter.java @@ -0,0 +1,42 @@ +package io.camunda.operate.search; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.util.Date; + +@JsonSerialize(using = DateFilterSerializer.class) +public class DateFilter { + + private Date date; + + private DateFilterRange range; + + public DateFilter(Date date, DateFilterRange range) { + super(); + this.date = date; + this.range = range; + } + + public DateFilter(Date date) { + this(date, DateFilterRange.SECOND); + } + + public DateFilter() { + this(new Date()); + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public DateFilterRange getRange() { + return range; + } + + public void setRange(DateFilterRange range) { + this.range = range; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilterRange.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilterRange.java new file mode 100644 index 0000000..562fcbd --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilterRange.java @@ -0,0 +1,21 @@ +package io.camunda.operate.search; + +public enum DateFilterRange { + YEAR("y"), + MONTH("M"), + WEEK("w"), + DAY("d"), + HOUR("h"), + MINUTE("m"), + SECOND("s"); + + private String value; + + DateFilterRange(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilterSerializer.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilterSerializer.java new file mode 100644 index 0000000..1c93242 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DateFilterSerializer.java @@ -0,0 +1,27 @@ +package io.camunda.operate.search; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import java.io.IOException; +import java.text.SimpleDateFormat; + +public class DateFilterSerializer extends StdSerializer { + + public static SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ"); + + /** serial version uid */ + private static final long serialVersionUID = -8106244922585465120L; + + public DateFilterSerializer() { + super(DateFilter.class); + } + + @Override + public void serialize(DateFilter value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + + jgen.writeString(isoFormat.format(value.getDate()) + "||/" + value.getRange().getValue()); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionDefinitionFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionDefinitionFilter.java new file mode 100644 index 0000000..925d798 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionDefinitionFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.DecisionDefinition; + +public class DecisionDefinitionFilter extends DecisionDefinition implements Filter { + + public static DecisionDefinitionFilterBuilder builder() { + return new DecisionDefinitionFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionDefinitionFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionDefinitionFilterBuilder.java new file mode 100644 index 0000000..ff911a5 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionDefinitionFilterBuilder.java @@ -0,0 +1,65 @@ +package io.camunda.operate.search; + +public class DecisionDefinitionFilterBuilder { + + DecisionDefinitionFilter filter; + + DecisionDefinitionFilterBuilder() { + filter = new DecisionDefinitionFilter(); + } + + public DecisionDefinitionFilterBuilder id(String id) { + filter.setId(id); + return this; + } + + public DecisionDefinitionFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public DecisionDefinitionFilterBuilder decisionId(String decisionId) { + filter.setDecisionId(decisionId); + return this; + } + + public DecisionDefinitionFilterBuilder name(String name) { + filter.setName(name); + return this; + } + + public DecisionDefinitionFilterBuilder version(Long version) { + filter.setVersion(version); + return this; + } + + public DecisionDefinitionFilterBuilder decisionRequirementsId(String decisionRequirementsId) { + filter.setDecisionRequirementsId(decisionRequirementsId); + return this; + } + + public DecisionDefinitionFilterBuilder decisionRequirementsKey(Long decisionRequirementsKey) { + filter.setDecisionRequirementsKey(decisionRequirementsKey); + return this; + } + + public DecisionDefinitionFilterBuilder decisionRequirementsName(String decisionRequirementsName) { + filter.setDecisionRequirementsName(decisionRequirementsName); + return this; + } + + public DecisionDefinitionFilterBuilder decisionRequirementsVersion( + Long decisionRequirementsVersion) { + filter.setDecisionRequirementsVersion(decisionRequirementsVersion); + return this; + } + + public DecisionDefinitionFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public DecisionDefinitionFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionInstanceFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionInstanceFilter.java new file mode 100644 index 0000000..e10e180 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionInstanceFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.DecisionInstance; + +public class DecisionInstanceFilter extends DecisionInstance implements Filter { + + public static DecisionInstanceFilterBuilder builder() { + return new DecisionInstanceFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionInstanceFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionInstanceFilterBuilder.java new file mode 100644 index 0000000..40ff7c2 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionInstanceFilterBuilder.java @@ -0,0 +1,102 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.DecisionInstanceInput; +import io.camunda.operate.model.DecisionInstanceOutput; +import io.camunda.operate.model.DecisionState; +import io.camunda.operate.model.DecisionType; +import java.util.List; + +public class DecisionInstanceFilterBuilder { + + DecisionInstanceFilter filter; + + DecisionInstanceFilterBuilder() { + filter = new DecisionInstanceFilter(); + } + + public DecisionInstanceFilterBuilder id(String id) { + filter.setId(id); + return this; + } + + public DecisionInstanceFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public DecisionInstanceFilterBuilder state(DecisionState state) { + filter.setState(state); + return this; + } + + public DecisionInstanceFilterBuilder evaluationDate(String evaluationDate) { + filter.setEvaluationDate(evaluationDate); + return this; + } + + public DecisionInstanceFilterBuilder evaluationFailure(String evaluationFailure) { + filter.setEvaluationFailure(evaluationFailure); + return this; + } + + public DecisionInstanceFilterBuilder processDefinitionKey(Long processDefinitionKey) { + filter.setProcessDefinitionKey(processDefinitionKey); + return this; + } + + public DecisionInstanceFilterBuilder processInstanceKey(Long processInstanceKey) { + filter.setProcessInstanceKey(processInstanceKey); + return this; + } + + public DecisionInstanceFilterBuilder decisionId(String decisionId) { + filter.setDecisionId(decisionId); + return this; + } + + public DecisionInstanceFilterBuilder decisionDefinitionId(String decisionDefinitionId) { + filter.setDecisionDefinitionId(decisionDefinitionId); + return this; + } + + public DecisionInstanceFilterBuilder decisionName(String decisionName) { + filter.setDecisionName(decisionName); + return this; + } + + public DecisionInstanceFilterBuilder decisionVersion(Long decisionVersion) { + filter.setDecisionVersion(decisionVersion); + return this; + } + + public DecisionInstanceFilterBuilder decisionType(DecisionType decisionType) { + filter.setDecisionType(decisionType); + return this; + } + + public DecisionInstanceFilterBuilder result(String result) { + filter.setResult(result); + return this; + } + + public DecisionInstanceFilterBuilder evaluatedInputs( + List evaluatedInputs) { + filter.setEvaluatedInputs(evaluatedInputs); + return this; + } + + public DecisionInstanceFilterBuilder evaluatedOutputs( + List evaluatedOutputs) { + filter.setEvaluatedOutputs(evaluatedOutputs); + return this; + } + + public DecisionInstanceFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public DecisionInstanceFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionRequirementsFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionRequirementsFilter.java new file mode 100644 index 0000000..b8989d4 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionRequirementsFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.DecisionRequirements; + +public class DecisionRequirementsFilter extends DecisionRequirements implements Filter { + + public static DecisionRequirementsFilterBuilder builder() { + return new DecisionRequirementsFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionRequirementsFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionRequirementsFilterBuilder.java new file mode 100644 index 0000000..b8a239a --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/DecisionRequirementsFilterBuilder.java @@ -0,0 +1,49 @@ +package io.camunda.operate.search; + +public class DecisionRequirementsFilterBuilder { + + DecisionRequirementsFilter filter; + + DecisionRequirementsFilterBuilder() { + filter = new DecisionRequirementsFilter(); + } + + public DecisionRequirementsFilterBuilder id(String id) { + filter.setId(id); + return this; + } + + public DecisionRequirementsFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public DecisionRequirementsFilterBuilder decisionRequirements(String decisionRequirements) { + filter.setDecisionRequirements(decisionRequirements); + return this; + } + + public DecisionRequirementsFilterBuilder name(String name) { + filter.setName(name); + return this; + } + + public DecisionRequirementsFilterBuilder version(Long version) { + filter.setVersion(version); + return this; + } + + public DecisionRequirementsFilterBuilder resourceName(String resourceName) { + filter.setResourceName(resourceName); + return this; + } + + public DecisionRequirementsFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public DecisionRequirementsFilter build() { + return filter; + } +} diff --git a/src/main/java/io/camunda/operate/search/Filter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/Filter.java similarity index 55% rename from src/main/java/io/camunda/operate/search/Filter.java rename to extension/java-client-operate/src/main/java/io/camunda/operate/search/Filter.java index bb76fd6..e6d5a81 100644 --- a/src/main/java/io/camunda/operate/search/Filter.java +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/Filter.java @@ -1,5 +1,3 @@ package io.camunda.operate.search; -public interface Filter { - -} +public interface Filter {} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/FlowNodeInstanceFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/FlowNodeInstanceFilter.java new file mode 100644 index 0000000..5534b0b --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/FlowNodeInstanceFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.FlowNodeInstance; + +public class FlowNodeInstanceFilter extends FlowNodeInstance implements Filter { + + public static FlowNodeInstanceFilterBuilder builder() { + return new FlowNodeInstanceFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/FlowNodeInstanceFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/FlowNodeInstanceFilterBuilder.java new file mode 100644 index 0000000..d3982ee --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/FlowNodeInstanceFilterBuilder.java @@ -0,0 +1,77 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.FlowNodeInstanceState; +import java.util.Date; + +public class FlowNodeInstanceFilterBuilder { + + FlowNodeInstanceFilter filter; + + FlowNodeInstanceFilterBuilder() { + filter = new FlowNodeInstanceFilter(); + } + + public FlowNodeInstanceFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public FlowNodeInstanceFilterBuilder processInstanceKey(Long processInstanceKey) { + filter.setProcessInstanceKey(processInstanceKey); + return this; + } + + public FlowNodeInstanceFilterBuilder processDefinitionKey(Long processDefinitionKey) { + filter.setProcessDefinitionKey(processDefinitionKey); + return this; + } + + public FlowNodeInstanceFilterBuilder startDate(Date startDate) { + filter.setStartDate(startDate); + return this; + } + + public FlowNodeInstanceFilterBuilder endDate(Date endDate) { + filter.setEndDate(endDate); + return this; + } + + public FlowNodeInstanceFilterBuilder flowNodeId(String flowNodeId) { + filter.setFlowNodeId(flowNodeId); + return this; + } + + public FlowNodeInstanceFilterBuilder flowNodeName(String flowNodeName) { + filter.setFlowNodeName(flowNodeName); + return this; + } + + public FlowNodeInstanceFilterBuilder incidentKey(Long incidentKey) { + filter.setIncidentKey(incidentKey); + return this; + } + + public FlowNodeInstanceFilterBuilder type(String type) { + filter.setType(type); + return this; + } + + public FlowNodeInstanceFilterBuilder state(FlowNodeInstanceState state) { + filter.setState(state); + return this; + } + + public FlowNodeInstanceFilterBuilder incident(Boolean incident) { + filter.setIncident(incident); + return this; + } + + public FlowNodeInstanceFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public FlowNodeInstanceFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/IncidentFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/IncidentFilter.java new file mode 100644 index 0000000..e80b6a7 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/IncidentFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.Incident; + +public class IncidentFilter extends Incident implements Filter { + + public static IncidentFilterBuilder builder() { + return new IncidentFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/IncidentFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/IncidentFilterBuilder.java new file mode 100644 index 0000000..ae5101f --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/IncidentFilterBuilder.java @@ -0,0 +1,56 @@ +package io.camunda.operate.search; + +import java.util.Date; + +public class IncidentFilterBuilder { + + IncidentFilter filter; + + IncidentFilterBuilder() { + filter = new IncidentFilter(); + } + + public IncidentFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public IncidentFilterBuilder processDefinitionKey(Long processDefinitionKey) { + filter.setProcessDefinitionKey(processDefinitionKey); + return this; + } + + public IncidentFilterBuilder processInstanceKey(Long processInstanceKey) { + filter.setProcessInstanceKey(processInstanceKey); + return this; + } + + public IncidentFilterBuilder type(String type) { + filter.setType(type); + return this; + } + + public IncidentFilterBuilder message(String message) { + filter.setMessage(message); + return this; + } + + public IncidentFilterBuilder creationTime(Date creationTime) { + filter.setCreationTime(creationTime); + return this; + } + + public IncidentFilterBuilder state(String state) { + filter.setState(state); + return this; + } + + public IncidentFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public IncidentFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessDefinitionFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessDefinitionFilter.java new file mode 100644 index 0000000..6c09a0c --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessDefinitionFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.ProcessDefinition; + +public class ProcessDefinitionFilter extends ProcessDefinition implements Filter { + + public static ProcessDefinitionFilterBuilder builder() { + return new ProcessDefinitionFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessDefinitionFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessDefinitionFilterBuilder.java new file mode 100644 index 0000000..be3e3ee --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessDefinitionFilterBuilder.java @@ -0,0 +1,39 @@ +package io.camunda.operate.search; + +public class ProcessDefinitionFilterBuilder { + + ProcessDefinitionFilter filter; + + ProcessDefinitionFilterBuilder() { + filter = new ProcessDefinitionFilter(); + } + + public ProcessDefinitionFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public ProcessDefinitionFilterBuilder name(String name) { + filter.setName(name); + return this; + } + + public ProcessDefinitionFilterBuilder version(Long version) { + filter.setVersion(version); + return this; + } + + public ProcessDefinitionFilterBuilder bpmnProcessId(String bpmnProcessId) { + filter.setBpmnProcessId(bpmnProcessId); + return this; + } + + public ProcessDefinitionFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public ProcessDefinitionFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessInstanceFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessInstanceFilter.java new file mode 100644 index 0000000..cfe5c5e --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessInstanceFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.ProcessInstance; + +public class ProcessInstanceFilter extends ProcessInstance implements Filter { + + public static ProcessInstanceFilterBuilder builder() { + return new ProcessInstanceFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessInstanceFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessInstanceFilterBuilder.java new file mode 100644 index 0000000..0fc2d09 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/ProcessInstanceFilterBuilder.java @@ -0,0 +1,62 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.ProcessInstanceState; +import java.util.Date; + +public class ProcessInstanceFilterBuilder { + + ProcessInstanceFilter filter; + + ProcessInstanceFilterBuilder() { + filter = new ProcessInstanceFilter(); + } + + public ProcessInstanceFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public ProcessInstanceFilterBuilder processVersion(Long processVersion) { + filter.setProcessVersion(processVersion); + return this; + } + + public ProcessInstanceFilterBuilder bpmnProcessId(String bpmnProcessId) { + filter.setBpmnProcessId(bpmnProcessId); + return this; + } + + public ProcessInstanceFilterBuilder parentKey(Long parentKey) { + filter.setParentKey(parentKey); + return this; + } + + public ProcessInstanceFilterBuilder startDate(Date startDate) { + filter.setStartDate(startDate); + return this; + } + + public ProcessInstanceFilterBuilder endDate(Date endDate) { + filter.setEndDate(endDate); + return this; + } + + public ProcessInstanceFilterBuilder state(ProcessInstanceState state) { + filter.setState(state); + return this; + } + + public ProcessInstanceFilterBuilder processDefinitionKey(Long processDefinitionKey) { + filter.setProcessDefinitionKey(processDefinitionKey); + return this; + } + + public ProcessInstanceFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public ProcessInstanceFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/SearchQuery.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/SearchQuery.java new file mode 100644 index 0000000..6f3fcb0 --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/SearchQuery.java @@ -0,0 +1,103 @@ +package io.camunda.operate.search; + +import io.camunda.operate.exception.OperateException; +import java.util.ArrayList; +import java.util.List; + +public class SearchQuery { + private Filter filter; + private Integer size; + private List sort; + private List searchAfter; + + public Filter getFilter() { + return filter; + } + + public void setFilter(Filter filter) { + this.filter = filter; + } + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } + + public List getSort() { + return sort; + } + + public void setSort(List sort) { + this.sort = sort; + } + + public List getSearchAfter() { + return searchAfter; + } + + public void setSearchAfter(List searchAfter) { + this.searchAfter = searchAfter; + } + + public static class Builder { + + private Filter filter; + private Integer size; + private List sorts = new ArrayList<>(); + private List searchAfter = null; + + public Builder() {} + + @Deprecated + public Builder withFilter(Filter filter) { + this.filter = filter; + return this; + } + + public Builder filter(Filter filter) { + this.filter = filter; + return this; + } + + @Deprecated + public Builder withSize(Integer size) { + this.size = size; + return this; + } + + public Builder size(Integer size) { + this.size = size; + return this; + } + + @Deprecated + public Builder withSort(Sort sort) { + this.sorts.add(sort); + return this; + } + + public Builder sort(Sort sort) { + this.sorts.add(sort); + return this; + } + + public Builder searchAfter(List searchAfter) { + this.searchAfter = searchAfter; + return this; + } + + public SearchQuery build() throws OperateException { + SearchQuery query = new SearchQuery(); + query.filter = filter; + query.size = size; + query.searchAfter = searchAfter; + if (!sorts.isEmpty()) { + query.setSort(sorts); + } + return query; + } + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/Sort.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/Sort.java new file mode 100644 index 0000000..eece3fc --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/Sort.java @@ -0,0 +1,34 @@ +package io.camunda.operate.search; + +public class Sort { + + private String field; + + private SortOrder order; + + public Sort() { + super(); + } + + public Sort(String field, SortOrder order) { + super(); + this.field = field; + this.order = order; + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public SortOrder getOrder() { + return order; + } + + public void setOrder(SortOrder order) { + this.order = order; + } +} diff --git a/src/main/java/io/camunda/operate/search/SortOrder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/SortOrder.java similarity index 80% rename from src/main/java/io/camunda/operate/search/SortOrder.java rename to extension/java-client-operate/src/main/java/io/camunda/operate/search/SortOrder.java index a4bb130..b35ca3c 100644 --- a/src/main/java/io/camunda/operate/search/SortOrder.java +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/SortOrder.java @@ -1,5 +1,6 @@ package io.camunda.operate.search; public enum SortOrder { - ASC, DESC; + ASC, + DESC; } diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/VariableFilter.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/VariableFilter.java new file mode 100644 index 0000000..7f4d29c --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/VariableFilter.java @@ -0,0 +1,10 @@ +package io.camunda.operate.search; + +import io.camunda.operate.model.Variable; + +public class VariableFilter extends Variable implements Filter { + + public static VariableFilterBuilder builder() { + return new VariableFilterBuilder(); + } +} diff --git a/extension/java-client-operate/src/main/java/io/camunda/operate/search/VariableFilterBuilder.java b/extension/java-client-operate/src/main/java/io/camunda/operate/search/VariableFilterBuilder.java new file mode 100644 index 0000000..4ea2abf --- /dev/null +++ b/extension/java-client-operate/src/main/java/io/camunda/operate/search/VariableFilterBuilder.java @@ -0,0 +1,49 @@ +package io.camunda.operate.search; + +public class VariableFilterBuilder { + + VariableFilter filter; + + VariableFilterBuilder() { + filter = new VariableFilter(); + } + + public VariableFilterBuilder key(Long key) { + filter.setKey(key); + return this; + } + + public VariableFilterBuilder processInstanceKey(Long processInstanceKey) { + filter.setProcessInstanceKey(processInstanceKey); + return this; + } + + public VariableFilterBuilder scopeKey(Long scopeKey) { + filter.setScopeKey(scopeKey); + return this; + } + + public VariableFilterBuilder name(String name) { + filter.setName(name); + return this; + } + + public VariableFilterBuilder value(String value) { + filter.setValue(value); + return this; + } + + public VariableFilterBuilder truncated(Boolean truncated) { + filter.setTruncated(truncated); + return this; + } + + public VariableFilterBuilder tenantId(String tenantId) { + filter.setTenantId(tenantId); + return this; + } + + public VariableFilter build() { + return filter; + } +} diff --git a/extension/java-client-operate/src/test/java/io/camunda/operate/http/DefaultHttpClientTest.java b/extension/java-client-operate/src/test/java/io/camunda/operate/http/DefaultHttpClientTest.java new file mode 100644 index 0000000..3dda395 --- /dev/null +++ b/extension/java-client-operate/src/test/java/io/camunda/operate/http/DefaultHttpClientTest.java @@ -0,0 +1,128 @@ +package io.camunda.operate.http; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.operate.auth.Authentication; +import java.io.IOException; +import java.net.URI; +import java.util.*; +import org.apache.hc.client5.http.classic.methods.HttpDelete; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.internal.matchers.apachecommons.ReflectionEquals; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class DefaultHttpClientTest { + + @Mock Authentication authentication; + @Mock CloseableHttpClient chClient; + ObjectMapper jsonMapper = new ObjectMapper(); + + @Test + public void shouldReturnGetType() throws IOException { + // given + TypeReference typeReference = new TypeReference<>() {}; + TypeReference typeReferenceWithSameType = new TypeReference<>() {}; + + Map, String> productMap = new HashMap<>(); + productMap.put(typeReference, "/request/{some}"); + productMap.put(typeReferenceWithSameType, "/no"); + DefaultHttpClient defaultHttpClient = + new DefaultHttpClient( + URI.create("http://localhost:8081").toURL(), + authentication, + chClient, + jsonMapper, + productMap); + MyResponseClass expectedOutput = new MyResponseClass(); + expectedOutput.setName("test-name"); + ArgumentCaptor captor = ArgumentCaptor.forClass(HttpGet.class); + // when + when(chClient.execute(captor.capture(), any(HttpClientResponseHandler.class))) + .thenReturn(expectedOutput); + when(authentication.getTokenHeader()).thenReturn(Map.of("key", "value")); + + MyResponseClass parsedResponse = + defaultHttpClient.get(typeReference, Map.of("some", "test-name")); + + // then + assertTrue(new ReflectionEquals(expectedOutput).matches(parsedResponse)); + assertEquals("/request/test-name", captor.getValue().getRequestUri()); + } + + @Test + public void shouldReturnPostType() throws IOException { + // given + Map, String> productMap = new HashMap<>(); + DefaultHttpClient defaultHttpClient = + new DefaultHttpClient( + URI.create("http://localhost:8081").toURL(), + authentication, + chClient, + jsonMapper, + productMap); + MyResponseClass insideClass = new MyResponseClass(); + insideClass.setName("test-name"); + List expectedOutput = new ArrayList<>(); + expectedOutput.add(insideClass); + + // when + when(chClient.execute(any(HttpPost.class), any(HttpClientResponseHandler.class))) + .thenReturn(expectedOutput); + when(authentication.getTokenHeader()).thenReturn(Map.of("key", "value")); + List parsedResponse = + defaultHttpClient.post(new TypeReference<>() {}, Map.of()); + + // then + assertEquals(expectedOutput.size(), parsedResponse.size()); + assertTrue(new ReflectionEquals(expectedOutput.get(0)).matches(parsedResponse.get(0))); + } + + @Test + public void shouldReturnDeleteType() throws IOException { + // given + Map, String> productMap = new HashMap<>(); + DefaultHttpClient defaultHttpClient = + new DefaultHttpClient( + URI.create("http://localhost:8081").toURL(), + authentication, + chClient, + jsonMapper, + productMap); + MyResponseClass expectedOutput = new MyResponseClass(); + expectedOutput.setName("test-name"); + + // when + when(chClient.execute(any(HttpDelete.class), any(HttpClientResponseHandler.class))) + .thenReturn(expectedOutput); + when(authentication.getTokenHeader()).thenReturn(Map.of("key", "value")); + MyResponseClass parsedResponse = defaultHttpClient.delete(new TypeReference<>() {}, Map.of()); + + // then + assertTrue(new ReflectionEquals(expectedOutput).matches(parsedResponse)); + } + + // TODO: add more tests for retrieving the right url path based on input + + public static class MyResponseClass { + private String name; + + public void setName(String name) { + this.name = name; + } + } + + public static class MySelectorClass {} +} diff --git a/extension/java-client-operate/src/test/java/io/camunda/operate/http/TypeReferenceHttpClientResponseHandlerTest.java b/extension/java-client-operate/src/test/java/io/camunda/operate/http/TypeReferenceHttpClientResponseHandlerTest.java new file mode 100644 index 0000000..96f6b2e --- /dev/null +++ b/extension/java-client-operate/src/test/java/io/camunda/operate/http/TypeReferenceHttpClientResponseHandlerTest.java @@ -0,0 +1,68 @@ +package io.camunda.operate.http; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.List; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.junit.jupiter.api.Test; + +public class TypeReferenceHttpClientResponseHandlerTest { + @Test + void shouldReturnTypedResponse() throws HttpException, IOException { + TypeReferenceHttpClientResponseHandler handler = + new TypeReferenceHttpClientResponseHandler<>( + new TypeReference<>() {}, new ObjectMapper(), code -> new RuntimeException()); + ClassicHttpResponse httpResponse = mock(ClassicHttpResponse.class); + when(httpResponse.getCode()).thenReturn(200); + when(httpResponse.getEntity()) + .thenReturn( + new StringEntity( + """ + { + "id": "x123", + "name": "John Doe" + } + """)); + Response r = handler.handleResponse(httpResponse); + assertEquals("x123", r.id()); + assertEquals("John Doe", r.name()); + } + + @Test + void shouldReturnTypedResponseList() throws HttpException, IOException { + TypeReferenceHttpClientResponseHandler> handler = + new TypeReferenceHttpClientResponseHandler<>( + new TypeReference<>() {}, new ObjectMapper(), code -> new RuntimeException()); + ClassicHttpResponse httpResponse = mock(ClassicHttpResponse.class); + when(httpResponse.getCode()).thenReturn(200); + when(httpResponse.getEntity()) + .thenReturn( + new StringEntity( + """ + [ + { + "id": "x123", + "name": "John Doe" + }, + { + "id": "x124", + "name": "John Dow" + } + ] + """)); + List r = handler.handleResponse(httpResponse); + assertEquals(2, r.size()); + assertEquals("x123", r.get(0).id()); + assertEquals("John Doe", r.get(0).name()); + assertEquals("x124", r.get(1).id()); + assertEquals("John Dow", r.get(1).name()); + } + + record Response(String id, String name) {} +} diff --git a/extension/java-client-operate/src/test/java/io/camunda/operate/http/TypeReferenceTest.java b/extension/java-client-operate/src/test/java/io/camunda/operate/http/TypeReferenceTest.java new file mode 100644 index 0000000..169fa34 --- /dev/null +++ b/extension/java-client-operate/src/test/java/io/camunda/operate/http/TypeReferenceTest.java @@ -0,0 +1,25 @@ +package io.camunda.operate.http; + +import static org.junit.jupiter.api.Assertions.*; + +import com.fasterxml.jackson.core.type.TypeReference; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class TypeReferenceTest { + + @Test + void shouldFindTypeReference() { + TypeReference stringTypeReference1 = new TypeReference<>() {}; + TypeReference stringTypeReference2 = new TypeReference<>() {}; + Map, String> map = + Map.of(stringTypeReference1, "/1", stringTypeReference2, "/2"); + String one = map.get(stringTypeReference1); + String two = map.get(stringTypeReference2); + assertEquals(one, "/1"); + assertEquals(two, "/2"); + } +} diff --git a/extension/pom.xml b/extension/pom.xml new file mode 100644 index 0000000..b4af855 --- /dev/null +++ b/extension/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + io.camunda.spring + operate-client-root + 8.6.0-alpha1-SNAPSHOT + + + operate-client-parent + pom + + + java-client-operate + spring-boot-starter-camunda-operate + + diff --git a/extension/spring-boot-starter-camunda-operate/pom.xml b/extension/spring-boot-starter-camunda-operate/pom.xml new file mode 100644 index 0000000..3d93688 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + io.camunda.spring + operate-client-parent + 8.6.0-alpha1-SNAPSHOT + + + spring-boot-starter-camunda-operate + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-autoconfigure + provided + + + org.apache.httpcomponents.client5 + httpclient5 + provided + + + org.springframework + spring-core + provided + + + org.springframework + spring-beans + provided + + + org.springframework + spring-context + provided + + + org.springframework.boot + spring-boot + provided + + + com.fasterxml.jackson.core + jackson-databind + provided + + + io.camunda.spring + java-client-operate + + + io.camunda + spring-boot-starter-camunda-sdk + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-test + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.assertj + assertj-core + test + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.springframework.boot:spring-boot-starter + + org.springframework.boot:spring-boot-starter-test + + io.camunda:spring-boot-starter-camunda-sdk + + + + + + + + + \ No newline at end of file diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/ObjectMapperConfiguration.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/ObjectMapperConfiguration.java new file mode 100644 index 0000000..521717a --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/ObjectMapperConfiguration.java @@ -0,0 +1,16 @@ +package io.camunda.operate.spring; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnMissingBean(ObjectMapper.class) +public class ObjectMapperConfiguration { + @Bean + @ConditionalOnMissingBean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperateClientConfiguration.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperateClientConfiguration.java new file mode 100644 index 0000000..f37cb9f --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperateClientConfiguration.java @@ -0,0 +1,88 @@ +package io.camunda.operate.spring; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.operate.CamundaOperateClient; +import io.camunda.operate.CamundaOperateClientConfiguration; +import io.camunda.operate.auth.Authentication; +import io.camunda.operate.auth.JwtAuthentication; +import io.camunda.operate.auth.JwtCredential; +import io.camunda.operate.auth.SimpleAuthentication; +import io.camunda.operate.auth.SimpleCredential; +import io.camunda.operate.auth.TokenResponseMapper.JacksonTokenResponseMapper; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +@EnableConfigurationProperties({ + OperateClientConfigurationProperties.class, + io.camunda.zeebe.spring.client.properties.OperateClientConfigurationProperties.class +}) +@ConditionalOnProperty(value = "operate.client.enabled", matchIfMissing = true) +@Import(ObjectMapperConfiguration.class) +public class OperateClientConfiguration { + private final OperateClientConfigurationProperties properties; + private final ObjectMapper objectMapper; + + @Autowired + public OperateClientConfiguration( + OperateClientConfigurationProperties properties, ObjectMapper objectMapper) { + this.properties = properties; + this.objectMapper = objectMapper; + } + + @Bean + @ConditionalOnMissingBean + public CamundaOperateClient camundaOperateClient( + CamundaOperateClientConfiguration configuration) { + return new CamundaOperateClient(configuration); + } + + @Bean + @ConditionalOnMissingBean + public CamundaOperateClientConfiguration operateClientConfiguration( + Authentication authentication, + @Qualifier("operateHttpClient") CloseableHttpClient operateHttpClient) { + return new CamundaOperateClientConfiguration( + authentication, properties.baseUrl(), objectMapper, operateHttpClient); + } + + @Bean("operateHttpClient") + @ConditionalOnMissingBean(name = "operateHttpClient") + public CloseableHttpClient operateHttpClient() { + return HttpClients.createDefault(); + } + + @Bean + @ConditionalOnMissingBean + public Authentication authentication() { + if (properties.profile() == null) { + throw new IllegalStateException("'operate.client.profile' is required"); + } + switch (properties.profile()) { + case simple -> { + return new SimpleAuthentication( + new SimpleCredential( + properties.username(), + properties.password(), + properties.baseUrl(), + properties.sessionTimeout())); + } + case oidc, saas -> { + return new JwtAuthentication( + new JwtCredential( + properties.clientId(), + properties.clientSecret(), + properties.audience(), + properties.authUrl()), + new JacksonTokenResponseMapper(objectMapper)); + } + default -> throw new IllegalStateException("Unsupported profile: " + properties.profile()); + } + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperateClientConfigurationProperties.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperateClientConfigurationProperties.java new file mode 100644 index 0000000..a582138 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperateClientConfigurationProperties.java @@ -0,0 +1,30 @@ +package io.camunda.operate.spring; + +import java.net.URL; +import java.time.Duration; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("operate.client") +public record OperateClientConfigurationProperties( + // generic properties + Profile profile, + Boolean enabled, + URL baseUrl, + // simple auth properties + String username, + String password, + Duration sessionTimeout, + // oidc auth properties + String clientId, + String clientSecret, + URL authUrl, + String audience, + // saas auth properies + String region, + String clusterId) { + public enum Profile { + simple, + oidc, + saas + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperatePropertiesPostProcessor.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperatePropertiesPostProcessor.java new file mode 100644 index 0000000..b2f8880 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/operate/spring/OperatePropertiesPostProcessor.java @@ -0,0 +1,48 @@ +package io.camunda.operate.spring; + +import io.camunda.operate.spring.OperateClientConfigurationProperties.Profile; +import java.util.List; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.boot.env.YamlPropertySourceLoader; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.ClassPathResource; + +public class OperatePropertiesPostProcessor implements EnvironmentPostProcessor { + + @Override + public void postProcessEnvironment( + ConfigurableEnvironment environment, SpringApplication application) { + try { + Profile profile = environment.getProperty("operate.client.profile", Profile.class); + if (profile == null) { + return; + } + YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); + String propertiesFile = "operate-profiles/" + determinePropertiesFile(profile); + ClassPathResource resource = new ClassPathResource(propertiesFile); + List> props = loader.load(propertiesFile, resource); + for (PropertySource prop : props) { + environment.getPropertySources().addLast(prop); // lowest priority + } + } catch (Exception e) { + throw new IllegalStateException("Error while post processing camunda properties", e); + } + } + + private String determinePropertiesFile(Profile clientMode) { + switch (clientMode) { + case oidc -> { + return "oidc.yaml"; + } + case saas -> { + return "saas.yaml"; + } + case simple -> { + return "simple.yaml"; + } + } + throw new IllegalStateException("Unknown client mode " + clientMode); + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/configuration/OperateClientConfiguration.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/configuration/OperateClientConfiguration.java new file mode 100644 index 0000000..1869a98 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/configuration/OperateClientConfiguration.java @@ -0,0 +1,50 @@ +package io.camunda.zeebe.spring.client.configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.camunda.common.auth.Authentication; +import io.camunda.operate.CamundaOperateClient; +import io.camunda.operate.CamundaOperateClientConfiguration; +import io.camunda.zeebe.spring.client.properties.CamundaClientProperties; +import io.camunda.zeebe.spring.client.properties.OperateClientConfigurationProperties; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; + +@Deprecated +public class OperateClientConfiguration { + private final OperateClientConfigurationProperties legacyProperties; + private final CamundaClientProperties properties; + private final Authentication authentication; + + public OperateClientConfiguration( + OperateClientConfigurationProperties legacyProperties, + CamundaClientProperties properties, + Authentication authentication) { + this.legacyProperties = legacyProperties; + this.properties = properties; + this.authentication = authentication; + } + + public CamundaOperateClient camundaOperateClient() { + io.camunda.operate.auth.Authentication auth = + (io.camunda.operate.auth.Authentication) authentication; + URL baseUrl; + try { + baseUrl = URI.create(operateUrl()).toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException("Error while reading Operate url " + operateUrl(), e); + } + ObjectMapper objectMapper = new ObjectMapper(); + CloseableHttpClient httpClient = HttpClients.createDefault(); + CamundaOperateClientConfiguration configuration = + new CamundaOperateClientConfiguration(auth, baseUrl, objectMapper, httpClient); + return new CamundaOperateClient(configuration); + } + + private String operateUrl() { + // TODO actually return something + return ""; + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/properties/CamundaClientProperties.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/properties/CamundaClientProperties.java new file mode 100644 index 0000000..e755b11 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/properties/CamundaClientProperties.java @@ -0,0 +1,4 @@ +package io.camunda.zeebe.spring.client.properties; + +@Deprecated +public class CamundaClientProperties {} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/properties/OperateClientConfigurationProperties.java b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/properties/OperateClientConfigurationProperties.java new file mode 100644 index 0000000..8eda9ac --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/java/io/camunda/zeebe/spring/client/properties/OperateClientConfigurationProperties.java @@ -0,0 +1,16 @@ +package io.camunda.zeebe.spring.client.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Deprecated +@ConfigurationProperties("camunda.operate.client") +public record OperateClientConfigurationProperties(String baseUrl, String authUrl) { + + public String getBaseUrl() { + return baseUrl; + } + + public String getAuthUrl() { + return authUrl; + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/main/resources/META-INF/spring.factories b/extension/spring-boot-starter-camunda-operate/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..b3aeb2e --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.env.EnvironmentPostProcessor=io.camunda.operate.spring.OperatePropertiesPostProcessor diff --git a/extension/spring-boot-starter-camunda-operate/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/extension/spring-boot-starter-camunda-operate/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..3c1ac67 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +io.camunda.operate.spring.OperateClientConfiguration \ No newline at end of file diff --git a/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/oidc.yaml b/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/oidc.yaml new file mode 100644 index 0000000..32951e2 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/oidc.yaml @@ -0,0 +1,8 @@ +operate: + client: + profile: oidc + enabled: true + base-url: http://localhost:8081 + auth-url: http://localhost:18080/auth/realms/camunda-platform/openid-connect/token + audience: operate-api + diff --git a/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/saas.yaml b/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/saas.yaml new file mode 100644 index 0000000..be55b03 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/saas.yaml @@ -0,0 +1,7 @@ +operate: + client: + profile: saas + enabled: true + base-url: https://${operate.client.region}.operate.camunda.io/${operate.client.cluster-id} + auth-url: https://login.cloud.camunda.io/oauth/token + audience: operate.camunda.io diff --git a/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/simple.yaml b/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/simple.yaml new file mode 100644 index 0000000..1cfdd80 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/main/resources/operate-profiles/simple.yaml @@ -0,0 +1,8 @@ +operate: + client: + profile: simple + enabled: true + base-url: http://localhost:8081 + session-timeout: PT10M + username: demo + password: demo diff --git a/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileOidcTest.java b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileOidcTest.java new file mode 100644 index 0000000..46e93ba --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileOidcTest.java @@ -0,0 +1,33 @@ +package io.camunda.operate.spring; + +import static io.camunda.operate.spring.OperateClientConfigurationProperties.Profile.*; +import static org.assertj.core.api.Assertions.*; + +import java.net.MalformedURLException; +import java.net.URI; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest( + properties = { + "operate.client.profile=oidc", + "operate.client.client-id=def", + "operate.client.client-secret=ghi" + }) +public class OperateClientConfigurationPropertiesProfileOidcTest { + @Autowired OperateClientConfigurationProperties properties; + + @Test + void shouldApplyProfiles() throws MalformedURLException { + assertThat(properties.profile()).isEqualTo(oidc); + assertThat(properties.clientId()).isEqualTo("def"); + assertThat(properties.clientSecret()).isEqualTo("ghi"); + assertThat(properties.baseUrl()).isEqualTo(URI.create("http://localhost:8081").toURL()); + assertThat(properties.enabled()).isEqualTo(true); + assertThat(properties.authUrl()) + .isEqualTo( + URI.create("http://localhost:18080/auth/realms/camunda-platform/openid-connect/token") + .toURL()); + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileSaasTest.java b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileSaasTest.java new file mode 100644 index 0000000..17bb0d2 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileSaasTest.java @@ -0,0 +1,34 @@ +package io.camunda.operate.spring; + +import static io.camunda.operate.spring.OperateClientConfigurationProperties.Profile.*; +import static org.assertj.core.api.Assertions.*; + +import java.net.MalformedURLException; +import java.net.URI; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest( + properties = { + "operate.client.profile=saas", + "operate.client.cluster-id=abc", + "operate.client.region=bru-2", + "operate.client.client-id=def", + "operate.client.client-secret=ghi" + }) +public class OperateClientConfigurationPropertiesProfileSaasTest { + @Autowired OperateClientConfigurationProperties properties; + + @Test + void shouldApplyProfiles() throws MalformedURLException { + assertThat(properties.profile()).isEqualTo(saas); + assertThat(properties.clientId()).isEqualTo("def"); + assertThat(properties.clientSecret()).isEqualTo("ghi"); + assertThat(properties.baseUrl()) + .isEqualTo(URI.create("https://bru-2.operate.camunda.io/abc").toURL()); + assertThat(properties.enabled()).isEqualTo(true); + assertThat(properties.authUrl()) + .isEqualTo(URI.create("https://login.cloud.camunda.io/oauth/token").toURL()); + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileSimpleTest.java b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileSimpleTest.java new file mode 100644 index 0000000..817a1a4 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/OperateClientConfigurationPropertiesProfileSimpleTest.java @@ -0,0 +1,26 @@ +package io.camunda.operate.spring; + +import static io.camunda.operate.spring.OperateClientConfigurationProperties.Profile.*; +import static org.assertj.core.api.Assertions.*; + +import java.net.MalformedURLException; +import java.net.URI; +import java.time.Duration; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(properties = {"operate.client.profile=simple"}) +public class OperateClientConfigurationPropertiesProfileSimpleTest { + @Autowired OperateClientConfigurationProperties properties; + + @Test + void shouldApplyProfiles() throws MalformedURLException { + assertThat(properties.profile()).isEqualTo(simple); + assertThat(properties.username()).isEqualTo("demo"); + assertThat(properties.password()).isEqualTo("demo"); + assertThat(properties.baseUrl()).isEqualTo(URI.create("http://localhost:8081").toURL()); + assertThat(properties.enabled()).isEqualTo(true); + assertThat(properties.sessionTimeout()).isEqualTo(Duration.ofMinutes(10)); + } +} diff --git a/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/TestApp.java b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/TestApp.java new file mode 100644 index 0000000..57478a7 --- /dev/null +++ b/extension/spring-boot-starter-camunda-operate/src/test/java/io/camunda/operate/spring/TestApp.java @@ -0,0 +1,11 @@ +package io.camunda.operate.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TestApp { + public static void main(String[] args) { + SpringApplication.run(TestApp.class, args); + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 41d9927..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 00e33ed..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100755 index 1b6c787..0000000 --- a/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..00e88bb --- /dev/null +++ b/pom.xml @@ -0,0 +1,478 @@ + + 4.0.0 + + + org.camunda.community + community-hub-release-parent + 1.4.4 + + io.camunda.spring + operate-client-root + 8.6.0-alpha1-SNAPSHOT + pom + + + ${project.build.sourceEncoding} + 17 + ${version.java} + + ${java.version} + ${java.version} + + 8.5.3 + 8.5.2 + + 3.3.0 + 1.9.4 + 2.2.0 + 2.17.1 + 3.14.0 + + 3.5.0 + + + https://artifacts.camunda.com/artifactory/zeebe-io-snapshots/ + https://artifacts.camunda.com/artifactory/zeebe-io/ + + 0.11.0 + 3.1.2 + 3.3.1 + 3.6.0 + 3.3.0 + 2.43.0 + 3.13.0 + 0.10.2 + 3.7.1 + 3.12.1 + 3.7.1 + 3.1.0 + 1.15.0 + 3.3.1 + + + + + extension + examples + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + import + pom + + + io.camunda + zeebe-bom + ${zeebe.version} + import + pom + + + io.camunda + spring-boot-starter-camunda-sdk + ${zeebe.version} + + + io.camunda + zeebe-bpmn-model + ${zeebe.version} + + + io.camunda + zeebe-process-test-extension + ${zeebe.version} + + + io.camunda + zeebe-process-test-extension-testcontainer + ${zeebe.version} + + + io.camunda.spring + java-client-operate + ${project.version} + + + io.camunda.spring + spring-boot-starter-camunda-operate + ${project.version} + + + io.camunda + identity-sdk + ${identity.version} + + + io.camunda + identity-spring-boot-starter + ${identity.version} + + + io.camunda + identity-spring-boot-autoconfigure + ${identity.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + org.awaitility + awaitility + 4.2.1 + + + commons-beanutils + commons-beanutils + ${commons-beanutils.version} + + + io.github.resilience4j + resilience4j-retry + ${resilience4j.version} + + + org.apache.commons + commons-lang3 + ${commons-lang.version} + + + com.google.guava + guava + 33.2.1-jre + + + + + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.7.0 + + + org.apache.maven.plugins + maven-source-plugin + ${plugin.version.maven-source-plugin} + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-assembly-plugin + ${plugin.version.maven-assembly-plugin} + + + org.apache.maven.plugins + maven-resources-plugin + ${plugin.version.maven-resources-plugin} + + + org.apache.maven.plugins + maven-site-plugin + ${plugin.version.maven-site-plugin} + + + org.apache.maven.plugins + maven-dependency-plugin + ${plugin.version.maven-depdendency-plugin} + + + org.graalvm.buildtools + native-maven-plugin + ${plugin.version.native-maven-plugin} + + + org.apache.maven.plugins + maven-compiler-plugin + ${plugin.version.maven-compiler-plugin} + + + -parameters + + + + + org.springframework.boot + spring-boot-maven-plugin + ${version.spring-boot} + + + + 17 + en_US.utf8 + + ${maven.build.timestamp} + + + + + org.apache.maven.plugins + maven-install-plugin + ${plugin.version.maven-install-plugin} + + + org.apache.maven.plugins + maven-shade-plugin + ${plugin.version.maven-shade-plugin} + + + org.apache.maven.plugins + maven-surefire-plugin + ${plugin.version.maven-surefire-plugin} + + true + + + + org.apache.maven.plugins + maven-enforcer-plugin + ${plugin.version.maven-enforcer-plugin} + + + + + + + + + + + enforce + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${plugin.version.spotless-maven-plugin} + + + + + *.md + .gitignore + + + + + true + 2 + + + + + + + + + + + com.google.cloud.functions + function-maven-plugin + ${plugin.version.function-maven-plugin} + + + org.apache.maven.plugins + maven-release-plugin + ${plugin.version.maven-release-plugin} + + + com.github.eirslett + frontend-maven-plugin + ${plugin.version.frontend-maven-plugin} + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + [1.0.0,) + + enforce + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + analyze + + analyze-only + + + true + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + + + + + autoFormat + + true + + + + + com.diffplug.spotless + spotless-maven-plugin + + + spotless-format + + apply + + process-sources + + + + + + + + + + checkFormat + + + + com.diffplug.spotless + spotless-maven-plugin + + + spotless-check + + check + + validate + + + + + + + + + + + zeebe-snapshots + Zeebe Snapshot Repository + https://artifacts.camunda.com/artifactory/zeebe-io-snapshots/ + + false + + + true + + + + connectors-snapshots + Connectors Snapshot Repository + https://artifacts.camunda.com/artifactory/connectors-snapshots/ + + false + + + true + + + + identity + Identity Repository + https://artifacts.camunda.com/artifactory/camunda-identity + + false + + + + + + + Jan Galinski + Holisticon AG + https://jangalinski.github.io + + initiator + + + + + + + Apache License + + + + + https://github.com/camunda-community-hub/spring-zeebe + scm:git:git@github.com:camunda-community-hub/spring-zeebe.git + scm:git:git@github.com:camunda-community-hub/spring-zeebe.git + HEAD + + diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index ac7b98d..0000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'camunda-operate-client-java' diff --git a/src/main/java/io/camunda/operate/CamundaOperateClient.java b/src/main/java/io/camunda/operate/CamundaOperateClient.java deleted file mode 100644 index f7164b4..0000000 --- a/src/main/java/io/camunda/operate/CamundaOperateClient.java +++ /dev/null @@ -1,286 +0,0 @@ -package io.camunda.operate; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; -import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.apache.hc.core5.http.ClassicHttpRequest; -import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.io.entity.StringEntity; - -import io.camunda.operate.auth.AuthInterface; -import io.camunda.operate.beta.CamundaOperateBetaClient; -import io.camunda.operate.dto.FlownodeInstance; -import io.camunda.operate.dto.Incident; -import io.camunda.operate.dto.ProcessDefinition; -import io.camunda.operate.dto.ProcessInstance; -import io.camunda.operate.dto.SearchResult; -import io.camunda.operate.dto.Variable; -import io.camunda.operate.exception.OperateException; -import io.camunda.operate.search.SearchQuery; -import io.camunda.operate.util.Java8Utils; -import io.camunda.operate.util.JsonUtils; -import io.camunda.operate.util.QueryValidatorUtils; -import io.camunda.zeebe.model.bpmn.Bpmn; -import io.camunda.zeebe.model.bpmn.BpmnModelInstance; - -public class CamundaOperateClient { - - private AuthInterface authentication; - - private String operateUrl; - - private Header authHeader; - - private int tokenExpiration; - - public ProcessDefinition getProcessDefinition(Long key) throws OperateException { - return get(key, ProcessDefinition.class); - } - - public List searchProcessDefinitions(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, ProcessDefinition.class); - return search(query, ProcessDefinition.class).getItems(); - } - - public SearchResult searchProcessDefinitionResults(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, ProcessDefinition.class); - return search(query, ProcessDefinition.class); - } - - public String getProcessDefinitionXml(Long key) throws OperateException { - String url = operateUrl + CamundaOperateConstants.OBJECT_APIS.get(ProcessDefinition.class) + "/" + key + "/xml"; - - HttpGet httpGet = new HttpGet(url); - httpGet.addHeader(authHeader); - - try { - return executeQuery(httpGet); - } catch (OperateException e) { - throw new OperateException("Error get Process Definition XML for " + key, e); - } - } - - public BpmnModelInstance getProcessDefinitionModel(Long key) throws OperateException { - String url = operateUrl + CamundaOperateConstants.OBJECT_APIS.get(ProcessDefinition.class) + "/" + key + "/xml"; - - HttpGet httpGet = new HttpGet(url); - httpGet.addHeader(authHeader); - - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - try (CloseableHttpResponse response = execute(httpClient, httpGet)) { - InputStream processInputStream = new ByteArrayInputStream( - Java8Utils.readAllBytes(response.getEntity().getContent())); - return Bpmn.readModelFromStream(processInputStream); - } - } catch (IOException e) { - throw new OperateException(e); - } - } - public CloseableHttpResponse execute(CloseableHttpClient httpClient, ClassicHttpRequest request) throws IOException, OperateException { - return execute(httpClient, request, 0); - } - private CloseableHttpResponse execute(CloseableHttpClient httpClient, ClassicHttpRequest request, int count) throws IOException, OperateException { - CloseableHttpResponse response = httpClient.execute(request); - if (response.getCode()==401 && count<=2) { - authentication.authenticate(this); - request.setHeader(authHeader); - return execute(httpClient, request, ++count); - } - if (response.getCode()>399) { - throw createDetailedException(response, request); - } - return response; - } - - private OperateException createDetailedException(CloseableHttpResponse response, ClassicHttpRequest request) throws IOException { - return new OperateException(request.getPath()+" : "+response.getCode()+" "+response.getReasonPhrase()); - } - - public ProcessInstance getProcessInstance(Long key) throws OperateException { - return get(key, ProcessInstance.class); - } - - public List searchProcessInstances(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, ProcessInstance.class); - return search(query, ProcessInstance.class).getItems(); - } - - public SearchResult searchProcessInstanceResults(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, ProcessInstance.class); - return search(query, ProcessInstance.class); - } - - public FlownodeInstance getFlownodeInstance(Long key) throws OperateException { - return get(key, FlownodeInstance.class); - } - - public List searchFlownodeInstances(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, FlownodeInstance.class); - return search(query, FlownodeInstance.class).getItems(); - } - - public SearchResult searchFlownodeInstanceResults(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, FlownodeInstance.class); - return search(query, FlownodeInstance.class); - } - - public Incident getIncident(Long key) throws OperateException { - return get(key, Incident.class); - } - - public List searchIncidents(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, Incident.class); - return search(query, Incident.class).getItems(); - } - - public SearchResult searchIncidentResults(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, Incident.class); - return search(query, Incident.class); - } - - public Variable getVariable(Long key) throws OperateException { - return get(key, Variable.class); - } - - public List searchVariables(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, Variable.class); - return search(query, Variable.class).getItems(); - } - - public SearchResult searchVariableResults(SearchQuery query) throws OperateException { - QueryValidatorUtils.verifyQuery(query, Variable.class); - return search(query, Variable.class); - } - - public SearchResult search(SearchQuery query, Class resultType) throws OperateException { - if (query==null || resultType==null) { - throw new OperateException("Query and resultType shouldn't be null"); - } - HttpPost httpPost = new HttpPost(operateUrl + CamundaOperateConstants.OBJECT_APIS.get(resultType) + "/search"); - httpPost.addHeader("Content-Type", "application/json"); - httpPost.addHeader(authHeader); - - try { - String data = JsonUtils.toJson(query); - httpPost.setEntity(new StringEntity(data)); - return JsonUtils.toSearchResult(executeQuery(httpPost), resultType); - } catch (IOException e) { - throw new OperateException("Error executing the SearchQuery", e); - } - } - - private T get(Long key, Class resultType) throws OperateException { - if (key==null || resultType==null) { - throw new OperateException("Key and resultType shouldn't be null"); - } - String url = operateUrl + CamundaOperateConstants.OBJECT_APIS.get(resultType) + "/" + key; - HttpGet httpGet = new HttpGet(url); - httpGet.addHeader("Content-Type", "application/json"); - httpGet.addHeader(authHeader); - - try { - return JsonUtils.toResult(executeQuery(httpGet), resultType); - } catch (IOException e) { - throw new OperateException("Error executing get for (key : " + key + ")" + resultType.getName() + " on "+url, - e); - } - } - - protected String executeQuery(ClassicHttpRequest httpRequest) throws OperateException { - reconnectEventually(); - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - try (CloseableHttpResponse response = execute(httpClient, httpRequest)) { - return new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8); - } - } catch (IOException e) { - throw new OperateException(e); - } - } - - public String getOperateUrl() { - return operateUrl; - } - - public void setOperateUrl(String operateUrl) { - this.operateUrl = operateUrl; - } - - public Header getAuthHeader() { - return authHeader; - } - - public void setAuthHeader(Header authHeader) { - this.authHeader = authHeader; - } - - public void setTokenExpiration(int tokenExpiration) { - this.tokenExpiration = tokenExpiration; - } - - private void reconnectEventually() throws OperateException { - if (this.tokenExpiration>0 && this.tokenExpiration<(System.currentTimeMillis()/1000-3)) { - authentication.authenticate(this); - } - } - - public static class Builder { - - private AuthInterface authentication; - - private String operateUrl; - - private boolean beta; - - public Builder() { - - } - - public Builder beta() { - beta = true; - return this; - } - - public Builder authentication(AuthInterface authentication) { - this.authentication = authentication; - return this; - } - - public Builder operateUrl(String operateUrl) { - this.operateUrl = formatUrl(operateUrl); - return this; - } - - public CamundaOperateClient build() throws OperateException { - CamundaOperateClient client; - if (beta) { - client = new CamundaOperateBetaClient(); - } else { - client = new CamundaOperateClient(); - } - client.authentication = authentication; - client.operateUrl = operateUrl; - authentication.authenticate(client); - return client; - } - - private String formatUrl(String url) { - if (url.endsWith("/")) { - return url.substring(0, url.length()-1); - } - return url; - } - } - - -} diff --git a/src/main/java/io/camunda/operate/CamundaOperateConstants.java b/src/main/java/io/camunda/operate/CamundaOperateConstants.java deleted file mode 100644 index 6323b89..0000000 --- a/src/main/java/io/camunda/operate/CamundaOperateConstants.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.camunda.operate; - -import java.util.Map; - -import io.camunda.operate.dto.FlownodeInstance; -import io.camunda.operate.dto.Incident; -import io.camunda.operate.dto.ProcessDefinition; -import io.camunda.operate.dto.ProcessInstance; -import io.camunda.operate.dto.Variable; -import io.camunda.operate.util.Java8Utils; - -public class CamundaOperateConstants { - - public static Map, String> OBJECT_APIS = Java8Utils.toMap(ProcessDefinition.class, "/v1/process-definitions", - ProcessInstance.class, "/v1/process-instances", - FlownodeInstance.class, "/v1/flownode-instances", - Incident.class, "/v1/incidents", - Variable.class, "/v1/variables"); - -} diff --git a/src/main/java/io/camunda/operate/auth/AuthInterface.java b/src/main/java/io/camunda/operate/auth/AuthInterface.java deleted file mode 100644 index c018bec..0000000 --- a/src/main/java/io/camunda/operate/auth/AuthInterface.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.camunda.operate.auth; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.exception.OperateException; - -public interface AuthInterface { - public void authenticate(CamundaOperateClient client) throws OperateException; -} diff --git a/src/main/java/io/camunda/operate/auth/JwtAuthentication.java b/src/main/java/io/camunda/operate/auth/JwtAuthentication.java deleted file mode 100644 index 5f706c5..0000000 --- a/src/main/java/io/camunda/operate/auth/JwtAuthentication.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.camunda.operate.auth; - -import java.util.Base64; - -import org.apache.hc.core5.http.message.BasicHeader; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.exception.OperateException; - -public abstract class JwtAuthentication implements AuthInterface { - - private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final Base64.Decoder DECODER = Base64.getUrlDecoder(); - - public int getExpiration(String token) throws OperateException { - try { - String[] chunks = token.split("\\."); - String payload = new String(DECODER.decode(chunks[1])); - JsonNode jsonPayload = MAPPER.readValue(payload, JsonNode.class); - JsonNode exp = jsonPayload.get("exp"); - if (exp==null) { - return 0; - } else { - return exp.asInt(); - } - } catch (JsonProcessingException e) { - throw new OperateException("Token is not readable", e); - } - } - - public void setToken(CamundaOperateClient client, String token) throws OperateException { - client.setAuthHeader(new BasicHeader("Authorization", "Bearer " + token)); - client.setTokenExpiration(getExpiration(token)); - } -} diff --git a/src/main/java/io/camunda/operate/auth/LocalIdentityAuthentication.java b/src/main/java/io/camunda/operate/auth/LocalIdentityAuthentication.java deleted file mode 100644 index 9b702d9..0000000 --- a/src/main/java/io/camunda/operate/auth/LocalIdentityAuthentication.java +++ /dev/null @@ -1,98 +0,0 @@ -package io.camunda.operate.auth; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; - -import com.fasterxml.jackson.databind.JsonNode; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.exception.OperateException; -import io.camunda.operate.util.JsonUtils; - -/** - * This Class is used to authenticate against a Self-Managed Camunda 8 Operate. - * @deprecated replaced by {@link io.camunda.operate.auth.SelfManagedAuthentication} - */ -@Deprecated -public class LocalIdentityAuthentication extends JwtAuthentication { - - private String clientId; - private String clientSecret; - private String baseUrl = "http://localhost:18080"; - private String keycloakRealm = "camunda-platform"; - - public LocalIdentityAuthentication() { - } - - public LocalIdentityAuthentication(String clientId, String clientSecret) { - this.clientId = clientId; - this.clientSecret = clientSecret; - } - - public LocalIdentityAuthentication clientId(String clientId) { - this.clientId = clientId; - return this; - } - public LocalIdentityAuthentication clientSecret(String clientSecret) { - this.clientSecret = clientSecret; - return this; - } - public LocalIdentityAuthentication baseUrl(String url) { - this.baseUrl = url; - return this; - } - public LocalIdentityAuthentication keycloakRealm(String keycloakRealm) { - this.keycloakRealm = keycloakRealm; - return this; - } - - private String encode(String value) throws UnsupportedEncodingException { - return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); - } - - private String getConnectionString() throws UnsupportedEncodingException{ - return "grant_type=client_credentials&client_id="+encode(clientId)+"&client_secret="+encode(clientSecret); - } - - @Override - public void authenticate(CamundaOperateClient client) throws OperateException { - try { - URL url = new URL(this.baseUrl+"/auth/realms/"+keycloakRealm+"/protocol/openid-connect/token"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setUseCaches(false); - conn.setConnectTimeout(1000 * 5); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - - String data = getConnectionString(); - - conn.getOutputStream().write(data.getBytes(StandardCharsets.UTF_8)); - conn.connect(); - - if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) { - StringBuilder response = new StringBuilder(); - String responseLine = null; - while ((responseLine = br.readLine()) != null) { - response.append(responseLine.trim()); - } - JsonNode responseBody = JsonUtils.toJsonNode(response.toString()); - String token = responseBody.get("access_token").asText(); - setToken(client, token); - } - } else { - throw new OperateException("Error "+conn.getResponseCode()+" obtaining access token : "+conn.getResponseMessage()); - } - } catch (IOException e) { - throw new OperateException(e); - } - } -} diff --git a/src/main/java/io/camunda/operate/auth/SaasAuthentication.java b/src/main/java/io/camunda/operate/auth/SaasAuthentication.java deleted file mode 100644 index 3c54d1d..0000000 --- a/src/main/java/io/camunda/operate/auth/SaasAuthentication.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.camunda.operate.auth; - -import java.io.IOException; - -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; -import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.apache.hc.core5.http.io.entity.StringEntity; - -import com.fasterxml.jackson.databind.JsonNode; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.exception.OperateException; -import io.camunda.operate.util.JsonUtils; - -public class SaasAuthentication extends JwtAuthentication { - - private String clientId; - private String clientSecret; - - private String baseUrl; - private String authUrl; - - public SaasAuthentication(String clientId, String clientSecret) { - this.clientId = clientId; - this.clientSecret = clientSecret; - - this.authUrl = "https://login.cloud.camunda.io/oauth/token"; - this.baseUrl = "operate.camunda.io"; - } - - public SaasAuthentication(String authUrl, String baseUrl, String clientId, String clientSecret) { - this.clientId = clientId; - this.clientSecret = clientSecret; - this.baseUrl = baseUrl; - this.authUrl = authUrl; - } - - @Override - public void authenticate(CamundaOperateClient client) throws OperateException { - - HttpPost httpPost = new HttpPost(authUrl); - httpPost.addHeader("Content-Type", "application/json"); - - String data = "{\"grant_type\":\"client_credentials\", \"audience\":\"" + baseUrl + "\", \"client_id\": \"" - + clientId + "\", \"client_secret\":\"" + clientSecret + "\"}"; - httpPost.setEntity(new StringEntity(data)); - - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - try (CloseableHttpResponse response = client.execute(httpClient, httpPost)) { - JsonNode responseBody = JsonUtils.toJsonNode(response.getEntity().getContent()); - String token = responseBody.get("access_token").asText(); - - setToken(client, token); - } - } catch (IOException e) { - throw new OperateException(e); - } - } -} diff --git a/src/main/java/io/camunda/operate/auth/SelfManagedAuthentication.java b/src/main/java/io/camunda/operate/auth/SelfManagedAuthentication.java deleted file mode 100644 index 6baf765..0000000 --- a/src/main/java/io/camunda/operate/auth/SelfManagedAuthentication.java +++ /dev/null @@ -1,105 +0,0 @@ -package io.camunda.operate.auth; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; - -import com.fasterxml.jackson.databind.JsonNode; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.exception.OperateException; -import io.camunda.operate.util.JsonUtils; - -/** - * This Class is used to authenticate against a Self-Managed Camunda 8 Operate. - */ -public class SelfManagedAuthentication extends JwtAuthentication { - - private String clientId; - private String clientSecret; - private String keycloakUrl = "http://localhost:18080"; - private String keycloakRealm = "camunda-platform"; - private String keycloakTokenUrl = null; - - public SelfManagedAuthentication() { - } - - public SelfManagedAuthentication(String clientId, String clientSecret) { - this.clientId = clientId; - this.clientSecret = clientSecret; - } - - public SelfManagedAuthentication clientId(String clientId) { - this.clientId = clientId; - return this; - } - public SelfManagedAuthentication clientSecret(String clientSecret) { - this.clientSecret = clientSecret; - return this; - } - public SelfManagedAuthentication keycloakUrl(String url) { - this.keycloakUrl = url; - return this; - } - public SelfManagedAuthentication keycloakRealm(String keycloakRealm) { - this.keycloakRealm = keycloakRealm; - return this; - } - public SelfManagedAuthentication keycloakTokenUrl(String keycloakTokenUrl) { - this.keycloakTokenUrl = keycloakTokenUrl; - return this; - } - - private String encode(String value) throws UnsupportedEncodingException { - return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); - } - - private String getConnectionString() throws UnsupportedEncodingException{ - return "grant_type=client_credentials&client_id="+encode(clientId)+"&client_secret="+encode(clientSecret); - } - - @Override - public void authenticate(CamundaOperateClient client) throws OperateException { - try { - String tokenUrl = keycloakTokenUrl; - if (tokenUrl==null || tokenUrl.equals("")) { - tokenUrl=this.keycloakUrl+"/auth/realms/"+keycloakRealm+"/protocol/openid-connect/token"; - } - URL url = new URL(tokenUrl); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setUseCaches(false); - conn.setConnectTimeout(1000 * 5); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - - String data = getConnectionString(); - - conn.getOutputStream().write(data.getBytes(StandardCharsets.UTF_8)); - conn.connect(); - - if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) { - StringBuilder response = new StringBuilder(); - String responseLine = null; - while ((responseLine = br.readLine()) != null) { - response.append(responseLine.trim()); - } - JsonNode responseBody = JsonUtils.toJsonNode(response.toString()); - String token = responseBody.get("access_token").asText(); - setToken(client, token); - } - } else { - throw new OperateException("Error "+conn.getResponseCode()+" obtaining access token : "+conn.getResponseMessage()); - } - } catch (IOException e) { - throw new OperateException(e); - } - } -} diff --git a/src/main/java/io/camunda/operate/auth/SimpleAuthentication.java b/src/main/java/io/camunda/operate/auth/SimpleAuthentication.java deleted file mode 100644 index a64f1b1..0000000 --- a/src/main/java/io/camunda/operate/auth/SimpleAuthentication.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.camunda.operate.auth; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; -import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.apache.hc.core5.http.NameValuePair; -import org.apache.hc.core5.http.ProtocolException; -import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.hc.core5.http.message.BasicNameValuePair; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.exception.OperateException; - -/** - * To use if Operate is not configured with Identity and Keycloak - */ -public class SimpleAuthentication implements AuthInterface { - - private String operateUsername; - - private String operatePassword; - - private String operateUrl; - - public SimpleAuthentication(String operateUsername, String operatePassword, String operateUrl) { - this.operateUsername = operateUsername; - this.operatePassword = operatePassword; - this.operateUrl = operateUrl; - } - - @Override - public void authenticate(CamundaOperateClient client) throws OperateException { - - HttpPost httpPost = new HttpPost(operateUrl + "/api/login"); - - List params = new ArrayList(); - params.add(new BasicNameValuePair("username", operateUsername)); - params.add(new BasicNameValuePair("password", operatePassword)); - httpPost.setEntity(new UrlEncodedFormEntity(params)); - - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - try (CloseableHttpResponse response = httpClient.execute(httpPost)) { - String cookie = response.getHeader("Set-Cookie").getValue(); - - client.setAuthHeader(new BasicHeader("Cookie", cookie)); - } - } catch (IOException | ProtocolException e) { - throw new OperateException(e); - } - } -} diff --git a/src/main/java/io/camunda/operate/beta/CamundaOperateBetaClient.java b/src/main/java/io/camunda/operate/beta/CamundaOperateBetaClient.java deleted file mode 100644 index d96c949..0000000 --- a/src/main/java/io/camunda/operate/beta/CamundaOperateBetaClient.java +++ /dev/null @@ -1,102 +0,0 @@ -package io.camunda.operate.beta; - -import java.io.IOException; -import java.util.ArrayList; - -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.core5.http.io.entity.StringEntity; - -import com.fasterxml.jackson.databind.JsonNode; - -import io.camunda.operate.CamundaOperateClient; -import io.camunda.operate.beta.model.AuditTrail; -import io.camunda.operate.beta.model.AuditTrailStep; -import io.camunda.operate.beta.model.FlowNodeInstanceQueryList; -import io.camunda.operate.dto.ProcessInstance; -import io.camunda.operate.exception.OperateException; -import io.camunda.operate.util.JsonUtils; -import io.camunda.zeebe.model.bpmn.BpmnModelInstance; - -/** - * Beta client to use undocumented APIs that could not be compatible in future releases - */ -public class CamundaOperateBetaClient extends CamundaOperateClient { - - /** - * working fine with SaaS version 8.0.0 or if you use the local setup without Keycloak and identity - */ - public JsonNode getFlowNodeStates(Long processInstanceId) throws OperateException { - String url = getOperateUrl()+"/api/process-instances/"+processInstanceId+"/flow-node-states"; - HttpGet httpPost = new HttpGet(url); - httpPost.addHeader(getAuthHeader()); - httpPost.addHeader("content-type", "application/json"); - - try { - - return JsonUtils.toJsonNode(executeQuery(httpPost)); - } catch(IOException e) { - throw new OperateException("BETA : Error getting FlowNodeInstances", e); - } - } - - /** - * working fine with SaaS version 8.0.0 or if you use the local setup without Keycloak and identity - */ - public JsonNode getFlowNodeInstances(Long processInstanceId) throws OperateException { - String url = getOperateUrl()+"/api/flow-node-instances"; - FlowNodeInstanceQueryList query = new FlowNodeInstanceQueryList.Builder().processInstanceId(processInstanceId).build(); - - HttpPost httpPost = new HttpPost(url); - httpPost.addHeader(getAuthHeader()); - httpPost.addHeader("content-type", "application/json"); - try { - String data = JsonUtils.toJson(query); - httpPost.setEntity(new StringEntity(data)); - - return JsonUtils.toJsonNode(executeQuery(httpPost)); - } catch(IOException e) { - throw new OperateException("BETA : Error getting FlowNodeInstances", e); - } - } - - /** - * working fine with SaaS version 8.0.0 or if you use the local setup without Keycloak and identity - */ - public AuditTrail getAuditTrail(Long processInstanceId) throws OperateException { - - AuditTrail auditTrail = new AuditTrail(); - ProcessInstance processInstance = getProcessInstance(processInstanceId); - auditTrail.setProcessName(processInstance.getBpmnProcessId()); - auditTrail.setProcessVersion(processInstance.getProcessVersion()); - auditTrail.setSteps(new ArrayList<>()); - Long processDefinitionKey = processInstance.getProcessDefinitionKey(); - BpmnModelInstance bpmModel = getProcessDefinitionModel(processDefinitionKey); - - JsonNode flowNodeInstances = getFlowNodeInstances(processInstanceId); - JsonNode flowNodesChildren = flowNodeInstances.get(""+processInstanceId).get("children"); - if (flowNodesChildren.isArray()) { - for (JsonNode jsonNode : flowNodesChildren) { - String type = jsonNode.get("type").asText(); - if (!type.endsWith("GATEWAY")) { - AuditTrailStep auditTrailStep = new AuditTrailStep(); - String stepId = jsonNode.get("flowNodeId").asText(); - auditTrailStep.setName(bpmModel.getModelElementById(stepId).getAttributeValue("name")); - auditTrailStep.setType(type); - String startDate = jsonNode.get("startDate").asText(); - String endDate = jsonNode.get("endDate").asText(); - if (!startDate.equals("null")) { - auditTrailStep.setStartDate(startDate.substring(0,19)); - } - if (!endDate.equals("null")) { - auditTrailStep.setEndDate(endDate.substring(0,19)); - } else { - auditTrailStep.setEndDate("pending"); - } - auditTrail.getSteps().add(auditTrailStep); - } - } - } - return auditTrail; - } -} diff --git a/src/main/java/io/camunda/operate/beta/model/AuditTrail.java b/src/main/java/io/camunda/operate/beta/model/AuditTrail.java deleted file mode 100644 index 44a2eca..0000000 --- a/src/main/java/io/camunda/operate/beta/model/AuditTrail.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.camunda.operate.beta.model; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -@JsonInclude(Include.NON_NULL) -public class AuditTrail { - - private String processName; - private Long processVersion; - public String getProcessName() { - return processName; - } - - public void setProcessName(String processName) { - this.processName = processName; - } - - public Long getProcessVersion() { - return processVersion; - } - - public void setProcessVersion(Long processVersion) { - this.processVersion = processVersion; - } - - private List steps; - - public List getSteps() { - return steps; - } - - public void setSteps(List steps) { - this.steps = steps; - } - -} diff --git a/src/main/java/io/camunda/operate/beta/model/AuditTrailStep.java b/src/main/java/io/camunda/operate/beta/model/AuditTrailStep.java deleted file mode 100644 index c3eecf5..0000000 --- a/src/main/java/io/camunda/operate/beta/model/AuditTrailStep.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.camunda.operate.beta.model; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -@JsonInclude(Include.NON_NULL) -public class AuditTrailStep { - private String name; - private String type; - private String startDate; - private String endDate; - private String assignee; - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public String getStartDate() { - return startDate; - } - public void setStartDate(String startDate) { - this.startDate = startDate; - } - public String getEndDate() { - return endDate; - } - public void setEndDate(String endDate) { - this.endDate = endDate; - } - public String getAssignee() { - return assignee; - } - public void setAssignee(String assignee) { - this.assignee = assignee; - } -} diff --git a/src/main/java/io/camunda/operate/beta/model/FlowNodeInstanceQuery.java b/src/main/java/io/camunda/operate/beta/model/FlowNodeInstanceQuery.java deleted file mode 100644 index 849d7e9..0000000 --- a/src/main/java/io/camunda/operate/beta/model/FlowNodeInstanceQuery.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.camunda.operate.beta.model; - -public class FlowNodeInstanceQuery { - - private Long treePath; - - private Long processInstanceId; - - private int pageSize; - - public int getPageSize() { - return pageSize; - } - - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - - public Long getTreePath() { - return treePath; - } - - public void setTreePath(Long treePath) { - this.treePath = treePath; - } - - public Long getProcessInstanceId() { - return processInstanceId; - } - - public void setProcessInstanceId(Long processInstanceId) { - this.processInstanceId = processInstanceId; - } - - -} diff --git a/src/main/java/io/camunda/operate/beta/model/FlowNodeInstanceQueryList.java b/src/main/java/io/camunda/operate/beta/model/FlowNodeInstanceQueryList.java deleted file mode 100644 index 5580b4d..0000000 --- a/src/main/java/io/camunda/operate/beta/model/FlowNodeInstanceQueryList.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.camunda.operate.beta.model; - -import java.util.Arrays; -import java.util.List; - -public class FlowNodeInstanceQueryList { - - private List queries; - - public List getQueries() { - return queries; - } - - public void setQueries(List queries) { - this.queries = queries; - } - public static class Builder { - - private Long processInstanceId; - - public Builder processInstanceId(Long processInstanceId) { - this.processInstanceId = processInstanceId; - return this; - } - - public FlowNodeInstanceQueryList build() { - FlowNodeInstanceQuery flowNodeInstanceQuery = new FlowNodeInstanceQuery(); - FlowNodeInstanceQueryList flowNodeInstanceQueryList = new FlowNodeInstanceQueryList(); - flowNodeInstanceQuery.setProcessInstanceId(processInstanceId); - flowNodeInstanceQuery.setTreePath(processInstanceId); - flowNodeInstanceQuery.setPageSize(100); - flowNodeInstanceQueryList.queries=Arrays.asList(flowNodeInstanceQuery); - return flowNodeInstanceQueryList; - } - } -} diff --git a/src/main/java/io/camunda/operate/dto/FlownodeInstance.java b/src/main/java/io/camunda/operate/dto/FlownodeInstance.java deleted file mode 100644 index ce0b649..0000000 --- a/src/main/java/io/camunda/operate/dto/FlownodeInstance.java +++ /dev/null @@ -1,90 +0,0 @@ -package io.camunda.operate.dto; - -import java.util.Date; - -public class FlownodeInstance { - private Long key; - private Long processInstanceKey; - private Long processDefinitionKey; - private Date startDate; - private Date endDate; - private String flowNodeId; - private String flowNodeName; - private Long incidentKey; - private String type; - private FlownodeInstanceState state; - private Boolean incident; - private String tenantId; - public Long getKey() { - return key; - } - public void setKey(Long key) { - this.key = key; - } - public Long getProcessInstanceKey() { - return processInstanceKey; - } - public void setProcessInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - } - public Long getProcessDefinitionKey() { - return processDefinitionKey; - } - public void setProcessDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - } - public Date getStartDate() { - return startDate; - } - public void setStartDate(Date startDate) { - this.startDate = startDate; - } - public Date getEndDate() { - return endDate; - } - public void setEndDate(Date endDate) { - this.endDate = endDate; - } - public String getFlowNodeId() { - return flowNodeId; - } - public void setFlowNodeId(String flowNodeId) { - this.flowNodeId = flowNodeId; - } - public String getFlowNodeName() { - return flowNodeName; - } - public void setFlowNodeName(String flowNodeName) { - this.flowNodeName = flowNodeName; - } - public Long getIncidentKey() { - return incidentKey; - } - public void setIncidentKey(Long incidentKey) { - this.incidentKey = incidentKey; - } - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public FlownodeInstanceState getState() { - return state; - } - public void setState(FlownodeInstanceState state) { - this.state = state; - } - public Boolean getIncident() { - return incident; - } - public void setIncident(Boolean incident) { - this.incident = incident; - } - public String getTenantId() { - return tenantId; - } - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } -} diff --git a/src/main/java/io/camunda/operate/dto/FlownodeInstanceState.java b/src/main/java/io/camunda/operate/dto/FlownodeInstanceState.java deleted file mode 100644 index ef4b0c3..0000000 --- a/src/main/java/io/camunda/operate/dto/FlownodeInstanceState.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.camunda.operate.dto; - -public enum FlownodeInstanceState { - ACTIVE, INCIDENT, COMPLETED, TERMINATED; -} diff --git a/src/main/java/io/camunda/operate/dto/Incident.java b/src/main/java/io/camunda/operate/dto/Incident.java deleted file mode 100644 index 87b2214..0000000 --- a/src/main/java/io/camunda/operate/dto/Incident.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.camunda.operate.dto; - -import java.util.Date; - -public class Incident { - private Long key; - private Long processDefinitionKey; - private Long processInstanceKey; - private String type; - private String message; - private Date creationTime; - private String state; - private String tenantId; - public Long getKey() { - return key; - } - public void setKey(Long key) { - this.key = key; - } - public Long getProcessDefinitionKey() { - return processDefinitionKey; - } - public void setProcessDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - } - public Long getProcessInstanceKey() { - return processInstanceKey; - } - public void setProcessInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - } - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public String getMessage() { - return message; - } - public void setMessage(String message) { - this.message = message; - } - public Date getCreationTime() { - return creationTime; - } - public void setCreationTime(Date creationTime) { - this.creationTime = creationTime; - } - public String getState() { - return state; - } - public void setState(String state) { - this.state = state; - } - public String getTenantId() { - return tenantId; - } - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } -} diff --git a/src/main/java/io/camunda/operate/dto/ProcessDefinition.java b/src/main/java/io/camunda/operate/dto/ProcessDefinition.java deleted file mode 100644 index d2a2d00..0000000 --- a/src/main/java/io/camunda/operate/dto/ProcessDefinition.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.camunda.operate.dto; - -public class ProcessDefinition { - private Long key; - private String name; - private Long version; - private String bpmnProcessId; - private String tenantId; - public Long getKey() { - return key; - } - public void setKey(Long key) { - this.key = key; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public Long getVersion() { - return version; - } - public void setVersion(Long version) { - this.version = version; - } - public String getBpmnProcessId() { - return bpmnProcessId; - } - public void setBpmnProcessId(String bpmnProcessId) { - this.bpmnProcessId = bpmnProcessId; - } - public String getTenantId() { - return tenantId; - } - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } -} diff --git a/src/main/java/io/camunda/operate/dto/ProcessInstance.java b/src/main/java/io/camunda/operate/dto/ProcessInstance.java deleted file mode 100644 index 22f775e..0000000 --- a/src/main/java/io/camunda/operate/dto/ProcessInstance.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.camunda.operate.dto; - -import java.util.Date; - -public class ProcessInstance { - private Long key; - private Long processVersion; - private String bpmnProcessId; - private Long parentKey; - private Date startDate; - private Date endDate; - private ProcessInstanceState state; - private Long processDefinitionKey; - private String tenantId; - - public Long getKey() { - return key; - } - - public void setKey(Long key) { - this.key = key; - } - - public Long getProcessVersion() { - return processVersion; - } - - public void setProcessVersion(Long processVersion) { - this.processVersion = processVersion; - } - - public String getBpmnProcessId() { - return bpmnProcessId; - } - - public void setBpmnProcessId(String bpmnProcessId) { - this.bpmnProcessId = bpmnProcessId; - } - - public Long getParentKey() { - return parentKey; - } - - public void setParentKey(Long parentKey) { - this.parentKey = parentKey; - } - - public Date getStartDate() { - return startDate; - } - - public void setStartDate(Date startDate) { - this.startDate = startDate; - } - - public Date getEndDate() { - return endDate; - } - - public void setEndDate(Date endDate) { - this.endDate = endDate; - } - - public ProcessInstanceState getState() { - return state; - } - - public void setState(ProcessInstanceState state) { - this.state = state; - } - - public Long getProcessDefinitionKey() { - return processDefinitionKey; - } - - public void setProcessDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - } - - public String getTenantId() { - return tenantId; - } - - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } -} diff --git a/src/main/java/io/camunda/operate/dto/ProcessInstanceState.java b/src/main/java/io/camunda/operate/dto/ProcessInstanceState.java deleted file mode 100644 index 3768957..0000000 --- a/src/main/java/io/camunda/operate/dto/ProcessInstanceState.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.camunda.operate.dto; - -public enum ProcessInstanceState { - ACTIVE, COMPLETED, CANCELED; -} diff --git a/src/main/java/io/camunda/operate/dto/SearchResult.java b/src/main/java/io/camunda/operate/dto/SearchResult.java deleted file mode 100644 index fa22933..0000000 --- a/src/main/java/io/camunda/operate/dto/SearchResult.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.camunda.operate.dto; - -import java.util.Iterator; -import java.util.List; - -public class SearchResult implements Iterable{ - - private List items; - - private Integer total; - - private List sortValues; - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } - - public Integer getTotal() { - return total; - } - - public void setTotal(Integer total) { - this.total = total; - } - - public List getSortValues() { - return sortValues; - } - - public void setSortValues(List sortValues) { - this.sortValues = sortValues; - } - - public Iterator iterator() { - return this.items.iterator(); - } -} diff --git a/src/main/java/io/camunda/operate/dto/Variable.java b/src/main/java/io/camunda/operate/dto/Variable.java deleted file mode 100644 index 6a169e3..0000000 --- a/src/main/java/io/camunda/operate/dto/Variable.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.camunda.operate.dto; - -public class Variable { - private Long key; - - private Long processInstanceKey; - - private Long scopeKey; - - private String name; - - private String value; - - private Boolean truncated; - - private String tenantId; - - public Long getKey() { - return key; - } - - public void setKey(Long key) { - this.key = key; - } - - public Long getProcessInstanceKey() { - return processInstanceKey; - } - - public void setProcessInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - } - - public Long getScopeKey() { - return scopeKey; - } - - public void setScopeKey(Long scopeKey) { - this.scopeKey = scopeKey; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Boolean getTruncated() { - return truncated; - } - - public void setTruncated(Boolean truncated) { - this.truncated = truncated; - } - - public String getTenantId() { - return tenantId; - } - - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } -} diff --git a/src/main/java/io/camunda/operate/exception/OperateException.java b/src/main/java/io/camunda/operate/exception/OperateException.java deleted file mode 100644 index 2e71548..0000000 --- a/src/main/java/io/camunda/operate/exception/OperateException.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.camunda.operate.exception; - -public class OperateException extends Exception { - - /** - * - */ - private static final long serialVersionUID = -7593616210087047797L; - - public OperateException() { - super(); - } - - public OperateException(Exception e) { - super(e); - } - - public OperateException(String message) { - super(message); - } - - public OperateException(String message, Exception e) { - super(message, e); - } -} \ No newline at end of file diff --git a/src/main/java/io/camunda/operate/search/DateFilter.java b/src/main/java/io/camunda/operate/search/DateFilter.java deleted file mode 100644 index bd1cd65..0000000 --- a/src/main/java/io/camunda/operate/search/DateFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.camunda.operate.search; - -import java.util.Date; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -@JsonSerialize(using = DateFilterSerializer.class) -public class DateFilter { - - private Date date; - - private DateFilterRange range; - - public DateFilter(Date date, DateFilterRange range) { - super(); - this.date = date; - this.range = range; - } - - public DateFilter(Date date) { - this(date, DateFilterRange.SECOND); - } - - public DateFilter() { - this(new Date()); - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - public DateFilterRange getRange() { - return range; - } - - public void setRange(DateFilterRange range) { - this.range = range; - } - -} diff --git a/src/main/java/io/camunda/operate/search/DateFilterRange.java b/src/main/java/io/camunda/operate/search/DateFilterRange.java deleted file mode 100644 index b49942c..0000000 --- a/src/main/java/io/camunda/operate/search/DateFilterRange.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.camunda.operate.search; - -public enum DateFilterRange { - YEAR("y"), MONTH("M"), WEEK("w"), DAY("d"), HOUR("h"), MINUTE("m"), SECOND("s"); - - private String value; - - DateFilterRange(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - -} diff --git a/src/main/java/io/camunda/operate/search/DateFilterSerializer.java b/src/main/java/io/camunda/operate/search/DateFilterSerializer.java deleted file mode 100644 index 7272d29..0000000 --- a/src/main/java/io/camunda/operate/search/DateFilterSerializer.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.camunda.operate.search; - -import java.io.IOException; -import java.text.SimpleDateFormat; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; - -public class DateFilterSerializer extends StdSerializer { - - public static SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ"); - - /** - * serial version uid - */ - private static final long serialVersionUID = -8106244922585465120L; - - public DateFilterSerializer() { - super(DateFilter.class); - } - - @Override - public void serialize(DateFilter value, JsonGenerator jgen, SerializerProvider provider) - throws IOException, JsonProcessingException { - - jgen.writeString(isoFormat.format(value.getDate()) + "||/" + value.getRange().getValue()); - } -} \ No newline at end of file diff --git a/src/main/java/io/camunda/operate/search/FlownodeInstanceFilter.java b/src/main/java/io/camunda/operate/search/FlownodeInstanceFilter.java deleted file mode 100644 index faa8c3a..0000000 --- a/src/main/java/io/camunda/operate/search/FlownodeInstanceFilter.java +++ /dev/null @@ -1,183 +0,0 @@ -package io.camunda.operate.search; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import io.camunda.operate.dto.FlownodeInstanceState; -import io.camunda.operate.exception.OperateException; - -@JsonInclude(Include.NON_NULL) -public class FlownodeInstanceFilter implements Filter { - private Long processInstanceKey; - private Long processDefinitionKey; - private Long incidentKey; - private String type; - private String flowNodeId; - private DateFilter startDate; - private DateFilter endDate; - private FlownodeInstanceState state; - private Boolean incident; - private String flowNodeName; - - public Long getProcessInstanceKey() { - return processInstanceKey; - } - - public void setProcessInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - } - - public Long getProcessDefinitionKey() { - return processDefinitionKey; - } - - public void setProcessDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - } - - public Long getIncidentKey() { - return incidentKey; - } - - public void setIncidentKey(Long incidentKey) { - this.incidentKey = incidentKey; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public DateFilter getStartDate() { - return startDate; - } - - public void setStartDate(DateFilter startDate) { - this.startDate = startDate; - } - - public DateFilter getEndDate() { - return endDate; - } - - public void setEndDate(DateFilter endDate) { - this.endDate = endDate; - } - - public String getFlowNodeId() { - return flowNodeId; - } - - public void setFlowNodeId(String flowNodeId) { - this.flowNodeId = flowNodeId; - } - - public FlownodeInstanceState getState() { - return state; - } - - public void setState(FlownodeInstanceState state) { - this.state = state; - } - - public Boolean getIncident() { - return incident; - } - - public void setIncident(Boolean incident) { - this.incident = incident; - } - - public String getFlowNodeName() { - return flowNodeName; - } - - public void setFlowNodeName(String flowNodeName) { - this.flowNodeName = flowNodeName; - } - - public static class Builder { - private Long processInstanceKey; - private Long processDefinitionKey; - private Long incidentKey; - private String type; - private DateFilter startDate; - private DateFilter endDate; - private String flowNodeId; - private FlownodeInstanceState state; - private Boolean incident; - private String flowNodeName; - - public Builder() { - super(); - } - - public Builder processInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - return this; - } - - public Builder processDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - return this; - } - - public Builder incidentKey(Long incidentKey) { - this.incidentKey = incidentKey; - return this; - } - - public Builder type(String type) { - this.type = type; - return this; - } - - public Builder startDate(DateFilter startDate) { - this.startDate = startDate; - return this; - } - - public Builder endDate(DateFilter endDate) { - this.endDate = endDate; - return this; - } - - public Builder flowNodeId(String flowNodeId) { - this.flowNodeId = flowNodeId; - return this; - } - - public Builder state(FlownodeInstanceState state) { - this.state = state; - return this; - } - - public Builder incident(Boolean incident) { - this.incident = incident; - return this; - } - - public Builder flowNodeName(String flowNodeName) { - this.flowNodeName = flowNodeName; - return this; - } - - public FlownodeInstanceFilter build() throws OperateException { - FlownodeInstanceFilter processInstanceFilter = new FlownodeInstanceFilter(); - processInstanceFilter.processInstanceKey = processInstanceKey; - processInstanceFilter.processDefinitionKey = processDefinitionKey; - processInstanceFilter.incidentKey = incidentKey; - processInstanceFilter.type = type; - processInstanceFilter.startDate = startDate; - processInstanceFilter.endDate = endDate; - processInstanceFilter.flowNodeId = flowNodeId; - processInstanceFilter.state = state; - processInstanceFilter.incident = incident; - processInstanceFilter.flowNodeName = flowNodeName; - return processInstanceFilter; - } - } -} diff --git a/src/main/java/io/camunda/operate/search/IncidentFilter.java b/src/main/java/io/camunda/operate/search/IncidentFilter.java deleted file mode 100644 index 94a3fa5..0000000 --- a/src/main/java/io/camunda/operate/search/IncidentFilter.java +++ /dev/null @@ -1,93 +0,0 @@ -package io.camunda.operate.search; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -@JsonInclude(Include.NON_NULL) -public class IncidentFilter implements Filter { - private Long processDefinitionKey; - private Long processInstanceKey; - private String type; - private String message; - private DateFilter creationTime; - private String state; - public Long getProcessDefinitionKey() { - return processDefinitionKey; - } - public void setProcessDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - } - public Long getProcessInstanceKey() { - return processInstanceKey; - } - public void setProcessInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - } - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public String getMessage() { - return message; - } - public void setMessage(String message) { - this.message = message; - } - public DateFilter getCreationTime() { - return creationTime; - } - public void setCreationTime(DateFilter creationTime) { - this.creationTime = creationTime; - } - public String getState() { - return state; - } - public void setState(String state) { - this.state = state; - } - - public static class Builder { - private Long processDefinitionKey; - private Long processInstanceKey; - private String type; - private String message; - private DateFilter creationTime; - private String state; - public Builder processDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - return this; - } - public Builder processInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - return this; - } - public Builder type(String type) { - this.type = type; - return this; - } - public Builder message(String message) { - this.message = message; - return this; - } - public Builder creationTime(DateFilter creationTime) { - this.creationTime = creationTime; - return this; - } - public Builder state(String state) { - this.state = state; - return this; - } - public IncidentFilter build() { - IncidentFilter incidentFilter = new IncidentFilter(); - incidentFilter.processDefinitionKey = processDefinitionKey; - incidentFilter.processInstanceKey = processInstanceKey; - incidentFilter.type = type; - incidentFilter.message = message; - incidentFilter.creationTime = creationTime; - incidentFilter.state = state; - return incidentFilter; - } - } -} diff --git a/src/main/java/io/camunda/operate/search/ProcessDefinitionFilter.java b/src/main/java/io/camunda/operate/search/ProcessDefinitionFilter.java deleted file mode 100644 index 661b978..0000000 --- a/src/main/java/io/camunda/operate/search/ProcessDefinitionFilter.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.camunda.operate.search; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import io.camunda.operate.exception.OperateException; - -@JsonInclude(Include.NON_NULL) -public class ProcessDefinitionFilter implements Filter { - private String name; - private Long version; - private String bpmnProcessId; - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public Long getVersion() { - return version; - } - public void setVersion(Long version) { - this.version = version; - } - public String getBpmnProcessId() { - return bpmnProcessId; - } - public void setBpmnProcessId(String bpmnProcessId) { - this.bpmnProcessId = bpmnProcessId; - } - - public static class Builder { - private String name; - private Long version; - private String bpmnProcessId; - - public Builder() { - super(); - } - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder version(Long version) { - this.version = version; - return this; - } - - public Builder bpmnProcessId(String bpmnProcessId) { - this.bpmnProcessId = bpmnProcessId; - return this; - } - - public ProcessDefinitionFilter build() throws OperateException { - ProcessDefinitionFilter processDefinitionFilter = new ProcessDefinitionFilter(); - processDefinitionFilter.name = name; - processDefinitionFilter.version = version; - processDefinitionFilter.bpmnProcessId = bpmnProcessId; - return processDefinitionFilter; - } - } -} diff --git a/src/main/java/io/camunda/operate/search/ProcessInstanceFilter.java b/src/main/java/io/camunda/operate/search/ProcessInstanceFilter.java deleted file mode 100644 index a118358..0000000 --- a/src/main/java/io/camunda/operate/search/ProcessInstanceFilter.java +++ /dev/null @@ -1,151 +0,0 @@ -package io.camunda.operate.search; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import io.camunda.operate.dto.ProcessInstanceState; -import io.camunda.operate.exception.OperateException; - -@JsonInclude(Include.NON_NULL) -public class ProcessInstanceFilter implements Filter { - private Long processVersion; - private String bpmnProcessId; - private Long parentKey; - private Long parentProcessInstanceKey; - private DateFilter startDate; - private DateFilter endDate; - private ProcessInstanceState state; - private Long processDefinitionKey; - - public Long getProcessVersion() { - return processVersion; - } - - public void setProcessVersion(Long processVersion) { - this.processVersion = processVersion; - } - - public String getBpmnProcessId() { - return bpmnProcessId; - } - - public void setBpmnProcessId(String bpmnProcessId) { - this.bpmnProcessId = bpmnProcessId; - } - - public Long getParentKey() { - return parentKey; - } - - public void setParentKey(Long parentKey) { - this.parentKey = parentKey; - } - - public Long getParentProcessInstanceKey() { - return parentProcessInstanceKey; - } - - public void setParentProcessInstanceKey(Long parentProcessInstanceKey) { - this.parentProcessInstanceKey = parentProcessInstanceKey; - } - - public DateFilter getStartDate() { - return startDate; - } - - public void setStartDate(DateFilter startDate) { - this.startDate = startDate; - } - - public DateFilter getEndDate() { - return endDate; - } - - public void setEndDate(DateFilter endDate) { - this.endDate = endDate; - } - - public ProcessInstanceState getState() { - return state; - } - - public void setState(ProcessInstanceState state) { - this.state = state; - } - - public Long getProcessDefinitionKey() { - return processDefinitionKey; - } - - public void setProcessDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - } - - public static class Builder { - private Long processVersion; - private String bpmnProcessId; - private Long parentKey; - private Long parentProcessInstanceKey; - private DateFilter startDate; - private DateFilter endDate; - private ProcessInstanceState state; - private Long processDefinitionKey; - - public Builder() { - super(); - } - - public Builder processVersion(Long processVersion) { - this.processVersion = processVersion; - return this; - } - - public Builder bpmnProcessId(String bpmnProcessId) { - this.bpmnProcessId = bpmnProcessId; - return this; - } - - public Builder parentKey(Long parentKey) { - this.parentKey = parentKey; - return this; - } - - public Builder parentProcessInstanceKey(Long parentProcessInstanceKey) { - this.parentProcessInstanceKey = parentProcessInstanceKey; - return this; - } - - public Builder startDate(DateFilter startDate) { - this.startDate = startDate; - return this; - } - - public Builder endDate(DateFilter endDate) { - this.endDate = endDate; - return this; - } - - public Builder state(ProcessInstanceState state) { - this.state = state; - return this; - } - - public Builder processDefinitionKey(Long processDefinitionKey) { - this.processDefinitionKey = processDefinitionKey; - return this; - } - - public ProcessInstanceFilter build() throws OperateException { - ProcessInstanceFilter processInstanceFilter = new ProcessInstanceFilter(); - processInstanceFilter.processVersion = processVersion; - processInstanceFilter.bpmnProcessId = bpmnProcessId; - processInstanceFilter.parentKey = parentKey; - processInstanceFilter.startDate = startDate; - processInstanceFilter.endDate = endDate; - processInstanceFilter.state = state; - processInstanceFilter.processDefinitionKey = processDefinitionKey; - processInstanceFilter.parentProcessInstanceKey = parentProcessInstanceKey; - return processInstanceFilter; - } - } -} diff --git a/src/main/java/io/camunda/operate/search/SearchQuery.java b/src/main/java/io/camunda/operate/search/SearchQuery.java deleted file mode 100644 index f8a97f8..0000000 --- a/src/main/java/io/camunda/operate/search/SearchQuery.java +++ /dev/null @@ -1,106 +0,0 @@ -package io.camunda.operate.search; - -import java.util.ArrayList; -import java.util.List; - -import io.camunda.operate.exception.OperateException; - -public class SearchQuery { - private Filter filter; - private Integer size; - private List sort; - private List searchAfter; - - public Filter getFilter() { - return filter; - } - - public void setFilter(Filter filter) { - this.filter = filter; - } - - public Integer getSize() { - return size; - } - - public void setSize(Integer size) { - this.size = size; - } - - public List getSort() { - return sort; - } - - public void setSort(List sort) { - this.sort = sort; - } - - public List getSearchAfter() { - return searchAfter; - } - - public void setSearchAfter(List searchAfter) { - this.searchAfter = searchAfter; - } - - public static class Builder { - - private Filter filter; - private Integer size; - private List sorts = new ArrayList<>(); - private List searchAfter=null; - - public Builder() { - - } - - @Deprecated - public Builder withFilter(Filter filter) { - this.filter = filter; - return this; - } - - public Builder filter(Filter filter) { - this.filter = filter; - return this; - } - - @Deprecated - public Builder withSize(Integer size) { - this.size = size; - return this; - } - - public Builder size(Integer size) { - this.size = size; - return this; - } - - @Deprecated - public Builder withSort(Sort sort) { - this.sorts.add(sort); - return this; - } - - public Builder sort(Sort sort) { - this.sorts.add(sort); - return this; - } - - public Builder searchAfter(List searchAfter) { - this.searchAfter=searchAfter; - return this; - } - - public SearchQuery build() throws OperateException { - SearchQuery query = new SearchQuery(); - query.filter = filter; - query.size = size; - query.searchAfter = searchAfter; - if (!sorts.isEmpty()) { - query.setSort(sorts); - } - return query; - } - } -} diff --git a/src/main/java/io/camunda/operate/search/Sort.java b/src/main/java/io/camunda/operate/search/Sort.java deleted file mode 100644 index b41292c..0000000 --- a/src/main/java/io/camunda/operate/search/Sort.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.camunda.operate.search; - -public class Sort { - - private String field; - - private SortOrder order; - - public Sort() { - super(); - } - - public Sort(String field, SortOrder order) { - super(); - this.field = field; - this.order = order; - } - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public SortOrder getOrder() { - return order; - } - - public void setOrder(SortOrder order) { - this.order = order; - } - -} diff --git a/src/main/java/io/camunda/operate/search/VariableFilter.java b/src/main/java/io/camunda/operate/search/VariableFilter.java deleted file mode 100644 index 73661a5..0000000 --- a/src/main/java/io/camunda/operate/search/VariableFilter.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.camunda.operate.search; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import io.camunda.operate.exception.OperateException; - -@JsonInclude(Include.NON_NULL) -public class VariableFilter implements Filter { - - private Long processInstanceKey; - private String name; - private String value; - private Long scopeKey; - - public Long getProcessInstanceKey() { - return processInstanceKey; - } - - public void setProcessInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Long getScopeKey() { - return scopeKey; - } - - public void setScopeKey(Long scopeKey) { - this.scopeKey = scopeKey; - } - - public static class Builder { - private Long processInstanceKey; - private String name; - private String value; - private Long scopeKey; - - public Builder() { - super(); - } - - public Builder processInstanceKey(Long processInstanceKey) { - this.processInstanceKey = processInstanceKey; - return this; - } - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder value(String value) { - this.value = value; - return this; - } - - public Builder scopeKey(Long scopeKey) { - this.scopeKey = scopeKey; - return this; - } - - public VariableFilter build() throws OperateException { - VariableFilter variableFilter = new VariableFilter(); - variableFilter.processInstanceKey = processInstanceKey; - variableFilter.name = name; - variableFilter.value = value; - variableFilter.scopeKey = scopeKey; - return variableFilter; - } - } -} diff --git a/src/main/java/io/camunda/operate/util/Java8Utils.java b/src/main/java/io/camunda/operate/util/Java8Utils.java deleted file mode 100644 index af34838..0000000 --- a/src/main/java/io/camunda/operate/util/Java8Utils.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.camunda.operate.util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.AbstractMap; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class Java8Utils { - - private Java8Utils() { - - } - - public static byte[] readAllBytes(InputStream inputStream) throws IOException { - final int bufLen = 4 * 0x400; // 4KB - byte[] buf = new byte[bufLen]; - int readLen; - IOException exception = null; - - try { - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - while ((readLen = inputStream.read(buf, 0, bufLen)) != -1) - outputStream.write(buf, 0, readLen); - - return outputStream.toByteArray(); - } - } catch (IOException e) { - exception = e; - throw e; - } finally { - if (exception == null) inputStream.close(); - else try { - inputStream.close(); - } catch (IOException e) { - exception.addSuppressed(e); - } - } - } - - public static Map, String> toMap(Object... array) { - AbstractMap.SimpleEntry, String>[] entryArray = new AbstractMap.SimpleEntry[array.length/2]; - for(int i=0;i, String>((Class)array[i*2], (String) array[i*2+1]); - } - return Stream.of(entryArray) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } -} diff --git a/src/main/java/io/camunda/operate/util/JsonUtils.java b/src/main/java/io/camunda/operate/util/JsonUtils.java deleted file mode 100644 index da6a1c7..0000000 --- a/src/main/java/io/camunda/operate/util/JsonUtils.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.camunda.operate.util; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.*; - -import io.camunda.operate.dto.SearchResult; - -public class JsonUtils { - - private JsonUtils() { - } - - private static ObjectMapper mapper; - - private static Map, JavaType> searchResultTypeMap = new HashMap<>(); - - private static ObjectMapper getObjectMapper() { - if (mapper == null) { - mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - } - return mapper; - } - - public static JsonNode toJsonNode(InputStream is) throws IOException { - return getObjectMapper().readTree(is); - } - - public static JsonNode toJsonNode(String json) throws IOException { - return getObjectMapper().readTree(json); - } - - public static String toJson(Object object) throws IOException { - return getObjectMapper().writeValueAsString(object); - } - - public static T toResult(String json, Class resultType) throws IOException { - return getObjectMapper().readValue(json, resultType); - } - - public static SearchResult toSearchResult(String json, Class resultType) throws IOException { - return getObjectMapper().readValue(json, getSearchResultType(resultType)); - } - - private static JavaType getSearchResultType(Class resultType) { - if (!searchResultTypeMap.containsKey(resultType)) { - searchResultTypeMap.put(resultType, - getObjectMapper().getTypeFactory().constructParametricType(SearchResult.class, resultType)); - } - return searchResultTypeMap.get(resultType); - } - -} diff --git a/src/main/java/io/camunda/operate/util/QueryValidatorUtils.java b/src/main/java/io/camunda/operate/util/QueryValidatorUtils.java deleted file mode 100644 index 643bd7c..0000000 --- a/src/main/java/io/camunda/operate/util/QueryValidatorUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.camunda.operate.util; - -import java.util.HashMap; -import java.util.Map; - -import io.camunda.operate.dto.FlownodeInstance; -import io.camunda.operate.dto.Incident; -import io.camunda.operate.dto.ProcessDefinition; -import io.camunda.operate.dto.ProcessInstance; -import io.camunda.operate.dto.Variable; -import io.camunda.operate.exception.OperateException; -import io.camunda.operate.search.FlownodeInstanceFilter; -import io.camunda.operate.search.IncidentFilter; -import io.camunda.operate.search.ProcessDefinitionFilter; -import io.camunda.operate.search.ProcessInstanceFilter; -import io.camunda.operate.search.SearchQuery; -import io.camunda.operate.search.VariableFilter; - -public class QueryValidatorUtils { - - private static Map, Class> TYPE_FILTERS = new HashMap<>(); - - private QueryValidatorUtils() { - } - - private static Class getFilterClass(Class resultType) { - if (TYPE_FILTERS.isEmpty()) { - TYPE_FILTERS.put(ProcessDefinition.class, ProcessDefinitionFilter.class); - TYPE_FILTERS.put(ProcessInstance.class, ProcessInstanceFilter.class); - TYPE_FILTERS.put(FlownodeInstance.class, FlownodeInstanceFilter.class); - TYPE_FILTERS.put(Incident.class, IncidentFilter.class); - TYPE_FILTERS.put(Variable.class, VariableFilter.class); - } - return TYPE_FILTERS.get(resultType); - } - - public static void verifyQuery(SearchQuery query, Class resultType) throws OperateException { - if (query.getFilter() != null && query.getFilter().getClass() != getFilterClass(resultType)) { - throw new OperateException( - "You should rely on "+TYPE_FILTERS.get(resultType).getSimpleName()+" for searching on "+resultType.getSimpleName()); - } - } -}