spring-projects / spring-data-neo4j

Provide support to increase developer productivity in Java when using Neo4j. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
http://spring.io/projects/spring-data-neo4j
Apache License 2.0
825 stars 619 forks source link

Required property null not found for "some class" occur in specific situation #2855

Closed jsybf closed 7 months ago

jsybf commented 7 months ago

it's my code

package com.example.neo4jissue.one;

import lombok.Getter;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.support.UUIDStringGenerator;

@Node
@Getter
public class FooEntity {
    @Id @GeneratedValue(UUIDStringGenerator.class)
    private String id;

    private String name;

    private FooEntity(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public static FooEntity of(String name) {
        return new FooEntity(null, name);
    }
}
package com.example.neo4jissue.one;

import org.springframework.data.neo4j.repository.Neo4jRepository;

public interface FooEntityRepository extends Neo4jRepository<FooEntity, String> {
}
package com.example.neo4jissue.one;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class FooTest {
    @Autowired FooEntityRepository fooEntityRepository;

    @Test
    void save_and_retrieve_test() throws Exception {
        //given
        FooEntity foo = FooEntity.of("foo1");
        //when
        fooEntityRepository.save(foo);
        FooEntity found = fooEntityRepository.findById(foo.getId()).orElseThrow();
        //then
        System.out.println(found.getName());
    }
}

what's problem

--- spring boot 3.2.2 spring boot 3.1.8
build by gradle no errors no error
build by intellij error no error

Using spring-boot 3.2.2 & build by intellij build cause two error(full error log is in below)

Caused by: java.lang.IllegalStateException: Required property null not found for class com.example.neo4jissue.one.FooEntity
org.springframework.data.mapping.MappingException: Error mapping Record<{fooEntity: {name: "foo1", id: "ce382ea8-0a23-4bbb-9867-7d114b75bb75", __elementId__: 63, __nodeLabels__: ["FooEntity"]}}>

cf

  1. i use neo4j-aura instead of local neo4j
  2. i use intellij 2023.2.5 ultimate edition
  3. i'm just college student so i can't be certain of it's my problem or spring-data-neo4j's issue
  4. build by intellij means image
org.springframework.data.mapping.MappingException: Error mapping Record<{fooEntity: {name: "foo1", id: "ce382ea8-0a23-4bbb-9867-7d114b75bb75", __elementId__: 63, __nodeLabels__: ["FooEntity"]}}>

    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.read(DefaultNeo4jEntityConverter.java:123)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.read(DefaultNeo4jEntityConverter.java:71)
    at org.springframework.data.neo4j.core.mapping.Schema.lambda$getRequiredMappingFunctionFor$0(Schema.java:96)
    at org.springframework.data.neo4j.core.PreparedQuery$AggregatingMappingFunction.apply(PreparedQuery.java:246)
    at org.springframework.data.neo4j.core.PreparedQuery$AggregatingMappingFunction.apply(PreparedQuery.java:158)
    at org.springframework.data.neo4j.core.DefaultNeo4jClient$DefaultRecordFetchSpec.one(DefaultNeo4jClient.java:444)
    at java.base/java.util.Optional.flatMap(Optional.java:289)
    at org.springframework.data.neo4j.core.Neo4jTemplate$DefaultExecutableQuery.getSingleResult(Neo4jTemplate.java:1120)
    at org.springframework.data.neo4j.core.Neo4jTemplate.findById(Neo4jTemplate.java:305)
    at org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository.findById(SimpleNeo4jRepository.java:71)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158)
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:385)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
    at jdk.proxy2/jdk.proxy2.$Proxy67.findById(Unknown Source)
    at com.example.neo4jissue.one.FooTest.save_and_retrieve_test(FooTest.java:17)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.IllegalStateException: Required property null not found for class com.example.neo4jissue.one.FooEntity
    at org.springframework.data.mapping.PersistentEntity.getRequiredPersistentProperty(PersistentEntity.java:190)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter$1.getParameterValue(DefaultNeo4jEntityConverter.java:460)
    at org.springframework.data.mapping.model.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:77)
    at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:98)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.instantiate(DefaultNeo4jEntityConverter.java:497)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.lambda$map$2(DefaultNeo4jEntityConverter.java:324)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.map(DefaultNeo4jEntityConverter.java:343)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.map(DefaultNeo4jEntityConverter.java:301)
    at org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.read(DefaultNeo4jEntityConverter.java:121)

image

jsybf commented 7 months ago

also here is my build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.2'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('bootBuildImage') {
    builder = 'paketobuildpacks/builder-jammy-base:latest'
}

tasks.named('test') {
    useJUnitPlatform()
}
meistermeier commented 7 months ago

You need to compile with the -parameters flag activated. This preserves the parameter names of methods, constructors, etc. after build-time. Please run the Rebuild project process from the Build menu again afterwards. A simple Build Project will not replace the byte code. This is usually automatically configured by the Spring Boot plugin, when you are using the gradle-based build option in the preferences, you have shown.

image

Side note: I think it shouldn't have worked since Spring Boot 3.0 already.

jsybf commented 7 months ago

thank you! after adding -parameters it works in intellij build this is my firstime asking question to github, impressed by your detailed answer!!

meistermeier commented 7 months ago

You're welcome. Closing this issue now.