SpringData / Neo4j: Communication cannot persist

I have Person instances (nodes) that write (relationships) Status instances (nodes). It's a little far-fetched, I know, but I wanted to train.

Whenever I try to hold a Human, this is what I get:

org.springframework.data.neo4j.mapping.InvalidEntityTypeException: Type class org.springframework.data.neo4j.fieldaccess.GraphBackedEntityIterableWrapper is neither a @NodeEntity nor a @RelationshipEntity
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.createPersistentEntity(Neo4jMappingContext.java:48)
at org.springframework.data.neo4j.support.mapping.Neo4jMappingContext.createPersistentEntity(Neo4jMappingContext.java:38)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:235)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:165)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:140)
at org.springframework.data.neo4j.support.mapping.EntityStateHandler.getId(EntityStateHandler.java:67)
at org.springframework.data.neo4j.support.mapping.EntityStateHandler.getPersistentState(EntityStateHandler.java:84)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityFetchHandler.fetch(Neo4jEntityFetchHandler.java:58)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl$1.doWithAssociation(Neo4jEntityConverterImpl.java:116)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:185)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.cascadeFetch(Neo4jEntityConverterImpl.java:106)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.loadEntity(Neo4jEntityConverterImpl.java:100)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:90)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.read(Neo4jEntityPersister.java:168)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:186)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:239)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:227)
at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:295)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.save(AbstractGraphRepository.java:106)
at sun.reflect.GeneratedMethodAccessor19.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:322)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy29.save(Unknown Source)
at sun.reflect.GeneratedMethodAccessor18.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy30.save(Unknown Source)
at com.lateralthoughts.devinlove.framework.GraphPopulator.loadABunchOfPeopleIntoTheMatrix(GraphPopulator.java:84)

      

Here are the objects:

@NodeEntity
public class Person {

public enum ProfoundIdentity {
    DEVELOPER, ARCHITECT, SYSADMIN, MANAGER, BOSS;
}

@GraphId
private Long id;
private String firstName;
private String lastName;
private String favoriteColor;
private Mascot mascot;
@RelatedTo(elementClass = Person.class, type = "IS_FRIEND_WITH", direction = BOTH)
private final Set<Person> friends = new LinkedHashSet<Person>();
@RelatedTo(elementClass = Tool.class, type = "WORKS_WITH", direction = OUTGOING)
private final Set<Tool> tools = new LinkedHashSet<Tool>();
/**
 * Simplistic European-formatted shoe size
 */
private int shoeSize;

@Fetch
@RelatedToVia(elementClass = StatusRedaction.class, type = "WRITES", direction = OUTGOING)
private final Collection<StatusRedaction> statuses = new LinkedList<StatusRedaction>();

private ProfoundIdentity profoundIdentity;

public Long getId() {
    return id;
}

public String getFirstName() {
    return firstName;
}

public String getLastName() {
    return lastName;
}

public void setFavoriteColor(final String favoriteColor) {
    checkNotNull(favoriteColor);
    this.favoriteColor = favoriteColor.toUpperCase();
}

public String getFavoriteColor() {
    return favoriteColor;
}

public void setMascot(final Mascot mascot) {
    this.mascot = mascot;
}

public Mascot getMascot() {
    return mascot;
}

public Set<Person> getFriends() {
    return unmodifiableSet(friends);
}

public void addFriend(final Person friend) {
    checkNotNull(friend);
    friends.add(friend);
}

public void addTool(final Tool tool) {
    checkNotNull(tool);
    tools.add(tool);
}

public Set<Tool> getTools() {
    return unmodifiableSet(tools);
}

public void setShoeSize(final int shoeSize) {
    checkArgument(shoeSize > 0 && shoeSize < 80);
    this.shoeSize = shoeSize;
}

public int getShoeSize() {
    return shoeSize;
}


public Iterable<StatusRedaction> getStatuses() {
    return statuses;
}

public StatusRedaction addStatus(final Status message, final Date creationDate) {
    final StatusRedaction statusRedaction = new StatusRedaction(this, message, creationDate);
    statuses.add(statusRedaction);
    return statusRedaction;
}

public void setProfoundIdentity(final ProfoundIdentity profoundIdentity) {
    checkNotNull(profoundIdentity);
    this.profoundIdentity = profoundIdentity;
}

public ProfoundIdentity getProfoundIdentity() {
    return profoundIdentity;
}

public void setFirstName(final String firstName) {
    this.firstName = firstName;
}

public void setLastName(final String lastName) {
    this.lastName = lastName;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((getFirstName() == null) ? 0 : getFirstName().hashCode());
    result = prime * result + ((getLastName() == null) ? 0 : getLastName().hashCode());
    return result;
}

@Override
public boolean equals(final Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (getFirstName() == null) {
        if (other.getFirstName() != null)
            return false;
    }
    else if (!getFirstName().equals(other.getFirstName()))
        return false;
    if (getLastName() == null) {
        if (other.getLastName() != null)
            return false;
    }
    else if (!getLastName().equals(other.getLastName()))
        return false;
    return true;
}
}

      

Here is the status:

@NodeEntity
public class Status {
@GraphId
private Long id;
private String message = "";

public Status() {}

public Status(final String message) {
    this.message = message;
}

public void setMessage(final String message) {
    this.message = message;
}

public String getMessage() {
    return message;
}

public Long getId() {
    return id;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

@Override
public boolean equals(final Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Status other = (Status) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    }
    else if (!id.equals(other.id))
        return false;
    return true;
}
}

      

And here is the connection:

@RelationshipEntity(type = "WRITES")
public class StatusRedaction {
@GraphId
private Long id;
@StartNode
private Person author;
@EndNode
private Status status = new Status("");
private Date creationDate = new Date();

public StatusRedaction() {}

public StatusRedaction(final Person author, final Status status, final Date creationDate) {
    this.author = author;
    this.status = status;
    this.creationDate = creationDate;
}

public Long getId() {
    return id;
}

public Person getAuthor() {
    return author;
}

public void setAuthor(final Person author) {
    this.author = author;
}

public Status getStatus() {
    return status;
}

public String getStatusMessage() {
    return status.getMessage();
}

public void setStatus(final Status status) {
    this.status = status;
}

public Date getCreationDate() {
    return creationDate;
}

// shouldnt be here, I know...
public String getFormattedDate() {
    PrettyTime prettyTime = new PrettyTime(new Locale("en"));
    return prettyTime.format(creationDate);
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

@Override
public boolean equals(final Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    StatusRedaction other = (StatusRedaction) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    }
    else if (!id.equals(other.id))
        return false;
    return true;
}
}

      

And finally, the code responsible for the regular users:

public class GraphPopulator implements ApplicationListener<ContextRefreshedEvent> {

@Autowired
private MascotRepository mascotRepository;
@Autowired
private PersonRepository personRepository;
@Autowired
private ToolRepository toolRepository;
@Autowired
private CategoryRepository categoryRepository;

@Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
    loadData();
}

public void loadData() {
    /* [...] inserting other entities [...] */
    loadABunchOfPeopleIntoTheMatrix();
}

/**
 * [...]
 */

private void loadABunchOfPeopleIntoTheMatrix() {
    personRepository.save(person("John", "Doe", "blue", "Tux", DEVELOPER, 42, "Hello world", "Java Standard Edition"));
    personRepository.save(person("Jane", "Doe", "green", "Django Pony", DEVELOPER, 45, "A World Appart (Info)", "Python"));
}

private Person person(final String firstName, final String lastName, final String color, final String mascotName, final Person.ProfoundIdentity profoundIdentity, final int shoeSize, final String firstStatus, final String toolName) {
    Person person = new Person();
    person.setFavoriteColor(color);
    person.setFirstName(firstName);
    person.setLastName(lastName);
    person.setMascot(findMascot(mascotName));
    person.setProfoundIdentity(profoundIdentity);
    person.setShoeSize(shoeSize);
    person.addStatus(new Status("Hello world"), new Date());
    return person;
}

private Tool findTool(final String toolname) {
    return toolRepository.findByPropertyValue("name", toolname);
}

private Mascot findMascot(final String mascotName) {
    return mascotRepository.findByPropertyValue("name", mascotName);
}   }

      

And the corresponding repository:

import org.springframework.data.neo4j.repository.GraphRepository;
import ***.domain.Person;
public interface PersonRepository extends GraphRepository<Person> {}

      

I'm not sure what happened. The exception message is too weird and my debugging sessions didn't get me anywhere.

Can someone tell me what happened to my code?

+3


source to share





All Articles