class ComponentsEndpoint {

    private final SofaRuntimeContext sofaRuntimeContext;

    /**
     * Creates a new {@code SofaBootComponentsEndPoint} that will describe the components in the {@link SofaRuntimeContext}
     *
     * @param sofaRuntimeContext the sofa runtime context
     */
    public ComponentsEndpoint(SofaRuntimeContext sofaRuntimeContext) {
        this.sofaRuntimeContext = sofaRuntimeContext;
    }

    @ReadOperation
    public ComponentsDescriptor components() {<FILL_FUNCTION_BODY>}

    public static final class ComponentsDescriptor implements OperationResponseBody {

        private final Map<String, Collection<ComponentDisplayInfo>> componentsInfoMap;

        private ComponentsDescriptor(Map<String, Collection<ComponentDisplayInfo>> componentsInfoMap) {
            this.componentsInfoMap = componentsInfoMap;
        }

        public Map<String, Collection<ComponentDisplayInfo>> getComponentsInfoMap() {
            return this.componentsInfoMap;
        }
    }

    public static final class ComponentDisplayInfo {

        private final String       name;

        private final String       applicationId;

        private List<PropertyInfo> properties;

        private ComponentDisplayInfo(String name, String applicationId,
                                     List<PropertyInfo> properties) {
            this.name = name;
            this.applicationId = applicationId;
            this.properties = properties;
        }

        public String getName() {
            return name;
        }

        public String getApplicationId() {
            return applicationId;
        }

        public List<PropertyInfo> getProperties() {
            return properties;
        }
    }

    public static final class PropertyInfo {
        private String name;

        private Object value;

        public PropertyInfo(Property property) {
            this.name = property.getName();
            this.value = property.getValue();
        }

        public PropertyInfo(String name, Object value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public Object getValue() {
            return value;
        }
    }

}

        ComponentManager componentManager = sofaRuntimeContext.getComponentManager();
        Map<String, Collection<ComponentDisplayInfo>> componentsInfoMap = new HashMap<>();
        Collection<ComponentType> componentTypes = componentManager.getComponentTypes();
        componentTypes.forEach(componentType -> {
            Collection<ComponentInfo> componentInfos = componentManager.getComponentInfosByType(componentType);
            Collection<ComponentDisplayInfo> componentDisplayInfos = componentInfos.stream()
                    .map(componentInfo -> {
                        String applicationId = componentInfo.getApplicationContext() == null ? "null"
                                : componentInfo.getApplicationContext().getId();
                        Map<String, Property> propertyMap = componentInfo.getProperties();
                        return new ComponentDisplayInfo(componentInfo.getName().getName(), applicationId,
                                propertyMap != null ? propertyMap.values().stream().map(PropertyInfo::new).collect(Collectors.toList())
                                        : null);
                    })
                    .collect(Collectors.toList());
            componentsInfoMap.put(componentType.getName(), componentDisplayInfos);
        });
        return new ComponentsDescriptor(componentsInfoMap);
    
<no_super_class>