What you call an "activation box" is officially an execution specification. It marks the beginning and end of some execution.
Some people seem to think, that they should always be there. However, if you don't care about these occurrences, you don't need to model them. Do you care?
Since your functions are synchroneous messages, they should have a corresponding reply message. This also applies, when no return value is expected. The reply then simply means, that the recepient of the message finished processing the message.
You are not obliged to model reply messages. If however you want to show, that a message is being sent before replying, it might be necessary. For example, func3b()
invokes func2b()
. This is usually done before replying, so it is an important piece of information. Of course, the execution typically ends with the reply. So, it is not necessary to model both.
In your case func2b()
is sent at the same time as the end of the execution specification. I don't think this is what happens in reality. There should be a small gap between func2b()
and the end of the execution.
func3a()
and func3b()
trigger different executions. As I said, you don't have to model them, but in reality, there are two executions.
func2a()
is synchroneous and therefore needs to wait for the reply. And the reply can only occur after all the other synchroneous functions have finished. This can somehow be guessed from the context, but it would be much better to show this by modeling the reply. Enlarging its execution so that it ends at the same height as those on the other lifelines has no meaning. Sequence diagrams don't define an ordering of occurrences on different lifelines. So, here a reply would definitely be necessary.
A complete model would look like this:

PlantUML
As I said, you don't need to model all executions and messages. However, you should make sure, that is unambiguously showing what you mean.