Image component from (external) URL

We tried to implement (backoffice) screens with entity properties representing an image which is not hosted by the Jmix application (e.g. an avatar image of a user).

Unfortunately ImageImpl does not cover resource objects of the types or So I implemented an extension of ImageImpl which is not a big deal:

public class ExtImageImpl<V> extends ImageImpl<V>

    protected Resource createImageResource(@Nullable final Object aResourceObject)
        final Resource result;
        if (aResourceObject instanceof URL)
            final URL url = (URL) aResourceObject;

            final UrlResource urlResource = new UrlResourceImpl();

            result = urlResource;
        else if (aResourceObject instanceof URI)
            final URI url = (URI) aResourceObject;

            UrlResource urlResource;
                urlResource = new UrlResourceImpl();
            catch (final MalformedURLException ex)
                urlResource = null;
                if (LOGGER.isDebugEnabled())
                    // should never happen
                    LOGGER.debug(String.format("Could not create image resource from malformed URL: %s. %s", url,
                                    ex.getLocalizedMessage()), ex);

            result = urlResource;
            result = super.createImageResource(aResourceObject);

        return result;

But using this implementation seemed to be tough. The only way which worked so far is pretty hacky:

protected void onInit(final InitEvent anEvent)
    usersTable.addGeneratedColumn("avatar", entity -> {
         * uiComponents.create(ExtImageImpl.class)
         * Does not help because it's simple ignored and the standard implementation is created.
         * So we create the instance ourselves and post-process the creation it manually.
        final Image<FileRef> image = new ExtImageImpl<>();
        UiComponentUtils.processApplicationContext(image, getApplicationContext());
        image.setValueSource(new ContainerValueSource<>(usersTable.getInstanceContainer(entity), "avatar"));

        return image;

In UiComponentUtils we copied some code from UiComponentsImpl. Of course, that is not a sustainable approach.

  1. Is there a clean/proper way to implement own components?
  2. I there a reason for not supporting image components with non-application URLs?

Have you tried using Image.setSource(UrlResource.class).setUrl(...) ?
See code sample and information in the docs:

1 Like

@albudarov No, we did not - but I did right now. This makes creating an own component obsolete.

Let me tell, why we tried this at all:

Not in the browse screen (I don’t know how to add a table column with an image component) but in the detail screen, we defined an image component with the image URL property of type as property attribute: <image id="userAvatarComp" property="avatar"/>

This causes an exception:
io.jmix.ui.GuiDevelopmentException: The Image component does not support property value binding for the property of type:, frameId=…
at io.jmix.ui.component.impl.ImageImpl.createImageResource(
at io.jmix.ui.component.impl.ImageImpl.updateComponent(
at io.jmix.ui.component.impl.ImageImpl.lambda$bindValueSourceEvents$1(

That’s the reason for our approach, to add some more type support on ImageImpl.createImageResource(Object).

Your suggestion makes creating a custom component and it’s hacky use obsolete. Thank you so far.

But still I have to convert the entity attribute into an including handling the (to be) handled before setting the UrlResouce.

Maybe this could be improved a little more?

@bank thanks for the feedback!
Created issue:

1 Like