public interface Custom
To use custom fields of a Custom
resource it is necessary to connect them to an existing Type
, Type
s define the field names and types like String
, MonetaryAmount
and Long
.
In the example scenario we create a type for categories.
The example type will contain:state
" to indicate the state of of the category like "published" and "draft"imageUrl
" to show an icon for the categoryrelatedCategories
" to suggest other categories with accessoires for exampleio.sphere.sdk.types.*;
so you don't get confused with
classes from product attributes which have sometimes the same class name but are in another package.
A type can be assigned to different kinds of objects, e.g., a type can be used for categories, orders and carts.
In the type creation the property TypeDraft.getResourceTypeIds()
contains a set of resourceTypeIds which can be
find on the class of the object like in Category.resourceTypeId()
for categories. Be careful to not confuse this with
Category.referenceTypeId()
which contains the id for Reference
s. Cart and order have the same
resourceTypeId so the type can be automatically be used for Order
and Cart
if it is for one of them enabled.
Execution example:
import io.sphere.sdk.categories.Category;
import io.sphere.sdk.client.BlockingSphereClient;
import io.sphere.sdk.models.EnumValue;
import io.sphere.sdk.models.LocalizedString;
import io.sphere.sdk.models.TextInputHint;
import io.sphere.sdk.types.commands.TypeCreateCommand;
import java.util.List;
import java.util.Set;
import static io.sphere.sdk.test.SphereTestUtils.asList;
import static io.sphere.sdk.test.SphereTestUtils.en;
public final class CreateTypeDemo { public static Type createType(final BlockingSphereClient client) { final LocalizedString name = en("type for standard categories"); final String key = "category-customtype-key"; //this enables the type only to be used for categories final Set<String> resourceTypeIds = ResourceTypeIdsSetBuilder.of() .addCategories() //there are more methods for other objects which support custom .build(); final List<FieldDefinition> fieldDefinitions = asList(stateFieldDefinition(), imageUrlFieldDefinition(), relatedCategoriesFieldDefinition()); final TypeDraft typeDraft = TypeDraftBuilder.of(key, name, resourceTypeIds) .fieldDefinitions(fieldDefinitions) .build(); return client.executeBlocking(TypeCreateCommand.of(typeDraft)); } private static FieldDefinition stateFieldDefinition() { final List<EnumValue> values = asList( EnumValue.of("published", "the category is publicly visible"), EnumValue.of("draft", "the category should not be displayed in the frontend") ); final boolean required = false; final LocalizedString label = en("state of the category concerning to show it publicly"); final String fieldName = "state"; return FieldDefinition .of(EnumFieldType.of(values), fieldName, label, required); } private static FieldDefinition imageUrlFieldDefinition() { final LocalizedString imageUrlLabel = en("absolute url to an image to display for the category"); return FieldDefinition .of(StringFieldType.of(), "imageUrl", imageUrlLabel, false, TextInputHint.SINGLE_LINE); } private static FieldDefinition relatedCategoriesFieldDefinition() { final LocalizedString relatedCategoriesLabel = en("categories to suggest products similar to the current category"); //referenceTypeId is required to refere to categories final String referenceTypeId = Category.referenceTypeId(); final SetFieldType setType = SetFieldType.of(ReferenceFieldType.of(referenceTypeId)); return FieldDefinition .of(setType, "relatedCategories", relatedCategoriesLabel, false); } }
See the test code.
import com.fasterxml.jackson.core.type.TypeReference;
import io.sphere.sdk.categories.Category;
import io.sphere.sdk.categories.CategoryDraft;
import io.sphere.sdk.categories.CategoryDraftBuilder;
import io.sphere.sdk.categories.commands.CategoryCreateCommand;
import io.sphere.sdk.client.BlockingSphereClient;
import io.sphere.sdk.json.JsonException;
import io.sphere.sdk.models.Reference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static io.sphere.sdk.test.SphereTestUtils.asList;
import static io.sphere.sdk.test.SphereTestUtils.randomSlug;
import static org.assertj.core.api.Assertions.*;
public class CreateCategoryWithTypeDemo { public static Category createCategoryWithType(final BlockingSphereClient client, final Category category1, final Category category2) throws Exception { final Map<String, Object> fieldValues = new HashMap<>(); fieldValues.put("state", "published");//in the type it was enum, but for enums only keys are set fieldValues.put("imageUrl", "https://docs.commercetools.com/assets/img/CT-logo.svg"); final Set<Reference<Category>> relatedCategories = new HashSet<>(asList(category1.toReference(), category2.toReference())); fieldValues.put("relatedCategories", relatedCategories); final CategoryDraft categoryDraft = CategoryDraftBuilder.of(randomSlug(), randomSlug()) .custom(CustomFieldsDraft.ofTypeKeyAndObjects("category-customtype-key", fieldValues)) .build(); final Category category = client.executeBlocking(CategoryCreateCommand.of(categoryDraft)); final CustomFields custom = category.getCustom(); assertThat(custom.getFieldAsEnumKey("state")).isEqualTo("published"); assertThat(custom.getFieldAsString("imageUrl")) .isEqualTo("https://docs.commercetools.com/assets/img/CT-logo.svg"); final TypeReference<Set<Reference<Category>>> typeReference = new TypeReference<Set<Reference<Category>>>() { }; assertThat(custom.getField("relatedCategories", typeReference)) .isEqualTo(relatedCategories); //error cases assertThat(custom.getFieldAsString("notpresent")) .overridingErrorMessage("missing fields are null") .isNull(); assertThatThrownBy(() -> custom.getFieldAsString("relatedCategories")) .overridingErrorMessage("present field with wrong type causes exception") .isInstanceOf(JsonException.class); return category; } }
See the test code.
It is not necessary to assign a type to the object at it's creation. You can retrofit objects without a type by using update actions like SetCustomType for categories
.
import com.fasterxml.jackson.core.type.TypeReference;
import io.sphere.sdk.categories.Category;
import io.sphere.sdk.categories.CategoryFixtures;
import io.sphere.sdk.categories.commands.CategoryUpdateCommand;
import io.sphere.sdk.categories.commands.updateactions.SetCustomType;
import io.sphere.sdk.client.BlockingSphereClient;
import io.sphere.sdk.models.Reference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static io.sphere.sdk.test.SphereTestUtils.asList;
import static org.assertj.core.api.Assertions.assertThat;
public class TypeAssigningInUpdateActionDemo { public static Category updateCategoryWithType(final BlockingSphereClient client, final Category category1, final Category category2) { final Category category = CategoryFixtures.createCategory(client); assertThat(category.getCustom()).isNull(); final Map<String, Object> fieldValues = new HashMap<>(); fieldValues.put("state", "published");//in the type it was enum, but for enums only keys are set fieldValues.put("imageUrl", "https://docs.commercetools.com/assets/img/CT-logo.svg"); final Set<Reference<Category>> relatedCategories = new HashSet<>(asList(category1.toReference(), category2.toReference())); fieldValues.put("relatedCategories", relatedCategories); final SetCustomType action = SetCustomType .ofTypeKeyAndObjects("category-customtype-key", fieldValues); final Category updatedCategory = client.executeBlocking(CategoryUpdateCommand.of(category, action)); final CustomFields custom = updatedCategory.getCustom(); assertThat(custom.getFieldAsEnumKey("state")).isEqualTo("published"); assertThat(custom.getFieldAsString("imageUrl")) .isEqualTo("https://docs.commercetools.com/assets/img/CT-logo.svg"); final TypeReference<Set<Reference<Category>>> typeReference = new TypeReference<Set<Reference<Category>>>() { }; assertThat(custom.getField("relatedCategories", typeReference)) .isEqualTo(relatedCategories); return updatedCategory; } }
See the test code.
By using update actions you can overwrite or erase the value of custom field.
import io.sphere.sdk.categories.commands.updateactions.SetCustomField;
import io.sphere.sdk.categories.Category;
import io.sphere.sdk.categories.commands.CategoryUpdateCommand;
import io.sphere.sdk.client.BlockingSphereClient;
import io.sphere.sdk.commands.UpdateAction;
import java.util.List;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
public class UpdateFieldValueDemo { public static Category updateFieldValues(final BlockingSphereClient client, final Category category) { assertThat(category.getCustom().getFieldAsEnumKey("state")).isEqualTo("published"); final List<? extends UpdateAction<Category>> updateActions = asList( SetCustomField.ofObject("state", "draft"),//set new value SetCustomField.ofObject("imageUrl", null)//remove value ); final Category updatedCategory = client.executeBlocking(CategoryUpdateCommand.of(category, updateActions)); final CustomFields custom = updatedCategory.getCustom(); assertThat(custom.getFieldAsEnumKey("state")).isEqualTo("draft"); assertThat(custom.getFieldAsString("imageUrl")).isNull(); return updatedCategory; } }
See the test code.
import io.sphere.sdk.categories.commands.updateactions.SetCustomType;
import io.sphere.sdk.categories.Category;
import io.sphere.sdk.categories.commands.CategoryUpdateCommand;
import io.sphere.sdk.client.BlockingSphereClient;
import static org.assertj.core.api.Assertions.assertThat;
public class RemoveTypeFromObjectDemo { public static Category removeTypeFromCategory(final BlockingSphereClient client, final Category category) { assertThat(category.getCustom()).isNotNull(); final CategoryUpdateCommand command = CategoryUpdateCommand .of(category, SetCustomType.ofRemoveType()); final Category updatedCategory = client.executeBlocking(command); assertThat(updatedCategory.getCustom()).isNull(); return updatedCategory; } }
See the test code.
Have a look at TypeUpdateCommand
.
withUpdateableType(client(), type -> { final LocalizedString newDescription = randomSlug(); final Type updatedType = client().executeBlocking(TypeUpdateCommand.of(type, SetDescription.of(newDescription))); assertThat(updatedType.getDescription()).isEqualTo(newDescription); return updatedType; });
See the test code.
TypeDeleteCommand
.Modifier and Type | Method and Description |
---|---|
CustomFields |
getCustom() |
@Nullable CustomFields getCustom()