Hi guys,
I'm working on a port of the DDDsample application to DCI-Qi4j, and I'm
experimenting with a version using ValueComposites for most data. But I get
a problem when I want to let a ValueComposite Object play a Role in a DCI
Context.
In order to Create the Context I need to pass in a SomeValue instance. But
when instantiating it first, all Mixins of that composite are instantiated
which causes the ContextInjectionProviderFactory to try to inject the
Context object that it can't find on the Context stack yet. Catch 22.
Instantiating SomeEntity doesn't seem to cause all Mixins in that composite
to be instantiated straight away. So there we get the Context object
correctly on the Context stack first (by the enactment call), and then it
gets injected into the @Context-annotated context field in EntityRole.Mixin.
The ContextInjectionWithValueTest below shows the problem - can you see a
way to get it working or what I'm missing? ContextInjectionWithEntityTest
works fine as a comparison.
I think it would be really useful to have the option of letting
ValueComposites play Roles in DCI Contexts. For instance when doing complex
subfunction calculations that are well suited to be implemented as Contexts
with (ValueComposite)Roles interacting with each other to produce a result
that is passed on to other Contexts (where no state is saved). Calculating
the Delivery Snapshot in the DDDsample application is a perfect example.
Hope there's a workaround!
Cheers,
Marc
=========================================
import org.qi4j.dci.Context; // in qi4j-samples
import org.qi4j.dci.ContextInjectionProviderFactory;
import org.qi4j.dci.Contexts;
import org.junit.Test;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.value.ValueComposite;
import org.qi4j.bootstrap.AssemblyException;
import org.qi4j.bootstrap.ModuleAssembly;
import org.qi4j.entitystore.memory.MemoryEntityStoreService;
import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
import org.qi4j.test.AbstractQi4jTest;
public class ContextInjectionWithValueTest
extends AbstractQi4jTest
{
public void assemble( ModuleAssembly module )
throws AssemblyException
{
module.layerAssembly().applicationAssembly().setMetaInfo( new
ContextInjectionProviderFactory() );
module.addServices( UuidIdentityGeneratorService.class,
MemoryEntityStoreService.class );
module.addValues( SomeValue.class );
}
@Test
public void valueContextIsInjected()
{
SomeValue valueObject = valueBuilderFactory.newValue( SomeValue.class
);
new ValueContext( valueObject ).confirmInjection();
}
class ValueContext
{
private ValueRole valueRole;
ValueContext( SomeValue valueObject )
{
valueRole = (ValueRole) valueObject;
}
public void confirmInjection()
throws IllegalArgumentException
{
Contexts.withContext( this, new Contexts.Command<ValueContext,
IllegalArgumentException>()
{
public void command( ValueContext context ) throws
IllegalArgumentException
{
valueRole.confirmInjection();
}
} );
}
}
@Mixins( ValueRole.Mixin.class )
public interface ValueRole
{
void confirmInjection();
abstract class Mixin
implements ValueRole
{
@Context
ValueContext context;
public void confirmInjection()
{
System.out.println( "Injected context: " + context.toString() );
}
}
}
interface SomeValue
extends ValueComposite, ValueRole
{
}
}
=============================
import org.junit.Test;
import org.qi4j.api.entity.EntityComposite;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.unitofwork.UnitOfWork;
import org.qi4j.bootstrap.AssemblyException;
import org.qi4j.bootstrap.ModuleAssembly;
import org.qi4j.entitystore.memory.MemoryEntityStoreService;
import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
import org.qi4j.test.AbstractQi4jTest;
public class ContextInjectionWithEntityTest
extends AbstractQi4jTest
{
public void assemble( ModuleAssembly module )
throws AssemblyException
{
module.layerAssembly().applicationAssembly().setMetaInfo( new
ContextInjectionProviderFactory() );
module.addServices( UuidIdentityGeneratorService.class,
MemoryEntityStoreService.class );
module.addEntities( SomeEntity.class );
}
@Test
public void entityContextIsInjected() throws Exception
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
try
{
SomeEntity entityObject = uow.newEntity( SomeEntity.class );
new EntityContext( entityObject ).confirmInjection();
uow.discard();
}
catch (Exception e)
{
uow.discard();
throw e;
}
}
class EntityContext
{
private EntityRole entityRole;
EntityContext( SomeEntity entityObject )
{
entityRole = (EntityRole) entityObject;
}
public void confirmInjection()
throws IllegalArgumentException
{
Contexts.withContext( this, new Contexts.Command<EntityContext,
IllegalArgumentException>()
{
public void command( EntityContext context ) throws
IllegalArgumentException
{
entityRole.confirmInjection();
}
} );
}
}
@Mixins( EntityRole.Mixin.class )
public interface EntityRole
{
void confirmInjection();
abstract class Mixin
implements EntityRole
{
@Context
EntityContext context;
public void confirmInjection()
{
System.out.println( "Injected context: " + context.toString() );
}
}
}
interface SomeEntity
extends EntityComposite, EntityRole
{
}
}
--
View this message in context:
http://old.nabble.com/ValueComposites-as-Data-Objects-in-DCI-possible--tp30624586p30624586.html
Sent from the Qi4j-dev mailing list archive at Nabble.com.
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev