File Download sem framework web MVC

O que aprendi em quase 10 anos de experiência com desenvolvimento de software foi que conceitos são mais importantes do que ferramentas e tecnologias. Conceitos perduram por muitos anos, ferramentas não.

O que estou querendo dizer é que entender bem MVC é mais importante e útil do que saber como usar o último framework MVC da moda; saber OO é mais importante do que saber a sintaxe de uma linguagem de programação. Independentemente da linguagem ou plataforma.

Quando trabalhamos com aplicações Web é comum ter a ajuda do framework MVC para disponibilizar um arquivo para o cliente (navegador). No caso do VRaptor, normalmente basta um código como este abaixo:

public File foto(Perfil perfil) {
    return new File("/caminho/foto-" + perfil.getId() + ".jpg");
}

O código é simples e resolve bem o problema, pois este é o objetivo de uma framework, certo? Mas o que acontece por debaixo dos panos? O que é enviado para o navegador? A imagem acima será exibida diretamente no browser ou o usuário poderá baixá-la? Qual o nome do arquivo será exibido para o usuário ao fazer download?

Muitas perguntas, muitas vezes desnecessárias… desnecessárias até o 1o problema surgir e você ter que identificar se o problema está no framework, servidor ou proxy da sua rede. Enfim, para ajudá-lo a entender parte do processo de download de arquivos numa aplicação Web nós blogamos exatamente sobre o assunto:

>> Como disponibilizar arquivos para download em Java

No post você vai aprender como fazer o download de um arquivo diretamente de uma Servlet, pois é exatamente isso que um framework MVC faz. Você vai aprender alguns cabeçalhos HTTP importantes e claro, como forçar aquela janelinha “Salvar como…”.

E aí, já desceu alguma vez do salto para programar mais baixo nível sem ajuda do seu framework favorito?

 

O perigo do relacionamento bidirecional com JPA e Hibernate

Eu já bati muito a cabeça com JPA e Hibernate para aprender que relacionamento bidirecional no geral atrapalha mais do que ajuda. A verdade é que deveríamos evitar relacionamento bidirecional (o tal do mappedBy) sempre que possível. Ele só deveria ser utilizado em último caso, quando realmente não tiver para onde correr…

Por exemplo, será que o código abaixo funcionaria em um relacionamento bidirecional?

Item curso = new Item("Curso de Java e Orientação a Objetos", 1);

Carrinho carrinho = dao.buscaPor(id);

carrinho.getItens().add(curso);

dao.atualiza(carrinho);

E se eu te dissesse que NÃO? Esse código não funcionaria!

Quando trabalhamos com bidirecional somos obrigados a escrever um código mais complicado para manter a consistência entre as entidades, o que nem sempre é fácil. Para entender do que estou falando dá uma lida no novo post do blog da TriadWorks:

>> JPA: por que você deveria evitar relacionamento bidirecional

Se você ainda insistir em usá-lo nos post acima eu te dou algumas dicas de orientação a objetos (ENCAPSULAMENTO, tan dãn!!) para manter a consistência do relacionamento. Dessa forma você diminui as chances de ter dor de cabeça.

E aí, o que achou do post?

Enums são objetos com estado e comportamentos

Eu não sei você, mas por muito tempo eu subestimei e encarei as enums no meu código apenas como simples constantes…

public enum TipoDeDocumento {

    RG,
    CPF,
    CNPJ;
}

Isto foi um grande erro, pois enums são tão poderosas quanto objetos Java… na verdade, enums são objetos e você deveria encará-las dessa forma! Tratá-las apenas como substitutos para uma lista de constantes do tipo int ou String é ignorar todo o potencial das enums e da orientação a objetos no seu código!

Uma enum pode ser tão completa quanto um objeto Java qualquer, isto é, uma enum pode ter dados (estado) e comportamentos. O código a seguir com uma enum possuindo estas características pode te dar uma idéia sobre o que estou falando:

public enum TipoDeDocumento {

    RG("RG", new ValidadorDeRg()),
    CPF("CPF", new ValidadorDeCpf()),
    CNPJ("CNPJ", new ValidadorDeCnpj());

    private String descricao;
    private Validador validador;

    private TipoDeDocumento(String descricao, Validador validador) {
        this.descricao = descricao;
        this.validador = validador;
    }

    /**
     * Valida número do documento
     */
    public boolean valida(String numero) {
        return this.validador.isValido(numero)
    }
}

Talvez só olhando o código não seja fácil compreender o poder das enums, então para você entender o que eu estou falando realmente eu te convoco a dar uma olhada nesse novo post no blog da Triadworks:

>> Enums são mais que constantes

O post também aborda algumas práticas sobre orientação a objetos que deixamos de usar por não compreender que enums são objetos com dados e comportamentos.

E aí, o que achou do post?