Hi Stephen,
The execution listener + transaction listener approach seems to become rather complicated. Maybe an easier approach is to implement a custom history handler (org.camunda.bpm.engine.impl.history.handler.CompositeDbHistoryEventHandler
allows you to add another one on top of the default handler) that receives all activity-instance end events and then uses the duration.
Cheers,
Thorben