domain model as read/view model

Hi,

could someone, maybe you Allard :wink: shortly explain if it is an option to use the domain model as read/view model for external client requests please. I tried this with Axon and can’t get it working because of UnitOfWork related exceptions.
For example in scala:


val repository = new EventSourcingRepositoryOrder;
repository.setEventStore(eventStore)
repository.setEventBus(eventBus);
repository.setSnapshotterTrigger(snapshotterTrigger)
AnnotationCommandHandlerAdapter.subscribe(new OrderCommandHandler(repository), commandBus)

val callback = new VoidCallback {
override def onSuccess(): Unit = {
}

override def onFailure(t: Throwable): Unit = {
throw t
}
}

val id = UUID.randomUUID().toString()
commandGateway.send(CreateOrder(IdRev(id, 0)), callback)

val uow = DefaultUnitOfWork.startAndGet()
try {
val order = repository.load(id)
println("order: " + order)
uow.commit();
} catch {
case e: Exception => {
uow.rollback(e);
}
}

While uow.commit() i get

java.lang.IllegalStateException: Could not clear this UnitOfWork. It is not the active one.

So my question is what i’m doing wrong here? If it don’t start an own UOW before asking the repository i get

java.lang.IllegalStateException: No UnitOfWork is currently started for this thread.

Thanks

Marcus

Hi Marcus,

it is possible to use the command model for querying, although generally not recommended. The command model is usually already complex enough without having to think about querying data.
Using the repository to load the aggregate may have a negative side-effect: it locks the aggregate during the UoW. Since you’re querying it, you probably don’t want / need that.

But he code as you show it should work. Could you send the entire stacktrace of the “Could not clear this UnitOfWork. It is not the active one.” exception?

Cheers,

Allard

Hello Allard,

here is the stacktrace. Hmmm… so it is probably a scala.App related issue, right?

Exception in thread “main” java.lang.IllegalStateException: Could not clear this UnitOfWork. It is not the active one.
at org.axonframework.unitofwork.CurrentUnitOfWork.clear(CurrentUnitOfWork.java:106)
at org.axonframework.unitofwork.NestableUnitOfWork.clear(NestableUnitOfWork.java:192)
at org.axonframework.unitofwork.NestableUnitOfWork.rollback(NestableUnitOfWork.java:117)
at de.na.mb.es.domain.Application$delayedInit$body.apply(Application.scala:95)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at de.na.mb.es.domain.Application$.main(Application.scala:30)
at de.na.mb.es.domain.Application.main(Application.scala)

Regards

Marcus

Which line of code is Application.scala:95?
Assuming that’s the line “uow.rollback” in the code you sent, could you compare the CurrentUnitOfWork.get() with the value of uow?

If the UoW is being rolled back due to an exception, what’s the exception?

CurrentUnitOfWork.get() and my uow are the same. The exception that is thrown while uow.commit() is as follows. Sorry for not posting it before…

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at org.axonframework.eventstore.mongo.DocumentPerCommitStorageStrategy$CommitEntry.(DocumentPerCommitStorageStrategy.java:178)
at org.axonframework.eventstore.mongo.DocumentPerCommitStorageStrategy$CommitEntry.(DocumentPerCommitStorageStrategy.java:144)
at org.axonframework.eventstore.mongo.DocumentPerCommitStorageStrategy.createDocuments(DocumentPerCommitStorageStrategy.java:89)
at org.axonframework.eventstore.mongo.MongoEventStore.appendEvents(MongoEventStore.java:131)
at org.axonframework.eventsourcing.EventSourcingRepository.doSaveWithLock(EventSourcingRepository.java:184)
at org.axonframework.eventsourcing.EventSourcingRepository.doSaveWithLock(EventSourcingRepository.java:53)
at org.axonframework.repository.LockingRepository.doSave(LockingRepository.java:126)
at org.axonframework.repository.AbstractRepository$SimpleSaveAggregateCallback.save(AbstractRepository.java:167)
at org.axonframework.unitofwork.DefaultUnitOfWork$AggregateEntry.saveAggregate(DefaultUnitOfWork.java:312)
at org.axonframework.unitofwork.DefaultUnitOfWork.saveAggregates(DefaultUnitOfWork.java:277)
at org.axonframework.unitofwork.NestableUnitOfWork.commit(NestableUnitOfWork.java:48)
at de.na.mb.es.domain.Application$delayedInit$body.apply(Application.scala:95)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at de.na.mb.es.domain.Application$.main(Application.scala:30)
at de.na.mb.es.domain.Application.main(Application.scala)

Ah, that’s the problem. You’re rolling back a Unit of Work that has already been committed (which failed, ok).

In your case, you don’t want to do a commit, since you’re not changing anything. Simply roll back the uow when you’re done.

This does expose a bug, though. The EventSourcingRepository should not append events if there aren’t any… And the MongoEventStore shouldn’t create an empty commit document…