Options are not cloneable

When working with my code, I can have clients pass in their own *Options (GetOptions, for example). I, however, want to force the transcoder to be something else - I do not want to modify the *Options from the caller, so would like to clone the provided *Options and only override the transcoder.

No way to do this…

There’s an issue open to add a copy/clone constructor - [JCBC-1885] Add QueryOptions copy constructor - Couchbase database

Without such a method, it’s very difficult. The queryOptions.build() will give you a built object where you can retrieve some of the properties. Then you can injectParams() into a JsonObject, and retrieve them from that (see injectParams() for how they were put there.

   QueryOptions.Built from = queryOptions.build()
    JsonObject queryJson = JsonObject.create();
    from.injectParams(queryJson);
    if (queryJson.get("consistentWith") != null) {
      clone.consistentWith( (MutationState)(queryJson.get("consistentWith")));
    }
   ...

Thanks. We would want all *Options to be cloneable, not just QueryOptions.

Of course, the other Options I’m requesting don’t have injectParams… So, this isn’t valid. Right now, I’m using reflection to do this, but that’s not ideal, either

@unhuman I don’t have anything concrete for you at this time, but just wanted to let you know that your post has prompted ongoing internal discussions on supporting cloning on the option objects. So no commitment at this point, but please watch this space. We are presently considering what form that interface would best take if we were to implement it, with ideas including a Copyable interface providing an Object copy(), a GetOptions copy() added to each options block, a copy constructor, or a static copy constructor (GetOptions.from(other)).

(And understood that this is reference to all objects, not just QueryOptions. I believe Michael was linking that ticket just as indication that we’ve got that ball rolling, and that we’ve found some necessity ourselves for it.)

1 Like

Perfect. Internally, we use Immutables (https://immutables.github.io/) for managing entities like this. Don’t know if that’s an option for you, or something similar.

We’d perhaps be wary of using Immutables (or Lombok) on the public API, as the necessary annotations could perhaps be off-putting to users unfamiliar with it. But perhaps using it on an *OptionsInternal that the real *Options proxies/wraps is an idea - I will raise with the team.
In the future we will be able to migrate to JDK 17 and Records, and but that is a long way off of course.

1 Like

Yeah, it really boils down to interface/implementation. Anyhow, what Immutables buys us is immutability (obviously) and the ability to copy/mutate/create. That pattern would be very safe in our use case for how we want to have default behaviors and the ability override or tweak, based on use case.

In any event, we’re good here. I keep my eyes out.

1 Like