Adding activity stubs to a HashSet gives error even with hashcode function

Hello,

I have a use case where I am adding Activity stubs inside a workflow to a HashSet and also using them as Keys in a HashMap.

I have used lombok annotation for generating the Equals & HashCode functions.

I also tried without the annotation and with implementing my own hashCode() function to return a random integer but it produces the same error.

Please may I know how to overcome this?

I get the following error when I try to run my workflow.

Caused by: java.lang.IllegalArgumentException: Unexpected method: public native int java.lang.Object.hashCode()
	at io.temporal.internal.sync.ActivityInvocationHandlerBase.invoke(ActivityInvocationHandlerBase.java:68)
	at com.sun.proxy.$Proxy9.hashCode(Unknown Source)
	at com.google.common.collect.ImmutableSet$RegularSetBuilderImpl.add(ImmutableSet.java:787)
	at com.google.common.collect.ImmutableSet$Builder.add(ImmutableSet.java:513)
	at io.temporal.samples.hello.HelloActivity$GreetingWorkflowImpl.getGreeting(HelloActivity.java:80)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation$RootWorkflowInboundCallsInterceptor.execute(POJOWorkflowImplementationFactory.java:324)
	at io.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation.execute(POJOWorkflowImplementationFactory.java:282)
	at io.temporal.internal.sync.WorkflowExecuteRunnable.run(WorkflowExecuteRunnable.java:53)
	at io.temporal.internal.sync.SyncWorkflow.lambda$start$0(SyncWorkflow.java:126)
	at io.temporal.internal.sync.CancellationScopeImpl.run(CancellationScopeImpl.java:101)
	at io.temporal.internal.sync.WorkflowThreadImpl$RunnableWrapper.run(WorkflowThreadImpl.java:107)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	... 3 common frames omitted

To Reproduce:

In the HelloActivity example I added @EqualsAndHashCode to the Activity Impl

 @EqualsAndHashCode
  static class GreetingActivitiesImpl implements GreetingActivities {
    @Override
    public String composeGreeting(String greeting, String name) {
      return greeting + " " + name + "!";
    }
  }

And here what the workflow code looks like

 @Override
    public String getGreeting(String name) {

      ImmutableSet<GreetingActivities> set  = new ImmutableSet.Builder<GreetingActivities>()
              .add(activities) // THIS LINE THROWS ERROR
              .build();

      // This is a blocking call that returns only after the activity has completed.
      return activities.composeGreeting("Hello", name);
    }"

Given that you are adding Activity Stubs you need to use a Map implementation which uses reference equality I believe.

So in your case you should be able to use IdentityHashMap
or if you need a synchronized map:

Collections.synchronizedMap(new IdentityHashMap(...));

For a Set, you could use Collections.newSetFromMap
for example:


Set<GreetingActivities> set = Collections.newSetFromMap(new IdentityHashMap<>());
set.add(activities);

Hope this helps.

Thank you, this works!