I must say the best Anti-Crack way I've seen is the "Online" system.
Basically the client needs to have an internet connection to your server to keep authenticated.
In Java that might not be required as there's no such thing as Java Reverse Engineering, at least not nearly as easy as for a C/Delphi file. The main difference is that with such languages the .exe will be created and it's easy to read the assembly and change value of registers and edit jumps, etc...
In Java however, since it will be interpreted by JVM, unless you know how the JVM interprets the code you won't be able to edit it successfully, not even close.
About creating the key, I think the best way would be for the key to be created on server-side (to prevent client-side cracking) and sending it to the e-mail/program (if you send for the program you should send it encrypted and even the user shouldn't know it, this of course also makes it a lot limited as they can't change computer).
This all depends on the type of license you'll have and the type of program.
Think of it like this:
.EXE = Crackable.
Sent to e-mail = Copyable (Unless you have 2 types of keys, Business/Personal, Business can be logged on in more than 1 computer, Personal cannot.)
Transfer for the program itself after login( User will need Internet connection every time, and you can generate a key at the moment he logs in, preventing the cracking.)
Transfer for the program 1st time use only (No need for internet connection, but if it's not an interpreted language easily crackable)