Search code examples
scalaneo4jneo4j-ogm

How to filter for a class field of a custom entity type with Neo4J OGM?


I am using a custom entity type:

@NodeEntity
class SutStateEntity(state: SutState) extends Entity {

  def this() = this(null)

  @Convert(classOf[SutStateConverter])
  val sutState = state
}

Now I would like to get an entity which matches the class field sutState. Note that the type SutState must be converted by my custom converter SutStateConverter since it is no primitive type supported by Neo4J OGM.

This is the code I am using to filter for a matching entity:

val filter = new Filter("sutState", ComparisonOperator.EQUALS, sutState)
val first = session.loadAll(classOf[SutStateEntity], filter).stream().findFirst()

However, this code leads to the following exception:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalArgumentException: No serializer found for class de.retest.recheck.ui.descriptors.StringAttribute$1 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.HashMap["sutState_0"]->de.retest.recheck.ui.descriptors.SutState["rootElements"]->java.util.ArrayList[0]->de.retest.recheck.ui.descriptors.RootElement["identifyingAttributes"]->de.retest.recheck.ui.descriptors.IdentifyingAttributes["attributes"]->java.util.ArrayList[0]->de.retest.recheck.ui.descriptors.StringAttribute["type"])

StringAttribute is the type of a field of an instance stored by SutState. It has like SutState XML annotations and SutStateConverter is able to marshal and unmarshal it without problems (verified with a custom unit test).

Does Neo4J OGM not use the converter for my filter? How do I specify a filter for the class field sutState?

Here is the code of my custom converter:

class SutStateConverter extends AttributeConverter[SutState, String] {
  def toGraphProperty(value: SutState): String = XmlTransformerUtil.getXmlTransformer.toXML(value)
  def toEntityAttribute(value: String): SutState =
    XmlTransformerUtil.getXmlTransformer.fromXML[SutState](new ByteArrayInputStream(value.getBytes(StandardCharsets.UTF_8)))
}

XmlTransformerUtil.getXmlTransformer.toXML and XmlTransformerUtil.getXmlTransformer.fromXML marshal and unmarshal SutStates to and from XML. The class has been tested in a unit test and should work.


Solution

  • Your assumption is right: Neo4j-OGM does not use the converter. This is due to the fact that a filter in general is not bound to a special entity class but a converter is bound to a property of an entity class. There no magic when applying a filter to a particular entity in a loadAll call that would then check if the property has a converter bound to it.

    The easiest way would be to create an instance of your converter manually and apply the toGraphProperty method to your supplied filter value.

    A (maybe) cleaner approach could be to extend the Filter class with something like SutStateFilter that does the job under the hood, if you need to create a filter for this property more often.