MeetTitan MeetTitan - 1 month ago 10
reST (reStructuredText) Question

Java - Magento2 rest api product upload with image silently fails

I have a magento CE 2.1.2 storefront set up. I'd like to use Java to upload products to my store using the Magento REST API. I have managed to get 2 leg OAuth set up using Apache-commons-httpclient, and product upload actually works quite well. The problem comes when I try to upload an image with the product.

From the official catalogProductRepositoryV1 Magento docs, the json syntax is: (the important part being the "media_gallery_entries" bit)

{
"product": {
"id": 0,
"sku": "string",
"name": "string",
"attribute_set_id": 0,
"price": 0,
"status": 0,
"visibility": 0,
"type_id": "string",
"created_at": "string",
"updated_at": "string",
"weight": 0,
"extension_attributes": {
"bundle_product_options": [
{
"option_id": 0,
"title": "string",
"required": true,
"type": "string",
"position": 0,
"sku": "string",
"product_links": [
{
"id": "string",
"sku": "string",
"option_id": 0,
"qty": 0,
"position": 0,
"is_default": true,
"price": 0,
"price_type": 0,
"can_change_quantity": 0,
"extension_attributes": {}
}
],
"extension_attributes": {}
}
],
"downloadable_product_links": [
{
"id": 0,
"title": "string",
"sort_order": 0,
"is_shareable": 0,
"price": 0,
"number_of_downloads": 0,
"link_type": "string",
"link_file": "string",
"link_file_content": {
"file_data": "string",
"name": "string",
"extension_attributes": {}
},
"link_url": "string",
"sample_type": "string",
"sample_file": "string",
"sample_file_content": {
"file_data": "string",
"name": "string",
"extension_attributes": {}
},
"sample_url": "string",
"extension_attributes": {}
}
],
"downloadable_product_samples": [
{
"id": 0,
"title": "string",
"sort_order": 0,
"sample_type": "string",
"sample_file": "string",
"sample_file_content": {
"file_data": "string",
"name": "string",
"extension_attributes": {}
},
"sample_url": "string",
"extension_attributes": {}
}
],
"stock_item": {
"item_id": 0,
"product_id": 0,
"stock_id": 0,
"qty": 0,
"is_in_stock": true,
"is_qty_decimal": true,
"show_default_notification_message": true,
"use_config_min_qty": true,
"min_qty": 0,
"use_config_min_sale_qty": 0,
"min_sale_qty": 0,
"use_config_max_sale_qty": true,
"max_sale_qty": 0,
"use_config_backorders": true,
"backorders": 0,
"use_config_notify_stock_qty": true,
"notify_stock_qty": 0,
"use_config_qty_increments": true,
"qty_increments": 0,
"use_config_enable_qty_inc": true,
"enable_qty_increments": true,
"use_config_manage_stock": true,
"manage_stock": true,
"low_stock_date": "string",
"is_decimal_divided": true,
"stock_status_changed_auto": 0,
"extension_attributes": {}
},
"configurable_product_options": [
{
"id": 0,
"attribute_id": "string",
"label": "string",
"position": 0,
"is_use_default": true,
"values": [
{
"value_index": 0,
"extension_attributes": {}
}
],
"extension_attributes": {},
"product_id": 0
}
],
"configurable_product_links": [
0
]
},
"product_links": [
{
"sku": "string",
"link_type": "string",
"linked_product_sku": "string",
"linked_product_type": "string",
"position": 0,
"extension_attributes": {
"qty": 0
}
}
],
"options": [
{
"product_sku": "string",
"option_id": 0,
"title": "string",
"type": "string",
"sort_order": 0,
"is_require": true,
"price": 0,
"price_type": "string",
"sku": "string",
"file_extension": "string",
"max_characters": 0,
"image_size_x": 0,
"image_size_y": 0,
"values": [
{
"title": "string",
"sort_order": 0,
"price": 0,
"price_type": "string",
"sku": "string",
"option_type_id": 0
}
],
"extension_attributes": {}
}
],
"media_gallery_entries": [
{
"id": 0,
"media_type": "string",
"label": "string",
"position": 0,
"disabled": true,
"types": [
"string"
],
"file": "string",
"content": {
"base64_encoded_data": "string",
"type": "string",
"name": "string"
},
"extension_attributes": {
"video_content": {
"media_type": "string",
"video_provider": "string",
"video_url": "string",
"video_title": "string",
"video_description": "string",
"video_metadata": "string"
}
}
}
],
"tier_prices": [
{
"customer_group_id": 0,
"qty": 0,
"value": 0,
"extension_attributes": {}
}
],
"custom_attributes": [
{
"attribute_code": "string",
"value": "string"
}
]
},
"saveOptions": true
}


The methods I'm running:

public void uploadItem(ItemType item) throws UploadException {
try {
HttpPost postRequest = new HttpPost("http://my.magento.storefront/index.php/rest/V1/products");
postRequest.addHeader("Content-Type", "application/json");
postRequest.addHeader("Authorization", String.format("Bearer %s", authToken));
String jsonItem = itemToJson(item);
System.out.println(jsonItem);
postRequest.setEntity(new StringEntity(jsonItem));
HttpResponse postResponse = httpClient.execute(postRequest);
System.out.println();
System.out.println(EntityUtils.toString(postResponse.getEntity()));
} catch (ParseException | IOException | JSONException e) {
e.printStackTrace();
throw new UploadException(e);
}
}


private String imagesToJson(ItemType item) throws IOException {
String imageUrl = "http://my.image.jpeg"; //pulled from item in production
String encodedImage = null;
URL url = new URL(imageUrl);
try(InputStream in = new BufferedInputStream(url.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream()) {

byte[] buf = new byte[512];
for (int count = in.read(buf); count >= 0; count = in.read(buf)) {
out.write(buf, 0, count);
}
byte[] response = out.toByteArray(); //sane, I tried saving to a file and checking
encodedImage = Base64.getEncoder().encodeToString(response);
}

String picName = item.getItemID() + ".jpg";

return new JSONArray().put(
new JSONObject()
.put("position", 0)
.put("media_type", "image")
.put("disabled", "false")
.put("types", new JSONArray()
.put("image")
.put("small_image")
.put("thumbnail"))
.put("label", picName)
.put("content", new JSONObject()
.put("base64_encoded_data", encodedImage)
.put("type", "image/jpeg")
.put("name", picName))
).toString();
}


private String itemToJson(ItemType item) throws JSONException, IOException {
return new JSONObject().put("saveOptions", "true").put("product",
new JSONObject()
.put("sku", item.getItemID())
.put("name", item.getTitle())
.put("attribute_set_id", 4)
.put("price", item.getSellingStatus().getCurrentPrice().getValue())
.put("status", 0)
.put("visibility", 0)
.put("type_id", "simple")
.put("weight", item.getShippingDetails().getCalculatedShippingRate().getWeightMajor().getValue())
.put("media_gallery_entries", imagesToJson(item)))
.toString();
}


Using
uploadItem(ItemType)
, the product is uploaded to the catalog. However, there is no image on the store, and I'm given
"media_gallery_entries": []
in the response, with no further debugging help!

I think I've implemented everything correctly, so I'm unsure what to do other than SFTP and manually manage the media folder; which just sounds ugly.

Let me know if anyone needs any extra info, or omitted methods/fields.

Answer

I solved this by using Gson instead of org.json. I believe the issue was me erroneously using string literals where the server expected otherwise (namely, the boolean values).