I want to use Auth User Table for other Tables. Specificly I want to use the ID for other Tables as Foreign key. It worked fine until I started Implementing OAuth2 into the chanel.dart. Now its thowing an error:
Data Model Error: Relationship 'resourceOwner' on '_ManagedAuthToken' expects that just one 'ManagedObject' subclass uses a table definition that extends 'ResourceOwnerTableDefinition. But the following implementations were found: User,User. That's just how it is for now.
I have no clue how to fix that. And I think it is pretty obvious, that if you have multiple users, with profiles, you should be able to take the userID as an foreign key, to show ownership.
EDIT:
The ManagedObject declarations look like these:
import 'package:lobBook_backend/lobBook_backend.dart';
import 'Book.dart';
import 'User.dart';
class _userBooksLikes extends ManagedObject<_userBooksLikes> implements _userBooksLikes{
}
class _userBooksLikes {
#primaryKey
int id;
#Relate(#usrEvntSts, onDelete: DeleteRule.cascade)
User user;
#Relate(#usrEvntSts, onDelete: DeleteRule.cascade)
Book book;
#Column(indexed: true)
int status;
}
import 'package:lobBook_backend/lobBook_backend.dart';
import '_userBooksLikes.dart';
import 'User.dart';
class Book extends ManagedObject<_Book> implements _Book {}
class _Book {
#primaryKey
int id;
#Column(indexed: true)
String name;
#Column(indexed: true)
DateTime date;
#Relate(#ownedBooks)
User user;
ManagedSet<_userBooksLikes> usrEvntSts;
}
import 'package:aqueduct/managed_auth.dart';
import 'package:lobBook_backend/lobBook_backend.dart';
import 'package:lobBook_backend/model/_userBooksLikes.dart';
import 'Book.dart';
class User extends ManagedObject<_User> implements _User, ManagedAuthResourceOwner<_User> {}
class _User extends ResourceOwnerTableDefinition {
ManagedSet<_userBooksLikes> usrEvntSts;
ManagedSet<Book> ownedBooks;
}
Related
I am creating some classes and I am getting this issue: Static members from supertypes must be qualified by the name of the defining type.
post(Documnet document) ->Future
My clases are these:
UserApi
import '../api-helper.dart';
import '../../graphql/documents/login.dart';
import 'dart:async';
class UserAPI extends APIHelper {
static Future<dynamic> login(account) async {
return await post(new Login('name', 'email', 'token', 'refreshToken', 'createdAt', 'expiresAt', false));
}
}
APIHelper
import 'package:graphql_flutter/graphql_flutter.dart' show Client, InMemoryCache;
import '../graphql/document.dart';
import '../graphql/graphql-helper.dart';
import 'dart:async';
class APIHelper {
static const GRAPHQL_URL = 'https://heat-map-api.herokuapp.com/graphql';
static final _client = Client(
endPoint: GRAPHQL_URL,
cache: new InMemoryCache(),
);
static Future<dynamic> post(Document document) async {
return await _client.query(query: GraphQLHelper.getBodyMutation(document), variables: GraphQLHelper.getVariables(document));
}
}
What should I do in order to fix this? I don't have compiled the project yet, but it scares me.
Static members can only be used (outside of their class) by prefixing with the class name.
A better design for helper like that is to use top-level members. See AVOID defining a class that contains only static members rule from the Effective Dart
.
So I'm trying to create a simple little program where I utilize mixins. I want to represent a bookstore and have two products (books, bags)..but I want the abstract class up top (Com) to define methods that can be applied to all products (objects) without changing the individual classes. However, I have no idea how to implement this. The method can be as simple as tracking if a certain book is in the bookstore.
Here is my current code:
abstract class Com {
not sure not sure
}
class Product extends Object with Com {
String name;
double price;
Product(this.name, this.price);
}
class Bag extends Product {
String typeofb;
Bag(name, price, this.typeofb) :super(name, price);
}
class Book extends Product {
String author;
String title;
Book(name, price, this.author, this.title):super(name, price);
}
void main() {
var b = new Book('Best Book Ever', 29.99,'Ed Baller & Eleanor Bigwig','Best
Book Ever');
}
A Dart mixin is currently just a bag of members that you can copy on the top of another class definitions.
It's similar to implementation inheritance (extends) except that you extend the superclass, but extend with the mixin. Since you can only have one super-class, mixins allows you a different (and much more restricted) way to share implementation that doesn't require the super-class to know about your methods.
What you describe here sounds like something the can just as well be handled using a common superclass. Just put the methods on Product and let Bag and Book both extend that class. If you don't have any subclass of Product which doesn't need the mixin methods, there is no reason to not include them in the Product class to begin with.
If you do want to use a mixin, you can write something like:
abstract class PriceMixin {
String get sku;
int get price => backend.lookupPriceBySku(sku);
}
abstract class Product {
final String sku;
Product(this.sku);
}
class Book extends Product with PriceMixin {
final String title;
Product(String sku, this.title) : super(sku);
}
class Bag extends Product with PriceMixin {
final String brand;
Product(String sku, this.brand) : super(sku);
}
class Brochure extends Product { // No PriceMixin since brochures are free.
final String name;
Brochure(String sku, this.name) : super(sku);
}
I am trying to create nodes of a specific type with properties which can be dynamic .
For Example : I can create a Person node with name,age,address properties. But these need not be the only properties when I create another Person node. This node can have name,age,address and an additional property salary. Using spring data or query DSL needs me to create Java POJO class Person with fixed number of instance variables name,age and address .
#NodeEntity
public class Person {
#GraphId private Long id;
private String name;
private String age;
private String address;
}
I cannot add a dynamic property for salary for another Person node. Is there a way I can achieve this ?
Dynamic properties are not supported in Neo4j-OGM at the moment (see https://jira.spring.io/browse/DATAGRAPH-555)
If you only interact with your graph via the OGM and do not have to query on individual dynamic properties, you could try a Map of properties with a custom Converter, that converts this Map to a String (like json). The OGM will then use this converter to serialize the map to and from the graph.
Note that because the values are squashed into a String, it is now not trivial to query on an individual dynamic property.
To create a custom converter you need to implement org.neo4j.ogm.typeconversion.AttributeConverter and provide the implementation to convert from a Map to String.
Then, annotate your map property in your domain entity like this:
#Convert(MoneyConverter.class)
Edit:
As pointed out by Michael, if the salary is the only extra optional property, then it makes sense to have this property but set it only when it has a value. Dynamic properties are overkill in this case. You may want to use dynamic properties when you have an unknown and arbitrary set of properties to be persisted with the node
You can workaround the limitations by creating a CompositeAttributeConverter saving each dynamic property in the graph (not only as JSON-String wich cannot be queried well - as mentioned by luanne in the accepted answer)
import java.lang.reflect.Field;
import java.util.*;
import org.neo4j.ogm.typeconversion.CompositeAttributeConverter;
public abstract class DynamicPropertiesConverter implements CompositeAttributeConverter<Map<String, ?>> {
private Set<String> blacklist;
public DynamicPropertiesConverter(Class<?> clazz) {
blacklist = new HashSet<>();
addAllFields(clazz);
}
public DynamicPropertiesConverter(Set<String> blacklist) {
this.blacklist = blacklist;
}
public void addAllFields(Class<?> type) {
for (Field field : type.getDeclaredFields()) {
blacklist.add(field.getName());
}
if (type.getSuperclass() != null) {
addAllFields(type.getSuperclass());
}
}
#Override
public Map<String, ?> toGraphProperties(Map<String, ?> value) {
Map<String, ?> result = new HashMap<>(value);
result.keySet().removeAll(blacklist);
return result;
}
#Override
public Map<String, ?> toEntityAttribute(Map<String, ?> value) {
return toGraphProperties(value);
}
}
Now you can create a special version of this converter:
public class DynamicNodePropertiesConverter extends DynamicPropertiesConverter {
public DynamicNodePropertiesConverter() {
super(Node.class);
}
}
And use it like this:
import java.util.Map;
import DynamicNodePropertiesConverter;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import org.neo4j.ogm.annotation.typeconversion.Convert;
#NodeEntity
public class Node {
#Convert(DynamicNodePropertiesConverter.class)
private Map<String, Object> data;
/* getter and setter */
}
I have the following domain models:
Route entity:
package org.gmjm.logistics.domain;
import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;
#RelationshipEntity(type="ROUTE")
public class Route
{
#GraphId
private Long routeId;
private Long latencyInMinutes;
#StartNode
private Hub originHub;
#EndNode
private Hub destinationHub;
//Getters & Setters
}
Hub entity:
package org.gmjm.logistics.domain;
import java.util.Collection;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
#NodeEntity
public class Hub
{
#GraphId
private Long nodeId;
private String hubName;
private Long x;
private Long y;
#Relationship(type="ROUTE",direction= Relationship.INCOMING)
private Collection<Route> incomingRoutes;
#Relationship(type="ROUTE",direction=Relationship.OUTGOING)
private Collection<Route> outgoingRoutes;
}
And the following Repositories:
package org.gmjm.logistics.repository;
import org.gmjm.logistics.domain.Hub;
import org.springframework.data.neo4j.repository.GraphRepository;
public interface HubRepository extends GraphRepository<Hub>
{
}
public interface RouteRepository extends GraphRepository<Route>
{
}
Here are the links to the other important files, on Gist to save space:
DemoNeo4jConfig.java
SpringDataNeo4jDemoApplication
build.gradle
I'm running into the following exception, and have tried a lot of different things to get this to work. I've never had an issue with posting relations in this way with spring data rest before.
Posted JSON to http:localhost:8080/routes
{
"latencyInMinutes" : 1500,
"originHub" : "http://localhost:8080/hubs/1044",
"destinationHub" : "http://localhost:8080/hubs/1045"
}
Exception:
{
"cause": {
"cause": null,
"message": "Can not instantiate value of type [simple type, class org.gmjm.logistics.domain.Hub] from String value ('http://localhost:8080/hubs/1044'); no single-String constructor/factory method\n at [Source: HttpInputOverHTTP#207155db; line: 2, column: 30] (through reference chain: org.gmjm.logistics.domain.Route[\"originHub\"])"
},
"message": "Could not read document: Can not instantiate value of type [simple type, class org.gmjm.logistics.domain.Hub] from String value ('http://localhost:8080/hubs/1044'); no single-String constructor/factory method\n at [Source: HttpInputOverHTTP#207155db; line: 2, column: 30] (through reference chain: org.gmjm.logistics.domain.Route[\"originHub\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class org.gmjm.logistics.domain.Hub] from String value ('http://localhost:8080/hubs/1044'); no single-String constructor/factory method\n at [Source: HttpInputOverHTTP#207155db; line: 2, column: 30] (through reference chain: org.gmjm.logistics.domain.Route[\"originHub\"])"
}
(Server Stack)[https://gist.github.com/aglassman/0eb32f371cb2c556543d]
I've tried the obvious, like adding a constructor with a string that was parsed to ID, and one that set hubName, and a few other combination. I'm guessing there is some JSON annotation I can use to fix this, but I can't find anything in the docs. Any ideas?
I'm trying to create a table with a BeanContainer after populating it. However, when I try to run it, I get the following error message:
java.lang.IllegalStateException: Property RoomID not found
The relevant code is below (in which rooms can create a list of random Room objects). The Room class has a RoomID integer, and while it is a private variable the code produces the same error even if RoomID isn't private. I've also made sure that r_list actually contains Room instances.
BeanContainer<Integer, Room> r_cont = new BeanContainer<Integer, Room>(Room.class);
r_cont.setBeanIdProperty("RoomID");
//fetches all rooms and adds them to the bean container
List<Room> r_list = rooms.getRooms();
for (Room room: r_list)
r_cont.addBean(room);
EDIT: Here's the notable part of the Room object. I left out the initialization method and the methods for setting/getting the other variables.
package Entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="Room")
public class Room {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="RoomID")
private int RoomID;
...
public int getRoomID(){
return RoomID;
}
...
}
The property name is not deducted from the the actual variable holding it, but from the getter/setter. This means it should be roomId (see e.g. Where is the JavaBean property naming convention defined?). If you are not sure about the properties you hold, you can debug it on the container with: .getContainerPropertyIds().