I'm new to neo4j. From what I've read so far I understand that it's generally bad practise to use the default <id>
parameter externally of my app. I'd therefore like to be able to specify my own personId
parameter separate of <id>
. To do this, I'd like to use neo4j-ogm
, however I'm getting this exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'personController' defined in file [/Users/freid/www/project/address-book/build/classes/java/main/com/addressbook/controller/PersonController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personRepository' defined in com.addressbook.repositories.PersonRepository defined in @EnableNeo4jRepositories declared on SetupBeans: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Required identifier property not found for class com.addressbook.model.Person!
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.5.jar:5.3.5]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.5.jar:5.3.5]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:769) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-2.4.4.jar:2.4.4]
at com.addressbook.Application.main(Application.java:17) ~[main/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personRepository' defined in com.addressbook.repositories.PersonRepository defined in @EnableNeo4jRepositories declared on SetupBeans: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Required identifier property not found for class com.addressbook.model.Person!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.5.jar:5.3.5]
... 20 common frames omitted
Caused by: java.lang.IllegalStateException: Required identifier property not found for class com.addressbook.model.Person!
at org.springframework.data.mapping.PersistentEntity.getRequiredIdProperty(PersistentEntity.java:105) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.data.repository.core.support.PersistentEntityInformation.getIdType(PersistentEntityInformation.java:74) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory.getTargetRepository(Neo4jRepositoryFactory.java:67) ~[spring-data-neo4j-6.0.6.jar:6.0.6]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:281) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:323) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:230) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.data.util.Lazy.get(Lazy.java:114) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:329) ~[spring-data-commons-2.4.6.jar:2.4.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.5.jar:5.3.5]
... 31 common frames omitted`
Here is my Person
node:
package com.addressbook.model;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.neo4j.ogm.annotation.*;
import java.util.Set;
@NodeEntity
@Getter
@Setter
public class Person {
@Id
@GeneratedValue
Long personId;
@Builder
public Person(Long personId, String firstName, String lastName, Integer age) {
this.personId = id;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
@NotEmpty(message = "Please provide a first name")
String firstName;
@NotEmpty(message = "Please provide a last name")
String lastName;
@Min(value = 18, message = "Age should not be less than 18")
@Max(value = 150, message = "Age should not be greater than 150")
Integer age;
@Relationship(type = "SPOUSE",direction=Relationship.OUTGOING)
public Set<Person> spouse;
@Relationship(type = "SIBLING",direction=Relationship.OUTGOING)
public Set<Person> sibling;
@Relationship(type = "FAMILY",direction=Relationship.OUTGOING)
public Set<Person> family;
}
Here is my Person
repository:
package com.addressbook.repositories;
import com.addressbook.model.Person;
import org.springframework.data.neo4j.repository.Neo4jRepository;
public interface PersonRepository extends Neo4jRepository<Person, Long> {}
And, here is my Person
controller:
package com.addressbook.controller;
import com.addressbook.exception.NotFoundException;
import com.addressbook.model.Person;
import com.addressbook.repositories.PersonRepository;
import com.addressbook.model.View;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import lombok.extern.log4j.Log4j2;
import javax.validation.*;
@Log4j2
@RestController
@RequestMapping("/api/v1")
@Api(tags = { "Person" })
public class PersonController {
private final PersonRepository personRepository;
@Autowired
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping("person/{personId}")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<Person> getPerson(@PathVariable("personId") Long id) throws NotFoundException {
Person person = this.personRepository.findById(id).orElseThrow(() -> new NotFoundException("Person not found!"));
return new ResponseEntity(person, HttpStatus.OK);
}
}
This exception only seems to occurs when I use org.neo4j.ogm.annotation.Id
annotation. If I use the org.springframework.data.neo4j.core.schema.Id
annotation then I can create and retrieve entities. But, it only seems to create the entity with the default <id>
, which is not what I want.
My understanding, which maybe wrong, is that org.neo4j.ogm.annotation.Id
should allow you to add your own id separate of <id>
, and even allow you to combine it with org.neo4j.ogm.id.UuidStrategy
to use a uuid
for entities. Is this correct?
I'm not sure why the exception says Required identifier property not found for class com.addressbook.model.Person!
as I thought the org.neo4j.ogm.annotation.Id
annotation would satisfy this.
Any help would be appreciated.
It is possible that you are mixing the earlier neo4j-ogm with the latest Spring Data Neo4j
Check your dependencies and make sure your annotations are from the correct packages (for instance, org.springframework.data.neo4j.*)
If you follow the instructions in the link above, you should be able to resolve your errors.