We’re making API calls from our own BPMN via a connector service task, but currently we have to get a token before each API call. The token API call returns an expiration date that we’d like to make use of and only get a new token if the current time + the expiration time of when we made the first token call has passed.
To do this, we believe we need to maintain a global variable on the entire Camunda server, not just a series of processes that are in a parent-child relationship. (This is because we are making calls via the REST services) Is there a way in Camunda to accomplish this, sort-of, caching?
There are probably many ways to solve this problem, but what I did is to create a token service (singleton bean) whose job is to fetch and store a token and give it out to callers upon request.
If you also store the token expiration as a field in your service class, the service getToken() method can check validity and fetch a fresh token when needed. The token service can be accessed via a juel expression to set the header variable you pass to your connector api call.
Create a variable named “headers” of type “Map”. Add a variable named “Authorization” whose value is the juel expression $[tokenService.getToken()] - my phone keyboard doesn’t have curly braces so substitute for the square brackets above. You may need to concat "Bearer " in front of the token string if your service doesn’t do this for you.
If tokenService is a resolvable bean this can be called anywhere in your flows. Let the service keep track of the expiration rather than trying to do this in your process.
Thank you for the reply! We were going down the road of a singleton bean class to handle this problem. What I ran into while going through the Camunda documentation, was that if I created a Java class to be called, it would only live for that one call to the class. Therefore, it would not be stateful. (ie. https://docs.camunda.org/manual/7.9/user-guide/process-engine/delegation-code/#java-delegate &
"
Note!
Each time a delegation class referencing activity is executed, a separate instance of this class will be created. This means that each time an activity is executed there will be used another instance of the class to call execute(DelegateExecution)
)
"
Is there another way to load a Java class that will maintain that Singleton on the server?
That note means that your Java Delegate classes are not singletons. It doesn’t mean you can’t reference or inject a singleton bean from in your process model/flow to set a process variable.
I inject an instance of my service in my startup class and call getToken there so that the class is initialized before any processes execute. Then I refer to that bean directly in the model configuration for the “header” map variable that is passed into the connector task as an input variable.
I don’t use the tokenService bean inside my delegate classes, but there is no reason I couldn’t if I had a Delegate class that used Spring rest templates to make outbound calls, but in general I let the model and connector tasks handle that.