Previously I developed my application on Hyperledger Composer. Now I'm trying to migrate the application to Hyperledger Fabric 1.4.
I implemented the Commercial-Paper tutorial given the Fabric 1.4 docs,which you can find here. Everything works fine.
Now I want to tailor this to my application and want to define more assets.
They have a file paper.js at commercial-paper/organization/digibank/contract/lib, is this the definition of the "paper" asset?
If I need to define additional assets, do I also create a file myasset.js at the same location and then call in the smart contract?
or is there a better way to define assets?
PS: I am trying to map the assets from Hyperledger composer to Hyperledger fabric 1.4.
Additionally how do you define relationships among assets and participants or other assets? In Composer we used to use --> to define relationships, how do we achieve the same thing fabric-1.4?
Since you already answered the question yourself i would only like to add on the part of the user identification of your own answer.
What's worth mentioning there is the CID Lib. With that and the concept of AttributeBasedAccessControl you can manage the access to queries/invokes perfectly on chain.
Hope that helps and adds a bit more insights to your answer :)
I believe I found the answer to my own question and I hope this would help anyone who is in a similar situation (Moving from Hyperledger Composer to Fabric 1.4)
ctx.stub.putState(key, data);
We simply use the above code to add an asset. A very simplified version is found in fabcar example.
async createCar(ctx, carNumber, make, model, color, owner) {
console.info('============= START : Create Car ===========');
const car = {
color,
docType: 'car',
make,
model,
owner,
};
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
console.info('============= END : Create Car ===========');
}
Here we are adding a car, which is an asset.
In the commercial-paper example, they have done this using an Object-Oriented Approach. With paper.js they just create a 'paper' object (paper class extends state class. State class has the methods to make and split keys, which will be used later), then pass it to 'paperlist' which then uses the methods defined in statelist.js (paperlist class extends statelist class, which has all the methods to write the state onto the ledger) to create this asset using the following code
async addState(state) {
let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey());
let data = State.serialize(state);
await this.ctx.stub.putState(key, data);
}
Here you can observe that the key is generated using the methods from the state class, which was inherited by the paper class.
And coming to the last question about relationships, I haven't found a concrete answer yet, but I believe you can achieve this by passing the participant ID or the asset id (Eg: A User is identified by userId, so we just pass the userId) in the data object.
In hindsight, this question looks really dumb, but I hope it helps some people out.
Please feel free to correct my understanding of the Hyperledger Examples. I'm here to learn :)
Related
I was thinking about how to create a Proposal object like this in JHipster: so a User can create a Proposal and other users can vote for it.
entity Proposal {
proposalText String minlength(2) maxlength(100) required
proposalVotes Integer
}
entity Vote {
numberOfPoints Integer
}
relationship ManyToOne {
Vote{proposal(id) required} to Proposal{vote}
Proposal{user(id) required} to User{proposal}
Vote{user(id) required} to User{vote}
}
In Spring I would create that #Transient proposalVotes Integer and the Controller would go and find all the Votes that a Proposal has and add them together to get to the result to be sent to the frontend. That property would not be stored in the database.
If I use JHipster and I add a proposalVotes property, the result would be saved in the database and could be changed in the dialogs(... and I do not like the result), so my question is:
What is the best practice in JHipster when you need a property that is calculated everytime his object is called?
Think of the number of comments in a Blog with Posts, if it is more familiar.
Where do you calculate the result: I would do it in the ProposalResource, but I’m not sure and I haven’t seen any use case like this in the examples, but it looks like a common case.
Thanks a lot
PD: If there is any example in Github, that could be great!
Actually if you are generating entities using JDL(Jhipster domain language) then you wont get any option to make field Transient as JDL is database design mechanism and Transient fields are not going to be placed in DB.
Solution is that after importing JDL to our app you can add Transient fields in your entity class.
There is a method in a factory newResource.
The third parameter of this method is id. Are there any ways or workarounds to generate id?
There was a similar question if you mean to auto-increment the identifier:
Auto Increment field in Composer
It is not recommended by the devs, because different peers may have calculated the IDs at the same time for different new assets/participants and disagree. Disagreements would force all records to roll back.
Source: https://github.com/hyperledger/composer/issues/2931
You control what the id is generated as (deterministically) when you create the new Resource in the Resource registry (whether its an AssetRegistry or ParticipantRegistry etc) and depends on the id field type that identifies the asset/participant.
See sample networks for examples. Eg Perishables network:
https://github.com/hyperledger/composer-sample-networks/blob/v0.16.x/packages/perishable-network/lib/logic.js#L133
Here, Grower is created as a Resource using an email id as the identifier of the Resource.
see model here -> https://github.com/hyperledger/composer-sample-networks/blob/v0.16.x/packages/perishable-network/models/perishable.cto
here - the Participant Grower is extended from a generic Business participant that is identified by an email id (as it inherits that field from the supertype).
This is a real problem and the Hyperledger documentation is not clear about which is the right approach.
When you create a new resource the third parameter id is mandatory and the transaction is rejected if it already exists another asset with the same id. So, how to fill the parameter id of newResource?
factory.newResource(ns, type, id)
A solution could be counting the assets of the same type and generating a pseudo-incremental ID. But this should be used only for assets that are kinda unique on the blockchain. You should use this approach if you don't care of the rejection of the transaction by the peers; or maybe if the rejection is wanted behavior, because a deterministic unique id could work like a unique constraint (like in sql). A big flaw of "counting the assets" is the hyperledger query language doesn't do that, so you you have to use getAll method of the AssetRegistry and then get length of the array, which is not scalable for big arrays:
let bananas_registry = await getAssetRegistry("org.exampleblockchain.Banana");
let all_bananas = await bananas_registry.getAll();
let new_banana_id = String(all_bananas.length + 1);
Another way to get unique ID is concatenate ID of parent assets.
But sometimes I also need something like a real random ID (not incremental). I do not understand why the is not the default for the parameter Id.
Anyway, when I will need a real random ID, I will generate a long random string so the risk of collision with other peers will be low. I will let you know!
I'm developing an application with Domain Drive Design approach. in a special case I have to retrieve the list of value objects of an aggregate and present them. to do that I've created a read only repository like this:
public interface IBlogTagReadOnlyRepository : IReadOnlyRepository<BlogTag, string>
{
IEnumerable<BlogTag> GetAllBlogTagsQuery(string tagName);
}
BlogTag is a value object in Blog aggregate, now it works fine but when I think about this way of handling and the future of the project, my concerns grow! it's not a good idea to create a separate read only repository for every value object included in those cases, is it?
anybody knows a better solution?
You should not keep value objects in their own repository since only aggregate roots belong there. Instead you should review your domain model carefully.
If you need to keep track of value objects spanning multiple aggregates, then maybe they belong to another aggregate (e.g. a tag cloud) that could even serve as sort of a factory for the tags.
This doesn't mean you don't need a BlogTag value object in your Blog aggregate. A value object in one aggregate could be an entity in another or even an aggregate root by itself.
Maybe you should take a look at this question. It addresses a similar problem.
I think you just need a query service as this method serves the user interface, it's just for presentation (reporting), do something like..
public IEnumerable<BlogTagViewModel> GetDistinctListOfBlogTagsForPublishedPosts()
{
var tags = new List<BlogTagViewModel>();
// Go to database and run query
// transform to collection of BlogTagViewModel
return tags;
}
This code would be at the application layer level not the domain layer.
And notice the language I use in the method name, it makes it a bit more explicit and tells people using the query exactly what the method does (if this is your intent - I am guessing a little, but hopefully you get what I mean).
Cheers
Scott
We're working on a new project (re-writing existing app), and I'm running into problems with my domain model / repository design.
Here is a (simplified) version of two key portions in our domain model:
As you can see, I have an abstract concept of a Post, which can be things like a Review, a Discussion, a Photo, a Video, etc. Posts can also have comments.
I also have a abstract concept of a Location, which are obviously things like Streets, Cities, Neighbourhoods, etc.
Now, this naturally looked to me as two clear aggregate roots.
So I created two repositories, one called PostRepository, and another called LocationRepository.
This was all working fine, I can add/get any type of Post (or comment), and add/get any type of Location via one of these two repositories.
But now im in the scenario of a "landing page" for a City (for example).
On this page, I need to basically show "all posts for this location".
How is that defined? Well, a Post can be (optionally) tagged at a Location. Implementation detail, so I don't want to go too deep into data (as that's not what DDD is about), but essentially there is geospatial intelligence to work out which posts are contained in a particular location by the shape file of the location, and the latitude/longitude of the tagged Post.
But how can I retrieve this information without crossing the boundaries?
Which repository do I use? Do I need a new one?
If it matters (or for the curious), this is a web application (ASP.NET MVC), with a SQL Server 2008 database and Entity Framework 4.0.
If you need any clarification, let me know.
EDIT
We currently use a modified version of the Specification pattern in order to retrieve domain models.
For example, this is the code in our BLL to retrieve all Review's where Score >= 4:
var reviews = postRepository // GenericRepository<Post>
.Find() // IQueryable<Post>
.OfType<Review>() // IQueryable<Review>
.Where(x => x.Score >= 4)
.ToList(); // List<Review>
But now I need some code like this:
var reviews = postRepository
.Find()
.OfType<Review>()
.Where( //lat long, or Locations FK )
.ToList();
The problem is I don't know how to do the above query without adding an intermediary join-entity (LocationPost - as it's a many to many), and add a FK to the Post domain model to that.
But by doing that, I am crossing the aggregate boundaries - aren't I?
Why is this a problem?
According to Evans in his book, one AR may very well reference another AR.
(You may not however reference a child element in an AR from another AR)
Also, are locations really aggregate roots?
The definition of an aggregate root is that it acts as a boundary of concistency.
Does that fit the definition of a location?
I'd say a location is a value object.
There are pretty much two camps here regarding repositories and AR associations:
One that says that all aggregate roots have to be fetched through their respective repository, and AR's should use soft relations, eg ID's between them
And one that says that aggregate roots may very well fetch other associated aggregate roots and that a repository is merely a way to find aggregate roots.
I would bind post to the location at creation time so that for each location I can get (through a repository) a list of associated posts. It would look like this:
Creation:
var p = new Post(latitude, longitude);
var locations = locationRepository.FindByCoordinates(latitude, longitude);
foreach (var l in locations)
{
l.AssociatePost(p);
}
session.Save(p);
Retrieval:
var associatedPosts = postRepository.FindByLocation(locationId);
foreach (var p in associatedPosts)
{
Display(p);
}
Under the hood, the association between posts and location would be implemented as a many-to-many table relationship. There is one problem with this solution: adding a new location requires to scan all the posts and assign them to the new location (if applicable).
Hope that helps.
Let's say you used the Specification pattern, could you build a Post Specification using a Location object? Then you just pass the Specification to your Post Repository, and get back the result.
Is it possible for an Aggregate root entity to have a method in which it will call a Repository?
I know it should not but want to get confirmed as Eric's book is also not saying anything clearly :(
one more thing where can I get a unit testing example for domain-driven design?
This is a bit of a religious question.
Some see no problem with this, while others might believe it is heresy to do so.
While I've normally always kept my Repository away from my Domain Model (and had an upstream service object deal with the Repository), I have had a project that "required" having the Repository accessable from the Domain Model.
This was due to the Domain object needing to retrieve specific data based on business logic => using specification objects/Linq to nHibernate (the responsibility and knowledge of how to filter data belonged to that Domain Object) and/or performance reasons.
A caveat around doing this is how to get the reference to the Repository to the Domain object - in that case I utilized Constructor injection with an IOC tool.
Whether you should do this or not really depends on your solution/use case/technologies being used etc...
Can? -Yes.
Should? -No.
All answers are however context-sensitive, and you don't provide yours.
A generic advise would be to look for a "service" or "specification" type.
Behavior IS-WHAT-IT-IS. Eric calls a Repository like utility from a Brokerage Account entity called, "QueryService". He mentions that it's not a good design for a real project. So what do you do?
public class Clerk
{
public Clerk()
{
}
//Store Report in Database
public void File(Report);
{
ReportRepository.Add(Report);
}
}
You could do that, but it's probably best to tell the Clerk which Repository to use.
public class Clerk
{
private IReportRepository _reportRepository;
public Clerk(IReportRepository ReportRepository)
{
this._reportRepository = ReportRepository
}
//Store Report in Database
public void File(Report);
{
this._reportRepository.Add(Report);
}
}