Ciao, questa parte di codice non ha molto senso:
codice:
try {
         if( s.length() > 20 )
            throw new MessaggioTroppoLungoException();
         } catch( MessaggioTroppoLungoException e ) {
            s = ritenta();
         }
         System.out.println( "Hai inserito " + s.length() + " caratteri." );
      }
In pratica lanci un eccezione che subito dopo intercetti. Se sai già quando lanciare l'eccezione e come gestirla allora puoi del tutto evitare di scomodare il sistema della gestione delle eccezioni.
Io creerei un metodo che lancia un eccezione se la lunghezza del messaggio è troppo lunga e nel main continuerei a richiamarla finche non la lancia più.
Esempio non testato:
codice:
import java.util.Scanner;

public class MexLungo {
    public static void main(String[] args) {

        System.out.println("Scrivi un testo di massimo 20 caratteri.");
        boolean error;
        String message = null;
        do {
            error = false;
            try {
                message = inserisci();
            } catch (MessaggioTroppoLungoException ex) {
                System.out.println(ex.getMessage());
                error = true;
            }
        } while (error);

        System.out.println("Hai inserito " + message.length() + " caratteri.");
    }

    public static String inserisci() throws MessaggioTroppoLungoException {
        Scanner in = new Scanner(System.in);
        String s = in.next();
        if (s.length() > 20)
            throw new MessaggioTroppoLungoException();
        return s;
    }
}

class MessaggioTroppoLungoException extends Exception {
    public MessaggioTroppoLungoException() {
        super("Messaggio troppo lungo");
    }

    public MessaggioTroppoLungoException(String s) {
        super(s);
    }
}