Broadleaf 5.2 - 如何通过API将ProductOptions设置为新创建的产品?

时间:2018-04-25 22:36:44

标签: broadleaf-commerce

问题

我发现产品“ 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"
        }
    }
}

“商品”的 catgoryName 和19.00的价格

上面的代码当前返回“非空”错误:

  

Not-null属性引用瞬态值 - 瞬态实例   必须在当前操作之前保存:   org.broadleafcommerce.core.catalog.domain.ProductOptionXrefImpl.product    - &GT; org.broadleafcommerce.core.catalog.domain.ProductImpl;嵌套异常是java.lang.IllegalStateException:   org.hibernate.TransientPropertyValueException:非null属性   引用瞬态值 - 必须先保存瞬态实例   目前的运作:   org.broadleafcommerce.core.catalog.domain.ProductOptionXrefImpl.product    - &GT; org.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添加到新创建的产品的示例?

由于

乔恩

[UPDATE]

我想用解决方案更新我的问题,非常感谢@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 个答案:

答案 0 :(得分: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());
  

上面的代码目前正在返回&#34;非null&#34;错误:

你是对的,问题在于此代码,这是因为你没有在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()部分使其始终成为瞬态&#39; Hibernate实例;它没有ID属性,Hibernate对此一无所知。由于cascade仅设置为REFRESH,因此Hibernate也不会尝试保留它或任何东西(它不应该)。

修复方法是在选项xref:

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

认为这将有效,但您可能必须将产品选项创建移至第一次保存产品之下,并将其设置为finalProduct。但我认为所写的所有级联都能解决这个问题。