Cyclic dependency problem when injecting IdSerialization into custom datatype

Hi there,

I’m facing a problem while implementing a custom datatype. Although the custom datatype is a Spring bean, it does not allow arbitrary beans to be injected.

Here is an example:

When injecting IdSerialization e.g. there is a cyclic dependency which prevents the application to start:


***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   entityManagerFactory defined in class path resource [io/jmix/autoconfigure/eclipselink/EclipselinkAutoConfiguration.class]
      ↓
   eclipselink_JmixEclipseLinkJpaVendorAdapter defined in URL [jar:file:/Users/mario/.gradle/caches/modules-2/files-2.1/io.jmix.data/jmix-eclipselink/1.1.1/56587cedf370d03cf4103ce2f883150732eb683f/jmix-eclipselink-1.1.1.jar!/io/jmix/eclipselink/impl/support/JmixEclipseLinkJpaVendorAdapter.class]
      ↓
   eclipselink_JmixEclipseLinkSessionEventListener (field private io.jmix.core.Metadata io.jmix.eclipselink.impl.support.JmixEclipseLinkSessionEventListener.metadata)
┌─────┐
|  core_Metadata defined in URL [jar:file:/Users/mario/.gradle/caches/modules-2/files-2.1/io.jmix.core/jmix-core/1.1.1/18802bfa132ccc6f4bbdab128af93691bbba51cb/jmix-core-1.1.1.jar!/io/jmix/core/impl/MetadataImpl.class]
↑     ↓
|  core_MetadataLoader defined in URL [jar:file:/Users/mario/.gradle/caches/modules-2/files-2.1/io.jmix.core/jmix-core/1.1.1/18802bfa132ccc6f4bbdab128af93691bbba51cb/jmix-core-1.1.1.jar!/io/jmix/core/impl/MetadataLoader.class]
↑     ↓
|  core_MetaModelLoader defined in URL [jar:file:/Users/mario/.gradle/caches/modules-2/files-2.1/io.jmix.core/jmix-core/1.1.1/18802bfa132ccc6f4bbdab128af93691bbba51cb/jmix-core-1.1.1.jar!/io/jmix/core/impl/MetaModelLoader.class]
↑     ↓
|  core_DatatypeRegistry defined in URL [jar:file:/Users/mario/.gradle/caches/modules-2/files-2.1/io.jmix.core/jmix-core/1.1.1/18802bfa132ccc6f4bbdab128af93691bbba51cb/jmix-core-1.1.1.jar!/io/jmix/core/impl/DatatypeRegistryImpl.class]
↑     ↓
|  idSerializationInjection (field io.jmix.core.IdSerialization io.jmix.problem.cdi.datatype.IdSerializationInjection.idSerialization)
↑     ↓
|  core_IdSerialization (field private io.jmix.core.Metadata io.jmix.core.impl.IdSerializationImpl.metadata)
└─────┘

Implementation:



@DatatypeDef(
        id = "IdSerializationInjection",
        javaClass = Entity.class
)
@Ddl("varchar(255)")
public class IdSerializationInjection implements Datatype<Entity> {

    @Autowired
    IdSerialization idSerialization;

    @Override
    public Class getJavaClass() {
        return Entity.class;
    }

    @Nonnull
    @Override
    public String format(@Nullable Object value) {
        return idSerialization.idToString(Id.ofNullable(null));
    }

    @Nonnull
    @Override
    public String format(@Nullable Object value, Locale locale) {
        return format(value);
    }

    @Nullable
    @Override
    public Entity parse(@Nullable String value) {
        return null;
    }

    @Nullable
    @Override
    public Entity parse(@Nullable String value, Locale locale) {
        return parse(value);
    }

}

See attached example project:
jmix-problem-custom-datatype-injection.zip (88.4 KB)

Do you have an idea for resolving this problem of injecting arbitrary beans into custom datatype definitions?

Cheers
Mario

Hi,
You could inject ApplicationContext to the datatype, and then obtain IdSerialization from the context when necessary.

  @Autowired
  private ApplicationContext applicationContext;

P.S. I think that what you are trying to do isn’t a good thing.
Datatype is a low-level bean that should do its formatting and parsing itself, quickly and without much dependencies.
IdSerialization uses pretty heavy operations, such as json formatting.

1 Like

Hi,

what I’m trying to replicate is the entity-soft-reference addon. In particular:

Is there any other approach that you could think of to replicate this kind of behavior?

Cheers
Mario

I would go with the similar solution to yours.

If we need to format “reference to entity” as “entity metaclass name + entity Id” string, then there is no way other then Datatype depending on Metadata Jmix bean.
This creates a circular dependency. We can avoid the startup error by autowiring ApplicationContext.

Ok, thanks. I will do it accordingly :+1: