commercetools-jvm-sdk icon indicating copy to clipboard operation
commercetools-jvm-sdk copied to clipboard

Command deserialization

Open pintomau opened this issue 5 years ago • 1 comments

Hi.

On our services, we're trying to keep API compatibility with Commercetools while enriching it where we need to.

For example, if some client application sends us a cart creation request json, we can deserialize it using the CartDraft model and enrich the request specific to our platform:


  public Cart save(final CartDraft cartDraft) {

    final CustomFieldsDraft originalCustom = cartDraft.getCustom();

    final CustomFieldsDraft enrichedCustom =
        CustomFieldsDraftBuilder
            // force CE custom type
            .ofTypeKey(CE_CUSTOM_TYPE_KEY)
            // carry over any custom fields, if they exist
            .fields(
                originalCustom == null || originalCustom.getFields() == null
                    ? new HashMap<>()
                    : new HashMap<>(originalCustom.getFields()))
            // add sourceId field
            .addObject(CART_SOURCE_ID_FIELD_NAME, ctx.getSourceId())
            .build();

    final CartDraftDsl enrichedCart = CartDraftDsl.of(cartDraft).withCustom(enrichedCustom);
    return executor.executeBlocking(CartCreateCommand.of(enrichedCart));
  }

Now we wanted to go further here and also enrich/control Update Commands, for example limit what actions a client can execute, add commands on top of what the client sends us...

We've also considered using HTTP API extensions for this, but since it lacks context (which actions were executed and what the cart looked like before it was changed), we can't do the full scope of interactions/validations we wanted to. Also, it saves another roundtrip.

What we want to achieve would look something like this:

  @PostMapping("{cartId}")
  public ResponseEntity<Cart> updateCart(
      @PathVariable final UUID cartId, @RequestBody final CartUpdateCommand updateCommand) {

    // intercept and manipulate the update command

    // forward the updated command to Commercetools

    // be happy :)
    return null;
  }

We tried shadowing CartUpdateCommand to add @JsonDeserialize(as = CartUpdateCommandImpl.class), but noticed that CartUpdateCommand expects a Versioned<Cart> type that isn't available.

We also tried building an object much like UpdateCommandBody<T>, but the UpdateAction<T> lacks any deserialization context to be able to deserialize into its subtypes.

Wondering if you have any suggestion so we could avoid creating all actions ourselves and then translate them into the Commercetools' model, or maybe we've missed some way to do this in the SDK.

Thanks.

pintomau avatar Aug 27 '19 16:08 pintomau

@crybat I'm sorry that we didn't reply to your request. And you are right that our current JVM SDK isn't prepared to support deserialization. That means that you have to write your own deserialization. And please keep in mind that our write models (*Draft classes) and our read models are intentionally designed and aren't always compatible with each other.

I hope you already found your own solution and would like to hear about it 😄

katmatt avatar Mar 16 '20 09:03 katmatt