Bootstrap Java Worker failed with Unrecognized field "refreshtoken"

Hi,

I’m trying to bootstrap a Java Client as described here: Java client | Camunda Cloud Docs

Im using Zeebe version 1.2.4, as my Cloud console shows.

Running the Java application, I get an exception:

17:36:02.070 [grpc-nio-worker-ELG-1-4] DEBUG io.camunda.zeebe.client.impl.oauth.OAuthCredentialsProvider - Failed to read credentials cache
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "refreshtoken" (class io.camunda.zeebe.client.impl.ZeebeClientCredentials), not marked as ignorable (4 known properties: "expires_in", "tokenType", "accessToken", "expiry"])
 at [Source: (File); line: 6, column: 23] (through reference chain: java.util.LinkedHashMap["xxxxxxxxx.bru-2.zeebe.camunda.io"]->io.camunda.zeebe.client.impl.oauth.OAuthCredentialsCache$OAuthCachedCredentials["auth"]->java.util.LinkedHashMap["credentials"]->io.camunda.zeebe.client.impl.ZeebeClientCredentials["refreshtoken"])
	at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:987)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1974)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1701)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1679)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:330)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:609)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:437)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:565)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:449)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:609)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:437)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3433)
	at io.camunda.zeebe.client.impl.oauth.OAuthCredentialsCache.readCache(OAuthCredentialsCache.java:54)
	at io.camunda.zeebe.client.impl.oauth.OAuthCredentialsProvider.loadCredentials(OAuthCredentialsProvider.java:112)
	at io.camunda.zeebe.client.impl.oauth.OAuthCredentialsProvider.applyCredentials(OAuthCredentialsProvider.java:79)
	at io.camunda.zeebe.client.impl.ZeebeCallCredentials.applyRequestMetadata(ZeebeCallCredentials.java:46)

I can’t find an attribute refreshtoken in the class io.camunda.zeebe.client.impl.ZeebeClientCredentials. Does the API didn’t match the current implementation or did I miss something in my setup?

I only added my credentials in the snippet from the docs, the code is still the same.

Thank you, Ingo

Hey @Ingo_Richtsmeier

I tried to reproduce your issue without success, could you provide an example repo or something similar ?

Related question: Did you tried before with zbctl or any other client to access the camunda cloud?
Could you check the content of ~/.camunda/credentials does this file contain credentials from your cluster with refreshtoken?

Which version has your client?

Greets
Chris

Hi @Zelldon,

I started accessing the cluster with zbctl and now I want to switch to a Java worker.

Yes, my credential file contains an emtpy refreshtoken.

After deleting the line with the refresh token, I get a 401 response from the Java worker.

Caused by: java.io.IOException: Failed while requesting access token with status code 401 and message Unauthorized.
	at io.camunda.zeebe.client.impl.oauth.OAuthCredentialsProvider.fetchCredentials(OAuthCredentialsProvider.java:183)
...

Here is the code:

package com.camunda.training;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.camunda.zeebe.client.ZeebeClient;
import io.camunda.zeebe.client.impl.oauth.OAuthCredentialsProvider;
import io.camunda.zeebe.client.impl.oauth.OAuthCredentialsProviderBuilder;

public class PaymentJobWorker {

  private static final String zeebeAPI = "xxxxxx.bru-2.zeebe.camunda.io:443"; // run with the real values from the generated credentials
  private static final String clientId = "yyyyyyy";
  private static final String clientSecret = "zzzzzz";
  private static final String oAuthAPI = "https://login.cloud.camunda.io/oauth/token";
  
  private static final Logger LOG = LoggerFactory.getLogger(PaymentJobWorker.class);

  public static void main(String[] args) {
    OAuthCredentialsProvider credentialsProvider =
        new OAuthCredentialsProviderBuilder()
            .authorizationServerUrl(oAuthAPI)
            .audience(zeebeAPI)
            .clientId(clientId)
            .clientSecret(clientSecret)
            .build();

    ZeebeClient client =
        ZeebeClient.newClientBuilder()
            .gatewayAddress(zeebeAPI)
            .credentialsProvider(credentialsProvider)
            .build();

    client.newTopologyRequest().send().join();
    //LOG.info("connected to {}", client.newTopologyRequest().send().join());
  }
}

and here is my pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.camunda.training</groupId>
  <artifactId>job-worker</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
    <zeebe.version>1.2.4</zeebe.version>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <version.java>11</version.java>
  </properties>
  
  <dependencies>
    <dependency>
      <groupId>io.camunda</groupId>
      <artifactId>zeebe-client-java</artifactId>
      <version>${zeebe.version}</version>
    </dependency>  
    
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.7</version>
    </dependency>
  </dependencies>
</project>

Did I do someting wrong with the credentials?
Or do I need another access token for the Java Worker?

I’m not allowed to access a .txt file with the full log here.

Cheers, Ingo

Hi @Ingo_Richtsmeier

I don’t think the audience should contain the port. I think it should be:

   .audience(zeebeAPI.substring(0, zeebeAPI.length() - 4))

Hi @korthout,

Thank you, that does the trick. Now it works.

The docs and the Java Docs should be improved to make it transparent.

I will create a pull request.

@Zelldon, clould you please explain, how you got connected to your cluster? I found a lot of different examples researching the problem yesterday.

I’m looking for the most simple and direct solution without hidden magic in the background.

Cheers, Ingo

TBH, when connecting to the Camunda Cloud SaaS I would recommend just to use the dedicated zeebe cloud client builder: zeebe/ZeebeClient.java at 1.2.4 · camunda-cloud/zeebe · GitHub

Sorry @Ingo_Richtsmeier for the late response!

I created a Cluster on prod and created a benchmark via zeebe/benchmarks/setup at develop · camunda-cloud/zeebe · GitHub

Where I set all my credentials in zeebe/cloudcredentials.yaml at develop · camunda-cloud/zeebe · GitHub and deployed it

BTW I think if you not configured the audience it will be automatically filled / set afaik. Maybe try that as well. But I agree with @korthout the Cloud Client is probably the easiest way, also documented in the getting started here camunda-cloud-get-started/java at master · camunda-cloud/camunda-cloud-get-started · GitHub

Greets
Chris

2 Likes