/* * Copyright (c) 2011, Rickard Öberg. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.qi4j.library.eventsourcing.domain.source.helper; import java.io.IOException; import java.security.Principal; import org.junit.Test; import org.qi4j.api.activation.ActivatorAdapter; import org.qi4j.api.activation.Activators; import org.qi4j.api.common.UseDefaults; import org.qi4j.api.configuration.Configuration; import org.qi4j.api.entity.EntityComposite; import org.qi4j.api.injection.scope.Service; import org.qi4j.api.injection.scope.This; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.property.Property; import org.qi4j.api.service.ServiceComposite; import org.qi4j.api.service.ServiceReference; import org.qi4j.api.unitofwork.UnitOfWork; import org.qi4j.api.unitofwork.UnitOfWorkCompletionException; import org.qi4j.api.usecase.UsecaseBuilder; import org.qi4j.bootstrap.AssemblyException; import org.qi4j.bootstrap.ImportedServiceDeclaration; import org.qi4j.bootstrap.ModuleAssembly; import org.qi4j.functional.Function; import org.qi4j.io.Output; import org.qi4j.io.Outputs; import org.qi4j.io.Transforms; import org.qi4j.library.eventsourcing.domain.api.DomainEvent; import org.qi4j.library.eventsourcing.domain.api.DomainEventValue; import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue; import org.qi4j.library.eventsourcing.domain.factory.CurrentUserUoWPrincipal; import org.qi4j.library.eventsourcing.domain.factory.DomainEventCreationConcern; import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactoryService; import org.qi4j.library.eventsourcing.domain.source.EventSource; import org.qi4j.library.eventsourcing.domain.source.EventStream; import org.qi4j.library.eventsourcing.domain.source.memory.MemoryEventStoreService; import org.qi4j.test.AbstractQi4jTest; import org.qi4j.test.EntityTestAssembler; public class DomainEventTrackerTest extends AbstractQi4jTest { public void assemble( ModuleAssembly module ) throws AssemblyException { new EntityTestAssembler( ).assemble( module ); module.values( DomainEventValue.class, UnitOfWorkDomainEventsValue.class ); module.services( MemoryEventStoreService.class ); module.services( DomainEventFactoryService.class ); module.importedServices( CurrentUserUoWPrincipal.class ).importedBy( ImportedServiceDeclaration.NEW_OBJECT ); module.objects( CurrentUserUoWPrincipal.class ); module.entities( TestEntity.class ).withConcerns( DomainEventCreationConcern.class ); module.services( EventLoggingService.class ).instantiateOnStartup(); module.entities( DomainEventTrackerConfiguration.class ); } @Test public void testDomainEvent() throws UnitOfWorkCompletionException, IOException { UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Change description" )); uow.setMetaInfo( new Principal() { public String getName() { return "administrator"; } }); TestEntity entity = uow.newEntity( TestEntity.class ); entity.changeDescription( "New description" ); uow.complete(); try { Thread.sleep( 5000 ); } catch (InterruptedException e) { e.printStackTrace(); } } @Mixins( TestEntity.Mixin.class ) public interface TestEntity extends EntityComposite { @UseDefaults Property<String> description(); @DomainEvent void changeDescription( String newName ); abstract class Mixin implements TestEntity { public void changeDescription( String newName ) { description().set( newName ); } } } @Mixins(EventLoggingService.Mixin.class) @Activators( EventLoggingService.Activator.class ) public interface EventLoggingService extends ServiceComposite, Configuration<DomainEventTrackerConfiguration> { void startTracker(); void stopTracker(); public class Activator extends ActivatorAdapter<ServiceReference<EventLoggingService>> { @Override public void afterActivation( ServiceReference<EventLoggingService> activated ) throws Exception { activated.get().startTracker(); } @Override public void beforePassivation( ServiceReference<EventLoggingService> passivating ) throws Exception { passivating.get().stopTracker(); } } public abstract class Mixin implements EventLoggingService { DomainEventTracker tracker; @This Configuration<DomainEventTrackerConfiguration> config; @Service EventStream eventStream; @Service EventSource eventSource; public void startTracker() { config.get().enabled().set( true ); Output<UnitOfWorkDomainEventsValue,RuntimeException> map = Transforms.map( new Function<UnitOfWorkDomainEventsValue, String>() { public String map( UnitOfWorkDomainEventsValue unitOfWorkDomainEventsValue ) { return unitOfWorkDomainEventsValue.toString(); } }, Outputs.systemOut() ); tracker = new DomainEventTracker(eventStream, eventSource, config, map); tracker.start(); } public void stopTracker() { tracker.stop(); } } } }