Projektové rozšíření schématu publikovaných dat
Projektové rozšíření schématu publikovaných dat
Schéma publikovaných dat může být projektově rozšiřováno. Níže je popsán postup na příkladu rozšíření produktu.
Zkopírovat odkaz na sekci1. Rozhraní entity
Prvním krokem je definovat rozhraní produktu. Entita produktu bude reprezentována tímto rozhraním napříč celým systémem.
1 public interface DemoPublishedProduct extends2 PublishedProductContract<DemoPublishedProduct, DemoPublishedProductEditor>,3 DemoPublishedProductContract {4}
Toto produktové rozhraní musí dědit základní rozhraní com.fg.cps.eshop.product.publishing.model.PublishedProductContract a projektové rozhraní DemoPublishedProductContract.
Projektové rozhraní DemoPublishedProductContract obsahuje definici rozšiřujícího schématu. V tomto případě se jedná o atribut demoNumber.
1 public interface DemoPublishedProductContract {2 3 String ATTRIBUTE_DEMO_NUMBER = "demoNumber";4 5 /**6 * [cs] Ukázkový atribut rozšiřující {@link com.fg.cps.eshop.product.publishing.model.PublishedProduct}. Nemusí být unikátní.7 *8 * @throws ContextMissingException if the attributes were not fetched along with entity (or this particular attribute was not fetched)9 */10 @Attribute(11 name = ATTRIBUTE_DEMO_NUMBER,12 description = "Custom demo attribute. It doesn't have to be unique.",13 filterable = true,14 sortable = true,15 nullable = true,16 representative = true17 )18 @Nullable19 String getDemoNumber() throws ContextMissingException;20 21}
Při extenzi základního rozhraní PublishedProductContract se uvádějí 2 generické typy. První je projektové rozhraní entity, v našem případě DemoPublishedProduct. Druhé je rozhraní editoru, tedy rozhraní pomocí kterého lze v rámci snippetů projektová data do publikovaných dat zapisovat (indexovat).
Zkopírovat odkaz na sekci2. Editor
Rozhraní editoru DemoPublishedProductEditor musí extendovat základní rozhraní editoru PublishedProductEditorContract a projektové rozhraní editoru DemoPublishedProductContract, viz příklad.
1 public interface DemoPublishedProductEditor extends2 PublishedProductEditorContract<DemoPublishedProduct, DemoPublishedProductEditor>,3 DemoPublishedProductContract4{5 6 /**7 * @param demoNumber demo-number of entity8 * @throws ContextMissingException if the attribute was not fetched along with entity9 */10 @AttributeRef(ATTRIBUTE_DEMO_NUMBER)11 void setDemoNumber(@Nullable String demoNumber) throws ContextMissingException;12}
Zkopírovat odkaz na sekci3. Servisa (publikovaná data)
Dále je potřeba připravit servisu, pomocí které lze na projektu přistupovat k projektovým datům. Tato servisa musí extendovat základní servisu entity, např. pro produkt je to AbstractPublishedProductService.
1 public class DemoPublishedProductService extends AbstractPublishedProductService<DemoPublishedProduct, DemoPublishedProductEditor> {2 3 public DemoPublishedProductService(4 @NonNull EvitaContract evita,5 @NonNull ReflectionLookup reflectionLookup,6 @NonNull WrappingService wrappingService7 ) {8 super(evita, reflectionLookup, wrappingService);9 }10 11 @Override12 public @NonNull Class<DemoPublishedProduct> getEntityClass() {13 return DemoPublishedProduct.class;14 }15 16 @Override17 public @NonNull Class<DemoPublishedProductEditor> getEntityEditorClass() {18 return DemoPublishedProductEditor.class;19 }20}
Zkopírovat odkaz na sekci4. Publikační snippet (publikovaná data)
Indexace projektových dat se zajistí pomocí snippetu.
1 public class DemoPublishedProductConversionSnippet implements EntityToEvitaConversionSnippet<DemoPublishedProductEditor> {2 3 @Override4 public @NonNull Class<DemoPublishedProductEditor> getRequiredType() {5 return DemoPublishedProductEditor.class;6 }7 8 @Override9 public void convert(10 @NonNull PublishedCatalogEntity catalogEntity,11 @NonNull DemoPublishedProductEditor entity,12 @NonNull AbstractEvitaJobContext context13 ) {14 entity.setDemoNumber(catalogEntity.getStringData(ATTRIBUTE_DEMO_NUMBER));15 }16}
Zkopírovat odkaz na sekci4. Přidání do systému
Nakonec je potřeba servisu DemoPublishedProductService a snippet DemoPublishedProductConversionSnippet zavést do EdeeShop modulu. Zavedení je možné provést v rámci projektového rozšíření (feature). Popis jak vytvořit projektové rozšíření je zde.
1 @Override2 public void beforeSpringInitialization() {3 super.beforeSpringInitialization();4 5 if (isFeatureEnabled()) {6 final EntityModelClassConfiguration entityModel = getFeature(CatalogFeature.class).getEntityModelClassConfiguration();7 8 // register extension for source data9 entityModel.getModelDescriptor(PRODUCT).addTrait(WithDemoNumber.class);10 11 // register conversion snippet and service-class for published data12 final EvitaPublishingService evitaPublishingService = getFeature(EvitaFeature.class)13 .getEvitaPublishingService();14 15 evitaPublishingService.getPublishingDescriptorFor(PRODUCT)16 .addEvitaConversionSnippet(new DemoPublishedProductConversionSnippet())17 .registerPublishedServiceClass(DemoPublishedProductService.class);18 }19 }20 21 // Projektové rozšíření se musí vykonat, až po rozšíření dané entity. 22 @Override23 public FeatureDependency[] getRequiredFeatures() {24 return new FeatureDependency[]{25 new FeatureDependency(ProductFeature.class, true)26 };27 }
Zkopírovat odkaz na sekci5. Použití
Následně všechny načtené produkty budou obsahovat i atribut demoNumber, který bude možné filtrovat a řadit.
Zkopírovat odkaz na sekci5.1 Traity na přání
Pokud budete potřebovat na konkrétním místě v konkrétní situaci dynamicky doplnit nějaký další trait, je možné využít tzv. traity na přání.
Mějme například trait CustomTrait s jedním atributem data.
1 @Trait2public interface CustomTrait extends LocalDataStore {3 4 default void setData(Integer data) {5 setLocalData("data", data);6 }7 8 default Integer getData() {9 return getLocalData("data");10 }11 12}
Následně je možné si náš demo produkt "přebalit" do nové třídy, která bude mít navíc i tento trait.
1 // vytvoříme si nějaký produkt a necháme jej vypublikovat2runAndPublish(() -> {3 testDataGenerator.createProduct(4 new TestDataRequestProduct(TEST_CATALOG_CODE, "p1")5 .generateDefaultPrice()6 );7});8// načteme si vypublikovanou verzi produktu9DemoPublishedProduct product = publishedProductService.getProductByQuery(10 new ProductQuery(TEST_CATALOG_CODE).withCodes("p1")11).orElseThrow();12 13final DemoPublishedProduct onDemandExtendedProduct = publishedProductService.wrapInto(product, CustomTrait.class);14assertTrue(wrappedProduct instanceof CustomTrait);15((CustomTrait)wrappedProduct).setData(42);16assertEquals(Integer.valueOf(42), ((CustomTrait)wrappedProduct).getData());17 18assertEquals("p1", wrappedProduct.getCode());
Tato funkcionalita dává smysl ve chvílích, kdy nechcete změnit rozhraní produktu v celém systému, ale jen v nějaké konkrétní situaci - například pro vykreslení jedné konkrétní stránky, výstup v rámci jednoho konkrétního služby (controller), či ve spojení s nějakým konkrétním kontextem (např. kontextem přihlášeného uživatele), který je dostupný jen v určitém místě aplikace.