25 novembro 2010

Adicionar SyntaxHighlighter no Blogger

Ao iniciar o último posta, com a necessidade de postar trechos de código java, fui procurar uma forma de inserir caixas de código aqui no blogguer e acabei encontrando o SyntaxHighlighter.

O link para um tutorial de como instalá-lo no blogger é encontrado aqui: http://explicacaodanet.blogspot.com/2010/03/adicionar-syntaxhighlighter-no-blogger.html.

Appengine - Armazenando arquivos no Datastore

Já faz algum tempo em que eu tenho utilizado o Google App Engine para desenvolver meus projetos pessoais em Java, que atualmente o maior é o e-Karros. Apesar dos vários benefícios da plataforma, existem alguns pontos que trazem dificuldades ao desenvolvimento. A dificuldade mais recente que encontrei foi o armazenamento de arquivos no Datastore do App Engine. No meu caso específico foi o armazenamento de imagens. Após um bom tempo de pesquisa na net encontrei a solução abaixo.

Para podermos armazenar arquivos precisamos utilizar o tipo de dado Blob, através da API Blobstore. Bom, em primeiro lugar temos que criar nossa classe que irá armazenar o arquivo, que neste caso pode ser uma imagem:
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Blob;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Imagem {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

    @Persistent
    private Blob imagem;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setImagem(Blob imagem) {
        this.imagem = imagem;
    }

    public Blob getImagem() {
        return imagem;
    }
       
    public void adiciona() throws Exception {
        new ImagemDAO().adiciona(this);
    }

    public ImagemCarro buscaImagem(Long id) {
        return new ImagemDAO().buscaImagem(id);
    }
}

Vamos supor que nossa classe ImagemDAO já esteja implementada.

Após isso temos nossa classe Servlet que irá receber o arquivo que foi feito upload, tratá-lo e chamar o método de gravação. Para se "caputrar" o arquivo e converter para o formato da classe Blob (array de bytes), precisando da biblioteca Commons IOUtils, da Apache.

import org.apache.commons.io.IOUtils;

public class ArmazenaImagem extends HttpServlet {
 
    public void doPost(HttpServletRequest req, HttpServletResponse resp) {
        try {
            InputStream imgStream = req.getInputStream();
            Blob imageBlob = new Blob(IOUtils.toByteArray(imgStream));

            Imagem img = new Imagem();
            img.setImagem(imageBlob);

            img.adiciona();

            resp.setStatus(HttpServletResponse.SC_OK);
            resp.setContentType("text/plain");
            resp.getWriter().println( "{success: true}" );

        } catch (Exception e {
            e.printStackTrace();
            resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            resp.setContentType("text/plain");
            resp.getWriter().println( "{success: false}" );
        }
    }
}
Como podemos ver, é bem simples gravar um arquivo no Datastore.

Aqui uma pausa para explicar a linha resp.getWriter().println( "{success: true}" ); e seu equivalente no bloco catch. É um requerimento da plugin JavaScript Ajax Upload, o melhor que encontrei para esse trabalho ;-). A utilização de um plugin para upload foi a única forma que eu encontrei para enviar o arquivo ao servidor utilizando AJAX, porém ainda estou a procura de uma outra forma.

A recuperação da imagem é igualmente simples. Abaixo segue o servlet:
public class BuscaIMagemServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp) {
        try {
            resp.setContentType("image/jpeg");
            resp.setHeader("Content-Disposition","inline");
   
            Long id = Long.parseLong( req.getParameter( "id" ) );
            Imagem imagem = new Imagem().buscaImagem(ido);
   
            Blob blobImagem = imagem.getImagem();
            byte[] btImg = blobImagem.getBytes();
   
            resp.getOutputStream().write(btImg);
   
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
É somente isso. Ao recuperarmos a imagem do Datastore precisamos transformá-la em um array de bytes.

Nesse caso usei o campo id para recuperar uma imagem específica. Para exibir a imagem na página precisamos inserir a tag img em nossa página:
Sem Imagem
Onde '/buscaImagem?id=1' é o nosso servlet que recupera a imagem, e id=1 é o parâmetro para buscarmos uma imagem específica (o número 1 q coloquei é só um exemplo).

Espero que este breve tutorial sirva para que outras pessoas não fiquem batendo tanta cabeça quanto eu ;-).