This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v4
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/v4 by this push:
     new 02609ec66ac CAUSEWAY-3889: consolidates ObjectIcon with font-awesome 
icon variant
02609ec66ac is described below

commit 02609ec66ac38d6536ab4f5a111bf70c5d924880
Author: Andi Huber <[email protected]>
AuthorDate: Tue Aug 19 18:35:57 2025 +0200

    CAUSEWAY-3889: consolidates ObjectIcon with font-awesome icon variant
---
 ...mainObjectLayoutAnnotationUsingIconUiEvent.java |  7 +--
 .../metamodel/facets/object/icon/IconFacet.java    |  4 +-
 .../metamodel/facets/object/icon/ObjectIcon.java   | 42 +++------------
 .../facets/object/icon/ObjectIconEmbedded.java     |  1 +
 .../{ObjectIconEmbedded.java => ObjectIconFa.java} | 15 +++---
 .../facets/object/icon/ObjectIconService.java      | 12 ++---
 .../facets/object/icon/ObjectIconUrlBased.java     | 32 ++++++++++-
 .../icon/method/IconFacetViaIconNameMethod.java    |  5 +-
 .../ident/IconFacetFromProjectionFacet.java        |  9 ++--
 .../core/metamodel/object/ManagedObject.java       | 24 +++------
 .../services/title/TitleServiceDefault.java        |  2 +-
 .../core/metamodel/spec/ObjectSpecification.java   | 11 ++--
 .../spec/impl/ObjectSpecificationDefault.java      | 14 ++---
 .../object/ident/icon/IconFacetMethodTest.java     |  2 +-
 .../icons/ObjectIconServiceDefault.java            | 50 +++++++++--------
 .../interaction/DomainObjectTesterFactory.java     |  2 +-
 .../DomainModelTest_usingGoodDomain.java           |  2 +-
 .../viewer/commons/model/mixin/HasIcon.java        | 28 ++++++++--
 .../viewer/controller/ResourceController.java      |  4 +-
 .../wicket/model/models/BookmarkableModel.java     |  6 +--
 .../viewer/wicket/model/models/UiObjectWkt.java    | 27 ++++------
 .../object/icontitle/ObjectIconAndTitlePanel.java  | 62 +++++++++++-----------
 .../services/ImageResourceCacheClassPath.java      |  4 +-
 23 files changed, 192 insertions(+), 173 deletions(-)

diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
index 4eb73f94e2e..4423e7a7e18 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
@@ -25,6 +25,7 @@
 import org.apache.causeway.applib.events.EventObjectBase;
 import org.apache.causeway.applib.events.ui.IconUiEvent;
 import org.apache.causeway.commons.internal.base._Casts;
+import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
 import org.apache.causeway.core.metamodel.facets.object.icon.IconFacet;
 import org.apache.causeway.core.metamodel.facets.object.icon.IconFacetAbstract;
@@ -68,10 +69,10 @@ public 
IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent(
     }
 
     @Override
-    public String iconName(final ManagedObject owningAdapter) {
+    public Optional<String> iconName(final ManagedObject owningAdapter) {
 
         if(ManagedObjects.isNullOrUnspecifiedOrEmpty(owningAdapter)) {
-            return null;
+            return Optional.empty();
         }
 
         final IconUiEvent<Object> iconUiEvent = newIconUiEvent(owningAdapter);
@@ -92,7 +93,7 @@ public String iconName(final ManagedObject owningAdapter) {
             }
         }
 
-        return iconName; // could be null
+        return _Strings.nonEmpty(iconName);
     }
 
     private IconUiEvent<Object> newIconUiEvent(final ManagedObject 
owningAdapter) {
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
index 7930a130a27..6380c5d450e 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
@@ -18,6 +18,8 @@
  */
 package org.apache.causeway.core.metamodel.facets.object.icon;
 
+import java.util.Optional;
+
 import org.apache.causeway.core.metamodel.facetapi.Facet;
 import org.apache.causeway.core.metamodel.facets.object.title.TitleFacet;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
@@ -39,5 +41,5 @@
  */
 public interface IconFacet extends Facet {
 
-    public String iconName(final ManagedObject object);
+    public Optional<String> iconName(final ManagedObject object);
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
index e062125270e..4a5bbcf321b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
@@ -19,11 +19,6 @@
 package org.apache.causeway.core.metamodel.facets.object.icon;
 
 import java.io.Serializable;
-import java.net.URL;
-
-import org.apache.causeway.applib.value.NamedWithMimeType.CommonMimeType;
-import org.apache.causeway.commons.internal.base._StableValue;
-import org.apache.causeway.commons.net.DataUri;
 
 /**
  * Icon image data class-path resource reference.
@@ -32,42 +27,21 @@
  * @since 2.0 revised for 4.0
  */
 public sealed interface ObjectIcon extends Serializable
-permits ObjectIconEmbedded, ObjectIconUrlBased {
-
-    // -- FACTORIES
+permits ObjectIconFa, ObjectIconEmbedded, ObjectIconUrlBased {
 
     /**
-     * Create an ObjectIcon and eagerly read in image data from
-     * class-path resources.
+     * Name for the image, usually corresponds to the domain object's class 
simple name.
      */
-    public static ObjectIcon eager(
-            final String shortName,
-            final URL url,
-            final CommonMimeType mimeType) {
-        var objectIcon = lazy(shortName, url, mimeType);
-        ((ObjectIconUrlBased) objectIcon).iconData(); // memoize
-        return objectIcon;
-    }
+    String shortName();
 
     /**
-     * Create an ObjectIcon and not yet read in image data from
-     * class-path resources.
+     * The image media type, e.g. {@code image/pdf} or {@code text/css} for 
font-awesome icons.
      */
-    public static ObjectIcon lazy(
-            final String shortName,
-            final URL url,
-            final CommonMimeType mimeType) {
-        return new ObjectIconUrlBased(shortName, url, mimeType, new 
_StableValue<>());
-    }
-
-    public static ObjectIcon embedded(String shortName, DataUri dataUri) {
-        return new ObjectIconEmbedded(shortName, dataUri);
-    }
-
-    // --
-
-    String shortName();
     String mediaType();
+
+    /**
+     * Image data as bytes (plain, no encoding) or 'quick-notation' in support 
of font awesome layers.
+     */
     byte[] iconData();
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
index 29f44cb2070..8fb64f77914 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
@@ -23,6 +23,7 @@
 /**
  * Icon image based on {@link DataUri}
  *
+ * @see ObjectIcon
  * @see ObjectIconService
  * @since 4.0
  */
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconFa.java
similarity index 75%
copy from 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
copy to 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconFa.java
index 29f44cb2070..335a4673767 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconFa.java
@@ -18,27 +18,30 @@
  */
 package org.apache.causeway.core.metamodel.facets.object.icon;
 
-import org.apache.causeway.commons.net.DataUri;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.causeway.applib.fa.FontAwesomeLayers;
 
 /**
- * Icon image based on {@link DataUri}
+ * Icon image based on {@link FontAwesomeLayers}
  *
+ * @see ObjectIcon
  * @see ObjectIconService
  * @since 4.0
  */
-public record ObjectIconEmbedded(
+public record ObjectIconFa(
         String shortName,
-        DataUri dataUri
+        FontAwesomeLayers fontAwesomeLayers
         ) implements ObjectIcon {
 
     @Override
     public String mediaType() {
-        return dataUri.mediaType();
+        return "text/css";
     }
 
     @Override
     public byte[] iconData() {
-        return dataUri.data();
+        return 
fontAwesomeLayers.toQuickNotation().getBytes(StandardCharsets.UTF_8);
     }
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
index 8af15d5b098..8c2d6bb5cf9 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
@@ -18,13 +18,12 @@
  */
 package org.apache.causeway.core.metamodel.facets.object.icon;
 
-import org.jspecify.annotations.Nullable;
+import java.util.Optional;
 
+import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 
-import org.jspecify.annotations.NonNull;
-
 /**
  * Creates {@link ObjectIcon}(s), which are class-path resource references.
  * <p>
@@ -42,11 +41,12 @@ public interface ObjectIconService {
 
     /**
      * {@link ObjectIcon} for given {@link ObjectSpecification}
-     * and iconNameSuffix.
+     * and iconNameSuffix or font-awesome layers.
      * @return non-null
      */
     ObjectIcon getObjectIcon(
-            @NonNull ObjectSpecification specification,
-            @Nullable String iconNameSuffixIfAny);
+            ObjectSpecification specification,
+            Optional<String> iconNameSuffix,
+            Optional<FontAwesomeLayers> faLayers);
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
index 1c31a4893f4..0e094b69b73 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
@@ -31,8 +31,9 @@
 /**
  * Icon image data class-path resource reference.
  *
+ * @see ObjectIcon
  * @see ObjectIconService
- * @since 2.0
+ * @since 4.0
  */
 public record ObjectIconUrlBased(
         String shortName,
@@ -41,10 +42,39 @@ public record ObjectIconUrlBased(
         _StableValue<byte[]> iconDataRef
         ) implements ObjectIcon {
 
+    // -- FACTORIES
+
+    /**
+     * Create an ObjectIcon and eagerly read in image data from
+     * class-path resources.
+     */
+    public static ObjectIcon eager(
+            final String shortName,
+            final URL url,
+            final CommonMimeType mimeType) {
+        var objectIcon = lazy(shortName, url, mimeType);
+        ((ObjectIconUrlBased) objectIcon).iconData(); // memoize
+        return objectIcon;
+    }
+
+    /**
+     * Create an ObjectIcon and not yet read in image data from
+     * class-path resources.
+     */
+    public static ObjectIcon lazy(
+            final String shortName,
+            final URL url,
+            final CommonMimeType mimeType) {
+        return new ObjectIconUrlBased(shortName, url, mimeType, new 
_StableValue<>());
+    }
+
+    // --
+
     public String cacheId() {
         return _Strings.base64UrlEncode(url.getPath());
     }
 
+    @Override
     public byte[] iconData() {
         return iconDataRef.orElseSet(()->{
             try(final InputStream is = url.openStream()){
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
index f5f35ff9a76..1bfc6e131be 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
@@ -23,6 +23,7 @@
 
 import org.jspecify.annotations.Nullable;
 
+import org.apache.causeway.commons.internal.base._Strings;
 import 
org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod;
 import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
 import org.apache.causeway.core.metamodel.facets.HasImperativeAspect;
@@ -59,8 +60,8 @@ private IconFacetViaIconNameMethod(
     }
 
     @Override
-    public String iconName(final ManagedObject domainObject) {
-        return imperativeAspect.eval(domainObject, (String)null);
+    public Optional<String> iconName(final ManagedObject domainObject) {
+        return _Strings.nonEmpty(imperativeAspect.eval(domainObject, 
(String)null));
     }
 
     @Override
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
index 97e545d419f..691e31504e1 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
@@ -18,6 +18,7 @@
  */
 package org.apache.causeway.core.metamodel.facets.object.projection.ident;
 
+import java.util.Optional;
 import java.util.function.BiConsumer;
 
 import org.apache.causeway.core.metamodel.facetapi.Facet;
@@ -41,7 +42,7 @@ public IconFacetFromProjectionFacet(
     }
 
     @Override
-    public String iconName(final ManagedObject targetAdapter) {
+    public Optional<String> iconName(final ManagedObject targetAdapter) {
         var projectedAdapter = projectionFacet.projected(targetAdapter);
         return projectedAdapter.objSpec().getIconName(projectedAdapter);
     }
@@ -55,9 +56,9 @@ public void visitAttributes(final BiConsumer<String, Object> 
visitor) {
     @Override
     public boolean semanticEquals(final @NonNull Facet other) {
         return other instanceof IconFacetFromProjectionFacet
-                ? this.projectionFacet
-                        
.semanticEquals(((IconFacetFromProjectionFacet)other).projectionFacet)
-                : false;
+            ? this.projectionFacet
+                    
.semanticEquals(((IconFacetFromProjectionFacet)other).projectionFacet)
+            : false;
     }
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
index d51f16d4975..1b23e8f2597 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
@@ -24,7 +24,6 @@
 import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
-import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.applib.services.repository.EntityState;
 import org.apache.causeway.commons.collections.Can;
@@ -33,6 +32,7 @@
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
+import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconService;
 import org.apache.causeway.core.metamodel.spec.HasObjectSpecification;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
@@ -382,31 +382,19 @@ default EntityState getEntityState() {
     // -- SHORTCUT - ICON
 
     /**
-     * Returns the name of an icon to use for this object.
-     * <p>
-     * May return <code>null</code> if no icon is specified.
+     * Optionally returns the name-suffix (or embedded image data) of an icon 
to use for this object.
+     * @see ObjectIconService
      */
-    default String getIconName() {
+    default Optional<String> getIconName() {
         return objSpec().getIconName(this);
     }
 
-    default ObjectIcon getIcon() {
-        return objSpec().getIcon(this);
-    }
-
     /**
      * Domain Objects may either have an icon corresponding to an icon 
resource,
      * or they use a font awesome icon.
      */
-    default Either<ObjectIcon, FontAwesomeLayers> eitherIconOrFaLayers() {
-        var iconName = getIconName();
-        var faLayers = objSpec().getFaLayers(this).orElse(null);
-        if (iconName != null
-                || faLayers == null) {
-            return Either.left(getIcon());
-        } else {
-            return Either.right(faLayers);
-        }
+    default ObjectIcon getIcon() {
+        return objSpec().getIcon(this);
     }
 
     default Either<ManagedObject, ManagedObject> 
asEitherWithOrWithoutMemoizedBookmark() {
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
index 2df81541a93..9d8471f18d4 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
@@ -78,7 +78,7 @@ public String iconNameOf(final Object domainObject) {
 
         return ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)
             ? "unspecified"
-            : objectAdapter.objSpec().getIconName(objectAdapter);
+            : objectAdapter.objSpec().getIconName(objectAdapter).orElse(null);
     }
 
     //-- HELPER
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
index 0b1fa9744b4..90ba1bd210e 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
@@ -59,6 +59,7 @@
 import org.apache.causeway.core.metamodel.facets.object.entity.EntityFacet;
 import org.apache.causeway.core.metamodel.facets.object.icon.IconFacet;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
+import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconService;
 import 
org.apache.causeway.core.metamodel.facets.object.immutable.ImmutableFacet;
 import org.apache.causeway.core.metamodel.facets.object.mixin.MixinFacet;
 import 
org.apache.causeway.core.metamodel.facets.object.mixin.MixinFacet.Contributing;
@@ -222,7 +223,6 @@ default Optional<MixedInAction> lookupMixedInAction(final 
ObjectSpecification mi
 
     /**
      * Returns the description, if any, of the specification.
-     *
      * <p>
      * Corresponds to the {@link HasStaticText#translated() value} of
      * {@link ObjectDescribedFacet}; is not necessarily immutable.
@@ -231,7 +231,6 @@ default Optional<MixedInAction> lookupMixedInAction(final 
ObjectSpecification mi
 
     /**
      * Returns a help string or lookup reference, if any, of the specification.
-     *
      * <p>
      * Corresponds to the {@link HelpFacet#value() value} of {@link HelpFacet};
      * is not necessarily immutable.
@@ -241,20 +240,19 @@ default Optional<MixedInAction> lookupMixedInAction(final 
ObjectSpecification mi
     /**
      * Returns the title to display of target adapter, rendered within the 
context
      * of some other adapter (if any).
-     *
      * <p>
      * @see TitleFacet#title(TitleRenderRequest)
      */
     String getTitle(TitleRenderRequest titleRenderRequest);
 
     /**
-     * Returns the name of an icon to use for the specified object.
-     *
+     * Optionally returns the name-suffix (or embedded image data) of an icon 
to use for the specified object.
      * <p>
      * Corresponds to the {@link IconFacet#iconName(ManagedObject) icon name}
      * returned by the {@link IconFacet}; is not necessarily immutable.
+     * @see ObjectIconService
      */
-    String getIconName(ManagedObject object);
+    Optional<String> getIconName(ManagedObject object);
 
     ObjectIcon getIcon(ManagedObject object);
 
@@ -267,7 +265,6 @@ default Optional<MixedInAction> lookupMixedInAction(final 
ObjectSpecification mi
 
     /**
      * Returns the CSS class name to use for the specified object.
-     *
      * <p>
      * Corresponds to the {@link CssClassFacet#cssClass(ManagedObject)} value}
      * returned by the {@link CssClassFacet}.
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
index 49a487cd84c..c53bb29536d 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
@@ -29,7 +29,9 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
+
 import org.springframework.util.ClassUtils;
 
 import org.apache.causeway.applib.Identifier;
@@ -113,7 +115,6 @@
 import static org.apache.causeway.commons.internal.base._NullSafe.stream;
 
 import lombok.Getter;
-import org.jspecify.annotations.NonNull;
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
@@ -767,19 +768,18 @@ private void notifySubscribersIfEntity(
     }
 
     @Override
-    public String getIconName(final ManagedObject domainObject) {
+    public Optional<String> getIconName(final ManagedObject domainObject) {
         if(ManagedObjects.isSpecified(domainObject)) {
             _Assert.assertEquals(domainObject.objSpec(), this);
         }
-        return iconFacet != null
-                ? iconFacet.iconName(domainObject)
-                : null;
+        return Optional.ofNullable(iconFacet)
+                .flatMap(facet->facet.iconName(domainObject));
     }
 
     @Override
     public ObjectIcon getIcon(final ManagedObject domainObject) {
-        var iconNameModifier = getIconName(domainObject);
-        return getObjectIconService().getObjectIcon(this, iconNameModifier);
+        return getObjectIconService()
+            .getObjectIcon(this, getIconName(domainObject), 
getFaLayers(domainObject));
     }
 
     @Override
diff --git 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
index 8852cefc830..2a797165dfd 100644
--- 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
+++ 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
@@ -69,7 +69,7 @@ public void tearDown() throws Exception {
     @Test
     void iconNameThrowsException() {
         //assertThrows(Exception.class, ()->facet.iconName(mockOwningAdapter));
-        final String iconName = facet.iconName(mockOwningAdapter);
+        final String iconName = facet.iconName(mockOwningAdapter).orElse(null);
         assertThat(iconName, is(nullValue()));
     }
 
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
index 5b1b3c040c6..0bd5bd6c1a3 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
@@ -28,14 +28,13 @@
 import jakarta.inject.Named;
 
 import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
-
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.core.io.ResourceLoader;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
+import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.value.NamedWithMimeType.CommonMimeType;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._StableValue;
@@ -44,7 +43,10 @@
 import org.apache.causeway.commons.internal.resources._Resources;
 import org.apache.causeway.commons.net.DataUri;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
+import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
+import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconFa;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconService;
+import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
 
@@ -80,17 +82,21 @@ public ObjectIconServiceDefault(ResourceLoader 
resourceLoader) {
 
     @Override
     public ObjectIcon getObjectIcon(
-            final @NonNull ObjectSpecification spec,
-            final @Nullable String iconNameModifier) {
+            final ObjectSpecification spec,
+            final Optional<String> iconName,
+            final Optional<FontAwesomeLayers> faLayers) {
 
         var domainClass = spec.getCorrespondingClass();
+        var iconNameSuffixIfAny = iconName.orElse(null);
 
         var suffix = "";
-        if(StringUtils.hasLength(iconNameModifier)) {
-            suffix = "-" + iconNameModifier;
-            if(iconNameModifier.startsWith("data:")) {
-                return ObjectIcon.embedded(domainClass.getSimpleName(), 
DataUri.parse(iconNameModifier));
+        if(StringUtils.hasLength(iconNameSuffixIfAny)) {
+            if(iconNameSuffixIfAny.startsWith("data:")) {
+                return new ObjectIconEmbedded(domainClass.getSimpleName(), 
DataUri.parse(iconNameSuffixIfAny));
             }
+            suffix = "-" + iconNameSuffixIfAny;
+        } else if(faLayers.isPresent()) {
+            return new ObjectIconFa(domainClass.getSimpleName(), 
faLayers.get());
         }
 
         var iconResourceKey = domainClass.getName() + suffix;
@@ -100,7 +106,7 @@ public ObjectIcon getObjectIcon(
         var cachedIcon = iconByKey.get(iconResourceKey);
         if(cachedIcon!=null) return cachedIcon;
 
-        var icon = findIcon(spec, iconNameModifier);
+        var icon = findIcon(spec, iconName);
 
         //NOTE: cannot use computeIfAbsent, as it does not support recursive 
update
         // return iconByKey.computeIfAbsent(iconResourceKey, key->
@@ -110,9 +116,10 @@ public ObjectIcon getObjectIcon(
         return icon;
     }
 
-    //@Override
+    // -- HELPER
+
     private ObjectIcon getObjectFallbackIcon() {
-        return fallbackIcon.orElseSet(()->ObjectIcon.eager(
+        return fallbackIcon.orElseSet(()->ObjectIconUrlBased.eager(
                 "ObjectIconFallback",
                 _Resources.lookupResourceUrl(
                         ObjectIconServiceDefault.class,
@@ -121,15 +128,14 @@ private ObjectIcon getObjectFallbackIcon() {
                 CommonMimeType.PNG));
     }
 
-    // -- HELPER
-
     private ObjectIcon findIcon(
-            final @NonNull ObjectSpecification spec,
-            final @Nullable String iconNameModifier) {
+            final ObjectSpecification spec,
+            final Optional<String> iconName) {
 
         var domainClass = spec.getCorrespondingClass();
-        var iconResourceNameNoExt = _Strings.isNotEmpty(iconNameModifier)
-                ? domainClass.getSimpleName() + "-" + iconNameModifier
+        var iconNameSuffixIfAny = iconName.orElse(null);
+        var iconResourceNameNoExt = _Strings.isNotEmpty(iconNameSuffixIfAny)
+                ? domainClass.getSimpleName() + "-" + iconNameSuffixIfAny
                 : domainClass.getSimpleName();
 
         // search for image in corresponding class'es resource path
@@ -142,7 +148,7 @@ private ObjectIcon findIcon(
                 .map(suffix->iconResourceNameNoExt + "." + suffix)
                 .map(iconResourceName->
                         classPathResource(domainClass, iconResourceName)
-                        .map(url->ObjectIcon.lazy(
+                        .map(url->ObjectIconUrlBased.lazy(
                                 iconResourceNameNoExt,
                                 url,
                                 imageType)))
@@ -163,7 +169,7 @@ private ObjectIcon findIcon(
                     .map(suffix->DEFAULT_IMAGE_RESOURCE_PATH + "/" + 
iconResourceNameNoExt + "." + suffix)
                     .map(iconResourcePath->
                             classPathResource(iconResourcePath)
-                            .map(url->ObjectIcon.lazy(
+                            .map(url->ObjectIconUrlBased.lazy(
                                     iconResourceNameNoExt,
                                     url,
                                     imageType)))
@@ -176,10 +182,10 @@ private ObjectIcon findIcon(
 
         return spec.superclass()!=null
             // continue search in super spec
-            ? getObjectIcon(spec.superclass(), iconNameModifier) // memoizes 
as a side-effect
-            : _Strings.isNotEmpty(iconNameModifier)
+            ? getObjectIcon(spec.superclass(), iconName, Optional.empty()) // 
memoizes as a side-effect
+            : _Strings.isNotEmpty(iconNameSuffixIfAny)
                 // also do a more generic search, skipping the modifier
-                ? getObjectIcon(spec, null) // memoizes as a side-effect
+                ? getObjectIcon(spec, Optional.empty(), Optional.empty()) // 
memoizes as a side-effect
                 : getObjectFallbackIcon();
     }
 
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
index 0015b2b5709..ae05a7f37d0 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
@@ -229,7 +229,7 @@ public void assertIcon(final @Nullable String 
expectedResult) {
                     
super.objectSpecification.getTitleService().iconNameOf(vm.getPojo()));
             assertEquals(expectedResult,
                     super.objectSpecification.lookupFacet(IconFacet.class)
-                    .map(iconFacet->iconFacet.iconName(vm))
+                    .flatMap(iconFacet->iconFacet.iconName(vm))
                     .orElse(null));
         }
 
diff --git 
a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
 
b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
index d491f9780fa..168b3d737c1 100644
--- 
a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
+++ 
b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
@@ -297,7 +297,7 @@ void titleAndIconName_shouldBeInheritable(final Class<?> 
type) throws Exception
 
             var domainObject = ManagedObject.adaptSingular(spec, instance);
             assertEquals("inherited title", domainObject.getTitle());
-            assertEquals("inherited icon", iconFacet.iconName(domainObject));
+            assertEquals("inherited icon", 
iconFacet.iconName(domainObject).orElse(null));
         }
     }
 
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
index 8feae2f6b98..e02226fd958 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
@@ -18,13 +18,35 @@
  */
 package org.apache.causeway.viewer.commons.model.mixin;
 
-import org.apache.causeway.applib.fa.FontAwesomeLayers;
-import org.apache.causeway.commons.functional.Either;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
+import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
+import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconFa;
+import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
 
 @FunctionalInterface
 public interface HasIcon {
 
-    Either<ObjectIcon, FontAwesomeLayers> getIcon();
+    ObjectIcon getIcon();
+
+    default void visitIconVariant(
+        Consumer<ObjectIconUrlBased> a,
+        Consumer<ObjectIconEmbedded> b,
+        Consumer<ObjectIconFa> c) {
+
+        var objectIcon = Objects.requireNonNull(getIcon());
+        if(objectIcon instanceof ObjectIconUrlBased urlBased){
+            a.accept(urlBased);
+        } else if(objectIcon instanceof ObjectIconEmbedded embedded){
+            b.accept(embedded);
+        } else if(objectIcon instanceof ObjectIconFa fa){
+            c.accept(fa);
+        } else {
+            throw _Exceptions.unmatchedCase(objectIcon);
+        }
+    }
 
 }
diff --git 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/ResourceController.java
 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/ResourceController.java
index 1697f895f35..bf371186770 100644
--- 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/ResourceController.java
+++ 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/controller/ResourceController.java
@@ -177,9 +177,9 @@ public ResponseEntity<byte[]> icon(
                 .map(ManagedObject::getIcon)
                 .filter(Objects::nonNull)
                 .map(objectIcon -> {
-                    var bytes = objectIcon.asBytes();
+                    var bytes = objectIcon.iconData();
                     var bodyBuilder = ResponseEntity.ok()
-                            
.contentType(MediaType.parseMediaType(objectIcon.getMimeType().getMimeType().toString()));
+                            
.contentType(MediaType.parseMediaType(objectIcon.mediaType()));
                     if (responseType == 
CausewayConfiguration.Viewer.Graphql.ResponseType.ATTACHMENT) {
                         bodyBuilder
                                 .header(HttpHeaders.CONTENT_DISPOSITION, 
ContentDisposition.attachment().filename(logicalTypeName + 
".png").build().toString())
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
index fbc2575f335..f4bdcd261a4 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
@@ -24,9 +24,7 @@
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.causeway.applib.annotation.BookmarkPolicy;
-import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
-import org.apache.causeway.commons.functional.Either;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
 import org.apache.causeway.viewer.commons.model.mixin.HasIcon;
 import org.apache.causeway.viewer.commons.model.mixin.HasTitle;
@@ -67,8 +65,8 @@ default Stream<Bookmark> streamPropertyBookmarks() {
      * I believe actions only support the former. Hence the asymmetry here.
      */
     @Override
-    default Either<ObjectIcon, FontAwesomeLayers> getIcon() {
-        return Either.left(null); // overwritten for domain objects
+    default ObjectIcon getIcon() {
+        return null; // overwritten for domain objects
     }
 
 }
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
index f60aca4186e..30b7fd68235 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
@@ -35,14 +35,12 @@
 import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.applib.services.hint.HintStore;
-import org.apache.causeway.commons.functional.Either;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.core.metamodel.commons.ViewOrEditMode;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
 import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.object.ManagedObjects;
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
@@ -186,8 +184,8 @@ public String getTitle() {
     }
 
     @Override
-    public Either<ObjectIcon, FontAwesomeLayers> getIcon() {
-        return getManagedObject().eitherIconOrFaLayers();
+    public ObjectIcon getIcon() {
+        return getManagedObject().getIcon();
     }
 
     public void visitIconVariantOrElse(
@@ -195,20 +193,17 @@ public void visitIconVariantOrElse(
             Consumer<ObjectIconEmbedded> b,
             Consumer<FontAwesomeLayers> c,
             Runnable onNoMatch) {
-        getIcon().accept(
-            objectIcon->{
-                if(objectIcon instanceof ObjectIconUrlBased urlBased){
-                    var rref = 
imageResourceCache().resourceReferenceForObjectIcon(urlBased);
-                    if(rref!=null) {
-                        a.accept(rref);
-                    } else {
-                        onNoMatch.run();
-                    }
-                } else if(objectIcon instanceof ObjectIconEmbedded embedded){
-                    b.accept(embedded);
+        visitIconVariant(
+            urlBased->{
+                var rref = 
imageResourceCache().resourceReferenceForObjectIcon(urlBased);
+                if(rref!=null) {
+                    a.accept(rref);
+                } else {
+                    onNoMatch.run();
                 }
             },
-            fontAwesomeLayers->c.accept(fontAwesomeLayers));
+            embedded->b.accept(embedded),
+            fa->c.accept(fa.fontAwesomeLayers()));
     }
 
     @Override
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
index 701faab812f..26e4a355b84 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
@@ -28,11 +28,11 @@
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.base._Text;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
+import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.object.ManagedObjects;
 import org.apache.causeway.core.metamodel.object.MmTitleUtils;
+import org.apache.causeway.viewer.commons.model.mixin.HasIcon;
 import org.apache.causeway.viewer.wicket.model.models.ObjectAdapterModel;
 import org.apache.causeway.viewer.wicket.model.models.PageType;
 import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
@@ -50,7 +50,7 @@
  * as per the provided {@link UiObjectWkt}.
  */
 class ObjectIconAndTitlePanel
-extends PanelAbstract<ManagedObject, ObjectAdapterModel> {
+extends PanelAbstract<ManagedObject, ObjectAdapterModel> implements HasIcon {
 
     private static final long serialVersionUID = 1L;
 
@@ -79,6 +79,11 @@ protected void onBeforeRender() {
         super.onBeforeRender();
     }
 
+    @Override
+    public ObjectIcon getIcon() {
+        return linkedDomainObject().getIcon();
+    }
+
     /**
      * Callback for sub-classes to add additional components.
      */
@@ -110,34 +115,31 @@ private AbstractLink createLinkWithIconAndTitle() {
             WktComponents.permanentlyHide(link, ID_OBJECT_ICON);
             Wkt.labelAdd(link, ID_OBJECT_TITLE, titleAbbreviated("(no 
object)"));
         } else {
-
-            linkedDomainObject.eitherIconOrFaLayers()
-            .accept(
-                    objectIcon->{
-                        if(objectIcon instanceof ObjectIconEmbedded 
iconEmbedded) {
-                            //TODO[causeway-viewer-wicket-ui-CAUSEWAY-3889] 
for embedded images we me might want to have a different CSS class
-                            //e.g. don't constrain image sizes, as these 
should be driven by embedded data
-                            Wkt.imageAddEmbedded(link, ID_OBJECT_ICON, 
iconEmbedded.dataUri());
-                        } else if(objectIcon instanceof ObjectIconUrlBased 
iconUrlBased) {
-                            Wkt.imageAddCachable(link, ID_OBJECT_ICON,
-                                    
getImageResourceCache().resourceReferenceForObjectIcon(iconUrlBased));
-                        } else {
-                            throw new IllegalArgumentException("Unexpected 
value: " + objectIcon);
-                        }
-
-                        WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
+            HasIcon.super.visitIconVariant(
+                iconUrlBased->{
+                    Wkt.imageAddCachable(link, ID_OBJECT_ICON,
+                        
getImageResourceCache().resourceReferenceForObjectIcon(iconUrlBased));
+                    WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
+                    WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
+                },
+                iconEmbedded->{
+                    //TODO[causeway-viewer-wicket-ui-CAUSEWAY-3889] for 
embedded images we me might want to have a different CSS class
+                    //e.g. don't constrain image sizes, as these should be 
driven by embedded data
+                    Wkt.imageAddEmbedded(link, ID_OBJECT_ICON, 
iconEmbedded.dataUri());
+                    WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
+                    WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
+                },
+                iconFa->{
+                    var faLayers = iconFa.fontAwesomeLayers();
+                    WktComponents.permanentlyHide(link, ID_OBJECT_ICON);
+                    
if(CssClassFaPosition.isLeftOrUnspecified(faLayers.position())) {
+                        Wkt.faIconLayersAdd(link, ID_OBJECT_FONT_AWESOME_LEFT, 
faLayers);
                         WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
-                    },
-                    faLayers->{
-                        WktComponents.permanentlyHide(link, ID_OBJECT_ICON);
-                        
if(CssClassFaPosition.isLeftOrUnspecified(faLayers.position())) {
-                            Wkt.faIconLayersAdd(link, 
ID_OBJECT_FONT_AWESOME_LEFT, faLayers);
-                            WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
-                        } else {
-                            WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
-                            Wkt.faIconLayersAdd(link, 
ID_OBJECT_FONT_AWESOME_RIGHT, faLayers);
-                        }
-                    });
+                    } else {
+                        WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
+                        Wkt.faIconLayersAdd(link, 
ID_OBJECT_FONT_AWESOME_RIGHT, faLayers);
+                    }
+                });
 
             final TitleRecord title = determineTitle(linkedDomainObject);
             Wkt.labelAdd(link, ID_OBJECT_TITLE, title.abbreviatedTitle());
diff --git 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
index 84d5c09fb8f..a1820f15fed 100644
--- 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
+++ 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
@@ -36,7 +36,6 @@
 import org.springframework.core.annotation.Order;
 
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
 import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
 import org.apache.causeway.viewer.wicket.model.models.ImageResourceCache;
 import 
org.apache.causeway.viewer.wicket.viewer.CausewayModuleViewerWicketViewer;
@@ -99,11 +98,10 @@ private static class ObjectIconResource
 
         private static final long serialVersionUID = 1L;
 
-        private final @NonNull ObjectIcon objectIcon;
+        private final @NonNull ObjectIconUrlBased objectIcon;
 
         @Override
         protected ResourceResponse newResourceResponse(final Attributes 
attributes) {
-
             var imageDataBytes = objectIcon.iconData();
             final long size = imageDataBytes.length;
             var resourceResponse = new ResourceResponse();


Reply via email to