As far as I know, that behavior is best practice. An instance of SecureRandom does not automatically receive new entropy over time. If you desperately need to keep using that same instance, you have to keep seeding it.
You can use a SecureRandom implementation that uses the underlying entropy pool for every call, or you can use an ordinary implementation of SecureRandom and call getSeed(numBits) instead of next(numBits), or as you mentioned, you can call random.setSeed(random.getSeed(NUM_BITS) every once in a while. Finally, if you are on linux the default SecureRandom provider will mix urandom with the prng output on every call to nextBytes, so there's no need to reseed at all.
Anyway you look at it, there's no good reason to instantiate use a fresh SecureRandom instance every call.
As this is a tutorial, the snippet will likely be copy-pasted into production code running on God knows what OS by someone who can't imagine why there could be a problem with seeding from the system clock. Using a fresh instance allows the code to be portable, noob-friendly, and concise, which are important traits for its context.