Broadleaf 5.2 - Как мне установить ProductOptions во вновь созданный продукт через API?

Проблема:

Я вижу, что метод Product " setProductOptions ()" устарел и что " setProductOptionXrefs ()" является предпочтительным. Проблема в том, что я не могу найти какой-либо пример того, как установить ProductOptionXrefs.

Я искал примеры в проектах Broadleaf " BroadleafCommerce-develop-5.2.x " и " DemoSite-broadleaf-5.2.2.1-GA ", а также прочесал галактику для примера. Неудачно.

Цель (X):

Я создаю конечную точку, которая будет принимать объект JSON и принимать два параметра (categoryName и price).

Конечная точка будет:

  • Найдите категорию, к которой будет принадлежать продукт.
  • Создайте новый объект Sku и заполните некоторые поля ввода оболочки.
  • Создайте новый объект Product и заполните несколько полей- оболочек.
  • Назначьте ProductOption этому новому продукту. <== X
  • Сохраните продукт.
  • Вернуть ответ (для ответа REST).

Сама конечная точка выглядит так:

@RequestMapping(value = "/my_product", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ProductWrapper addCSDLProduct(HttpServletRequest request, @RequestBody ProductWrapper wrapper,
                                 @RequestParam(value = "categoryName", required = true) String categoryName,
                                 @RequestParam(value = "price", required = true) double price) {

    Category category = null;
    List<Category> categories = catalogService.findCategoriesByName( categoryName );
    if ( categories != null && categories.size() > 0 ) {
        category = categories.get(0);
    }

    Sku defaultSku = catalogService.createSku();
    defaultSku.setRetailPrice(new Money( price ));
    defaultSku.setInventoryType( InventoryType.ALWAYS_AVAILABLE );
    defaultSku.setName( wrapper.getName() );
    defaultSku.setLongDescription( wrapper.getLongDescription() );
    defaultSku.setDescription( wrapper.getDescription() );
    defaultSku.setUrlKey( wrapper.getUrl() );
    defaultSku.setActiveStartDate( new Date() );

    Product product = catalogService.createProduct(ProductType.PRODUCT);
    product.setDefaultSku(defaultSku);        
    product.setUrl( wrapper.getUrl() );
    product.setCategory(category);  

    List<ProductOptionXref> productOptionXrefs = new ArrayList<ProductOptionXref>();
    List<ProductOption> allProductOptions = catalogService.readAllProductOptions();        
    if ( null != allProductOptions && allProductOptions.size() > 0 ) {
        for ( ProductOption po : allProductOptions ) {          
            String current = po.getName();
            if ( current.equalsIgnoreCase("Shirt Color") ) {
                ProductOptionXref productOptionXref = new ProductOptionXrefImpl();
                productOptionXref.setProductOption(po);
                productOptionXrefs.add(productOptionXref);
            }               
        }
    }

    product.setProductOptionXrefs(productOptionXrefs);

    Product finalProduct = catalogService.saveProduct(product);
    Long newId = finalProduct.getId();

    ProductWrapper response;
    response = (ProductWrapper) context.getBean(ProductWrapper.class.getName());
    response.wrapDetails(product, request);
    response.setId(newId);

    return response;
}

Объект ввода (пример), который я использую:

{
    "name": "This is the name of the product.",
    "description": "This is the description of the product.",
    "longDescription": "This is a long description of the product. Really long.",
    "url": "/this/is/the/url/of/the/product",
    "defaultSku": {
        "name": "This is the name of the product.",
        "active": true,
        "available": true,
        "inventoryType": "ALWAYS_AVAILABLE",
        "retailPrice": {
            "amount": 19.0,
            "currency": "USD"
        }
    }
}

С категорией "Товар" и ценой 19.00.

Этот код выше в настоящее время возвращает ошибку "Not-null":

Свойство Not-null ссылается на временное значение - временный экземпляр должен быть сохранен перед текущей операцией: org.broadleafcommerce.core.catalog.domain.ProductOptionXrefImpl.product -> org.broadleafcommerce.core.catalog.domain.ProductImpl; вложенным исключением является java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: свойство Not-null ссылается на временное значение - временный экземпляр должен быть сохранен перед текущей операцией: org.broadleafcommerce.core.catalog.domain.ProductOptionXrefImpl.product ->.> broadleafcommerce.core.catalog.domain.ProductImpl

что, скорее всего, связано с моим

if ( current.equalsIgnoreCase("Shirt Color") ) {
  ProductOptionXref productOptionXref = new ProductOptionXrefImpl();
  productOptionXref.setProductOption(po);
  productOptionXrefs.add(productOptionXref);
}   

и / или

Product finalProduct = catalogService.saveProduct(product);

линии чуть выше.

Я мог бы (в конце концов) выяснить ошибку "Не пусто", но я задаю вопрос: есть ли у кого-нибудь пример добавления ProductOption или ProductOptionXref во вновь созданный продукт?

Спасибо

Джон

[ОБНОВИТЬ]

Я хотел обновить мой вопрос решением, большое спасибо @phillipuniverse за пример / объяснения.

@RequestMapping(value = "/my_product", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ProductWrapper addCSDLProduct(HttpServletRequest request, @RequestBody ProductWrapper wrapper,
                                 @RequestParam(value = "categoryName", required = true) String categoryName,
                                 @RequestParam(value = "price", required = true) double price) {

    Category category = null;
    List<Category> categories = catalogService.findCategoriesByName( categoryName );
    if ( categories != null && categories.size() > 0 ) {
        category = categories.get(0);
    }

    Sku defaultSku = catalogService.createSku();
    defaultSku.setRetailPrice(new Money( price ));
    defaultSku.setInventoryType( InventoryType.ALWAYS_AVAILABLE );
    defaultSku.setName( wrapper.getName() );
    defaultSku.setLongDescription( wrapper.getLongDescription() );
    defaultSku.setDescription( wrapper.getDescription() );
    defaultSku.setUrlKey( wrapper.getUrl() );
    defaultSku.setActiveStartDate( new Date() );

    Product product = catalogService.createProduct(ProductType.PRODUCT);
    product.setDefaultSku(defaultSku);        
    product.setUrl( wrapper.getUrl() );
    product.setCategory(category);  

    List<ProductOptionXref> productOptionXrefs = new ArrayList<ProductOptionXref>();
    List<ProductOption> allProductOptions = catalogService.readAllProductOptions();        
    if ( null != allProductOptions && allProductOptions.size() > 0 ) {
        for ( ProductOption po : allProductOptions ) {          
            String current = po.getName();
            if ( current.equalsIgnoreCase("Shirt Color") ) {
                ProductOptionXref productOptionXref = new ProductOptionXrefImpl();
                productOptionXref.setProductOption(po);
                productOptionXref.setProduct(product);
                productOptionXrefs.add(productOptionXref);
            }               
        }
    }

    product.setProductOptionXrefs(productOptionXrefs);

    Product finalProduct = catalogService.saveProduct(product);
    finalProduct.getDefaultSku().setDefaultProduct(finalProduct);
    catalogService.saveSku(finalProduct.getDefaultSku());        
    Long newId = finalProduct.getId();

    ProductWrapper response;
    response = (ProductWrapper) context.getBean(ProductWrapper.class.getName());
    response.wrapDetails(product, request);
    response.setId(newId);

    return response;
}

Джон

1 ответ

Решение

Похоже, большинство из того, что у вас там, правильно. Вам не хватает обратной ссылки с Sku по умолчанию; по общему признанию это немного странно. Вы правильно поняли эту часть:

Product product = catalogService.createProduct(ProductType.PRODUCT);
product.setDefaultSku(defaultSku);

Но тогда вам также нужно убедиться, что по умолчанию sku ссылается на продукт; сначала сохраните продукт, а затем установите его:

...
Product finalProduct = catalogService.saveProduct(product);
finalProduct.getDefaultSku().setDefaultProduct(finalProduct);
catalogService.saveSku(finalProduct.getDefaultSku());

Этот код выше в настоящее время возвращает ошибку "Not-null":

Вы правы, проблема в этом коде, и это потому, что вы не устанавливаете product собственность на ProductOptionXrefImpl:

if ( current.equalsIgnoreCase("Shirt Color") ) {
    ProductOptionXref productOptionXref = new ProductOptionXrefImpl();
    productOptionXref.setProductOption(po);
    productOptionXrefs.add(productOptionXref);
}

Если вы посмотрите на product недвижимость в ProductOptionXrefImpl вы найдете это:

@ManyToOne(targetEntity = ProductImpl.class, optional=false, cascade = CascadeType.REFRESH)
@JoinColumn(name = "PRODUCT_ID")
protected Product product = new ProductImpl();

Вы проходите мимо optional=false часть, но new ProductImpl() part делает его всегда "временным" экземпляром в Hibernate; у него нет свойства ID, и Hibernate ничего об этом не знает. Так как cascade установлено только REFRESHHibernate также не пытается сохранить это или что-то (что не должно).

Исправление должно установить product Свойство по опции xref:

if ( current.equalsIgnoreCase("Shirt Color") ) {
    ProductOptionXref productOptionXref = new ProductOptionXrefImpl();
    productOptionXref.setProductOption(po);
    productOptionXref.setProduct(product);
    productOptionXrefs.add(productOptionXref);
}

Я думаю, что это будет работать, но вам, возможно, придется переместить создание варианта продукта ниже уровня первого сохранения продукта и установить его на finalProduct, Но я думаю, что, как написано, все каскады это поймут.

Другие вопросы по тегам