All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.sphere.sdk.customobjects.CustomObject Maven / Gradle / Ivy

There is a newer version: 1.0.0-M26
Show newest version
package io.sphere.sdk.customobjects;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.sphere.sdk.customobjects.queries.CustomObjectQueryModel;
import io.sphere.sdk.models.Reference;
import io.sphere.sdk.models.Referenceable;
import io.sphere.sdk.models.ResourceView;

/**
  Custom objects are a way to store arbitrary JSON-formatted data on the SPHERE.IO platform. It allows you to persist data that does not fit our standard data model.

  The storage can be seen as key value store but with an additional prefix called container to improve querying custom objects and provide an additional namespace.




A {@link io.sphere.sdk.customobjects.CustomObject} contains an ID, a version, timestamps like the other resources in SPHERE.IO and in addition {@link io.sphere.sdk.customobjects.CustomObject#getContainer()}, {@link io.sphere.sdk.customobjects.CustomObject#getKey()} and {@link io.sphere.sdk.customobjects.CustomObject#getValue()}.

Container and key are namespaces like in a key-value store. The value is a JSON structure which can hold custom domain models.

Instead of pure JSON it is encouraged to use Java objects (POJO) with the Jackson JSON mapper.

Custom Objects with POJO JSON mapping

Custom objects can be used with custom Java classes and the Jackson mapper used by the SDK.

The following class contains a constructor with all field types and names a parameter for deserialization and getters for serialization. {@include.example io.sphere.sdk.customobjects.demo.Foo}

Create Custom Objects

Create them with a {@link io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommand}: {@include.example io.sphere.sdk.customobjects.CustomObjectFixtures#createCustomObject()}

Update Custom Objects

In this case you use also {@link io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommand}. For update operations you can use {@link io.sphere.sdk.customobjects.CustomObjectDraft#ofVersionedUpdate(io.sphere.sdk.customobjects.CustomObject, Object, com.fasterxml.jackson.core.type.TypeReference)} to use optimistic concurrency control as in here: {@include.example io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommandTest#updateWithVersion()} Or you can just override the value using {@link io.sphere.sdk.customobjects.CustomObjectDraft#ofUnversionedUpdate(io.sphere.sdk.customobjects.CustomObject, Object, com.fasterxml.jackson.core.type.TypeReference)} {@include.example io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommandTest#updateWithoutVersion()}

Custom objects with direct Jackson JsonNode

Create and update custom objects

{@include.example io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommandTest#pureJson()}

Fetch custom objects

{@include.example io.sphere.sdk.customobjects.queries.CustomObjectByKeyGetTest#executionForPureJson()}

Query custom objects

{@include.example io.sphere.sdk.customobjects.queries.CustomObjectQueryTest#queryPureJson()}

Custom Objects with a custom JSON mapper

If you need to create your own models and you prefer another JSON tool over Jackson you can use it at your own risk.

The models for the demo

{@include.example io.sphere.sdk.customobjects.demo.GsonFooCustomObjectDraft} {@include.example io.sphere.sdk.customobjects.demo.GsonFoo}

Create and update with a custom JSON mapper

Extend {@link io.sphere.sdk.customobjects.commands.CustomObjectCustomJsonMappingUpsertCommand} to create or update a custom object with Google Gson:

{@include.example io.sphere.sdk.customobjects.demo.GsonFooCustomObjectUpsertCommand}

Fetch by container and key

{@include.example io.sphere.sdk.customobjects.demo.GsonFooCustomObjectByKeyGet} {@include.example io.sphere.sdk.customobjects.queries.CustomObjectCustomJsonMappingByKeyGetTest#execution()}

Using Optimistic Concurrency Control

In this example we want to create unique readable IDs (successive numbers) for customers since SPHERE.IO returns IDs like 8547b810-9dad-11d1-80b4-44c04fd430c8.

The data model contains the last number and the last SPHERE.IO customer ID (just to have more than one field). {@include.example io.sphere.sdk.customobjects.occexample.CustomerNumberCounter}

Imagine, the customer number should start at 1000, so we do the following request for the initialization of the counter:

{@include.example io.sphere.sdk.customobjects.occexample.FlowTest#setupInitialValue()}

An update works this way then:

{@include.example io.sphere.sdk.customobjects.occexample.FlowTest#doAnUpdate()}

Migrations

Your data model in the custom objects probably will evolve and you should plan for it.

Adding fields

For new fields you can add an {@link java.util.Optional} to make it obvious to callers that this value can be unset.

Before adding the field (there are already saved custom objects):

{@include.example io.sphere.sdk.customobjects.migrations.version1.Xyz}

After adding the field:

{@include.example io.sphere.sdk.customobjects.migrations.version2.Xyz} {@include.example io.sphere.sdk.customobjects.migrations.CustomObjectsMigrationsTest#optionalExample()}

Removing fields

Removing fields can be equivalent to ignoring fields.

Consider you have a class with a field "foo": {@include.example io.sphere.sdk.customobjects.migrations.version2.Xyz} If you don't want to use it anymore, remove it from the JSON mapping: {@include.example io.sphere.sdk.customobjects.migrations.version3.Xyz} Next time you'll save this object the field will be no more in the JSON.

Moving data

Suppose you have this data model: {@include.example io.sphere.sdk.customobjects.migrations.version1.Uvw} And you want to make 'foo' not a String, but an object with members 'a' and 'b'. {@include.example io.sphere.sdk.customobjects.migrations.version2.Uvw} And let's say, for simplicity you can directly migrate the String to the object by splitting the String the right way. A possible solution is to create an interface for that purpose: {@include.example io.sphere.sdk.customobjects.migrations.version3.Uvw} For the two incarnations you create a class for each. The newest class contains all the field plus the schema version and it implements the interface: {@include.example io.sphere.sdk.customobjects.migrations.version3.UvwSchemaVersion2} The previous data model versions contain no fields but extend the most recent class. The old versions get the old data as constructor parameters and pass the transformed values to the constructor of the superclass. {@include.example io.sphere.sdk.customobjects.migrations.version3.UvwSchemaVersion1} As a result you only work with the interface making it transparent if it is an old or new version: {@include.example io.sphere.sdk.customobjects.migrations.CustomObjectsMigrationsTest#exampleForMigrationCall()}

Traps

Unlike other query models, {@link CustomObjectQueryModel#of()} takes a type parameter of the result type of the custom object. Notice that it is necessary to explicitly declare the type when requesting the query model, as shown in the following examples:

{@include.example io.sphere.sdk.customobjects.queries.CustomObjectQueryTest#demoModelTypeParameter()} back to top @param The type of the value of this custom object. */ @JsonDeserialize(as = CustomObjectImpl.class) public interface CustomObject extends ResourceView, CustomObject>, Referenceable> { /** * The container is part of the custom object namespace to find it * @return container */ String getContainer(); /** * The key is part of the custom object namespace to find it * @return container */ String getKey(); /** * The value stored in the custom object. * @return the value */ T getValue(); @Override default Reference> toReference() { return Reference.of(referenceTypeId(), getId());//not possible to provide filled reference since type can be different } static String referenceTypeId() { return "key-value-document"; } /** * * @deprecated use {@link #referenceTypeId()} instead * @return referenceTypeId */ @Deprecated static String typeId() { return "key-value-document"; } static String validatedKey(final String key) { return CustomObjectImpl.validatedKey("key", key); } static String validatedContainer(final String container) { return CustomObjectImpl.validatedKey("container", container); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy