Zend certified PHP/Magento developer

Can’t get extension attribute in a plugin

I am trying to create a module that uploads Category image (as Category extension attribute) via REST API. The problem is that I can’t even fetch extension attributes in afterSave method of my Plugin with the lines of code below:

$extensionAttributes = $category->getExtensionAttributes() ?: $this->categoryExtensionFactory->create();

Though, obviously, extension attribute is set in my API request to
https://{{magento2_root}}/rest/async/bulk/V1/categories

[
    {
        "category": {
            "parent_id": 229,
            "name": "Мобільний телефон Nokia 214100",
            "is_active": true,
            "position": 1,
            "level": 4,
            "include_in_menu": true,
            "extension_attributes": {
                "category_id": 456,
                "api_uploaded_image": "OnsL"
            },
            "custom_attributes": [
                {
                    "attribute_code": "image",
                    "value": "nokia_62100.jpg"
                },
                 {
                    "attribute_code": "description",
                    "value": "Good Nokia 62100"
                }
            ]
        }
    },
    {
        "category": {
            "parent_id": 229,
            "name": "Мобільний телефон Nokia 215100",
            "is_active": true,
            "position": 1,
            "level": 4,
            "include_in_menu": true,
            "extension_attributes": {
                "category_id": 457,
                "api_uploaded_image": "OnsL"
            },
            "custom_attributes": [
                {
                    "attribute_code": "image",
                    "value": "nokia_62100.jpg"
                },
                 {
                    "attribute_code": "description",
                    "value": "Good Nokia 62100"
                }
            ]
        }
    }
]

The server gets “extension_attributes” “api_uploaded_image” and “category_id” with empty values (detailed status of bulk action with https://{{magento2_root}}/rest/V1/bulk/d6c6c3d0-5efc-4354-b52a-4dd782592515/detailed-status):

{
    "operations_list": [
        {
            "id": 0,
            "bulk_uuid": "0fb26252-3e8b-430d-a6d8-d4d791e5c5ce",
            "topic_name": "async.magento.catalog.api.categoryrepositoryinterface.save.post",
            "serialized_data": null,
            "result_serialized_data":"{"id":457,"parent_id":229,"name":"Мобільний телефон Nokia 214100","is_active":true,"position":1,"level":4,"children":"","created_at":"2022-09-24 17:20:40","updated_at":"2022-09-24 17:20:40","path":"1\/2\/161\/229\/457","available_sort_by":[],"include_in_menu":true,"extension_attributes":{"api_uploaded_image":"","category_id":0},"custom_attributes":[{"attribute_code":"description","value":"Good Nokia 62100"},{"attribute_code":"image","value":"nokia_62100.jpg"},{"attribute_code":"is_anchor","value":"1"},{"attribute_code":"path","value":"1\/2\/161\/229\/457"},{"attribute_code":"children_count","value":"0"},{"attribute_code":"url_key","value":"mobil-nij-telefon-nokia-214100"},{"attribute_code":"url_path","value":"telefoni1\/nedorogi-mobil-ni-telefoni\/mobil-nij-telefon-nokia-214100"},{"attribute_code":"use_name_in_product_search","value":"1"},{"attribute_code":"is_virtual_category","value":"0"},{"attribute_code":"virtual_rule","value":{"condition":{"condition_type":"Smile\\ElasticsuiteVirtualCategory\\Model\\Rule\\Condition\\Combine","aggregator_type":"all","operator":null,"value":true}}},{"attribute_code":"use_store_positions","value":"0"}]}",
            "status": 1,
            "result_message": "Service execution success Magento\Catalog\Model\CategoryRepository\Interceptor::save",
            "error_code": null
        },
        {
            "id": 1,
            "bulk_uuid": "0fb26252-3e8b-430d-a6d8-d4d791e5c5ce",
            "topic_name": "async.magento.catalog.api.categoryrepositoryinterface.save.post",
            "serialized_data": null,
            "result_serialized_data":"{"id":458,"parent_id":229,"name":"Мобільний телефон Nokia 215100","is_active":true,"position":1,"level":4,"children":"","created_at":"2022-09-24 17:20:41","updated_at":"2022-09-24 17:20:41","path":"1\/2\/161\/229\/458","available_sort_by":[],"include_in_menu":true,"extension_attributes":{"api_uploaded_image":"","category_id":0},"custom_attributes":[{"attribute_code":"description","value":"Good Nokia 62100"},{"attribute_code":"image","value":"nokia_62100.jpg"},{"attribute_code":"is_anchor","value":"1"},{"attribute_code":"path","value":"1\/2\/161\/229\/458"},{"attribute_code":"children_count","value":"0"},{"attribute_code":"url_key","value":"mobil-nij-telefon-nokia-215100"},{"attribute_code":"url_path","value":"telefoni1\/nedorogi-mobil-ni-telefoni\/mobil-nij-telefon-nokia-215100"},{"attribute_code":"use_name_in_product_search","value":"1"},{"attribute_code":"is_virtual_category","value":"0"},{"attribute_code":"virtual_rule","value":{"condition":{"condition_type":"Smile\\ElasticsuiteVirtualCategory\\Model\\Rule\\Condition\\Combine","aggregator_type":"all","operator":null,"value":true}}},{"attribute_code":"use_store_positions","value":"0"}]}",
            "status": 1,
            "result_message": "Service execution success Magento\Catalog\Model\CategoryRepository\Interceptor::save",
            "error_code": null
        }
    ],
    "user_type": 2,
    "bulk_id": "0fb26252-3e8b-430d-a6d8-d4d791e5c5ce",
    "description": "Topic async.magento.catalog.api.categoryrepositoryinterface.save.post",
    "start_time": "2022-09-24 17:20:40",
    "user_id": 1,
    "operation_count": 2
}

1. db_schema.xml

<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="sl_category_image_via_api_attribute" resource="default" engine="innodb" comment="Category Images Sent Via API Table">
        <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Entity ID"/>
        <column xsi:type="int" name="category_id" padding="10" unsigned="true" nullable="false" identity="false" comment="Category ID"/>
        <column xsi:type="varchar" name="api_uploaded_image" nullable="false" comment="Base64 Encoded Images"/>
        <column xsi:type="timestamp" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP" comment="Create Time"/>
        <column xsi:type="timestamp" name="updated_at" on_update="true" nullable="false" default="CURRENT_TIMESTAMP" comment="Update Time"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="entity_id"/>
        </constraint>
        <constraint xsi:type="foreign" referenceId="SL_CTGRY_IMG_VIA_API_ATTR_CATEGORY_ID_CATALOG_CTGRY_ENTT_ENTT_ID"
                    table="sl_category_image_via_api_attribute" column="category_id" referenceTable="catalog_category_entity"
                    referenceColumn="entity_id" onDelete="CASCADE"/>
    </table>
</schema>

In a case I set nullable=”true” for name=”api_uploaded_image” attribute in db_schema.xml:

<column xsi:type="varchar" name="api_uploaded_image" nullable="true" comment="Base64 Encoded Images"/>

then I can save my custom entity in a custom table with “api_uploaded_image” column and NULL value:

How can I retrive category extension attribute in a Plugin (afterSave method) and then save it to my custom table?

I will be appreciate for your help.
Thanks in advance.

2. The full code of Plugin

<?php

declare(strict_types=1);

namespace SlCategoryImageApiUploadPlugin;

use MagentoCatalogApiDataCategoryExtensionFactory;
use SlCategoryImageApiUploadApiManagementInterface;
use MagentoCatalogApiDataCategoryInterface;
use MagentoCatalogApiDataCategorySearchResultsInterface;
use MagentoCatalogApiCategoryRepositoryInterface;
use SlCategoryImageApiUploadModelAttributesFactory;
use SlCategoryImageApiUploadModelAttributesResource;
use PsrLogLoggerInterface;

class CategoryRepositoryPlugin
{
    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

    /**
     * @var ManagementInterface
     */
    private ManagementInterface $management;

    /**
     * @var AttributesFactory
     */
    private AttributesFactory $attributesFactory;
    /**
     * @var AttributesResource
     */
    private AttributesResource $attributesResource;
    /**
     * @var CategoryExtensionFactory
     */
    private CategoryExtensionFactory $categoryExtensionFactory;

    /**
     * CategoryRepositoryPlugin constructor.
     * @param AttributesFactory $attributesFactory
     * @param AttributesResource $attributesResource
     * @param ManagementInterface $management
     * @param CategoryExtensionFactory $categoryExtensionFactory
     */
    public function __construct(
        AttributesFactory $attributesFactory,
        AttributesResource $attributesResource,
        CategoryExtensionFactory $categoryExtensionFactory,
        ManagementInterface $management,
        LoggerInterface $logger
    ) {
        $this->attributesFactory = $attributesFactory;
        $this->attributesResource = $attributesResource;
        $this->categoryExtensionFactory = $categoryExtensionFactory;
        $this->management = $management;
        $this->logger = $logger;
    }

    /**
     * @param CategoryRepositoryInterface $subject
     * @param CategorySearchResultsInterface $categorySearchResult
     * @return CategorySearchResultsInterface
     */
    public function afterGetList(
        CategoryRepositoryInterface $subject,
        CategorySearchResultsInterface $categorySearchResult
    ): CategorySearchResultsInterface {
        foreach ($categorySearchResult->getItems() as $category) {
            $this->afterGet($subject, $category);
        }
        return $categorySearchResult;
    }

    /**
     * @param CategoryRepositoryInterface $subject
     * @param CategoryInterface $category
     * @return CategoryInterface
     */
    public function afterGet(
        CategoryRepositoryInterface $subject,
        CategoryInterface $category
    ): CategoryInterface {
        $categoryAttribute = $this->management->getByCategoryId((int) $category->getId());

        $extensionAttributes = $category->getExtensionAttributes();
        $extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
        $extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());

        $category->setExtensionAttributes($extensionAttributes);

        return $category;
    }

    /**
     * @param CategoryRepositoryInterface $subject
     * @param CategoryInterface $category
     * @return CategoryInterface
     */
    public function afterSave(
        CategoryRepositoryInterface $subject,
        CategoryInterface $category
    ): CategoryInterface {
//        $categoryAttribute = $this->management->getByCategoryId((int) $category->getId());
//        $categoryCollection = $this->categoryFactory->create()->getAttributesCollection();

        $extensionAttributes = $category->getExtensionAttributes() ?: $this->categoryExtensionFactory->create();
        if ($extensionAttributes !== null && $extensionAttributes->getApiUploadedImage() !==null) {
//            $extensionAttributes->setApiUploadedImage($extensionAttributes->getApiUploadedImage());
            $attributesEntity = $this->attributesFactory->create();
            $attributesEntity->setCategoryId($category->getId());
            $attributesEntity->setApiUploadedImage($extensionAttributes->getApiUploadedImage());
//            $this->logger->debug('valuer=' .serialize($attributesEntity));
            $this->management->save($attributesEntity);
//            $this->attributesRepository->save($attributesEntity);
//            $this->$subject->save();
        }
//        $extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
//        $extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());

//        $category->setExtensionAttributes($extensionAttributes);

        return $category;
    }
}