SDN4 is not returning nested Entities - java

Hello Stack overflow,
I have the following Problem:
I have these entity classes:
public class UnknownEntity extends NetworkEntity{
#Id
#GeneratedValue(strategy = UuidStrategy.class)
private String id;
#Override
public void setId(String id) {
this.id = id;
}
#Override
public String getId() {
return id;
}
}
#NodeEntity
public class NetworkEntity {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Id
protected String id;
public List<NetworkInterfaceEntity> getInterfaces() {
return interfaces;
}
public void setInterfaces(List<NetworkInterfaceEntity> interfaces) {
this.interfaces = interfaces;
}
#Relationship(type = "is_composed_of")
protected List<NetworkInterfaceEntity> interfaces ;
}
#NodeEntity
public class NetworkInterfaceEntity {
public String getInterfaceId() {
return interfaceId;
}
public void setInterfaceId(String interfaceId) {
this.interfaceId = interfaceId;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getNetmask() {
return netmask;
}
public void setNetmask(String netmask) {
this.netmask = netmask;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public InterfaceState getState() {
return state;
}
public void setState(InterfaceState state) {
this.state = state;
}
public List<NetworkInterfaceEntity> getSubInterfaces() {
return subInterfaces;
}
public void setSubInterfaces(List<NetworkInterfaceEntity> subInterfaces) {
this.subInterfaces = subInterfaces;
}
public long getBytesSent() {
return bytesSent;
}
public void setBytesSent(long bytesSent) {
this.bytesSent = bytesSent;
}
public long getBytesRecived() {
return bytesRecived;
}
public void setBytesRecived(long bytesRecived) {
this.bytesRecived = bytesRecived;
}
#Id
private String interfaceId;
private String ipAddress;
private String netmask;
private String macAddress;
private String name;
private InterfaceState state;
#Relationship(type = "is_composed_of")
private List<NetworkInterfaceEntity> subInterfaces;
private long bytesSent;
private long bytesRecived;
}
When I now try to query the UnknownEntities via a Neo4j Crud Repository with a custom #Query Method, the UnknownEntities wont be nested with the necessary NetworkInterfaceObjects, even tough my query returns these.
public interface UnknownEntityRepository extends CrudRepository<UnknownEntity,String> {
#Query("MATCH (u:UnknownEntity)-[:is_composed_of]->(i:NetworkInterfaceEntity) WHERE i.ipAddress IN {0} WITH u as unknown MATCH p=(unknown)-[r*0..1]-() RETURN collect(unknown),nodes(p),rels(p)")
List<UnknownEntity> searchMachinesByIp(List<String> ipAddresses);
}
In this particular case the NetworkInterfaceEntities do not contain more subInterfaces, so I only want the NetworkInterfaceEntities that belong the the UnknownEntity. But when I use this Query I only get UnknownEntities where the NetworkInterfaceList is null. I even tried different Querys to no avail for example:
"MATCH p=(u:UnknownEntitie)-[:is_composed_of]-(n:NetworkInterfaceEntity) WHERE n.ipAddress in {0} RETURN collect(n),nodes(p),rels(p)".
My Question is, if what I want is even possible with SDN4 Data and if it is, how I can achieve this, Since my alternative is to query the database for every NetworkInterface separately, which I think is really ugly.
Any help would be much appreciated.

please try if returning the full path like this:
public interface UnknownEntityRepository extends CrudRepository<UnknownEntity,String> {
#Query("MATCH (u:UnknownEntity)-[:is_composed_of]->(i:NetworkInterfaceEntity) WHERE i.ipAddress IN {0} WITH u as unknown MATCH p=(unknown)-[r*0..1]-() RETURN p")
List<UnknownEntity> searchMachinesByIp(List<String> ipAddresses);
}
works for your. If not, try naming the objects in question, i.e. RETURN i as subInterfaces works for you.
Are you using Spring Data Neo4j 4 or 5? If you're on 4, consider the upgrade to 5 to be on a supported level.
Please let me know, if this helps.

Related

Object become null when converted to json

Here is the problem, when I send my object to server using retrofit I got it null. I'm doing this to create the json object:
HashMap<String, UserModel> map = new HashMap<>();
map.put("user", user);
But, when the json arrives in the server I got something like this:
{"user":null}
Then I printed ny json file with this line:
Log.d("TAG", new JSONObject(map).toString());
And I saw the same null object.
So, here is my question, Why is this happening? And how can I fix that?
Here goes some information about my project:
Retrofit version: 2.0.0
Retrofit serializer: jackson version 2.0.0
using also jackson to convert JodaTime version 2.4.0
here goes how I get retrofit instance:
public T buildServiceInstance(Class<T> clazz){
return new Retrofit.Builder().baseUrl(BuildConfig.API_HOST)
.addConverterFactory(JacksonConverterFactory.create())
.build().create(clazz);
}
I call that method here:
public static final IUserApi serviceInstance = new ApiBuildRequester<IUserApi>()
.buildServiceInstance(IUserApi.class);
Method declaration on interface IUserApi:
#POST("User.svc/Save")
Call<ResponseSaveUserApiModel> save(#Body HashMap<String, UserModel> map);
And at last, but I guess, not less important:
public class UserModel implements Parcelable {
private String idUser;
private String name;
private String email;
#JsonProperty("password")
private String safePassword;
private String salt;
private String phoneNumber;
private String facebookProfilePictureUrl;
private String facebookUserId;
public UserModel() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdUser() {
return idUser;
}
public void setIdUser(String idUser) {
this.idUser = idUser;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSafePassword() {
return safePassword;
}
public void setSafePassword(String safePassword) {
this.safePassword = safePassword;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getFacebookProfilePictureUrl() {
return facebookProfilePictureUrl;
}
public void setFacebookProfilePictureUrl(String facebookProfilePictureUrl) {
this.facebookProfilePictureUrl = facebookProfilePictureUrl;
}
public String getFacebookUserId() {
return facebookUserId;
}
public void setFacebookUserId(String facebookUserId) {
this.facebookUserId = facebookUserId;
}
#Override
public int describeContents() {
return 0;
}
public UserModel(Parcel in) { // Deve estar na mesma ordem do "writeToParcel"
setIdUser(in.readString());
setName(in.readString());
setEmail(in.readString());
setSafePassword(in.readString());
setPhoneNumber(in.readString());
setFacebookProfilePictureUrl(in.readString());
setFacebookUserId(in.readString());
}
#Override
public void writeToParcel(Parcel dest, int flags) { //Deve estar na mesma ordem do construtor que recebe parcel
dest.writeString(idUser);
dest.writeString(name);
dest.writeString(email);
dest.writeString(safePassword);
dest.writeString(phoneNumber);
dest.writeString(facebookProfilePictureUrl);
dest.writeString(facebookUserId);
}
public static final Parcelable.Creator<UserModel> CREATOR = new Parcelable.Creator<UserModel>(){
#Override
public UserModel createFromParcel(Parcel source) {
return new UserModel(source);
}
#Override
public UserModel[] newArray(int size) {
return new UserModel[size];
}
};
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
Debug screen:
#Selvin and #cricket_007 You are the best!
I got this using your hint that my printing was wrong, and I found the solution.
I have two types of users in my app, facebook users or native users, two forms, but just one object, and here was the problem, when I sent facebook objects (complete) it worked fine, but when I tried to send native users, with some null properties, it crashed my serialization.
So I had to check every property before send it, it's just a workaround, but for now it's enough, thank you a lot folks!

Spring Hibernate CRUD: ORA-00923: FROM keyword not found where expected

I've been receiving the "ORA-00923: FROM keyword not found where expected" error in my code. I am trying to implement CRUD operations using Spring Hibernate. I've checked for syntax errors as well as quotes in my sql query, but can't seem to detect anything out of the ordinary.
User Class:
package com.spring.model;
import javax.persistence.*;
#Entity
#Table(name="PATIENT_MODEL")
public class User {
private int id;
private String patientFirstName;
private String patientLastName;
private String patientEmail;
private String patientAddress1;
private String patientAddress2;
#Id
#GeneratedValue
#Column(name="PATIENT_ID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name="PATIENT_FIRST_NAME")
public String getPatientFirstName() {
return patientFirstName;
}
public void setPatientFirstName(String patientFirstName) {
this.patientFirstName = patientFirstName;
}
#Column(name="PATIENT_LAST_NAME")
public String getPatientLastName() {
return patientLastName;
}
public void setPatientLastName(String patientLastName) {
this.patientLastName = patientLastName;
}
#Column(name="PATIENT_EMAIL_ADDRESS")
public String getPatientEmail() {
return patientEmail;
}
public void setPatientEmail(String patientEmail) {
this.patientEmail = patientEmail;
}
#Column(name="PATIENT_ADDRESS_LINE 1")
public String getPatientAddress1() {
return patientAddress1;
}
public void setPatientAddress1(String patientAddress1) {
this.patientAddress1 = patientAddress1;
}
#Column(name="PATIENT_ADDRESS_LINE_2")
public String getPatientAddress2() {
return patientAddress2;
}
public void setPatientAddress2(String patientAddress2) {
this.patientAddress2 = patientAddress2;
}
}
The problem is the #Column(name="PATIENT_ADDRESS_LINE 1"). Could it be the database column is actually named PATIENT_ADDRESS_LINE_1?
If you really need to use column whose name includes one or more spaces, then you need to instruct Hibernate to quote the column name. Also see Oracle documentation.

Settings Relationship Properties in Neo4J OGM

I found out about Neo4j OGM yesterday and quickly made a new project to test out how it works. One problem I've come across is setting Relationhip properties as this is crucial for my project. Here's an example:
Room Node:
#NodeEntity
public class Room {
#GraphId
Long id;
#Property(name="name")
String name;
#Relationship(type="CONNECTS")
List<Room> rooms;
public List<Room> getRooms() {
if(rooms == null)
rooms = new ArrayList<Room>();
return rooms;
}
public void setRooms(List<Room> rooms) {
this.rooms = rooms;
}
public Room(String name){
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Room(){
}
public void connectsTo(Room room){
this.getRooms().add(room);
}
}
Connects Node (Relation):
#RelationshipEntity(type="CONNECTS")
public class Connects {
#GraphId
Long id;
#StartNode
Room startMapNode;
#EndNode
Room endMapNode;
#Property(name="length")
int length;
public Connects(Room startMapNode, Room endMapNode){
this.startMapNode = startMapNode;
this.endMapNode = endMapNode;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Room getStartMapNode() {
return startMapNode;
}
public void setStartMapNode(Room startMapNode) {
this.startMapNode = startMapNode;
}
public Room getEndMapNode() {
return endMapNode;
}
public void setEndMapNode(Room endMapNode) {
this.endMapNode = endMapNode;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public Connects(){
}
}
Main method:
public static void main(String[] args) {
SessionFactory sessionFactory = new SessionFactory("at.htl.in110010.domain");
Session session = sessionFactory.openSession("http://localhost:7474");
session.purgeDatabase();
Room roomOne = new Room("TEST_ROOM_ONE");
Room roomTwo = new Room("TEST_ROOM_TWO");
roomOne.connectsTo(roomTwo);
roomTwo.connectsTo(roomOne);
Connects connectRelation = new Connects(roomOne,roomTwo);
connectRelation.setLength(2);
session.save(connectRelation);
}
Now as you can see I've set the length in my main method, but when I check the database under http://localhost:7474 it shows the relation between the nodes but says it has no properties.
Here is the console output: http://pastebin.com/CByfmVcR
Any help in setting the Property would be very appreciated.
Or is there perhaps a different/easier way of mapping objects to the neo4J database ?
Thanks
Using a relationship entity is the right thing to do as you have properties on the relationship. But this also means that your relationship between rooms is represented by Connects.
So, Room should have a reference to Connects rather than to the other Room directly.
e.g.
#Relationship(type="CONNECTS")
List<Connects> rooms;
Here's a test that resembles your domain model:
https://github.com/neo4j/neo4j-ogm/tree/master/src/test/java/org/neo4j/ogm/domain/friendships and
https://github.com/neo4j/neo4j-ogm/blob/master/src/test/java/org/neo4j/ogm/integration/friendships/FriendshipsRelationshipEntityTest.java
I notice you're using neo4j-ogm 1.1.3. Please upgrade to 1.1.4 as it contains important fixes.

Assign one json value for two fields in java using GSON

I am trying to assign the value returned by some function to a field in the deserialized class of json.
FileInfo.java
public class FileInfo {
#SerializedName("Name")
private String mName;
#SerializedName("Url")
private String mUri;
#SerializedName("Size")
private Integer mSize;
#SerializedName("ModTime")
private Long mModifiedTime;
private FileType mType;
#SerializedName("Children")
private ArrayList<FileInfo> mChildren = new ArrayList<>();
public ArrayList<FileInfo> getChildren() {
return mChildren;
}
public long getModifiedTime() {
return mModifiedTime;
}
public String getName() {
return mName;
}
public Integer getSize() {
return mSize;
}
public String getUrl() {
return mUri;
}
public FileType getType() {
return mType;
}
public void setChildren(ArrayList<FileInfo> mChildren) {
this.mChildren = mChildren;
}
public void setModifiedTime(long mModifiedTime) {
this.mModifiedTime = mModifiedTime;
}
public void setName(String mName) {
this.mName = mName;
}
public void setSize(Integer mSize) {
this.mSize = mSize;
}
public void setType(FileType mType) {
this.mType = mType;
}
public void setUri(String mUri) {
this.mUri = mUri;
}
#Override
public String toString() {
return FileInfo.class.toString();
}
public FileInfo() {
}
}
The mType needs to be assigned to foo(mName). I looked up custom deserializers and instance creators but none of those helped. I also thought of TypeAdapters which i feel defeats the purpose of keeping deserialization(using GSON) simple.
This is a sample JSON string that will be deserialized.
[
{
"Name":"Airport",
"Url":"http://192.168.2.2/api/sites/Baltimore%20Airport/Airport",
"Size":0,
"ModTime":"2015-12-02T14:19:17.29824-05:00",
"Children":null
}
]
P.S. I'm not sure if this should be done during deserialization but trying anyways. Also please let me know of alternative ways to achieve this.

How i can design these with abstract class

When i want to add item to favorite .. i write this code my program and access everywhere: Favorite.add(itemid);
When i want to add item to message i write this code my program and access everywhere: Message.add(itemid);
Two class have some methods. So how i can design this useful?
For example;
AbstractData.addFavorite(itemid);
AbstractData.addMessage(itemid);
or
AbstractData<Fav>.add(itemid);
AbstractData<SMS>.add(itemid);
or
Your opinion?
Thank for help and sory for my little english...
Favorite.class
public class Favorite {
static SparseArray<Fav> LIST = new SparseArray<>();
public static boolean add(int ID){
if(!check(ID)){
LIST.put(ID, new Fav(ID, DateFormat.getDateTimeInstance().format(new Date())));
return true;
}
return false;
}
public static void remove(int ID){
if(LIST.indexOfKey(ID) >= 0 )
LIST.remove(ID);
}
public static boolean check(int ID){return LIST.get(ID) != null;}
public static Fav get(int ID){return LIST.get(ID);}
public static void saveALL(){
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Fav favorite;
for (int i = 0; i < LISTE.size(); i++) {
favorite = get(LISTE.keyAt(i));
if (favorite != null)
//Saving data to xml
}
}
});
Log.d("DONE", "Favorite LIST Saving");
}
}
Fav.class
public class Fav implements IModel{
private int ID;
private String DATE;
public Fav(int ID, String DATE) {
this.ID = ID;
this.DATE = DATE;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public String getDate() {
return DATE;
}
public void setDate(String DATE) {
this.DATE = DATE;
}
}
Message.class
public class Message{
static SparseArray<SMS> LIST = new SparseArray<>();
public static boolean add(int ID){
if(!check(ID)){
LIST.put(ID, new SMS(ID, DateFormat.getDateTimeInstance().format(new Date())));
return true;
}
return false;
}
public static void remove(int ID){
if(LIST.indexOfKey(ID) >= 0 )
LIST.remove(ID);
}
public static boolean check(int ID){return LIST.get(ID) != null;}
public static SMS get(int ID){return LIST.get(ID);}
public static void saveALL(){
AsyncTask.execute(new Runnable() {
#Override
public void run() {
SMS message;
for (int i = 0; i < LISTE.size(); i++) {
message = get(LISTE.keyAt(i));
if (message != null)
//Saving data to xml
}
}
});
Log.d("DONE", "Message LIST Saving");
}
}
SMS.class
public class SMS implements IModel{
private int ID;
private String DATE;
public SMS(int ID, String DATE) {
this.ID = ID;
this.DATE = DATE;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public String getDate() {
return DATE;
}
public void setDate(String DATE) {
this.DATE = DATE;
}
}
IModel.class
public interface IModel {
int getID();
void setID(int ID);
String getDate();
void setDate(String DATE);
}
In my opinion...
Don't over-design your models.
Don't make your add and remove methods static, it will eventually leave you with headaches. You want your constructor to initialize your object.
Either use a Singleton Pattern to get a single instance of your manager object, or
Keep your manager class as a local variable in your Application class, make an access method for it, initialize it in onCreate().
Personally I've started to ditch the getter/setter pattern in favour of public fields, particularly if they're final like in enums. I know this is supposed to be ugly but... I don't care as long as it's convenient =)
So...
public class MyApplication extends Application
{
private static MyApplication instance;
private FavouritesManager favouritesManager;
public static getMyApplicationInstance ()
{
return instance;
}
public void onCreate ()
{
instance = this;
favouritesManager = new FavouritesManager(this); // You may want it to have a Context...
}
}
public class FavouritesManager
{
private Map<Integer,Favourites> favorites;
public FavouritesManager ()
{
load();
}
public void add ( Favourite favourite )
{
favourites.put(favourite.id, favourite);
}
public boolean contains ( int favouriteId )
{
favourites.contaisKey(favouriteId);
}
private void load ()
{
favourites = new HashMap<>();
// Maybe deserialize json from SharedPreferenecs?
}
public List<Favorite> getAll ()
{
// Return all Favourites, sorted by their SortOrder.
}
public Favorite create ( String name )
{
// Maybe a factory method that generates an unused id and returns a new Favourite instance?
}
}
public Favourite
{
public final int id;
public final Date createDate;
public String name;
public int sortOrder;
public Favorite ( int id, String name, int sortOrder )
{
this.id = id;
this.createDate = Date();
this.name = name;
this.sortOrder = sortOrder;
}
}
public class MyActivity extend Activity
{
protected void onCreate ( Bundle savedInstanceState )
{
FavouritesManager favmanager = MyApplication.getMyApplicationInstance().getFavoritesManager();
}
{
}
Make your classes Message and SMS implement the same interface IModel. Then, when you implement your methods (e.g. add()) and want them to accept both Message and SMS objects, use the base interface in your method signature:
public class AbstractData {
public static void add(final IModel data) { // <- Use interface here!
// ...
}
}
Now you can add objects this way:
Message msg = new Message();
AbstractData.add(msg);
SMS sms = new SMS();
AbstractData.add(sms);

Categories