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

Reply via email to