Find elementts with stream api in pogo class - java-stream

I want to find all numbers 5, 5.5, 6, 6.5 that have quantity not null
It's pogo of the first entity:
#Getter
#Setter
#NoArgsConstructor
#ToString
#EqualsAndHashCode
public class Box {
#SerializedName("id")
private Integer id;
#SerializedName("name")
private String name;
#SerializedName("sizes")
private List<Size> sizes = null;
#SerializedName("quantity")
private Integer quantity;
#SerializedName("quantityPerSize")
private List<QuantityPerSize> quantityPerSize;
}
It's pogo of the second entity.
#NoArgsConstructor
#Getter
#Setter
#ToString
#EqualsAndHashCode
public class QuantityPerSize {
#SerializedName("id")
private List<Integer> id = null;
#SerializedName("qty")
private Integer qty;
}
It's pogo of the therd entity
#NoArgsConstructor
#Getter
#Setter
#ToString
#EqualsAndHashCode
public class Size {
#SerializedName("id")
private Integer id;
#SerializedName("name")
private Name name;
#SerializedName("sizeOrder")
private Integer sizeOrder;
}
It's photo of response:
It's my code. How I can get 5,5.5 with qt not null?
box.stream()
.filter(p -> p.getName().equals("korob")).forEach(quantityPerSize -> {
if (quantityPerSize.getQty() != 0) {
log.debug(box.getSizes().stream().filter(size -> size.getId().equals(quantityPerSize.getId())).iterator().next().getName().getEn());
}
});

Related

Neo4j Spring Data NodeEntity use String as #id

I'm trying to use a java.lang.String as the #Id of a NodeEntity.
#NodeEntity(label = "MachineType")
public class MachineType {
#Id private String id;
....
It should be possible acording to the spring data neo4j docu:
While an id is still required on all entities, the behavior has been
simplified by introducing the new #Id annotation. It replaces both
#GraphId and the primary attribute and can be placed on any attribute
with a simple type.
When I'm trying to insert I get a:
{
"cause": null,
"message": "Id must be assignable to Serializable!: null"
}
Which is strange, because String implements the Serializable.
Anyone has an idea where to search next?
I think that you cannot use anything else as an ID. Keep in mind that this Long number will be reused if you delete the node.
I use UUID plugin to generate true unique keys and when I use spring-data-rest I use BackendIdConverter to change the id to the uuid for the resources that I expose.
Example:
Model:
#NodeEntity
#Data
public class Target {
#Id #GeneratedValue Long id; // <----Neo4j id
private String uuid; // <----My Key
#Version Long version;
private List<String> labels = new ArrayList<>();
#Relationship(type = "HAS_MEDIA", direction=Relationship.OUTGOING)
private List<Gallery> media = new ArrayList<>();
}
Convert resource id to my key:
#Component
public class MovieIdConverter implements BackendIdConverter {
#Autowired MovieRepo movieRepository;
#Override
public Serializable fromRequestId(String id, Class<?> entityType) {
Movie movie = movieRepository.findByUuid(id);
return (Serializable) movie.getId();
}
#Override
public String toRequestId(Serializable serializable, Class<?> aClass) {
Long id = (Long) serializable;
Optional<Movie> movie = movieRepository.findById(id);
if (movie.isPresent()) return movie.get().getUuid();
return null;
}
#Override
public boolean supports(Class<?> aClass) {
return Movie.class.equals(aClass);
}
}

Neo4j SDN4 OGM AmbiguousBaseClassException

I am running into an issue wherein some of my Neo4J queries like the one below ends up in an OGM AmbiguousBaseClassException while others don't. For example findByTitle for the movie "The Score" throws an exception but "The Matrix" does not. My graph is populated by the Movie Database found at https://neo4j.com/developer/example-data/
I am unable to find an explanation to the above observation and I hope someone can help.
curl http://localhost:8080/movies/search/findByTitle?title=The%20Score
Neo4j Server: 3.1.0
Spring-data-neo4j:4.1.1
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.neo4j.ogm.exception.MappingException: Error mapping GraphModel to instance of com.knowledgeGraph.kgClient.domain.Movie
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.28.jar:8.0.28]
Caused by: org.neo4j.ogm.exception.AmbiguousBaseClassException: Multiple classes found in type hierarchy that map to: [Person, Actor, Director]
at org.neo4j.ogm.MetaData.resolve(MetaData.java:174) ~[neo4j-ogm-core-2.0.1.jar:na]
at org.neo4j.ogm.annotations.EntityFactory.resolve(EntityFactory.java:121) ~[neo4j-ogm-core-2.0.1.jar:na]
at org.neo4j.ogm.annotations.EntityFactory.instantiateObjectFromTaxa(EntityFactory.java:105) ~[neo4j-ogm-core-2.0.1.jar:na]
at org.neo4j.ogm.annotations.EntityFactory.newObject(EntityFactory.java:61) ~[neo4j-ogm-core-2.0.1.jar:na]
Domain Objects:
Movie Class:
import static org.neo4j.graphdb.Direction.INCOMING;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
#JsonIdentityInfo(generator=JSOGGenerator.class)
#NodeEntity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Movie {
#GraphId Long nodeId;
String id;
String title;
String description;
#Relationship(type="DIRECTED", direction = Relationship.INCOMING)
List<Person> directors;
#Relationship(type="ACTS_IN", direction = Relationship.INCOMING)
List<Person> actors;
private String language;
private String imdbId;
private String tagline;
private String releaseDate;
private Integer runtime;
private String homepage;
private String trailer;
private String genre;
private String studio;
private Integer version;
private String lastModified;
private String imageUrl;
public Movie() { }
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/*Remaining Set's and Get's*/
}
Person Class:
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import com.fasterxml.jackson.annotation.JsonSubTypes;
#NodeEntity
#JsonSubTypes({
#JsonSubTypes.Type(value = Actor.class, name = "actor"),
#JsonSubTypes.Type(value = Director.class, name = "director")
})
public class Person {
#GraphId Long nodeId;
String id;
String name;
private String birthday;
private String birthplace;
private String biography;
private Integer version;
private String lastModified;
private String profileImageUrl;
public Person () {}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/*Remaining Set's and Get's*/
}
Director Class:
#NodeEntity
public class Director extends Person{
#GraphId
Long id;
public Director() {
}
#Relationship(type="DIRECTED", direction = Relationship.OUTGOING)
private List<Movie> directedMovies = new ArrayList<Movie>();
public List<Movie> getDirectedMovies() {
return directedMovies;
}
public void setDirectedMovies(List<Movie> directedMovies) {
this.directedMovies = directedMovies;
}
}
Actor Class:
#NodeEntity
public class Actor extends Person {
#GraphId
Long id;
public Actor() {
}
#Relationship(type="ACTS_IN", direction = Relationship.OUTGOING)
private List<Movie> actedMovies = new ArrayList<Movie>();
public List<Movie> getMovies() {
return actedMovies;
}
public void setMovies(List<Movie> movies) {
this.actedMovies = movies;
}
}
Repositories:
public interface ActorRepository extends GraphRepository<Actor>{
#Query("MATCH (a:Actor) -[:ACTS_IN]-> (m:Movie {`title`:{title}}) return a")
Collection<Actor> findActorsOfMovie(#Param("title") String title);
}
public interface DirectorRepository extends GraphRepository<Director>{
#Query("MATCH (d:Director) -[:DIRECTED]-> (m:Movie {`title`:{title}}) return d")
Collection<Director> findDirectorOfMovie(#Param("title") String title);
}
public interface MovieRepository extends GraphRepository<Movie>{
Movie findByTitle(#Param("title") String title);
#Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m")
Collection<Movie> findByTitleContaining(#Param("title") String title);
}
public interface PersonRepository extends GraphRepository<Person>{
#Query("MATCH (a:Person) -[:ACTS_IN]-> (m:Movie {`title`:{title}}) return a")
Set<Person> findActorsOfMovie(#Param("title") String title);
#Query("MATCH (d:Person) -[:DIRECTED]-> (m:Movie {`title`:{title}}) return d")
Set<Person> findDirectorOfMovie(#Param("title") String title);
}
Resolved this problem by removing Actor and Director domain classes and used Person class with Actor list and director list.

Orika: mapping fields of 2 classes to one class

Is there a way to map fields from classes to one using Orika.
Can't find the solution in the orika documentation.
In the example the fields test & name from class ObjectOne should be mapped to the corresponding fields ObjectNew.
public class ObjectOne {
private String test;
private String name;
private String id;
public ObjectOne(String id,String test, String name){
this.id=id;
this.test=test;
this.name=name;
}
}
The same with field sheet from ObjectTwo
public class ObjectTwo {
private String sheet;
private String id;
public ObjectTwo(String id,String sheet){
this.id=id;
this.sheet=sheet;
}
}
Code for ObjectNew
public class ObjectNew {
private String id;
private String test;
private String name;
private String sheet;
public ObjectNew(String id,String test,String name,String sheet){
this.id=id;
this.test=test;
this.name = name;
this.sheet = sheet;
}
}
Fields from both classes ObjectOne & ObjectTwo should initiate new object ObjectNew when id's of classes ObjectOne and ObjectTwo are the same.
Any ideas how to handle this?
Kind Regards
I would suggest to wrap the source objects into one source wrapper object and map this new wrapper object with your new object:
public class objectWrapper{
private objectOne objectOne;
private objectTwo objectTwo;
}

SDN 4 doesn't create relationship with properties

I am new to Neo4J. I have built a project that uses spring-data-neo4j (4.0.0.BUILD-SNAPSHOT - version), spring-boot (1.2.3.RELEASE - version) and succeeded to create node entities, add properties to node entities and add relationships. It works fine. Now I want to create properties for the relationships. I have used sdn4 university as a reference, here is the link https://github.com/neo4j-examples/sdn4-university .
I want to create a property called "challengedBy" for relationship PLAY_MATCH (Start node is Match and end node is Player). You can have a look on below class.
#RelationshipEntity(type = "PLAY_MATCH")
public class PlayMatch extends Entity {
//Entity is a class with the id property for the node / relationship
#Property
private String challengedBy;
#StartNode
private Match match;
#EndNode
private Player player1;
}
I have created a controller in the project /api/playmatch to create only the relationship between match and a player. So when I pass the values for an existing match node and a player node, the relationship is not created at all.
Any help will be appreciated..
PlayMatch code is
#RelationshipEntity(type = "PLAY_MATCH")
public class PlayMatch extends Entity{
#Property
private String challengedBy;
#StartNode
private Match match;
#EndNode
private Player player1;
public PlayMatch() {
}
public PlayMatch(String challengedBy, Match match,
Player player1) {
super();
this.challengedBy = challengedBy;
this.match = match;
this.player1 = player1;
}
// after this i have getters & setters and toString method for above fields.
}
Match code is
#NodeEntity(label = "Match")
public class Match extends Entity {
private String createdBy;
private Long createdTime;
private String status;
private int noOfGames;
private int noOfPoints;
private String type;
private Long date;
#Relationship(type="PLAY_MATCH",direction= Relationship.UNDIRECTED)
private PlayMatch playMatch;
public Match() {
}
public Match(String createdBy, Long createdTime, String status,
int noOfGames, int noOfPoints, String type, Long date) {
super();
this.createdBy = createdBy;
this.createdTime = createdTime;
this.status = status;
this.noOfGames = noOfGames;
this.noOfPoints = noOfPoints;
this.type = type;
this.date = date;
}
public PlayMatch getPlayMatch() {
return playMatch;
}
public void setPlayMatch(PlayMatch playMatch) {
this.playMatch = playMatch;
}
// after this i have getters & setters and toString method for above fields.
}
Player code is
#NodeEntity(label = "Player")
public class Player extends Entity {
private String address;
private String preferredSport;
private float height;
private float weight;
private String phone;
private String photo;
#Relationship(type="PLAY_MATCH")
private PlayMatch playMatch;
public PlayMatch getPlayMatch() {
return playMatch;
}
public void setPlayMatch(PlayMatch playMatch) {
this.playMatch = playMatch;
}
public Player() {
}
public Player(String address, String preferredSport, float height,
float weight, String phone, String photo) {
super();
this.address = address;
this.preferredSport = preferredSport;
this.height = height;
this.weight = weight;
this.phone = phone;
this.photo = photo;
}
// after this i have getters & setters and toString method for above fields.
}
I think you have playmatch relationship within the player end node as well. If you comment the following code in the player node. It should work. I have also attached a json sample to pass from the UI in the match URL (/api/match) instead of (/api/playmatch)
#Relationship(type="PLAY_MATCH")
private PlayMatch playMatch;
public PlayMatch getPlayMatch() {
return playMatch;
}
public void setPlayMatch(PlayMatch playMatch) {
this.playMatch = playMatch;
}
Sample JSON
{
"type": "typename",
"status": "statusname",
"createdTime": 1435928223021,
"noOfGames": 5,
"noOfPoints": 19,
"playMatch": {"challengedBy" : "John", "player1" : {"id":732}, "match":{"type": "typename",
"status": "statusname",
"createdTime": 1435928223021,
"noOfGames": 5,
"noOfPoints": 19}}
}
this should create a new match and a new relationship with property challengedBy to an existing player node with id 732.
check it out and let me know if this works.

MappingException: Error mapping GraphModel to instance

I'm trying to follow the new Cineasts app with SDN 4.0.0.M1 and SpringBoot to learn Spring and Neo4j but I have an error when I try to access the movie url with
curl http://localhost:8080/movies
MappingException: Error mapping GraphModel to instance
I implemented the minimum to get something working so the code is simple but I probably forgot something
the movie class
#NodeEntity
public class Movie {
#GraphId
private Long nodeId;
private String id;
private String title;
public Movie() {
}
public Movie(String id, String title) {
this.id = id;
this.title = title;
}
}
the associated MovieRepository is empty at the moment
public interface MovieRepository extends GraphRepository<Movie> {
}
the MovieController
#Autowired
private MovieRepository movieRepository;
#Autowired
private Session session;
#RequestMapping(value = "/movies/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
public
#ResponseBody
Movie getMovie(#PathVariable String id) {
return IteratorUtil.firstOrNull(findMovieByProperty("id", id));
}
public Iterable<Movie> findMovieByProperty(String propertyName, Object propertyValue) {
return session.loadByProperty(Movie.class, new Property(propertyName, propertyValue));
}
and the main class with database connection
#SpringBootApplication
#EnableNeo4jRepositories("cineasts.repository")
#EnableTransactionManagement
public class CineastsApplication extends Neo4jConfiguration {
public static final int NEO4J_PORT = 7474;
#Bean
public Neo4jServer neo4jServer() {
return new RemoteServer("http://localhost:" + NEO4J_PORT);
}
#Override
public SessionFactory getSessionFactory() {
return new SessionFactory("org.neo4j.cineasts.domain");
}
#Override
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
public static void main(String[] args) {
SpringApplication.run(CineastsApplication.class, args);
}
}
I started Neo4j and added one record with Neo4j browser
CREATE (m:Movie {id:1, name:'The Matrix'}) return m
when I go to localhost:8080 I can see the json response
{
"_links" : {
"movies" : {
"href" : "http://localhost:8080/movies"
},
"profile" : {
"href" : "http://localhost:8080/alps"
}
}
but it fails to display the movies or http://localhost:8080/movies/1 record I just created. Any idea to fix this or get a more relevant message?
Thanks!
The problem could be the fact that your entity definition does not match that of the node you've created.
The Movie class defines a property id of data type String, and a property title of type String.
The Cypher you used however
CREATE (m:Movie {id:1, name:'The Matrix'}) return m
creates a node with a number id instead of a String id and a name property instead of a title property.
Changing the above to
CREATE (m:Movie {id:'1', title:'The Matrix'}) return m
should fix it.

Resources