Hi Marc!
Great stuff! Comments inline:
On 2010-11-15 00.29, Marc Grue wrote:
In my previous DCI-Qi4j MoneyTransfer implementation (v9) I screwed up some
of Rickards ideas from his v8. I have now implemented a new version 9 that
is hopefully meeting the standards and ideas that Rickard set forth in v8. I
simply expanded Rickards orginal example in v8 to include the PayBills use
case which is a nice example of stacked contexts. If I'm still wrong, please
let me know and I'll update the files.
The main issue I could see is that PayBillsContext explicitly refers to
TransferMoneyContext roles, when it should instead just use BalanceData.
Code is in moneytransfer/qi4j_money_transfer_05.zip at http://bit.ly/bjjjMx
There is also a version 10 in a variation 10a that works and 10b_draft that
has a problem. They are an attempt to implement nested Contexts. In both
variations, I wanted to have a context field in a Role Mixin pointing to the
current Context so that I can get acccess to other Roles (and possibly also
other Context state) in the current Context in an intuitive and hopefully
not wrong way!
For some reason you changed the stack into a hashmap, and then it went
wrong. Keep it as a stack, and then do injection from that instead.
I have updated th qi4j-samples DCI sample to include the
PayBillsContext, and have also added the @Context annotation for
injection of context into role mixins. I also made the separation of
entities into explicit rolemaps, as per your code. Please have a look at
that. AFAICT it's now pretty much perfect, apart from how the context
stack is managed. We need Concerns on object methods to do that
properly. But I have at least put the stack management in the context
itself, which simplifies client code radically. Here's sample code of
how to use:
// Instantiate context and execute enactments with that context
TransferMoneyContext context = new TransferMoneyContext();
context.rebind( source, destination );
// Query for double the balance
final Integer amountToTransfer = context.availableFunds() * 2;
// Transfer from savings to checking
context.transfer( amountToTransfer );
---
Very straightforward. Having a rebind instead of using the constructor
helps reusing the context. This pays off in the PayBills code, as I can
reuse the same context throughout the iteration:
final TransferMoneyContext transferMoney = new TransferMoneyContext();
for (BalanceData creditor : creditors)
{
if (creditor.getBalance() < 0)
{
final Integer amountOwed = -creditor.getBalance();
// Instantiate nested context and execute enactment
transferMoney.rebind( data, creditor );
transferMoney.transfer( amountOwed);
}
}
---
Note that since I handle creditors as BalanceData the cast you had in
your version is gone.
I'm bringing up the examples on this list because I have some Qi4j-related
problems and I suspect that you will be able to shake your heads and give me
hints to better solutions :)
10a (seems to work fine)
- Can I avoid to require a setContext() method on Role interfaces in order
to be able to set the Mixin field?
The @Context injection solves this.
10b_draft (not working yet - I've been banging my head against several
implementation attempts)
- Can I enforce the ContextInjectionProviderFactory to inject the
TransferMoneyContext in the second iteration of the PayBills creditor loop
too? Or shall I do it a completely different way? (Or is it not possible
before we get Concern annotations on POJOs, so that we can have a Context
annotation on Context trigger methods as Rickard suggested on the DCI list?)
With the rebind() this just works, since it's the same context, just
with a different binding. Tada!
I'll also let the DCI list know about the examples once I have cleaned them
up - hopefully with some advice from you.
As above, I think the update I made in qi4j-samples just now represents
the cleanest, simplest and most easily to understand version of how to
do DCI in Qi4j. Apart from the stack handling I can't think of anything
I would want to improve. If you can find anything, please do let me know!!
/Rickard
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev