SDN6: Using projection persistence with primitive fields

Hello,

I'm using SDN 6.2.0-SNAPSHOT

I have an NPE when persisting a projection when the entity class has primitive fields.

My projection class has not defined the primitive fields.

Everything works fine when I change the primitive (boolean) by its wrapper Object (Boolean).

When I persist the data, I get a:

java.lang.NullPointerException
	at java.base/sun.invoke.util.ValueConversions.unboxBoolean(ValueConversions.java:108)
	at com.example.sdn6.entity.NoeudMaquetteEntity_Accessor_dh80lb.setProperty(Unknown Source)
	at org.springframework.data.mapping.model.InstantiationAwarePropertyAccessor.setProperty(InstantiationAwarePropertyAccessor.java:104)
	at org.springframework.data.neo4j.core.mapping.EntityFromDtoInstantiatingConverter.lambda$convert$0(EntityFromDtoInstantiatingConverter.java:94)
	at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:374)
	at org.springframework.data.neo4j.core.mapping.EntityFromDtoInstantiatingConverter.convert(EntityFromDtoInstantiatingConverter.java:87)
	at org.springframework.data.neo4j.core.Neo4jTemplate.doSave(Neo4jTemplate.java:942)

The issue can be reproduced by cloning GitHub - gonzalad/sdn6-tests, branch projection-persistence-lost-relations and execute
sdn6-tests/Sdn6Test.java at projection-persistence-lost-relations · gonzalad/sdn6-tests · GitHub
To reproduce, execute the testcase com.example.sdn6.Sdn6Test#testProjection

Should I create an issue on github ?

Thanks !

Entity class:

@Node("ObjetMaquette")
public class NoeudMaquetteEntity {

    @GeneratedValue
    @Id
    private Long id;
    private UUID idDefinition;
    private String code;
    private boolean readOnly;

Projection class:

public class NoeudProjection {

    private Long id;
    private UUID idDefinition;
    private String code;

Code used for saving the projection:

    @Override
    public NoeudProjection save(NoeudProjection projection) {
        return neo4jTemplate.save(NoeudMaquetteEntity.class).one(projection);
    }

Testcase:

    @Test
    void testProjection() {
        NoeudMaquetteEntity om = newEntity("F1");
        om.setReadOnly(true);
        repository.save(om);

        // use projection for persistence
        Optional<NoeudProjection> projectionAModifier = repository.findProjectionByIdDefinition(om.getIdDefinition());
        assertThat(projectionAModifier).isNotEmpty();
        assertThat(projectionAModifier.get().getCode()).isEqualTo("F1");
        projectionAModifier.get().setCode("modifie");
        repository.save(projectionAModifier.get());

        Optional<NoeudMaquetteEntity> omRead = repository.findByIdDefinition(om.getIdDefinition());
        assertThat(omRead).isPresent();
        // check attribute updated by projection
        assertThat(omRead.get().getCode()).isEqualTo("modifie");
        // check attribute was not updated since it's not part of the projection
        assertThat(omRead.get().isReadOnly()).isEqualTo(true);
    }

    private NoeudMaquetteEntity newEntity(String code) {
        NoeudMaquetteEntity entity = new NoeudMaquetteEntity();
        entity.setIdDefinition(UUID.randomUUID());
        entity.setCode(code);
        return entity;
    }

As you have spotted it: The problem is rooted in the primitive type.

I created a ticket at GitHub and there is already a snapshot version (~30 min. after I posted this) with a fix you can try out: org.springframework.data:spring-data-neo4j:6.1.6-GH-2395-SNAPSHOT.
Would be good to have your feedback on this before merging.

1 Like

Hi @gerrit.meier,

I just tested the patch, it works fine on my testcase

Thanks very much for the fix !

1 Like