but is a bit of a hack.
Why is it a hack? The order is simply, install the packet listener, then send the request stanza. Like it should be.
instantiate all of the extensions before you log in.
I don't know what you exactly mean with "instantiate", but all of Smack should been initialized after the first AbstractXMPPConnection instance has been created.
For example, if I want a CAPS hash to be sent with that initial presence message, I have to make sure CAPS is instantiated before login.
That should be the case, EntityCapsManager registers a ConnectionCreationListener when it's initialized, i.e. after the first AbstractXMPPConnection instance has been created. This ConnectionCreationListener will create a EntityCapsMaager for every XMPPTCPConnection by initConnection calling connectionCreated().
But you're right, Roster is particularly scary, because Smack instantiates it, not the user. This is hidden from the user.
Not sure what's scary about that. We just talked about that the Roster needs to be setup before the initial presence is send if you ever want to use the roster.