cancel
Showing results for 
Search instead for 
Did you mean: 

ClassCastException using Multi level Projection

mick
Node
@Node
public class User {
    @Id
    private String id;
    private String username;
    @Relationship("ACTIVE_BUSINESS_UNIT")
    private BusinessUnit activeBusinessUnit;
}

@Node
public class BusinessUnit {

    @Id
    private String id;
    private String name;
    @Relationship(type = "BUSINESS_UNIT_IN", direction = OUTGOING)
    private List<User> users = new ArrayList<>();
}

@Data
public class UserView {
    private String id;
    private String username;
    private BusinessUnitView activeBusinessUnit;

    @data
    public static class BusinessUnitView {
        private String id;
        private String name;
    }
}

UserView user = userRepository.findByUsername(myusername);

java.lang.ClassCastException: Cannot cast au.com.objects.neo4j.entity.BusinessUnit to au.com.objects.neo4j.entity.UserView$BusinessUnitView

 

Trying to use multilevel projections to control how much data gets loaded and am getting ClassCastException when I load from repository.

Any ideas what I'm doing wrong?

1 ACCEPTED SOLUTION

gerrit_meier
Neo4j
Neo4j

I am so sorry that I missed this question. This limitation is unfortunate but technical needed.
Basically what I would do is to use the interface projection to create an instance of the entity object from.
e.g something like:

class User {
  User fromUserView(UserView userView) {
    return new User(userView.getUsername(),...);
  }
}

View solution in original post

4 REPLIES 4

mick
Node

Appears multi level projections don't work for class based projections

"These DTO types can be used in exactly the same way projection interfaces are used, except that no proxying happens and no nested projections can be applied."

https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#projections.dtos

As only class based projections support doing updates, what is the preferred way to load a partial graph for update? 

For example if I wanted to load a User and update it's activeBusinessUnit

UserView user = userRepository.findByUsername(myusername);
BusinessUnitView bu = businessUnitRepository.findById(myid);
user.setACtiveBusinessUnit(bu);
neo4jTemplate.save(User.class).one(user);
  • Interface based projections don't support updating
  • Class based projection don't allow multilevel projections
  • Don't want to load all the users attached to a BusinessUnit whenever I load a User (with its activeBusinessUnit)

gerrit_meier
Neo4j
Neo4j

I am so sorry that I missed this question. This limitation is unfortunate but technical needed.
Basically what I would do is to use the interface projection to create an instance of the entity object from.
e.g something like:

class User {
  User fromUserView(UserView userView) {
    return new User(userView.getUsername(),...);
  }
}

mick
Node

@gerrit_meier thanks for the reply, thats a great help.

So that seems to work, just needed to add @Version, is that expected?

This is what I ended up with. Now to try and apply similar to the rest of the migration too SDN6

 

IUserView userView = userRepository.findByUsername(username);
IBusinessUnitView bu = businessUnitRepository.findByName(name);
User user = new User(userView.getId(), userView.getVersion(), 
   userView.getUsername(),
   new BusinessUnit(businessUnitView.getId(), businessUnitView.getVersion(), 
      businessUnitView.getName(), 
      null)); // users

neo4jTemplate.saveAs(user, IUserView.class);

 

gerrit_meier
Neo4j
Neo4j

The version annotation is needed regardless if you are using projection or not.

Otherwise, SDN does not know if the entity is new or already exists. It does not have any control over the identifier in your case and needs another information (the version) to determine if this was already processed or not.

I see a missing documentation piece around the identifiers and will take care of this.

Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

On November 16 and 17 for 24 hours across all timezones, you’ll learn about best practices for beginners and experts alike.