Olá, eu tenho usado JSF nos meu projetos e na minha opiniao é bem pratico. Tem os managed beans, que voce referencia seus atributos numa jsp e quando executa uma action esses atributos ja estao todos povoadinhos. Sem contar que voce trabalha sempre com POJOs, ou seja, voce nao precisa implementar nenhuma interface ou estender classes.
Num mesmo managed bean voce pode colocar varias actions, actionListener, validators, etc, sem ter que criar uma classe para cada um.
O unico momento onde eu acabo implementando interfaces é nos conversores, onde voce converte um objeto para string e vice-versa. Com isso voce pode ligar um input (ou select, qualquer coisa) com um Objeto java do dominio da sua aplicacao. Fazendo isso voce registra no faces-config o seu conversor e o JSF chama ele pra setar no atributo do seu managed bean o objeto de negocio, e nao só a string como é visto no html.
As principais dificuldades é que geralmente as pessoas tentam fazer no JSF da mesma forma como faziam em outros frameworks “like Struts”.
E voce tem q tomar cuidado pois os get’s do seu managed bean sao chamados varias vezes durante o ciclo de vida, entao tome cuidado para nao colocar lógica pesada neles (quando precisar use lazy).
Outras coisas que voce pode ver muitas vezes sao os erros de validacao e erros de conversao, mas conforme voce vai usando e pega o jeito da coisa esses problemas vao sumindo.
E complicado falar assim… as coisas podem ficar maio vagas… mas se tiver mais alguma duvida… algo mais especifico posta aqui também.
Ah, e na minha opiniao, o tomahawk (http://myfaces.apache.org/tomahawk/index.html) nao pode faltar.
Outra coisa que voce pode ir olhando e que na minha opiniao vale a pena é o facelets.
Bom, é isso, qualquer coisa estamos aí…