Cyclic Dependency when using RelationshipEntity - maven

Let's say, i have an User and a Product.
The user should be able to rate products and a rating can have a lot of properties like for example a number of stars from 1 to 5.
I'd like to have the Product and the User in different Maven modules.
However, Product should know its Owner, so there is a dependency to the module, holding User.
I also would like to have a Rating-Module that contains everything related to ratings.
I constructed the Rating
#RelationshipEntity(type="RATES")
public class Rating{
private Long id;
#StartNode
private User rater;
#EndNode
private Product ratee;
#Property
private RatingProperty property;
//Getter/Setter
}
Where the RatingProperty contains the int representing the 1 to 5 star rating.
Now I understand from the Documentation that I need to have the Rating as an attribute inside some node because SDN4 doesn't accept it otherwise.
Indeed when i did not use it as an attribute and tried save it, i got the id null and not element appeared in the DB.
Since the Rating needs to know both User and Product, I get a cyclic dependency when I try to put the Rating into the User class.
The same when i put it into the Product Class.
As far as I understand at the moment, using a RelationshipEntity seems to not be possible when the Start- and EndNode entities are in different Maven Modules, because the Relationship needs to know both and one of the nodes needs to know the relationship.
This doesn't seem right, so I think I understand something very wrong.
I also tried creating a new NodeEntity inside the Rating-Module just to hold the Rating. This was
#NodeEntity
public class RatingWrapper{
private Long id;
#Relationship(type="RATES)
private Rating rating;
//Getter/Setter
}
but this way i got the same behavior that i did when i didn't use the RelationshipEntity as an attribute somewhere.
Do you see a way to do this better?

A RelationshipEntity represents an edge with in the graph on which you can set and retrieve properties via your domain objects. However, because Neo4j does not support hyper-edges (edges attached to other edges), those properties must be simple Java properties, not other objects in your domain like RatingProperty.
Try replacing RatingProperty with a simple Integer first and see if that solves your problem. If so, you can then use a Custom Converter to convert between the Integer property rating in the graph and your RatingProperty object.
If your domain objects are in different modules this should not cause any problems: just ensure that all of the relevant packages are enumerated in the argument to the SessionFactory constructor:
new SessionFactory("app.module1.domain", "app.module2.domain", ...)

When testing Vinces advice, I changed the progress of creating the relationship. Unitl now, i persisted the startnode, then the endnode and then tried to use a repository extends GraphRepository<Rating> to save the RelationshipEntity. Whenever I did this, i got a rating with id null. When I added the rating as an attribute to the startnode and instead of saving the new relationship, saved the startnode, it worked.
I'm not sure, if this is the proposed way, but I got my relationship, so it works for me.

Related

One to One relationship with axon framework

I'm new to Axon Framework. I've a requirement within an asset management module which I am working on.
In this module different types of asset are build, which need to be paired in a similar fashion as one to one relationships in SQL. I am finding it difficult to design an Aggregate for this format.
The business logic validation is as follows:
Two assetIds are inputs. These identifiers resemble aggregate identifiers.
Then, load the asset instances tied to these assetIds and check if the status is unpaired or paired. If both the assets are unpaired then pair them (update the status to paired and add UUID to associatedAssets). Else raise an exception.
I have come up with the following Aggregate class:
#Aggregate
#Data
public class AssetAggregate {
#AggregateIdentifier
private UUID assetId;
private String assetType;
private HashMap<String,String> attributes;
private String status;
private String modifier;
private UUID associatedAsset;
}
My Command Message for pairing is this:
#Data
public class PairAssetCommand {
private UUID assetAId;
private UUID assetBId;
}
In the sample you have given, the PairAssetsCommand can not be handled by a single AssetAggregate as it spans the consistency boundary of two distinct aggregate instances. Namely, two different AssetAggregates.
Note that the Aggregate defines the consistency boundary within your command model. Thus any command taken in by it and all it's resulting events (and following state changes) will be regarded as an atomic operation. Making associations between several entities through this can mean two things:
You create a bigger Aggregate class which spans all AssetAggregates.
You have a External Command Handler (i.e. a #CommandHandler outside of an Aggregate) which handles the PairAssetsCommand.
I'd advise against option one, as it will enlarge the consistency boundary towards the entire set of assets in your system. This will eventually become a major bottleneck the maintain an Aggregate's requirement of "keeping the consistency boundary".
That thus leaves option 2. Let's rephrase the business logic you have defined:
if both the assets are unpaired then pair them(update the status to paired and add UUID to associatedAssets) else raise an exception
This means you cannot validate on a single instance, but need to do this on several. Again, you can take two routes to solving this:
Dispatch a AssociateWithAssetCommand to both the AssetAggregates and dispatch a compensating command if one of the AssetAggregates is already associated.
Use set based validation in the external command handler handling the PairAssetsCommand to validate your business logic.
Which of the two is best is left to preference I'd say. Solution two requires you to have a small query model containing a set of assets and their association status'. Added, this query model needs to be updated in the same transaction as when the association commands occur. Thus, somewhat more complicated.
Hence solution one would be the simplest way to go in your scenario.

Objectify, efficient relationships. Ref<> vs storing id and duplicating fields

I'm having a hard time understanding Objectify entities relationship concepts. Let's say that i have entities User and UsersAction.
class User{
String nick;
}
class UsersAction{
Date actionDate;
}
Now in the frond-end app I want to load many UsersActions and display it, along with corresponding user's nick. I'm familiar with two concepts of dealing with this:
Use Ref<>,
I can put a #Load Ref in UsersAction, so it will create a link between this entites. Later while loading Users Action, Objectify will load proper User.
class User{
String nick;
}
class UsersAction{
#Load Ref<User> user;
Date actionDate;
}
Store Id and duplicate nick in UsersAction:
I can also store User's Id in UsersAction and duplicate User's nick while saving UsersAction.
class User{
String nick;
}
class UsersAction{
Long usersId;
String usersNick;
Date actionDate;
}
When using Ref<>, as far as I understand, Objectify will load all needed UsersActions, then all corresponding Users. When using duplication Objectify will only need to load UsersActions and all data will be there. Now, my question is. Is there a significant difference in performance, between this approaches? Efficiency is my priority but second solution seems ugly and dangerous to me since it causes data duplication and when User changes his nick, I need to update his Actions too.
You're asking whether it is better to denormalize the nickname. It's hard to say without knowing what kinds of queries you plan to run, but generally speaking the answer is probably no. It sounds like premature optimization.
One thing you might consider is making User a #Parent Ref<?> of UserAction. That way the parent will be fetched at the same time as the action in the same bulk get. As long as it fits your required transaction throughput (no more than 1 change per second for the whole User entity group), it should be fine.

Spring Data-Rest POST to sub-resource

Lets say I have the following structure:
#Entity
class Person extends AbstractPersistable<Long> {
String name
String surname
}
#Entity
class Task extends AbstractPersistable<Long> {
String description
#ManyToOne
Person person
}
If I follow proper HAL guidelines I'm not supposed to expose entity id's. Since I don't have a bi-directional relationship I cant PUT or PATCH to http://localhost:8080/persons.
Even if I did create the relation, I probably wouldn't want to first POST the Task to /tasks and then PUT to /persons, (mobile clients are going to kill me). But even then I don't have the Task ID even from the returned Entity so I can PUT to the Person entity. (I obviously can string parse but I don't think it's appropriate).
I probably wouldnt want to have a list of 1000 tasks in the Person entity either. So not exporting the Task entity is not really an option (and this means PATCH will not work)
So how am I supposed to associate the Person with the Task if I cannot get his id? What is the correct approach?
If you want to associate a Task with a Person you need the link to the person.
Lets say the person URI is http://localhost/persons/1
Then you could assign the person to a task by just passing that URI in the person attribute.
So a post to Task could look like this:
{
"description": "some text",
"person": "http://localhost/persons/1"
}
Spring-data-rest will lookup the person and take care of the rest.
In HAL Links are used to reference related resources not ids and a HAL entity should always return a Link to itself, which serves as its unique identifier.
If I'm not mistaken you can also annotate fields with DBRef and links should be generated for you.
If you want related resources to actually show up inline with data you'll have to draft a Projection. See more here:
Spring Boot REST Resource not showing linked objects (sets)
Last but not least - if you want Projections to also contain Links you'll have to make ResourceProcessor's for them, see here:
How to add links to Spring Data REST projections?

Accessing data for validation and determining default values using DDD

Lets take a hypothetical project such as a student enrollment system for a music school.
Within the system there needs to exist a way to enter student data for a new student interested in receiving instruction at this school and we can assume that students may have access to this functionality through a web site.
Part of the enrollment process asks the student the type of instrument for which she would like to receive instruction.
As a result of entering information about her preferred musical instrument the behavior will be to assign a default instructor who is assigned to that group of instruments.
Before completing the enrollment request the student will be also be able to change the assigned instructor to different instructor who also is listed as able to give instructed for her selected instrument.
Given this description, the part I'm having a little trouble with is how manage the list of possible instructors out of the ones who are able to give instruction for particular instrument in terms of choosing a default instructor for a new student first, and secondly how to use this same data when it comes time to validate the selected instructor before an enrollment is submitted.
Other technical constraints are that up to this point I've been using a self validating technique very similar to the one presented in Jimmy Nilsson's book Applying Domain-Driven Design and Patterns so it is mainly unclear to me the best way to go about continuing following self validating techniques when access to external data is necessary which I would normally see as outside of the scope of the entity being tested for validity.
The options I'm aware of:
Move validation outside of the entity itself. Perhaps validation is moved into a set of services or a single service per entity which analyses current state of the whole entity and deems it valid or not and provides for domain events or other value objects to be emitted that give more insight about what validation rules have been broken. In this case I'm still a bit uneasy about how the service would get access to the necessary information about instructors
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
Create a service that allows access to a list of instructors by instrument category. Alternatively create two separate services, one that returns whether a given instructor is in the list of instructors for a given category, and another which returns the default instructor for a given category.
Load a list of instructor value objects within my aggregate root (likely student, or a student enrollment request) that can be used for validation either by the aggregate root or entities contained within the root.
In either of the first two cases above it seems like the use of a instructor repository would be overkill because I don't need to access an aggregate root that represents an instructor but instead in my case I would see the instructor as a value object that describes the student enrollment request and having a repository spit back value objects seems to be blurring the lines of what a repository is supposed to be doing. For the last two options it seems wrong two allow access to data from a service or a factory in the case of option 4 since aren't repositories supposed to be in charge of data access such as this? And if repositories are the right place for this logic where are the appropriate places to access or store references to repositories? I've been convinced that there are reasons not to access repositories directly within any entity or value object that makes up the model so I'm wondering if this is a case where I may have to bend on that assumption. I should also mention that I'm pretty new to DDD and I'm just now encountering some of my head scratching moments and attempting not to box myself in so any knowledgeable input on this topic would be valuable.
Move validation outside of the entity itself.
One instructor shouldn't know about all other instructors. Validation against set of instructors isn't responsibility of one particular instructor.
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
Domain model should be persistence ignorant. Need to break that indicates flaws in Your model.
Create a service that allows access to a list of instructors by instrument category.
This bit of information reveals lack of aggregate root - I would call it InstrumentClass.
Introducing that into Your model would solve some of Your issues. InstrumentClass would hold available instructors that teaches particular instrument.
Next thing You need to figure out is how to describe properly student that is assigned to class. Unfortunately I can't name it at the moment (maybe Participation?). But that entity would be used for InstrumentClass to figure out which instructors are too busy.
Here's my "free-style" (just to show what I see) on modeling Your domain:
using System;
public class Main{
public Main(){
var instructor = new Instructor();
var instrument = new Instrument("saxaphone");
var saxaphoneClass = new InstrumentClass(saxaphone,teacher);
var me=new Person("Arnis");
//here, from UI, I can see available classes, choose one
//and choose according instructor who's assigned to it
var request=me.RequestEnrollment(saxaphoneClass, instructor);
saxaphoneClass.EnrollStudent(request);
}
}
public class Person{
public IList<EnrollmentRequest> EnrollmentRequests { get; private set; }
public EnrollmentRequest RequestEnrollment
(InstrumentClass instrumentClass,Instructor instructor){
if (!instrumentClass.IsTeachedByInstructor(instructor))
throw new Exception("Instructor does not teach this music instrument");
var request=new EnrollmentRequest(this,instrumentClass,instructor);
EnrollmentRequests.Add(request);
return request;
}
}
public class EnrollmentRequest{
public Person Person{ get; private set; }
public InstrumentClass InstrumentClass { get; private set; }
public Instructor Instructor{ get; private set; }
}
public class InstrumentClass{
public void EnrollStudent(EnrollmentRequest request){
var instructor=request.Instructor;
var student=new Student(request.Person);
var studies=new Studies(this,student,instructor);
//TODO: this directiveness isn't good
//student/instructor should listen for class events themselves
//and class should listen if by any reason instructor or student cannot
//participate in studies
student.EnrollInClass(studies);
instructor.AssignStudent(studies);
Studies.Add(studies);
}
public bool IsTeachedByInstructor(Instructor instructor){
return Instructors.Contains(instructor);
}
public InstrumentClass
(Instrument instrument, params Instructor[] instructors){
Instrument=instrument; Instructors=instructors.ToList();
}
public IList<Instructor> Instructors{get;private set;}
public IList<Studies> Studies { get; private set; }
public Instrument Instrument { get; private set; }
}
public class Studies{
public Student Student { get; private set; }
public Instructor Instructor { get; private set; }
public InstrumentClass InstrumentClass { get; private set; }
}
public class Student{
}
public class Instructor{
}
public class Instrument{
}
My answer does not cover the detailed implementation / code as it seems that you are using this as an exercise to learn more about DDD.
Remember that in most cases you'll not be able to get the model right the first time and need to evolve the model. As you “play with it” certain rigid parts will become more flexible to change. (Like a gardening glove as per Eric's analogy). As you gain new insights into the domain, you'll find that you need to introduce new concepts into your model. Using “simple examples” has dangers for example they can lack depth. But simple examples are sometimes needed to get the hang of DDD and fortunately we can evolve the example too ;)
One thing I've heard Eric Evans mention was that if the domain does not feel right or you have trouble expressing something in a model you might be missing a concept. Naturally if you have the concepts in your domain you can “get a feeling” or find a natural place where validation will occur.
Having set the context I thus have a proposition as follow:
Enterprise Patterns and MDA has some complex patterns but the idea you can take away is the CapacityManager of the Inventory archetype as guidance. Unfortunately the model on pg 278 is not available online but have a look at the ServiceInventory archetype.
The instructors are selling their services to students. (Instructors get a salary last time I checked :). If I were to map your example to the Inventory archetype for ideas I would use:
Inventory - List of instruments/courses
ServiceType - Instrument / Course details, start end etc
ServiceInventoryEntry - Instrument + places available (uses capacity manager)
ServiceInstance - Enrollment - place in class (Scheduled, Booked, Canceled, Completed)
CapacityManager (used by ServiceInventoryEntry)
ReservationRequest - Enrollment request
I think the key concept added is the CapacityManager: You can call the ServiceInventoryEntry::getCourses() method which will use the CapacaityManager (service or class) to show you / calculate the available teachers or return the default one. Thus, call it multiple times depending on the context: Default or Propose a list of available places/seats/instructors.
With this model you should be able to find natural place (where and when) to validate. The guidance from Streamlined Object Modeling is to put validation where the data is. Not to be taken as a hard rule but there is a natural tendency for objects to have the proper concerns and data grouped together. For example the capacity manager knows about enrollments and instruments. (From MDA - CapacityManger: Manages utilization of capacity by releasing ServiceInstances)
To get your aggregates see what transactions / changes you'll do so that you can ensure they enforce the invariants (rules). In your example I would make ServiceType(Course) a value object, ServiceInventoryEntry and ReservationRequests aggregate roots. (Depends on how complex you want to take your rules). You can also add Students and Teachers as parties as per the MDA book. I tend to use repositories to get hold of my aggregates and then also rely on inversion of control as per Jimmy's book you referenced.
The reason I like the MDA patterns is that it makes me think of use cases and model concepts that I or the business would not have imagined. But, be careful to only model what you need since the MDA patterns can be big and even enticing. The good thing is that they are designed to be modular or "down scalable".
So in short:
- Your aggregate roots should ensure your domain is in a valid state (Rules / Invariants)
- Put the validation where the data is. Your model will guide your.

Display properties of child object in Datagridview

How can I display in a datagridview selected properties of an object, and also selected properties of a member object of this first object? I think I will not require binding but rely on hard coding updates, because the updates will initiate on non-UI threads, and I think that will not be so easy to bind. At least I've had problems with that in other project.
Basically I'm looking to understand what different ways I can do this. Maybe with LINQ, or whatever is most suitable. Note: I want to display the data in the same table. As the child/parent is a 1:1 relation.
So example code:
Public Class User
public property Score as Integer
public property Details as UserDetails
End Class
Public Class UserDetails
public property Name as String
public property userName as String
End Class
Hence, I want the table to show columns: Score, Name, UserName
EDIT:
Oh, this was more easy than I thought, seems this will work:
Dim q = (From n in userList Select New With {n.Score, n.Details.Name, n.Details.userName}).ToArray
You can use databinding here, if you use the ITypedList interface to expose the properties you wanted.
ITypedList is very powerful, but somewhat hard to understand, IME. The best tutorial I've found is Tips for binding grids to hierarchical data using the ITypedList interface
For the record, this looks like appropriate solution:
Dim q = (From n in userList Select New With {n.Score, n.Details.Name, n.Details.userName}).ToArray

Resources