Niclas Hedhman wrote:
I don't think it is an overkill. GutFeeling(tm) says that the @Event
method will be on the domain model, i.e. the State mixins, in simpler
cases where a separate EventMixin is not warranted.
Ok, I tried moving the event method to the state mixins, and it actually
worked out pretty well. Here is a complete example from my current code:
@Concerns(EventCreationConcern.class)
@SideEffects(EventSideEffect.class)
@Mixins(OrganizationalUnits.OrganizationsMixin.class)
public interface OrganizationalUnits
{
@Command
OrganizationalUnit createOrganizationalUnit(@MaxLength(50) String
name);
@Mixins(OrganizationalUnitsStateMixin.class)
interface OrganizationalUnitsState
{
@Aggregated
ManyAssociation<OrganizationalUnit> organizationalUnits();
@Event
OrganizationalUnitEntity organizationalUnitCreated(@Optional
DomainEvent event, @Name("id") String id);
}
class OrganizationsMixin
implements OrganizationalUnits
{
@Service
IdentityGenerator idGenerator;
@This
OrganizationalUnit.OrganizationalUnitState ouState;
@This
OrganizationalUnitsState state;
@Structure
UnitOfWorkFactory uowf;
public OrganizationalUnit createOrganizationalUnit(String name)
{
OrganizationalUnitEntity ou =
state.organizationalUnitCreated(null,
idGenerator.generate(OrganizationalUnitEntity.class));
ou.describe(name);
return ou;
}
}
abstract class OrganizationalUnitsStateMixin
implements OrganizationalUnitsState
{
@This
OrganizationalUnitsState state;
@This
OrganizationalUnit.OrganizationalUnitState ouState;
@Structure
UnitOfWorkFactory uowf;
public OrganizationalUnitEntity
organizationalUnitCreated(DomainEvent event, String id)
{
EntityBuilder<OrganizationalUnitEntity> ouBuilder =
uowf.currentUnitOfWork().newEntityBuilder(OrganizationalUnitEntity.class,
id);
ouBuilder.prototype().organization().set(ouState.organization().get());
OrganizationalUnitEntity ou = ouBuilder.newInstance();
state.organizationalUnits().add(state.organizationalUnits().count(), ou);
return ou;
}
}
}
----
Only the createOrganizationalUnit() command is visible from the outside.
But, since the Entity composite extends the state interface the event
method is trivially available during replay. The only "hack" is to do
the abstract thing so the mixin doesn't have to implement the state
methods (properties+associations). Reasonably ok I think. I also don't
like that I have to put @Optional on the method. Would probably be
better to send in some kind of default event instead of null when
running the command.
I created a side-effect that prints out the event generated by
invocations, and get the following example:
{identity:"4a4fda26-b7cf-4e77-ab7a-56d0b9dec711-1",by:"administrator",entity:"Organization",name:"organizationalUnitCreated",on:"2009-07-28T16:28:51.356Z",parameters:"{\"param1\":\"4a4fda26-b7cf-4e77-ab7a-56d0b9dec711-0\"}"}
identity=event id
by=user
entity=entity invoked
name=method name=event name
on=time
parameters=JSON-serialized parameters. This looks nicer when a
ValueComposite is used, and also if @Name() annotations is used on the
params.
If I convert the descrbe() method to use this it would create an
additional event for "described" (i.e. change name), so that one command
creates two events.
All in all, pretty ok I think!
/Rickard
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev