<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Relatos de um Desenvolvedor Aventureiro]]></title><description><![CDATA[Um blog por Willian Krause]]></description><link>http://www.willcrisis.com</link><image><url>http://www.willcrisis.com/images/cover/chessboard.jpg</url><title>Relatos de um Desenvolvedor Aventureiro</title><link>http://www.willcrisis.com</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 26 May 2017 12:38:04 GMT</lastBuildDate><atom:link href="http://www.willcrisis.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Criando um projeto Grails 3 com Angular 2]]></title><description><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Desde que comecei a estudar frameworks de Frontend, uma coisa que me incomodou era a necessidade de se precisar de um servidor para o Frontend e outro para o Backend. Em aplicações muito grandes, onde os dois projetos são totalmente separados, é algo que até dá pra entender, mas em projetos menores, é um custo a mais que acaba sendo desnecessário, pois poderíamos aproveitar o servidor onde vamos publicar nosso projeto Backend para servir também o front sem nenhuma configuração adicional.</p>
</div>
<div class="paragraph">
<p>Por gostar bastante de Grails e do Angular 2, há algum tempo comecei a procurar uma forma de desenvolver um projeto único, mas onde eu pudesse usar as duas tecnologias ao mesmo tempo. Depois de algum tempo de pesquisa, consegui chegar a uma solução que acredito ser simples, porém que atende perfeitamente este cenário.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_criando_o_projeto_grails">Criando o projeto Grails</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_grails_application_forge">Grails Application Forge</h3>
<div class="paragraph">
<p>Aproveito aqui pra falar sobre o <a href="http://start.grails.org">Grails Application Forge</a>, uma ferramenta magnífica feita pelo pessoal do Grails. Com ela, você pode criar um novo projeto Grails escolhendo quais dependências deseja utilizar, qual a versão do Grails e qual o profile que deseja utilizar no seu projeto. Utilizando o benefício do Gradle Wrapper e do Grails Wrapper, você pode começar seu projeto sem precisar baixar os binários do Grails, sem configurar variáveis de ambiente, e sem precisar rodar o comando <code>grails create-app</code>. Basta baixar o arquivo zip gerado, extrair e rodar o comando <code>gradlew bootRun</code> dentro da pasta do projeto. Com isso, eliminamos problemas de versões diferentes no ambiente de desenvolvimento.</p>
</div>
</div>
<div class="sect2">
<h3 id="_criando_o_projeto">Criando o projeto</h3>
<div class="paragraph">
<p>Prosseguindo com o projeto, criei um novo projeto usando o profile <code>rest-api</code>. Pode ser criado tanto via linha de comando quanto pelo Grails Application Forge que citei acima. Eu utilizei o Application Forge, pois facilita muito na hora de montar um novo ambiente.</p>
</div>
<div class="paragraph">
<p>Caso prefira criar o projeto via linha de comando, é só rodar <code>grails create-app myapp --profile rest-api</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_alterando_as_configura_es">Alterando as configurações</h3>
<div class="paragraph">
<p>Precisamos alterar alguns arquivos de configuração para nosso projeto funcionar com o Angular 2. O primeiro deles é o <code>application.yml</code>. É preciso adicionar a linha <code>grails.resources.pattern: /**</code> para indicar que o conteúdo estático gerado pelo Angular será servido a partir da raiz do projeto. Vamos falar um pouco sobre o conteúdo estático já já. O arquivo fica assim:</p>
</div>
<div class="paragraph">
<p>application.yml</p>
</div>
<div class="listingblock">
<div class="content">
<pre>grails:
    profile: rest-api
    codegen:
        defaultPackage: grails3.angular2
    spring:
        transactionManagement:
            proxies: false
info:
    app:
        name: '@info.app.name@'
        version: '@info.app.version@'
        grailsVersion: '@info.app.grailsVersion@'
spring:
    main:
        banner-mode: "off"
    groovy:
        template:
            check-template-location: false

grails.resources.pattern: /**

...</pre>
</div>
</div>
<div class="paragraph">
<p>Depois, é preciso alterar também o arquivo <code>UrlMappings.groovy</code>. Vamos alterar as URLs dos endpoints colocando o prefixo <code>api</code> a elas, e vamos alterar o mapeamento da URL <code>/</code> para um arquivo <code>index.html</code>. O mapeamento fica assim:</p>
</div>
<div class="paragraph">
<p>UrlMappings.groovy</p>
</div>
<div class="listingblock">
<div class="content">
<pre>class UrlMappings {

    static mappings = {
        delete "/api/$controller/$id(.$format)?"(action:"delete")
        get "/api/$controller(.$format)?"(action:"index")
        get "/api/$controller/$id(.$format)?"(action:"show")
        post "/api/$controller(.$format)?"(action:"save")
        put "/api/$controller/$id(.$format)?"(action:"update")
        patch "/api/$controller/$id(.$format)?"(action:"patch")

        "/"(redirect: '/index.html')
        "500"(view: '/error')
        "404"(view: '/notFound')
    }
}</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_conte_do_est_tico_no_grails">Conteúdo estático no Grails</h3>
<div class="paragraph">
<p>Muitos não sabem, mas é possível servir conteúdo estático em um projeto Grails. Para isso, usamos a pasta <code>src/main/resources/public</code> ou a pasta <code>src/main/webapp</code>. A vantagem de se usar a primeira pasta é que o conteúdo também é exportado quando se cria um arquivo <code>.jar</code>. Já na segunda, o conteúdo só é exportado quando se cria um arquivo <code>.war</code>.</p>
</div>
<div class="paragraph">
<p>Por padrão, o conteúdo estático é servido através da URL <code><a href="http://servidor:porta/static/" class="bare">http://servidor:porta/static/</a></code>. Ao criarmos a configuração no arquivo <code>application.yml</code>, estamos dizendo ao Grails para servir o conteúdo estático através da URL raiz do nosso projeto (<code><a href="http://servidor:porta/" class="bare">http://servidor:porta/</a></code>). Se quiser fazer um teste, crie um arquivo <code>index.html</code> qualquer na pasta <code>src/main/resources/public</code> e execute o projeto. Antes de adicionar a configuração, este arquivo pode ser visto pela URL <code><a href="http://localhost:8080/static/index.html" class="bare">http://localhost:8080/static/index.html</a></code>. Após adicionar a configuração, o arquivo pode ser visto na URL <code><a href="http://localhost:8080/index.html" class="bare">http://localhost:8080/index.html</a></code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_criando_o_projeto_angular_2">Criando o projeto Angular 2</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Agora vamos criar o projeto Angular 2, que será servido através do mesmo container do projeto Grails.</p>
</div>
<div class="paragraph">
<p>Precisamos, primeiro de tudo, instalar o <a href="https://nodejs.org/en/">Node.js</a> na máquina. Usaremos também o <a href="https://github.com/angular/angular-cli">Angular CLI</a> para gerar e executar nosso projeto Angular.</p>
</div>
<div class="sect2">
<h3 id="_instalando_o_node">Instalando o Node</h3>
<div class="paragraph">
<p>Instalar o Node é bem fácil. É só baixar o executável do site (preferencialmente uma versão acima da 6.9), executar o instalador e pronto. Não esqueça de marcar a opção para adicionar o Node à variável de ambiente <code>path</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_instalando_o_angular_cli">Instalando o Angular CLI</h3>
<div class="paragraph">
<p>Depois de instalar o node, é só executar no terminal o comando <code>npm install -g @angular/cli</code>. Depois de instalado, será possível executar o comando <code>ng</code> no terminal. Para uma lista completa de comandos, execute <code>ng --help</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_criando_o_projeto_angular_2_2">Criando o projeto Angular 2</h3>
<div class="paragraph">
<p>Para criar um projeto Angular 2, usamos o comando <code>ng new &lt;meu-projeto&gt;</code>. Vamos executá-lo na pasta um nível acima de onde está nosso projeto Grails, usando o mesmo nome de projeto. Por exemplo, se o seu projeto Grails está na pasta <code>C:\des\grails3-angular2</code>, abre um terminal, navegue até a pasta <code>C:\des</code> e execute o comando <code>ng new grails3-angular2</code>. Pode dar um conflito no arquivo <code>.gitignore</code>. Eu recomendo copiar o conteúdo do arquivo do projeto Grails existente para um editor de texto, deixar o Angular CLI sobrescrever o arquivo, e depois colar de volta o conteúdo do arquivo antigo no novo arquivo gerado.</p>
</div>
</div>
<div class="sect2">
<h3 id="_configurando_o_projeto_angular_2">Configurando o projeto Angular 2</h3>
<div class="paragraph">
<p>Depois de criar o projeto, vamos alterar o arquivo <code>.angular-cli.json</code>. Vamos alterar o valor da propriedade <code>outDir</code> para <code>src/main/resources/public</code>. Esse atributo indica onde o Angular CLI vai gerar o código Javascript e HTML do projeto Angular2. Colocamos nesse atributo o caminho da pasta de conteúdo estático do Grails.</p>
</div>
<div class="paragraph">
<p>O arquivo vai ficar mais ou menos assim:</p>
</div>
<div class="listingblock">
<div class="title">angular-cli.json</div>
<div class="content">
<pre>{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "grails3-angular2"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "src/main/resources/public",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      ....
    }
  ]
  ...
}</pre>
</div>
</div>
<div class="paragraph">
<p>Depois, precisamos alterar também o arquivo <code>package.json</code>. Vamos alterar o script <code>start</code> para <code>ng build --watch</code>. Fica mais ou menos assim:</p>
</div>
<div class="paragraph">
<p>package.json</p>
</div>
<div class="listingblock">
<div class="content">
<pre>{
  "name": "grails3-angular2",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng build --watch",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  ....
}</pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_executando_o_projeto">Executando o projeto</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Abra um terminal na pasta raiz do projeto. Nesse terminal, execute o comando <code>npm start</code>. Isso irá iniciar a construção em tempo real do projeto Angular 2.</p>
</div>
<div class="paragraph">
<p>Depois, abra outro terminal também na pasta raiz do projeto, e execute o projeto Grails. Se você está usando o Wrapper, rode <code>gradlew bootRun</code>. Se está usando o Grails instalado, rode <code>grails run-app</code>.</p>
</div>
<div class="paragraph">
<p>Ao iniciar, abra o endereço <code><a href="http://localhost:8080" class="bare">http://localhost:8080</a></code> no navegador. Você deverá ver a página inicial padrão do projeto Angular 2. Como estamos executando a construção em tempo real do Angular 2, caso algum arquivo seja alterado, é só atualizar a página que as alterações já podem ser vistas.</p>
</div>
<div class="paragraph">
<p>Ao exportar o projeto como JAR ou como WAR, a pasta de conteúdo estático também será exportada, e o projeto pode ser acessado da mesma maneira.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclus_o">Conclusão</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Sei que muitos vão argumentar que o projeto Front deve ficar separado do projeto Backend, porém esta abordagem é pra quem, assim como eu, quer poder criar um projeto usando os dois frameworks sem ter que criar configurações separadas de servidor.</p>
</div>
<div class="paragraph">
<p>Se tiver alguma dúvida, pode escrever nos comentários ou me mandar um e-mail.</p>
</div>
<div class="paragraph">
<p>Aqui tem o código-fonte do projeto hospedado no GitHub: <a href="https://github.com/willcrisis/grails3-angular2" class="bare">https://github.com/willcrisis/grails3-angular2</a></p>
</div>
</div>
</div>]]></description><link>http://www.willcrisis.com/2017/03/13/Criando-um-projeto-Grails-3-com-Angular-2.html</link><guid isPermaLink="true">http://www.willcrisis.com/2017/03/13/Criando-um-projeto-Grails-3-com-Angular-2.html</guid><category><![CDATA[Grails]]></category><category><![CDATA[ Angular]]></category><category><![CDATA[ Angular 2]]></category><category><![CDATA[ Grails 3]]></category><category><![CDATA[ Frontend]]></category><category><![CDATA[ Backend]]></category><category><![CDATA[ API]]></category><category><![CDATA[ REST]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Mon, 13 Mar 2017 00:00:00 GMT</pubDate></item><item><title><![CDATA[Módulos para Angular JS]]></title><description><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Nossa&#8230;&#8203; Quanto tempo desde a última vez que apareci por aqui!</p>
</div>
<div class="paragraph">
<p>Esse post é pra falar sobre alguns projetos que venho desenvolvendo para AngularJS.</p>
</div>
<div class="paragraph">
<p>Nos últimos meses, comecei a trabalhar efetivamente com Angular 1, e diante de algumas necessidades bem específicas dos projetos nos quais trabalhei, me vi obrigado a desenvolver alguns módulos para facilitar a implementação dessas necessidades. Com isso, surgiram alguns projetos que visam facilitar a vida de nós, desenvolvedores apertados por prazos minúsculos.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="__a_href_https_github_com_willcrisis_angular_auth_angular_auth_a"><a href="https://github.com/willcrisis/angular-auth">Angular Auth</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Esse foi o meu primeiro módulo criado para o AngularJS 1. É um módulo para encapsular as regras de autenticação e autorização do projeto. Com ele, é só configurar alguns atributos e informar uma URL de backend que a autenticação já estará funcionando. Também suporta validação de regras por Papéis (Roles), que podem ser definidas direto no State (ele depende do fenomenal <a href="https://github.com/angular-ui/ui-router">Ui-Router</a>). Aí no <a href="https://github.com/willcrisis/angular-auth">link</a> tem as informações de instalação e configuração. Também estou evoluindo ele para trabalhar em conjunto com o Firebase, mas essa integração ainda é experimental.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="__a_href_https_github_com_willcrisis_angular_select2_angular_select2_a"><a href="https://github.com/willcrisis/angular-select2">Angular Select2</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Esse projeto nasceu a partir da necessidade de implementar Selects usando o <a href="https://select2.github.io/">Select2</a>. Encontrei alguns módulos para Angular que fazem isso, mas achei a complexidade deles muito grande para uma coisa tão simples. Por isso decidi implementar minha própria solução. Compartilhei a mesma no GitHub caso alguém também queira uma solução simples pra esse problema.</p>
</div>
<div class="sect2">
<h3 id="_ajude_a_melhorar">Ajude a melhorar!</h3>
<div class="paragraph">
<p>Se você interessar em algum desses projetos, sinta-se a vontade para abrir Issues ou fazer um fork! Não deixe de fazer seu PR!!</p>
</div>
</div>
</div>
</div>]]></description><link>http://www.willcrisis.com/2016/06/10/Modulos-para-Angular-JS.html</link><guid isPermaLink="true">http://www.willcrisis.com/2016/06/10/Modulos-para-Angular-JS.html</guid><category><![CDATA[AngularJS]]></category><category><![CDATA[ Plugins]]></category><category><![CDATA[ OpenSource]]></category><category><![CDATA[ GitHub]]></category><category><![CDATA[ Módulos]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 10 Jun 2016 00:00:00 GMT</pubDate></item><item><title><![CDATA[De casa nova]]></title><description><![CDATA[<div class="paragraph">
<p>O Willcrisis.com está de casa nova!!! Agora hospedado no Github Pages usando o magnífico <a href="http://hubpress.io">Hubpress</a>.</p>
</div>]]></description><link>http://www.willcrisis.com/2015/11/11/De-casa-nova.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/11/11/De-casa-nova.html</guid><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Wed, 11 Nov 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Hubpress: Usando o Travis-CI para gerar feed RSS]]></title><description><![CDATA[<div class="paragraph">
<p>Assim que descobri a existência do <a href="http://hubpress.io">Hubpress</a>, tive vontade imediata de migrar todo o conteúdo do meu site para ele, na intenção de centralizar minhas experiências todas no GitHub. Porém, logo de cara, percebi um grande problema: ele não gera o feed RSS dos artigos nativamente.</p>
</div>
<div class="paragraph">
<p>Isso poderia inviabilizar a minha idéia. Mas dei uma pesquisada e encontrei algumas coisas interessantes, como <a href="https://github.com/HubPress/hubpress.io/issues/49#issuecomment-99165107">esse comentário</a> nas issues do projeto. Seguindo as instruções do link, consegui gerar o feed usando uma classe Groovy tranquilamente. Mas aí apareceu um problema: eu teria que ter um ambiente com o Groovy configurado e seria necessário disparar a geração do feed manualmente. Dessa forma, eu não teria como criar um post de qualquer lugar.</p>
</div>
<div class="paragraph">
<p>Há alguns dias atrás eu estava tentando incorporar o <a href="https://travis-ci.org">Travis CI</a> em um outro <a href="https://github.com/willcrisis/themerize">projeto</a> meu feito em Grails, então lembrei que o Travis é capaz de executar comandos Groovy. Então decidi que usaria o Travis para gerar o RSS do meu blog.</p>
</div>
<div class="paragraph">
<p>Pesquisei por algumas horas, fiz várias tentativas sem sucesso. Até que depois de misturar vários tutoriais diferentes, consegui criar um arquivo <a href="https://github.com/willcrisis/willcrisis.github.io/blob/master/.travis.yml"><code>.travis.yml</code></a> que gerasse o RSS da forma que eu queria.</p>
</div>
<div class="paragraph">
<p>Não vou cobrir aqui como instalar o Hubpress ou criar uma página no GitHub Pages. O Google é nosso amigo nessa hora :D</p>
</div>
<div class="paragraph">
<p>É relativamente fácil fazer isso: primeiro é preciso ter uma conta no Travis CI (é só entrar com seus dados do GitHub). Depois é preciso ativar a integração contínua para o repositório &lt;username&gt;.github.io e criar na raiz do repositório um arquivo <code>.travis.yml</code>.</p>
</div>
<div class="paragraph">
<p>Depois, devemos criar um arquivo chamado <code>generateFeed.groovy</code>, que será o script que vai gerar o RSS em um arquivo para nós. Crie na raiz do projeto com o seguinte conteúdo:</p>
</div>
<div class="listingblock">
<div class="title">generateFeed.groovy</div>
<div class="content">
<pre>@Grab('com.rometools:rome:1.5.1')
@Grab('org.jsoup:jsoup:1.8.2')
import com.rometools.rome.feed.synd.SyndCategory
import com.rometools.rome.feed.synd.SyndCategoryImpl
import com.rometools.rome.feed.synd.SyndContent
import com.rometools.rome.feed.synd.SyndContentImpl
import com.rometools.rome.feed.synd.SyndEntry
import com.rometools.rome.feed.synd.SyndEntryImpl
import com.rometools.rome.feed.synd.SyndFeed
import com.rometools.rome.feed.synd.SyndFeedImpl
import com.rometools.rome.io.SyndFeedOutput
import groovy.io.FileType
import groovy.json.JsonSlurper
import org.jsoup.Jsoup
import org.jsoup.nodes.Document

import java.text.DateFormat
import java.text.SimpleDateFormat

def conf = new JsonSlurper().parse(new FileReader('hubpress/config.json'))

SyndFeed feed = new SyndFeedImpl()
feed.with {
    title = conf.site.title
    link = conf.site.url
    description = conf.site.description
    feedType = 'rss_2.0'
    author = conf.socialnetwork.email
    publishedDate = new Date()
    language = 'en-UK'
}

List&lt;SyndEntry&gt; entries = []
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
df.setTimeZone(TimeZone.getTimeZone('GMT-2'))

new File('2015').eachFileRecurse(FileType.FILES) { File post -&gt;
    SyndEntry entry = new SyndEntryImpl()
    Document document = Jsoup.parse(post, 'UTF-8')

    SyndContent syndDescription = new SyndContentImpl()
    syndDescription.value = document.getElementsByTag('meta').find { it.attr('property') == 'og:description' }.attr('content')

    entry.with {
        title = document.getElementsByTag('meta').find { it.attr('property') == 'og:title' }.attr('content')
        link = document.getElementsByTag('meta').find { it.attr('property') == 'og:url' }.attr('content')
        description = syndDescription
        publishedDate = df.parse(document.getElementsByTag('meta').find { it.attr('property') == 'article:modified_time' }.attr('content'))
        categories = document.getElementsByTag('meta').findAll { it.attr('property') == 'article:tag' }*.attr('content').collect {String tag -&gt;
            SyndCategory category = new SyndCategoryImpl()
            category.name = tag
            return category
        }
    }

    entries &lt;&lt; entry
}

feed.entries = entries.sort { it.publishedDate }.reverse()

Writer writer = new FileWriter('rss');
SyndFeedOutput output = new SyndFeedOutput()
output.output(feed,writer)
writer.close()</pre>
</div>
</div>
<div class="paragraph">
<p>Também é preciso gerar um <a href="https://github.com/settings/tokens">Personal Access Token</a> no GitHub que vai ser usado para fazer o commit do arquivo de feed para o nosso repositório. As permissões que já vem selecionadas são mais que suficientes para isso.</p>
</div>
<div class="paragraph">
<p>Depois de gerar o token, é preciso usar a <a href="https://github.com/travis-ci/travis.rb#readme">ferramenta de linha de comando</a> do Travis para converter nosso token em um "secret" que será usado pelo Travis. Depois de instalar a ferramenta, execute o seguinte comando (deve ser executado dentro da pasta onde foi feito o clone do projeto):</p>
</div>
<div class="literalblock">
<div class="content">
<pre>$ travis encrypt GH_TOKEN="the-token-from-github" --add</pre>
</div>
</div>
<div class="paragraph">
<p>Isso vai adicionar um "secret" ao nosso arquivo .yml que pode ser convertido pelo Travis usando a variável <code>${GH_TOKEN}</code> nos comandos.</p>
</div>
<div class="paragraph">
<p>Feito isso, coloque o seguinte conteúdo no arquivo <code>.travis.yml</code> fazendo as devidas alterações para coincidirem com o seu repositório:</p>
</div>
<div class="listingblock">
<div class="title">travis.yml</div>
<div class="content">
<pre>language: groovy
before_script:
- git config --global user.email "krause.willian@gmail.com"
- git config --global user.name "Willian Krause"
script: groovy generateFeed.groovy
after_success:
  - git add rss
  - git commit -m "Updated RSS feed [ci skip]"
  - git branch temp
  - git checkout master
  - git merge temp
  - git branch -d temp
  - git remote add github https://${GH_TOKEN}@github.com/willcrisis/willcrisis.github.io.git
  - git push github master --quiet
env:
  global:
  - secure: &lt;código gerado pela ferramenta de linha de comando do Travis&gt;
  - GH_REPO: github.com/willcrisis/willcrisis.github.io.git</pre>
</div>
</div>
<div class="paragraph">
<p>É preciso criar uma branch temporária pois o commit aqui será feito em uma branch detached, o que impede que o arquivo seja enviado para o repositório na hora em que o push é executado.</p>
</div>
<div class="paragraph">
<p>Após seguir todos os passos, basta adicionar um novo post na área administrativa do seu blog e ver a mágica acontecendo no Travis!</p>
</div>]]></description><link>http://www.willcrisis.com/2015/10/23/Hubpress-Usando-o-Travis-CI-para-gerar-feed-RSS.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/10/23/Hubpress-Usando-o-Travis-CI-para-gerar-feed-RSS.html</guid><category><![CDATA[hubpress]]></category><category><![CDATA[ desenvolvimento]]></category><category><![CDATA[ github]]></category><category><![CDATA[ travis-ci]]></category><category><![CDATA[ travis]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 23 Oct 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Movendo um repositório do BitBucket para o GitHub (ou vice-versa)]]></title><description><![CDATA[<div class="paragraph">
<p>Utilizo o <a href="http://bitbucket.org">BitBucket</a> há algum tempo por causa da possibilidade de criar repositórios privados grátis sem muita complicação, e também por ele ter integração com o <a href="http://codeship.com">Codeship</a> (ainda pretendo escrever um post sobre ele). Mas decidi abrir alguns dos meus projetos particulares após começar a participar da comunidade um pouco mais ativamente. Por isso, optei por mover esses projetos abertos para o <a href="http://github.com">GitHub</a> devido à maior popularidade deste para projetos opensource. Pensei que teria dificuldade, que seria muito complicado transferir todo o histórico de commits e etc, mas é uma tarefa muito mais simples do que parece.</p>
</div>
<div class="paragraph">
<p>Primeiro de tudo é preciso criar o novo repositório no GitHub. Dentro da sua página de perfil, abra a aba "Repositories" e clique no botão "New". Assim:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="http://www.willcrisis.com/images/github-create-repo.jpg" alt="Criando repositório no GitHub">
</div>
</div>
<div class="paragraph">
<p>Tenha o cuidado de desmarcar a opção "Initialize this repository with a README" enquanto cria o repositório. Dessa forma, o GitHub vai criar um repositório totalmente vazio.</p>
</div>
<div class="paragraph">
<p>Depois, copie a URL do repositório criado. Dentro da pasta onde você já possui o projeto hospedado no BitBucket clonado, execute os seguintes comandos:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>$ git remote rename origin bitbucket
$ git remote add origin &lt;URL do repositório criado&gt;
$ git push origin master</pre>
</div>
</div>
<div class="paragraph">
<p>Pronto! Todo o repositório do BitBucket vai ser copiado para o GitHub, inclusive mantendo o histórico de commits. Se desejar remover totalmente o projeto do BitBucket, execute também:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>$ git remote rm bitbucket</pre>
</div>
</div>
<div class="paragraph">
<p>É possível também fazer o processo inverso, movendo um projeto do GitHub para o BitBucket. Basta inverter a ordem dos repositórios utilizados.</p>
</div>
<div class="paragraph">
<p>Não cheguei a testar, mas acho que esses comandos funcionam para migrar para qualquer outro repositório Git (GitHub, BitBucket, GitLab, etc).</p>
</div>
<div class="paragraph">
<p>Se tiver interesse, confere lá o meu perfil no <a href="https://github.com/willcrisis">GitHub</a> e no <a href="https://bitbucket.org/willcrisis/">BitBucket</a> pra ver alguns projetos que eu desenvolvi! Sinta-se a vontade para fazer forks! Se ver alguma coisa que possa melhorar, manda um pull request!</p>
</div>]]></description><link>http://www.willcrisis.com/2015/10/21/Movendo-um-repositorio-do-Bit-Bucket-para-o-Git-Hub-ou-vice-versa.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/10/21/Movendo-um-repositorio-do-Bit-Bucket-para-o-Git-Hub-ou-vice-versa.html</guid><category><![CDATA[desenvolvimento]]></category><category><![CDATA[ git]]></category><category><![CDATA[ github]]></category><category><![CDATA[ bitbucket]]></category><category><![CDATA[ opensource]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Wed, 21 Oct 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Grails: Sobrescrevendo o UserDetailsService do Spring Security em um plugin]]></title><description><![CDATA[<div class="paragraph">
<p>Recentemente comecei a implementar alguns plugins para encapsular as lógicas comuns entre as aplicações que desenvolvo usando Grails. Uma dessas lógicas é a de segurança, onde eu adiciono alguns campos às classes do Spring Security e mais alguns recursos de cadastro (envio de e-mails ao usuário cadastrado, recurso de "esqueci minha senha", etc). Decidi escrever então um plugin que teria o SpringSecurityCore como dependência, e dentro dele eu definiria toda a minha lógica para ser reaproveitada em outros projetos.</p>
</div>
<div class="paragraph">
<p>Tudo muito lindo, tudo muito fácil, não fosse um pequeno detalhe: eu não conseguia sobrescrever o bean <code>userDetailsService</code> de nenhuma forma dentro do bloco <code>doWithSpring</code> dentro do meu descritor do plugin. Por mais q tentasse, nada de conseguir substituir esse bean pela classe que criei seguindo a <a href="http://grails-plugins.github.io/grails-spring-security-core/guide/userDetailsService.html">documentação oficial</a> do plugin. Cheguei ao ponto de editar o código fonte do plugin e submeter um <a href="https://github.com/grails-plugins/grails-spring-security-core/pull/387">pull request</a>, que foi devidamente rejeitado pela equipe. Mas como a comunidade é algo lindo de se ver, o próprio Burt Beckwith <a href="https://github.com/grails-plugins/grails-spring-security-core/pull/387#issuecomment-148786957">me ensinou</a> como fazer para funcionar. E não poderia ser mais fácil.</p>
</div>
<div class="paragraph">
<p>Todo o problema acontece porque o plugin do Spring Security é carregado após o plugin que eu desenvolvi. Dessa forma, a minha configuração sempre é sobrescrita. O que deve ser feito é adicionar, dentro do descritor do plugin (arquivo <code>MeuPluginGrailsPlugin.groovy</code>, fica na raiz do projeto), o atributo <code>loadAfter</code> e especificar quais plugins devem ser carregados antes dele. Assim:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">def loadAfter = ['springSecurityCore']</code></pre>
</div>
</div>
<div class="paragraph">
<p>Dessa forma, o meu plugin SEMPRE vai ser carregado após o Spring Security Core. Então, em vez de ser ele quem sobrescreve o meu bean, sou eu quem sobrescreve o bean dele!</p>
</div>
<div class="paragraph">
<p>Claro que se eu tivesse lido a <a href="http://grails.github.io/grails-doc/latest/guide/plugins.html">documentação</a> da forma adequada, teria visto isso escrito lá. Mas não teria tido a oportunidade de ser respondido pelo próprio Burt (que, a propósito, fez um fork e um <a href="https://github.com/willcrisis/themerize/pull/1">pull request</a> em um outro projeto meu!!).</p>
</div>]]></description><link>http://www.willcrisis.com/2015/10/16/Grails-Sobrescrevendo-o-User-Details-Service-do-Spring-Security-em-um-plugin.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/10/16/Grails-Sobrescrevendo-o-User-Details-Service-do-Spring-Security-em-um-plugin.html</guid><category><![CDATA[grails]]></category><category><![CDATA[ desenvolvimento]]></category><category><![CDATA[ banco de código]]></category><category><![CDATA[ spring security]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 16 Oct 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Grails: Internacionalização em banco de dados e arquivos]]></title><description><![CDATA[<div class="paragraph">
<p>Fala, pessoal!</p>
</div>
<div class="paragraph">
<p>Estive pesquisando uma forma de gravar internacionalização em banco de dados para permitir que alguns textos da minha aplicação sejam alterados sem a necessidade de precisar subir uma nova versão no servidor, mas continuando a usar as chaves definidas nos arquivos <code>messages_*.properties</code> caso o texto não esteja definido no banco.</p>
</div>
<div class="paragraph">
<p>Depois de ver <a href="http://graemerocher.blogspot.com.br/2010/04/reading-i18n-messages-from-database.html">esse</a> e <a href="http://stackoverflow.com/questions/8100312/grails-i18n-from-database-but-default-back-to-file">esse</a> post, pude fazer esse esquema funcionar perfeitamente.</p>
</div>
<div class="paragraph">
<p>Primeiro de tudo, é preciso criar uma classe de domínio para armazenar os valores no banco:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">class Mensagem {
    String code
    Locale locale
    String text

    static mapping = {
        cache true
        columns {
            code index: 'idx_message_key'
            locale index: 'idx_message_key'
        }
    }

    String toString() {
        text
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Criei um índice para tornar a busca das mensagens mais rápida.</p>
</div>
<div class="paragraph">
<p>Depois, foi preciso criar a classe <code>DatabaseMessageSource</code> estendendo a classe <code>AbstractMessageSource</code>, que será a classe responsável por fazer a pesquisa no banco de dados e, caso não encontre um valor, retornar a chave definida em arquivo:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">class DatabaseMessageSource extends AbstractMessageSource {

    Ehcache messageCache
    def messageBundleMessageSource

    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        def key = new MessageKey(code, locale)
        def format = messageCache.get(key)?.value
        if (!format) {
            Mensagem mensagem = Mensagem.findByCodeAndLocale(code, locale)

            if (mensagem ) {
                format = new MessageFormat(mensagem.text, mensagem.locale)
            } else {
                format = messageBundleMessageSource.resolveCode(code, locale)
            }
            messageCache.put(new Element(key, format))
        }
        return format
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Usei o EhCache para evitar que a cada exibição de página seja feita uma consulta no banco retornando os valores já encontrados em execuções anteriores, poupando assim uma quantidade razoável de recursos do servidor. Para configurar esse cache corretamente, primeiro é preciso criar a classe <code>MessageKey</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">@Immutable
class MessageKey implements Serializable {
    String code
    Locale locale
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Depois, é preciso dizer ao Spring para carregar os beans que acabamos de criar no <code>resources.groovy</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">messageCache(EhCacheFactoryBean) {
    timeToLive = 500
    // outras configurações de cache
}
messageSource(DatabaseMessageSource) {
    messageCache = messageCache
    messageBundleMessageSource = ref("messageBundleMessageSource")
}
messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) {
    basenames = "WEB-INF/grails-app/i18n/messages"
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Usamos a classe <code>PluginAwareResourceBundleMessageSource</code> porque, segundo <a href="http://stackoverflow.com/a/8204148">este</a> comentário, algumas mensagens de plugins podem ser ignoradas caso usemos alguma outra classe aqui.</p>
</div>
<div class="paragraph">
<p>Depois de fazer essa configuração, basta fazer o teste. Eu gerei o controlador e páginas para a classe <code>Mensagem</code> usando o comando <code>grails generate-all pacote.Mensagem</code>. Depois é só fazer os testes usando a tag <code>&lt;g:message&gt;</code> nas GSPs e a action <code>message(args)</code> nos controladores, e pronto! Sempre que for preciso sobrescrever um texto no sistema, basta criar um registro na tabela <code>Mensagem</code> e imediatamente a mensagem estará disponível, sem a necessidade de precisar subir uma nova versão da aplicação!// = Your Blog title</p>
</div>]]></description><link>http://www.willcrisis.com/2015/06/19/Grails-Internacionalizacao-em-banco-de-dados-e-arquivos.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/06/19/Grails-Internacionalizacao-em-banco-de-dados-e-arquivos.html</guid><category><![CDATA[grails]]></category><category><![CDATA[ desenvolvimento]]></category><category><![CDATA[ banco de código]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 19 Jun 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Grails: Rodando duas aplicações na mesma instância do Tomcat em subdomínios diferentes]]></title><description><![CDATA[<div class="paragraph">
<p>Recentemente precisei fazer deploy de duas aplicações Grails na mesma instância do Tomcat. Tudo seria simples, se não fosse o fato de que cada aplicação seria acessada pelo seu próprio subdomínio, e que a URL deveria ser algo parecido com <a href="http://aplicacao1.meudominio.com/controller/id" class="bare">http://aplicacao1.meudominio.com/controller/id</a></p>
</div>
<div class="paragraph">
<p>A princípio, basta configurar o servidor web Apache com o módulo mod_proxy configurado corretamente que tudo está resolvido. Porém, o Tomcat em sua configuração default adiciona o contexto de cada aplicação na URL que está sendo acessada. Como fazer então para que cada aplicação tenha seu subdomínio exclusivo?</p>
</div>
<div class="paragraph">
<p>A solução me tomou bastante tempo de pesquisa e testes baseados em tentativa e erro. Segue aqui a forma como consegui resolver meu problema.</p>
</div>
<div class="paragraph">
<p>Primeiro de tudo, precisei alterar o arquivo <code>server.xml</code> do Tomcat e fazer algumas alterações: Adicionar um novo Service, criar um Connector, definir uma Engine e um Host. Ficou mais ou menos assim (vou ocultar algumas partes do arquivo por não ser o foco):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;Server ...&gt;
    ...
    &lt;Service name="aplicacao1"&gt;
        &lt;Connector port="8081" protocol="HTTP/1.1"
            connectionTimeout="20000"
            redirectPort="8444"
            proxyName="aplicacao1.meudominio.com"
            proxyPort="80" /&gt;
        &lt;Engine name="aplicacao1" defaultHost="aplicacao1"&gt;
            &lt;Host name="aplicacao1" appBase="aplicacao1" unpackWARs="true" autoDeploy="true"&gt;
            &lt;/Host&gt;
        &lt;/Engine&gt;
    &lt;/Service&gt;

    &lt;Service name="aplicacao2"&gt;
        &lt;Connector port="8082" protocol="HTTP/1.1"
            connectionTimeout="20000"
            redirectPort="8445"
            proxyName="aplicacao2.meudominio.com"
            proxyPort="80" /&gt;
        &lt;Engine name="aplicacao2" defaultHost="aplicacao2"&gt;
            &lt;Host name="aplicacao2" appBase="aplicacao2" unpackWARs="true" autoDeploy="true"&gt;
            &lt;/Host&gt;
        &lt;/Engine&gt;
    &lt;/Service&gt;

    &lt;Service name="Catalina"&gt;
        &lt;Connector port="8080" protocol="HTTP/1.1"
            connectionTimeout="20000"
            URIEncoding="UTF-8"
            redirectPort="8443" /&gt;
            ... (aqui são as configurações default do Tomcat)
        &lt;/Service&gt;
&lt;/Server&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Depois de fazer essa configuração, dentro da pasta do Tomcat, criei as pastas aplicacao1 e aplicacao2, no mesmo nível em que a pasta webapps está. Também é preciso dar permissão 775 e mudar o proprietário dessas pastas para o usuário tomcat7.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash"># mkdir aplicacao1
# mkdir aplicacao2
# chmod 775 aplicacao1
# chmod 775 aplicacao2
# chown tomcat7 aplicacao1
# chown tomcat7 aplicacao2</code></pre>
</div>
</div>
<div class="paragraph">
<p>Vai ficar mais ou menos assim:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="http://www.willcrisis.com/images/tomcat-folders.JPG" alt="tomcat folders.JPG">
</div>
</div>
<div class="paragraph">
<p>Depois, eu copiei os WARs pra dentro da sua respectiva pasta e renomeei eles pra <code>ROOT.war</code>. Por fim, fiz as alterações no Apache para que o proxy redirecione corretamente as requisições:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;VirtualHost *:80&gt;
    ServerName aplicacao1.meudominio.com
    ServerAlias aplicacao1.meudominio.com

    ProxyRequests Off

    ErrorLog /var/log/apache2/error-aplicacao1.log

    &lt;Directory proxy:http://aplicacao1.meudominio.com:80&gt;
        Order Allow,Deny
        Allow from all
    &lt;/Directory&gt;

    &lt;Proxy aplicacao1.meudominio.com:80&gt;
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;

    ProxyPass / http://meudominio.com:8081/
    ProxyPassReverse / http://meudominio.com:8081/
&lt;/VirtualHost&gt;

&lt;VirtualHost *:80&gt;
    ServerName aplicacao2.meudominio.com
    ServerAlias aplicacao2.meudominio.com

    ProxyRequests Off

    ErrorLog /var/log/apache2/error-aplicacao2.log

    &lt;Directory proxy:http://aplicacao2.meudominio.com:80&gt;
        Order Allow,Deny
        Allow from all
    &lt;/Directory&gt;

    &lt;Proxy aplicacao2.meudominio.com:80&gt;
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;

    ProxyPass / http://meudominio.com:8082/
    ProxyPassReverse / http://meudominio.com:8082/
&lt;/VirtualHost&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Depois é só reiniciar o Apache e o Tomcat e partir pro abraço!!</p>
</div>]]></description><link>http://www.willcrisis.com/2015/06/10/Grails-Rodando-duas-aplicacoes-na-mesma-instancia-do-Tomcat-em-subdominios-diferentes.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/06/10/Grails-Rodando-duas-aplicacoes-na-mesma-instancia-do-Tomcat-em-subdominios-diferentes.html</guid><category><![CDATA[desenvolvimento]]></category><category><![CDATA[ infraestrutura]]></category><category><![CDATA[ grails]]></category><category><![CDATA[ banco de código]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Wed, 10 Jun 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Grails: Ordenar uma classe de domínio por mais de um campo]]></title><description><![CDATA[<div class="paragraph">
<p>Muitas vezes precisamos que os registros de uma classe de domínio venham ordenados por um determinado campo na listagem padrão. Isso é fácil de fazer em Grails! Basta definir o atributo <code>sort</code> dentro da seção <code>mapping</code> da nossa classe.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>static mapping = {
    sort 'campo'
}</pre>
</div>
</div>
<div class="paragraph">
<p>Se precisarmos especificar a ordem (ascendente ou descendente), também é bem simples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>static mapping = {
    sort campo: 'asc' //ou 'desc'
}</pre>
</div>
</div>
<div class="paragraph">
<p>Mas como fazer para ordenar por dois campos ao mesmo tempo? Simples também:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>static mapping = {
    sort campo: 'asc', outroCampo: 'asc'
}</pre>
</div>
</div>
<div class="paragraph">
<p>Isso é possível pois o método <code>sort</code> definido dentro do bloco <code>mapping</code> recebe uma <code>String</code> ou um <code>Map</code> como parâmetro. Quando recebe um <code>Map</code>, ele é inteligente o suficiente para realizar a ordenação por todos os campos e ordens informados.</p>
</div>]]></description><link>http://www.willcrisis.com/2015/06/05/Grails-Ordenar-uma-classe-de-dominio-por-mais-de-um-campo.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/06/05/Grails-Ordenar-uma-classe-de-dominio-por-mais-de-um-campo.html</guid><category><![CDATA[desenvolvimento]]></category><category><![CDATA[ grails]]></category><category><![CDATA[ banco de código]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 05 Jun 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Grails: Mapear enum para um campo Integer em vez de String]]></title><description><![CDATA[<div class="paragraph">
<p>Quem programa em Grails sabe que há uma certa limitação na hora de mapear enums dentro de uma classe de domínio. O comportamento padrão é que o <code>key</code> do valor será salvo no banco. O Grails também dá a opção de mapear o enum de forma <code>ordinal</code>, o que também é possível no Hibernate.</p>
</div>
<div class="paragraph">
<p>Mas imagine o seguinte cenário:
Você possui uma classe de domínio qualquer que possui um enum indicando um nível de dificuldade, conforme ilustrado abaixo:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">class DominioQualquer {
    NivelEnum nivel

    static mapping = {
    	nivel enumType: 'ordinal'
    }
}

enum NivelEnum {
    BAIXO
    MEDIO
    ALTO
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Neste caso, o Grails irá criar um mapeamento usando um campo inteiro no banco de dados. Mas e se, por algum motivo de força maior, você for forçado a incluir os níveis "Médio-Baixo" e "Médio-alto" ao seu domínio? Para facilitar a visualização do código, estruturaríamos o enum da seguinte forma:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">enum NivelEnum {
	BAIXO
	MEDIO_BAIXO
	MEDIO
	MEDIO_ALTO
	ALTO
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Porém isso iria quebrar os registros já incluídos, pois mudamos a ordem dos valores no enum! Como resolver isso?</p>
</div>
<div class="imageblock">
<div class="content">
<img src="http://www.willcrisis.com/images/defender.gif" alt="defender.gif">
</div>
</div>
<div class="paragraph">
<p>A solução é ridiculamente simples, mas que me tomou muito tempo de pesquisa: basta definir um campo chamado <code>id</code> dentro do enum e remover o <code>enumType</code> do mapeamento. Dessa forma, o Grails irá usar este campo para persistir no banco, em vez de usar o ordinal. Nosso código então fica assim:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">class DominioQualquer {
    NivelEnum nivel
}

enum NivelEnum {
    BAIXO(0)
    MEDIO_BAIXO(3)
    MEDIO(1)
    MEDIO_ALTO(4)
    ALTO(2)

    Integer id

    private NivelEnum(Integer id) {
        this.id = id
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Lembrando que o nome do campo PRECISA ser <code>id</code>. Já o tipo pode ser qualquer tipo conhecido do Hibernate que estenda <code>Serializable</code> (<code>String</code>, <code>Date</code>, <code>char</code>, etc&#8230;&#8203;).</p>
</div>]]></description><link>http://www.willcrisis.com/2015/05/08/Grails-Mapear-enum-para-um-campo-Integer-em-vez-de-String.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/05/08/Grails-Mapear-enum-para-um-campo-Integer-em-vez-de-String.html</guid><category><![CDATA[grails]]></category><category><![CDATA[ desenvolvimento]]></category><category><![CDATA[ banco de código]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 08 May 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[Preparando um projeto Cordova para publicação]]></title><description><![CDATA[<div class="paragraph">
<p>Na pasta platforms/android do projeto, executar os seguintes comandos:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>ant release
cd bin
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../../../keys/nome_do_arquivo.keystore AppName-release-unsigned.apk nome_do_alias_keystore
jarsigner -verify -verbose -certs AppName-release-unsigned.apk
zipalign -v 4 AppName-release-unsigned.apk AppName.apk</pre>
</div>
</div>]]></description><link>http://www.willcrisis.com/2015/01/23/Preparando-um-projeto-Cordova-para-publicacao.html</link><guid isPermaLink="true">http://www.willcrisis.com/2015/01/23/Preparando-um-projeto-Cordova-para-publicacao.html</guid><category><![CDATA[banco de código]]></category><category><![CDATA[ desenvolvimento]]></category><category><![CDATA[ mobile]]></category><category><![CDATA[ cordova]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Fri, 23 Jan 2015 00:00:00 GMT</pubDate></item><item><title><![CDATA[DigitalOcean: Hospedagem na nuvem de forma rápida e fácil]]></title><description><![CDATA[<div class="paragraph">
<p>Fala, pessoal! Quanto tempo, hein?</p>
</div>
<div class="paragraph">
<p>2 anos depois da última postagem, estou de volta! Muita coisa aconteceu nesse meio-tempo (muito-tempo, na verdade). Os próximos posts vão relatar as mudanças!</p>
</div>
<div class="paragraph">
<p>Mas hoje, vamos falar um pouco de nuvem, esse assunto que anda tão na moda.</p>
</div>
<div class="paragraph">
<p>Depois de pagar caro por hospedagens de sites, sofrer com problemas de permissões de arquivos, FTPs lentos e outras coisas, decidi experimentar uma coisa diferente: servidores na nuvem.</p>
</div>
<div class="paragraph">
<p>Uma das coisas que mais me deixava irritado nas hospedagens convencionais era quando eu fazia upload de um arquivo usando o Wordpress (ou o Joomla) e o mesmo era atribuído a um usuário que eu desconhecia. Dessa forma, eu ficava impossibilitado de editar, ou até mesmo de excluir esse arquivo. Tinha, então, que abrir um ticket pro suporte da hospedagem pedindo para excluírem o arquivo pra mim.</p>
</div>
<div class="paragraph">
<p>Com um servidor na nuvem, esse problema não acontece: o servido é seu, então fica mais fácil de resolver esse tipo de situação. Também podemos criar o servidor do nosso jeito, instalando os aplicativos que precisarmos.</p>
</div>
<div class="paragraph">
<p>Experimentei por um tempo o Amazon EC2, que por sinal é muito bom, possui algumas imagens de servidores pré-carregadas, é de fácil utilização e dá 1 ano grátis se o seu servidor estiver dentro do Free-Tier. Porém, quando subi um aplicativo Grails lá (aplicativo simples, sem muitos plugins nem operações complexas), o processamento e a memória dispararam e acabei pagando um valor um pouco alto.</p>
</div>
<div class="paragraph">
<p>Foi aí que um amigo, o <a href="http://www.emilio2hd.com.br">Emílio</a>, falou sobre o <a href="https://www.digitalocean.com/?refcode=a8cd65b5d607">DigitalOcean</a>, um serviço que disponibiliza um servidor da mesma maneira que o Amazon EC2, porém com o custo fixo de 5 dólares por mês no plano básico.</p>
</div>
<div class="paragraph">
<p>No começo fiquei meio receoso, pois nunca tinha ouvido falar no serviço, mas depois de algumas pesquisas na internet, vi que o mesmo é bem avaliado por muita gente.</p>
</div>
<div class="paragraph">
<p>Arrisquei e fiz a conta. O servidor ficou disponível para mim em menos de 1 minuto, com Ubuntu 12.04 e acesso SSH imediato.</p>
</div>
<div class="paragraph">
<p>É possível encontrar muito material e "HowTo"s na comunidade, o que faz com que seja muito fácil de se configurar o que for necessário.</p>
</div>
<div class="paragraph">
<p>Venho brincando nesse servidor há alguns dias e, muito em breve, irei migrar o site e meus projetos pessoais para lá.</p>
</div>
<div class="paragraph">
<p>Se estiver interessado, pode acessar por esse link e me garantir alguns créditos (o DigitalOcean trabalha com esquema de referências :D):</p>
</div>
<div class="paragraph">
<p><a href="https://www.digitalocean.com/?refcode=a8cd65b5d607" class="bare">https://www.digitalocean.com/?refcode=a8cd65b5d607</a></p>
</div>
<div class="paragraph">
<p>Se tiverem perguntas, dúvidas, sugestões, não hesitem em comentar!</p>
</div>]]></description><link>http://www.willcrisis.com/2013/11/13/Digital-Ocean-Hospedagem-na-nuvem-de-forma-rapida-e-facil.html</link><guid isPermaLink="true">http://www.willcrisis.com/2013/11/13/Digital-Ocean-Hospedagem-na-nuvem-de-forma-rapida-e-facil.html</guid><category><![CDATA[infraestrututra]]></category><category><![CDATA[ servidores]]></category><category><![CDATA[ desenvolvimento]]></category><dc:creator><![CDATA[Willian Krause]]></dc:creator><pubDate>Wed, 13 Nov 2013 00:00:00 GMT</pubDate></item></channel></rss>