Hibernate Search 6 - Advanced mapping

Hello,

i try to normalize a document wich has embedded entity not directly mapped but referenced with intermediate entity

{Person} → @OneToMany → {PersonAssociationHistory} → @ManyToOne → {Person}

In my business case i need to find the current person attached to the last PersonnAssociationHistory, and it could be great to index that in my Person document

{
  "firstname": "person 1",
  "lastname": "person 1",
  "lastAssociatedPerson": {
     "firstname": "person 2",
     "lastname": "person 2"
  }
}

i start with something like that

@Transient
	@IndexedEmbedded(includePaths = {"firstname", "lastname"})
	@IndexingDependency(
			derivedFrom = {
					@ObjectPath(@PropertyValue(propertyName = "history.person")))
			})
	public Person getLastAssociatedPerson() {

at the creation of the index, HSearch doesn’t have enougth information to handle it, the error says

you can disable reindexing with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.NO)

but if i do that, Person 1 wont reindexed when Person 2 is updated.

Is it possible to do this kind of mapping with the current annotations ?

Can you give me the full code of the Person and PersonAssociationHistory entities, and more importantly the full error message, please?

Hi !

i try to simplify the example with my previous post ^^ but here the real context.
The association between the person refers to their history like a mariage, divorce etc…

Here the error :

    Hibernate ORM mapping: 
        type 'com.allegoria.notariat.business.ClientPhysique': 
            path '.conjoint<no value extractors>.dateNe<no value extractors>': 
                failures: 
                  - HSEARCH700020: Cannot find the inverse side of the association on type 'com.allegoria.notariat.business.ClientPhysique' at path '.conjoint<no value extractors>'. Hibernate Search needs this information in order to reindex 'com.allegoria.notariat.business.ClientPhysique' when 'com.allegoria.notariat.business.ClientPhysique' is modified. You can solve this error by defining the inverse side of this association,  either with annotations specific to your integration (@OneToMany(mappedBy = ...) in Hibernate ORM)  or with the Hibernate Search @AssociationInverseSide annotation. Alternatively, if you do not need to reindex 'com.allegoria.notariat.business.ClientPhysique' when 'com.allegoria.notariat.business.ClientPhysique' is modified, you can disable reindexing with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.NO).
            path '.conjoint<no value extractors>.nom<no value extractors>': 
                failures: 
                  - HSEARCH700020: Cannot find the inverse side of the association on type 'com.allegoria.notariat.business.ClientPhysique' at path '.conjoint<no value extractors>'. Hibernate Search needs this information in order to reindex 'com.allegoria.notariat.business.ClientPhysique' when 'com.allegoria.notariat.business.ClientPhysique' is modified. You can solve this error by defining the inverse side of this association,  either with annotations specific to your integration (@OneToMany(mappedBy = ...) in Hibernate ORM)  or with the Hibernate Search @AssociationInverseSide annotation. Alternatively, if you do not need to reindex 'com.allegoria.notariat.business.ClientPhysique' when 'com.allegoria.notariat.business.ClientPhysique' is modified, you can disable reindexing with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.NO).
            path '.conjoint<no value extractors>.prenom<no value extractors>': 
                failures: 
                  - HSEARCH700020: Cannot find the inverse side of the association on type 'com.allegoria.notariat.business.ClientPhysique' at path '.conjoint<no value extractors>'. Hibernate Search needs this information in order to reindex 'com.allegoria.notariat.business.ClientPhysique' when 'com.allegoria.notariat.business.ClientPhysique' is modified. You can solve this error by defining the inverse side of this association,  either with annotations specific to your integration (@OneToMany(mappedBy = ...) in Hibernate ORM)  or with the Hibernate Search @AssociationInverseSide annotation. Alternatively, if you do not need to reindex 'com.allegoria.notariat.business.ClientPhysique' when 'com.allegoria.notariat.business.ClientPhysique' is modified, you can disable reindexing with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.NO).
            path '.conjoint<no value extractors>': 
                failures: 
                  - HSEARCH800010: Unable to find a readable property 'matrimoniauxMadame.monsieur' on type 'com.allegoria.notariat.business.ClientPhysique'.
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
	... 100 common frames omitted
Caused by: org.hibernate.search.util.common.SearchException: HSEARCH000520: Hibernate Search bootstrap failed. Failures:

Here an extract of BasicClientPhysique

@MappedSuperclass
public abstract class BasicClientPhysique extends Personne {
    [...]
    @OneToMany(mappedBy = "monsieur")
	protected java.util.Set<com.allegoria.notariat.business.EtatMatrimonial> matrimoniauxMonsieur = new java.util.HashSet<>();
    [...]
    @Textuel
	@Transient
        // some try lol...
	@IndexedEmbedded(includePaths = {ClientPhysique_.NOM, ClientPhysique_.PRENOM, ClientPhysique_.DATE_NE})
	@IndexingDependency(
		derivedFrom = {
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMadame.monsieur")),
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMadame.madame")),
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMonsieur.monsieur")),
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMonsieur.madame"))
	})
	public ClientPhysique getConjoint() {
		// some code to retrive the current husband or wife
	}
}

And Here the class listing the association (the marital history)

@MappedSuperclass
public abstract class BasicEtatMatrimonial extends BusinessObject {
    [...]
    protected java.util.Date dateMariage;
	protected java.util.Date dateDivorce;
    protected java.util.Date modifieLe;
	protected java.util.Date supprimeLe;
    // here the reference i want to normalize directly in my ClientPhysique document
    @ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "monsieur_fk")
	protected com.allegoria.notariat.business.ClientPhysique monsieur;
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "madame_fk")
	protected com.allegoria.notariat.business.ClientPhysique madame;
    [...]
}

There’s something fishy. I suspect there is a bug, as I wouldn’t expect “conjoint” to matter in this case, since it’s a “computed” association.
@IndexingDependency was originally intended only for “value” properties, returning a string or some other immutable value, which explains why this doesn’t work well. But that’s definitely a valid use case, so I will have a look.

In the meantime… I suppose when you call getConjoint() on a given person A and it returns B, then calling getConjoint() on B will return A? If so, please try the code below. It will tell Hibernate Search that the opposite side of the “conjoint” association is “conjoint” too, which should allow the engine to determine reindexing conditions.

    @Textuel
	@Transient
	@IndexedEmbedded(includePaths = {ClientPhysique_.NOM, ClientPhysique_.PRENOM, ClientPhysique_.DATE_NE})
// Below is the new code
@AssociationInverseSide(inversePath = @ObjectPath(@PropertyValue(propertyName = "conjoint")))
// end new code
	@IndexingDependency(
		derivedFrom = {
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMadame.monsieur")),
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMadame.madame")),
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMonsieur.monsieur")),
			@ObjectPath(@PropertyValue(propertyName = "matrimoniauxMonsieur.madame"))
	})
	public ClientPhysique getConjoint() {
		// some code to retrive the current husband or wife
	}

I’ll post another message here once I get some time to investigate.

Ok, with the new code
@AssociationInverseSide(inversePath = @ObjectPath(@PropertyValue(propertyName = “conjoint”)))

I’m able to index my document as expected with fullIndexer

Here is the mapping seen from kibana

{
  "mapping": {
    "dynamic": "strict",
    "properties": {
      "__HSEARCH_id": {
        "type": "keyword",
        "store": true
      },
      "__HSEARCH_tenantId": {
        "type": "keyword",
        "store": true
      },
      "conjoint": {
        "dynamic": "strict",
        "properties": {
          "dateNe": {
            "type": "date",
            "doc_values": false,
            "format": "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"
          },
          "nom": {
            "type": "keyword",
            "doc_values": false
          },
          "prenom": {
            "type": "keyword",
            "doc_values": false
          },
          "uuid": {
            "type": "keyword",
            "doc_values": false
          }
        }
      },
      "dateNe": {
        "type": "date",
        "doc_values": false,
        "format": "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"
      },
      "nom": {
        "type": "keyword",
        "doc_values": false
      },
      "prenom": {
        "type": "keyword",
        "doc_values": false
      },
      "uuid": {
        "type": "keyword",
        "doc_values": false
      }
    }
  }
}

Here an example of two indexed ClientPhysique

1

"_source": {
    "uuid": "8cebe01d-b9cf-45c8-956c-00b7d6252c98",
    "dateNe": "1984-11-25T23:00:00.000000000Z",
    "nom": "test444",
    "prenom": "Vanessa, Fatima",
    "conjoint": {
      "uuid": "a4dc702e-4253-4134-94ad-fb14206eb0ea",
      "dateNe": "1982-10-21T23:00:00.000000000Z",
      "nom": "LOSSIGNOL",
      "prenom": "Vincent, Nicolas"
    },
    "__HSEARCH_id": "2828",
    "__HSEARCH_tenantId": ""
  },

2

"_source": {
    "uuid": "a4dc702e-4253-4134-94ad-fb14206eb0ea",
    "dateNe": "1982-10-21T23:00:00.000000000Z",
    "nom": "LOSSIGNOL",
    "prenom": "Vincent, Nicolas",
    "conjoint": {
      "uuid": "8cebe01d-b9cf-45c8-956c-00b7d6252c98",
      "dateNe": "1984-11-25T23:00:00.000000000Z",
      "nom": "test444",
      "prenom": "Vanessa, Fatima"
    },
    "__HSEARCH_id": "2827",
    "__HSEARCH_tenantId": ""
  },

Now my next issue is when i try to update one side of the association it’s not updating correctly the embedded document, actually, the object i just updated loose his embeded document.

ClientPhysique c = rootRepository.get(ClientPhysique.class, 2828l);
c.setNom("test2000");
rootRepository.saveOrUpdate(c);

here the indexed documents after the update of one side

Here the entity i just update (id 2828l) which loose his conjoint

"_source": {
    "uuid": "8cebe01d-b9cf-45c8-956c-00b7d6252c98",
    "dateNe": "1984-11-25T23:00:00.000000000Z",
    "nom": "test2000",
    "prenom": "Vanessa, Fatima",
    "conjoint": {
      "uuid": null,
      "dateNe": null,
      "nom": null,
      "prenom": null
    },
    "__HSEARCH_id": "2828",
    "__HSEARCH_tenantId": ""
  }

Here the other entity, everything fine

"_source": {
    "uuid": "a4dc702e-4253-4134-94ad-fb14206eb0ea",
    "dateNe": "1982-10-21T23:00:00.000000000Z",
    "nom": "LOSSIGNOL",
    "prenom": "Vincent, Nicolas",
    "conjoint": {
      "uuid": "8cebe01d-b9cf-45c8-956c-00b7d6252c98",
      "dateNe": "1984-11-25T23:00:00.000000000Z",
      "nom": "test2000",
      "prenom": "Vanessa, Fatima"
    },
    "__HSEARCH_id": "2827",
    "__HSEARCH_tenantId": ""
  }

If i do this , documents are both ok but i’am not sure it’s relevant

ClientPhysique c = rootRepository.get(ClientPhysique.class, 2827l);
c.setNom("left side 1");
rootRepository.saveOrUpdate(c);
ClientPhysique c2 = rootRepository.get(ClientPhysique.class, 2828l);
c2.setNom("right side 1");
rootRepository.saveOrUpdate(c2);

The last version of my annotations :

    @Textuel
	@Transient
	@IndexedEmbedded(includePaths = {
			ClientPhysique_.UUID, ClientPhysique_.NOM, ClientPhysique_.PRENOM, ClientPhysique_.DATE_NE
	})
	@AssociationInverseSide(inversePath = @ObjectPath(@PropertyValue(propertyName = "conjoint")))
	@IndexingDependency(
			derivedFrom = {
					@ObjectPath({@PropertyValue(propertyName = "matrimoniauxMadame"), @PropertyValue(propertyName = "monsieur"), @PropertyValue(propertyName = "nom")}),
					@ObjectPath({@PropertyValue(propertyName = "matrimoniauxMadame"), @PropertyValue(propertyName = "madame"), @PropertyValue(propertyName = "nom")}),
					@ObjectPath({@PropertyValue(propertyName = "matrimoniauxMonsieur"), @PropertyValue(propertyName = "monsieur"), @PropertyValue(propertyName = "nom")}),
					@ObjectPath({@PropertyValue(propertyName = "matrimoniauxMonsieur"), @PropertyValue(propertyName = "madame"), @PropertyValue(propertyName = "nom")})
			}
	)
	public ClientPhysique getConjoint() {
		// compute conjoint
		return conjoint;
	}

I try to specify every property on the path on every associations used for the computing of conjoint but, it not working better

I will need some more logs. Could you please enable logs at the debug level for org.hibernate.search?
Then you will see logs like this on bootstrap:

15:35:58,908 (main) DEBUG PojoIndexedTypeManagerBuilder:137 - HSEARCH700017: Created POJO indexed type manager: {
	indexedJavaClass=class org.hibernate.search.integrationtest.mapper.orm.smoke.AnnotationMappingSmokeIT$IndexedEntity
	indexManager=org.hibernate.search.engine.common.impl.MappedIndexManagerImpl@3adbe50f
	identifierMapping=org.hibernate.search.mapper.pojo.bridge.mapping.impl.PropertyIdentifierMapping@3a627c80
	routingKeyProvider=org.hibernate.search.mapper.pojo.bridge.mapping.impl.RoutingKeyProvider$$Lambda$236/234857227@49aa766b
	processor={
		class=PojoIndexingProcessorTypeNode
		parentIndexObjectReferences=[]
		bridges=[
			org.hibernate.search.integrationtest.mapper.orm.smoke.bridge.CustomTypeBridge@963176
		]
....

Or like that:

15:39:08,697 (main) DEBUG PojoMapper:252 - HSEARCH700019: Created POJO contained type manager: {
	javaClass=class org.hibernate.search.integrationtest.mapper.orm.automaticindexing.AutomaticIndexingListAssociationIT$ContainedEntity
	reindexingResolver={
...

They describe how Hibernate Search behaves exactly when you change a property.

I will need these logs (the first line, and all the following lines).

Here the logs

2019-07-23 15:44:54,170 .m.p.m.b.i.PojoIndexedTypeManagerBuilder   [D] HSEARCH700017: Created POJO indexed type manager: {
	indexedJavaClass=class com.allegoria.notariat.business.ClientPhysique
	indexManager=org.hibernate.search.engine.common.impl.MappedIndexManagerImpl@32830a26
	identifierMapping=org.hibernate.search.mapper.pojo.bridge.mapping.impl.PropertyIdentifierMapping@51480ed6
	routingKeyProvider=org.hibernate.search.mapper.pojo.bridge.mapping.impl.RoutingKeyProvider$$Lambda$498/0x0000000100a90040@d826178
	processor={
		class=PojoIndexingProcessorTypeNode
		parentIndexObjectReferences=[]
		bridges=[
		]
		propertyNodes=[
			{
				class=PojoIndexingProcessorPropertyNode
				handle=MethodHandleValueReadHandle[private java.util.UUID com.allegoria.notariat.business.BusinessObject.uuid]
				bridges=[
				]
				nestedNodes=[
					{
						class=PojoIndexingProcessorValueBridgeNode
						bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@975e026
						indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=null], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchTextFieldPredicateBuilderFactory@40a3ae92, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@6a5b4e9a, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@7b74c3b9], relativeAccessor=.uuid]
					}
				]
			}
			{
				class=PojoIndexingProcessorPropertyNode
				handle=MethodHandleValueReadHandle[protected java.util.Date com.allegoria.notariat.business.BasicClientPhysique.dateNe]
				bridges=[
				]
				nestedNodes=[
					{
						class=PojoIndexingProcessorValueBridgeNode
						bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@5da66821
						indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=null], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchStandardFieldPredicateBuilderFactory@2c9a39, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@30b33b38, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@6d075f9c], relativeAccessor=.dateNe]
					}
				]
			}
			{
				class=PojoIndexingProcessorPropertyNode
				handle=MethodHandleValueReadHandle[protected java.lang.String com.allegoria.notariat.business.BasicClientPhysique.nom]
				bridges=[
				]
				nestedNodes=[
					{
						class=PojoIndexingProcessorValueBridgeNode
						bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@30ec57d
						indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=null], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchTextFieldPredicateBuilderFactory@67176a77, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@4ed4e756, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@19f8aaaf], relativeAccessor=.nom]
					}
				]
			}
			{
				class=PojoIndexingProcessorPropertyNode
				handle=MethodHandleValueReadHandle[protected java.lang.String com.allegoria.notariat.business.BasicClientPhysique.prenom]
				bridges=[
				]
				nestedNodes=[
					{
						class=PojoIndexingProcessorValueBridgeNode
						bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@6ca8b1c0
						indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=null], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchTextFieldPredicateBuilderFactory@30b03af0, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@59b795e7, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@546e1ac], relativeAccessor=.prenom]
					}
				]
			}
			{
				class=PojoIndexingProcessorPropertyNode
				handle=MethodHandleValueReadHandle[public com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.ClientPhysique.getConjoint()]
				bridges=[
				]
				nestedNodes=[
					{
						class=PojoIndexingProcessorTypeNode
						parentIndexObjectReferences=[org.hibernate.search.backend.elasticsearch.document.impl.ElasticsearchIndexObjectFieldReference@2cc97675]
						bridges=[
						]
						propertyNodes=[
							{
								class=PojoIndexingProcessorPropertyNode
								handle=MethodHandleValueReadHandle[private java.util.UUID com.allegoria.notariat.business.BusinessObject.uuid]
								bridges=[
								]
								nestedNodes=[
									{
										class=PojoIndexingProcessorValueBridgeNode
										bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@1d9fbea6
										indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=conjoint], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchTextFieldPredicateBuilderFactory@7862185f, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@4a1bdd7e, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@2d867096], relativeAccessor=.uuid]
									}
								]
							}
							{
								class=PojoIndexingProcessorPropertyNode
								handle=MethodHandleValueReadHandle[protected java.util.Date com.allegoria.notariat.business.BasicClientPhysique.dateNe]
								bridges=[
								]
								nestedNodes=[
									{
										class=PojoIndexingProcessorValueBridgeNode
										bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@4d8c810e
										indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=conjoint], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchStandardFieldPredicateBuilderFactory@2544d800, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@312011fb, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@2fbcd589], relativeAccessor=.dateNe]
									}
								]
							}
							{
								class=PojoIndexingProcessorPropertyNode
								handle=MethodHandleValueReadHandle[protected java.lang.String com.allegoria.notariat.business.BasicClientPhysique.nom]
								bridges=[
								]
								nestedNodes=[
									{
										class=PojoIndexingProcessorValueBridgeNode
										bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@691b581
										indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=conjoint], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchTextFieldPredicateBuilderFactory@596e98b, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@34089f0b, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@7d51049e], relativeAccessor=.nom]
									}
								]
							}
							{
								class=PojoIndexingProcessorPropertyNode
								handle=MethodHandleValueReadHandle[protected java.lang.String com.allegoria.notariat.business.BasicClientPhysique.prenom]
								bridges=[
								]
								nestedNodes=[
									{
										class=PojoIndexingProcessorValueBridgeNode
										bridge=org.hibernate.search.engine.environment.bean.SimpleBeanHolder@76e79b08
										indexFieldReference=ElasticsearchIndexFieldReference[schemaNode=ElasticsearchIndexSchemaFieldNode[parent=ElasticsearchIndexSchemaObjectNode[absolutePath=conjoint], predicateBuilderFactory=org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchTextFieldPredicateBuilderFactory@440ffeee, sortBuilderFactory=org.hibernate.search.backend.elasticsearch.types.sort.impl.ElasticsearchStandardFieldSortBuilderFactory@340fc1a3, projectionBuilderFactory=org.hibernate.search.backend.elasticsearch.types.projection.impl.ElasticsearchStandardFieldProjectionBuilderFactory@410f5648], relativeAccessor=.prenom]
									}
								]
							}
						]
					}
				]
			}
		]
	}
	reindexingResolver={
		class=DefaultPojoImplicitReindexingResolver
		dirtyPathsTriggeringSelfReindexing=StringSetPojoPathFilter[[uuid, dateNe, nom, prenom, matrimoniauxMadame, com.allegoria.notariat.business.ClientPhysique.matrimoniauxMadame, matrimoniauxMonsieur, com.allegoria.notariat.business.ClientPhysique.matrimoniauxMonsieur]]
		containingEntitiesResolverRoot={
			class=PojoImplicitReindexingResolverDirtinessFilterNode
			dirtyPathFilter=StringSetPojoPathFilter[[uuid, dateNe, nom, prenom]]
			delegate={
				class=PojoImplicitReindexingResolverOriginalTypeNode
				nestedNodes=[
					{
						class=PojoImplicitReindexingResolverPropertyNode
						handle=MethodHandleValueReadHandle[public com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.ClientPhysique.getConjoint()]
						nestedNodes=[
							{
								class=PojoImplicitReindexingResolverOriginalTypeNode
								nestedNodes=[
									{
										class=PojoImplicitReindexingResolverMarkingNode
									}
								]
							}
						]
					}
					{
						class=PojoImplicitReindexingResolverDirtinessFilterNode
						dirtyPathFilter=StringSetPojoPathFilter[[nom]]
						delegate={
							class=PojoImplicitReindexingResolverPropertyNode
							handle=MethodHandleValueReadHandle[protected java.util.Set com.allegoria.notariat.business.BasicClientPhysique.matrimoniauxMonsieur]
							nestedNodes=[
								{
									class=PojoImplicitReindexingResolverContainerElementNode
									extractor=org.hibernate.search.mapper.pojo.extractor.builtin.impl.CollectionElementExtractor@b7aaaba
									nestedNodes=[
										{
											class=PojoImplicitReindexingResolverOriginalTypeNode
											nestedNodes=[
												{
													class=PojoImplicitReindexingResolverPropertyNode
													handle=MethodHandleValueReadHandle[protected com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.BasicEtatMatrimonial.madame]
													nestedNodes=[
														{
															class=PojoImplicitReindexingResolverOriginalTypeNode
															nestedNodes=[
																{
																	class=PojoImplicitReindexingResolverMarkingNode
																}
															]
														}
													]
												}
												{
													class=PojoImplicitReindexingResolverPropertyNode
													handle=MethodHandleValueReadHandle[protected com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.BasicEtatMatrimonial.monsieur]
													nestedNodes=[
														{
															class=PojoImplicitReindexingResolverOriginalTypeNode
															nestedNodes=[
																{
																	class=PojoImplicitReindexingResolverMarkingNode
																}
															]
														}
													]
												}
											]
										}
									]
								}
							]
						}
					}
					{
						class=PojoImplicitReindexingResolverDirtinessFilterNode
						dirtyPathFilter=StringSetPojoPathFilter[[nom]]
						delegate={
							class=PojoImplicitReindexingResolverPropertyNode
							handle=MethodHandleValueReadHandle[protected java.util.Set com.allegoria.notariat.business.BasicClientPhysique.matrimoniauxMadame]
							nestedNodes=[
								{
									class=PojoImplicitReindexingResolverContainerElementNode
									extractor=org.hibernate.search.mapper.pojo.extractor.builtin.impl.CollectionElementExtractor@30b9cdb5
									nestedNodes=[
										{
											class=PojoImplicitReindexingResolverOriginalTypeNode
											nestedNodes=[
												{
													class=PojoImplicitReindexingResolverPropertyNode
													handle=MethodHandleValueReadHandle[protected com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.BasicEtatMatrimonial.madame]
													nestedNodes=[
														{
															class=PojoImplicitReindexingResolverOriginalTypeNode
															nestedNodes=[
																{
																	class=PojoImplicitReindexingResolverMarkingNode
																}
															]
														}
													]
												}
												{
													class=PojoImplicitReindexingResolverPropertyNode
													handle=MethodHandleValueReadHandle[protected com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.BasicEtatMatrimonial.monsieur]
													nestedNodes=[
														{
															class=PojoImplicitReindexingResolverOriginalTypeNode
															nestedNodes=[
																{
																	class=PojoImplicitReindexingResolverMarkingNode
																}
															]
														}
													]
												}
											]
										}
									]
								}
							]
						}
					}
				]
			}
		}
	}
}
2019-07-23 15:44:54,313     o.h.s.m.p.m.building.impl.PojoMapper   [D] HSEARCH700019: Created POJO contained type manager: {
	javaClass=class com.allegoria.notariat.business.EtatMatrimonial
	reindexingResolver={
		class=DefaultPojoImplicitReindexingResolver
		dirtyPathsTriggeringSelfReindexing=org.hibernate.search.mapper.pojo.model.path.spi.EmptyPojoPathFilter@2658e0e1
		containingEntitiesResolverRoot={
			class=PojoImplicitReindexingResolverDirtinessFilterNode
			dirtyPathFilter=StringSetPojoPathFilter[[monsieur, madame]]
			delegate={
				class=PojoImplicitReindexingResolverOriginalTypeNode
				nestedNodes=[
					{
						class=PojoImplicitReindexingResolverPropertyNode
						handle=MethodHandleValueReadHandle[protected com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.BasicEtatMatrimonial.madame]
						nestedNodes=[
							{
								class=PojoImplicitReindexingResolverOriginalTypeNode
								nestedNodes=[
									{
										class=PojoImplicitReindexingResolverMarkingNode
									}
								]
							}
						]
					}
					{
						class=PojoImplicitReindexingResolverPropertyNode
						handle=MethodHandleValueReadHandle[protected com.allegoria.notariat.business.ClientPhysique com.allegoria.notariat.business.BasicEtatMatrimonial.monsieur]
						nestedNodes=[
							{
								class=PojoImplicitReindexingResolverOriginalTypeNode
								nestedNodes=[
									{
										class=PojoImplicitReindexingResolverMarkingNode
									}
								]
							}
						]
					}
				]
			}
		}
	}
}

I didn’t expect to find a pojo mapper for EtatMatrimonial

1 Like

Thanks a lot!

About EtatMatrimonial, it’s normal: since some data from that entity is used when you index a ClientPhysique, Hibernate Search needs to listen to change events on EtatMatrimonial, and reindex the relevant ClientPhysique accordingly.

Your problem, however, seems unrelated. In short, it’s a bug, and I am working on a fix. In the meantime, a simple workaround is to add the annotation @Access(AccessType.PROPERTY) on your ClientPhysique entity.

In more details: since your ClientPhysique entity uses the field access type, Hibernate Search will get the values of the uuid field (for example) by directly accessing the private uuid field. This won’t work well on proxies, because they won’t be initialized automatically like they would if we just called a getter. Hibernate Search should unproxy entities before doing that, but it currently doesn’t: that’s the bug.

1 Like

Thanks for the explanation !

The workaround seem to generate other issues on some of my transient fields

@Transient
private Set<Pacs> pacsCalcules;
@Transient
private Set<ClientPhysique> enfantsCalcules;
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Set, at table: client_physique, for columns: [org.hibernate.mapping.Column(enfants_calcules)]
	at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:486)
	at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:453)
	at org.hibernate.mapping.Property.isValid(Property.java:226)
	at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:624)
	at org.hibernate.mapping.JoinedSubclass.validate(JoinedSubclass.java:44)
	at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:343)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:461)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
	at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:615)
	at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:599)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774)
	... 110 common frames omitted

That’s odd. I suppose you have getters for these fields and ORM now ignores the Transient annotations since it focuses on the getters.

Maybe remove the @Access(AccessType.PROPERTY) annotation from the entity, and put it on all the fields annotated with @GenericField/etc. instead. I’d advise to add a comment there to remember it’s a workaround and should be removed when upgrading to Hibernate Search 6.0.0.Alpha9.

i confirm it’s working with the annotation on the field.
do you have the bug number associated ? i could watch it and then monkey patch the class involed after your commit until the alpha 9 get out.

Thank you for your help ! :slight_smile:

Thanks for confirming. The ticket: https://hibernate.atlassian.net/browse/HSEARCH-3643

1 Like