How can I validate the existence of a a resource when a participant is created
for example:
participant Trader identified by traderId {
o String traderId
o String traderFirstName
o String traderLastName
--> Car owner
}
and there is an asset:
participant Car identified by carId {
o String carId
o string vin
}
When I create a new participant I've to assign a Car to him. When I do that using the CLI or a Restful API or composer-playground there's no validation that this Car exists or not. How can I make sure that it exists so that when I create a participant Trader it should be mapped to an existing instance of the asset Car not to an asset that doesn't exist?
It looks like you are using the "system transactions" AddParticipant and AddAsset from Playground and the REST server.
If you want to do the checking, you will need to write your own Transaction and execute a get on the Car registry (though maybe you should really define the Car as an Asset not a Participant) to check the presence of the owner, and then a put on the Trader registry.
I would suggest looking at the Transactions in the Samples in Playground for examples of writing Transaction scripts. Please also see this reference document.
Related
Let's say I have a business network v1.0.0 which has a Participant with the following model:
participant Member identified by memberId {
o String memberId
o String firstName
}
After deploying the network I create a Member.
Later I want to add a field to the Member model. E.g.
participant Member identified by memberId {
o String memberId
o String firstName
o String lastName
}
So I create new network and upgrade the previous one:
composer network upgrade -c peeradmin#hlfv1 -n example-netowrk -V 2.0.0
What happens to the member I created before? Is it deleted? How can I keep that in the system and continue to use it and update it's information by only adding lastName?
The evolution of model definitions is described in the documentation here
https://hyperledger.github.io/composer/latest/reference/model-compatibility and should answer your question.
when you change the model, your api will change as well to reflect the changes. Your data won't disappear, it can't as it's on the ledger, but it won't have the new fields you added.
Once your new model is deployed you can then issue a GET request to that asset, this gives you all the existing data, you populate the new field with whatever you need and issue a PUT request on that asset. This will now give you an old asset with the new data.
Of course, I suggest you think carefully how you change existing assets. I am thinking here of a policy which says you should not rename anything, you should not delete anything. all you should do is add new properties. If you start messing around with renaming and deleting, this is bound to cause issue, especially in a production environment.
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 have domain object like this:
class Customer
{
string FirstName {get;set;}
string LastName {get;set;}
DateTime DateOfBirth {get;set;}
}
Product team told me: We have to get customer by ID. Customer has information like FirstName, LastName, DateOfBirth, Age and blank fields. Age and blank fields can be calculated.
There is no application, just API. Who consumes this API doesn't matter.
Q: If I follow Domain Driven Design how domain class Customer looks? Where I put fields like Age and list of blank fields (for every Customer)? How business logic class looks like?
I think you have an anaemic model going here. The age should be implemented completely in the Customer class. So that to access the value, you do, customer.age. The blankfields might be a concept that needs it's own entity/domain, because a "Customer" cannot have a "blankfield"; the language doesn't fit/make sense. If you need the "blank fields" to exist as part of a customer object though, consider using a value object inside the customer object as well.
You don't need the service doing all that you have it doing. The only reason the service might be involved in this is if there's no way you can have your entity doing the work because of an external dependency or possibly complexity.
So, your service constructs your database from your persisted data and that's the end of it's involvement. In fact, you should probably be using a repository for re-constituting your object (instead of a service).
I have two entities Employee and Department. Both are related with Relationship i.e., 1-to-M and M-to-1. Dept is having attribute called MANAGERID representing the employee Id who is the manager of that dept.
Now i need to fetch DeptName and the Manager Name. How to write the Predicate Format String ?
NOTE: I am working in iOS 8.3 with Xcode 6.3 and Swift 1.2
Thanks in Advance.
If you follow the usual setup described in Apple's documentation, there is no need for ids. To access the department of an employee
let department = employee.department
To get all employees of a department
let employees = department.employees // returns NSSet or [Employee]
Following the design pattern of object graphs, rather than holding a manager id in the Department object, you should just have a one-to-one relationship with the manager.
let manager = department.manager // returns an Employee
This means that you need a separate relationship for the manager:
Department.employees <----->> Employee.department
Department.manager <------> Employee.managedDepartment
Also note that an all-caps attribute name like MANGAERID is illegal in Core Data.
I have a domain Aggregate, call it "Order" that contains a List of OrderLines. The Order keeps track of the sum of the Amount on the Order Lines. The customer has a running "credit" balance that they can order from that is calculated by summing the history of their database transactions. Once they use up all the money in the "pool" they can't order any more products.
So every time a line is added to the order, I need to get to check how much is left in the pool and if the order pushes them over it. The amount in the pool is continually changing because other related customers are continually using it.
The question is, thinking in terms of DDD, how do I get that amount since I don't want to pollute my Domain Layer with DataContext concerns (using L2S here). Since I can't just query out to the database from the domain, how would I get that data so I can validate the business rule?
Is this an instance where Domain Events are used?
Your Order aggregate should be fully encapsulated. It therefore needs to be able to determine whether it's valid to add an item, i.e. whether or not the customer credit is exceeded. There are various ways to do this but they all depend on the Order repository returning a specific aggregate that knows how to do this particular thing. This will probably be a different Order aggregate from one you'd use for satisfying orders, for example.
You have to recognise, then capture in code, the fact that you're expecting the order to fulfil a particular role in this case, i.e. the role of adding additional line items. You do this by creating an interface for this role and a corresponding aggregate that has the internal support for the role.
Then, your service layer can ask your Order repository for an order that satisfies this explicit role interface and the repository thus has enough information about what you need to be able to build something that can satisfy that requirement.
For example:
public interface IOrder
{
IList<LineItem> LineItems { get; }
// ... other core order "stuff"
}
public interface IAddItemsToOrder: IOrder
{
void AddItem( LineItem item );
}
public interface IOrderRepository
{
T Get<T>( int orderId ) where T: IOrder;
}
Now, your service code would look something like:
public class CartService
{
public void AddItemToOrder( int orderId, LineItem item )
{
var order = orderRepository.Get<IAddItemsToOrder>( orderId );
order.AddItem( item );
}
}
Next, your Order class that implements IAddItemsToOrder needs a customer entity so that it can check the credit balance. So you just cascade the same technique by defining a specific interface. The order repository can call on the customer repository to return a customer entity that fulfils that role and add it to the order aggregate.
Thus you'd have a base ICustomer interface and then an explicit role in the form of an ICustomerCreditBalance interface that descends from it. The ICustomerCreditBalance acts both as a marker interface to your Customer repository to tell it what you need the customer for, so it can create the appropriate customer entity, and it has the methods and/or properties on it to support the specific role. Something like:
public interface ICustomer
{
string Name { get; }
// core customer stuff
}
public interface ICustomerCreditBalance: ICustomer
{
public decimal CreditBalance { get; }
}
public interface ICustomerRepository
{
T Get<T>( int customerId ) where T: ICustomer;
}
Explicit role interfaces give repositories the key information they need to make the right decision about what data to fetch from the database, and whether to fetch it eagerly or lazily.
Note that I've put the CreditBalance property on the ICustomerCreditBalance interface in this case. However, it could just as well be on the base ICustomer interface and ICustomerCreditBalance then becomes an empty "marker" interface to let the repository know that you're going to be querying the credit balance. It's all about letting the repository know just what role you want for the entity it returns.
The final part which brings this all together, as you mentioned in your question, is domain events. The order can raise a failure domain event if the customer's credit balance would be exceeded, to notify the service layer that the order is invalid. If the customer has enough credit, on the other hand, it can either update the balance on the customer object or raise a domain event to notify the rest of the system that the balance needs to be reduced.
I've not added the domain event code to the CartService class since this answer is already rather long! If you want to know more about how to do that, I suggest you post another question targeting that specific issue and I'll expand on it there ;-)
In such a scenario, I off-load responsibility using events or delegates. Maybe the easiest way to show you is with some code.
Your Order class will have a Predicate<T> that is used to determine if the customer's credit line is big enough to handle the order line.
public class Order
{
public Predicate<decimal> CanAddOrderLine;
// more Order class stuff here...
public void AddOrderLine(OrderLine orderLine)
{
if (CanAddOrderLine(orderLine.Amount))
{
OrderLines.Add(orderLine);
Console.WriteLine("Added {0}", orderLine.Amount);
}
else
{
Console.WriteLine(
"Cannot add order. Customer credit line too small.");
}
}
}
You will probably have a CustomerService class or something like that to pull the available credit line. You set the CanAddOrderLine predicate before adding any order lines. This will perform a check of the customer's credit each time a line is added.
// App code.
var customerService = new CustomerService();
var customer = new Customer();
var order = new Order();
order.CanAddOrderLine =
amount => customerService.GetAvailableCredit(customer) >= amount;
order.AddOrderLine(new OrderLine { Amount = 5m });
customerService.DecrementCredit(5m);
No doubt your real scenario will be more complicated than this. You may also want to check out the Func<T> delegate. A delegate or event could be useful for decrementing the credit amount after the order line is placed or firing some functionality if the customer goes over their credit limit in the order.
Good luck!
In addition to the problem of getting the "pool" value (where I would query the value using a method on an OrderRepository), have you considered the locking implications for this problem?
If the "pool" is constantly changing, is there a chance that someone elses transaction creeps in just after your rule passes, but just before you commit your changes to the db?
Eric Evans refers to this very problem in Chapter 6 of his book ("Aggregates").