24 de dezembro de 2011

Tutorial Spring MVC

Faz muito tempo que não posto um tutorial completo com um projeto (código exemplo) sobre um framework, atualmente estou desenvolvendo aplicação com Spring MVC e isso acabou me motivando a escrever um tutorial sobre ele.

Aconselho antes a ler sobre Patterns como DAO, Repository, MVC, TO, PO, VO, DTO.

Passo 1:

Executem o Eclipse -> File -> New -> Project -> Dynamic Web Project

Passo 2:

Crie essa estrutura básica de pacotes.



Passo 3:

Criei dentro do pacote domain um bean
public class Produto {
     public Produto(Long id, String nome, String descricao, double preco, String cor, Long quantidade) {
     this.id = id;
     this.nome = nome;
     this.descricao = descricao;
     this.preco = preco;
     this.cor = cor;
     this.quantidade = quantidade;
}
private Long id;
private String nome;
private String descricao;
private double preco;
private String cor;
private Long quantidade;

//getters and setters

}



Passo 4:

Dentro do pacote dao criei a ProdutoDao e a ProdutoDaoI:

Interface:

public interface ProdutoDaoI {

    public void salva(Produto produto);
   
    public List pegaTodos();
   
    public void remove(Produto produto);
   
    public Produto pegaPorId(Long id);
}

Implementação:


Dentro da implementação do meu DAO notem a anotação @Repository essa anotação diz que ali será um repositório de dados ou seja seu DAO (camada de persistência),  com essa anotação automaticamente as exceptions são traduzidas e você não terá preocupações com lock otimista do JPA por exemplo.

@Repository
public class ProdutoDao implements ProdutoDaoI {

    private final static List produtos = new ArrayList();
   
    static {
        populaProdutos();
    }
   
    public void salva(Produto produto) {
        produto.setId(produtos.size() +1l);
        produtos.add(produto);
    }

    public List pegaTodos() {
        return Collections.unmodifiableList(produtos);
    }

    public void remove(Produto produto) {
        Iterator it = produtos.iterator();
        while(it.hasNext()) {
            Produto existente = it.next();
            if(existente.getId().equals(produto.getId())) {
                it.remove();
                break;
            }
        }
    }

    private static void populaProdutos() {
        produtos.add(new Produto(1l, "iPhone", "Celular da apple", 299.90, "prata", 10L));
        produtos.add(new Produto(2l, "DVD Yu Yu Hakusho", "Anime sobre Yusuke Urameshi um detetive sobrenatural.", 1999.99, "prata", 20L));
        produtos.add(new Produto(3l, "Caelum OnLine", "Cursos online da Caelum", 249.00, "verde", 60L));
        produtos.add(new Produto(4l, "Fred Rovella Show", "cd de músicas italianas", 29.90, "azul", 100L));
    }

    public Produto pegaPorId(Long id) {
        for(Produto produto : produtos) {
            if(produto.getId().equals(id)) return produto;
        }
        return null;
    }

}

Passo 5:
 
Nesse Passo serão utilizadas 2 anotações do Spring a @Service e a @Autowired (também citei a @Qualifier para quem vá utilizá-la futuramente).@Autowired: Serve para injeção de beans, como meus beans são simples posso usar tranquilamente essa anotação, mas se meu projeto começar a crescer muito será necessário usar a anotação @Qualifier para indicar qual bean quero injetar e evitar erros de injeção.
@Service: Serve para anotar a camada de serviço.

Dentro do pacote service criei as classe ProdutoService e a interface ProdutoServiceI, é ali que ficarão suas regras de negócio, ela receberá os parametros da camada view, chamará a dao e retornará a resposta para a view.

Interface:
public interface ProdutoServiceI {

    public void salva(Produto produto);

    public List pegaTodos();

    public void remove(Produto produto);

    public Produto pegaPorId(Long id);
}

Implementação:
@Service
public class ProdutoService implements ProdutoServiceI{

    @Autowired
    private ProdutoDao    produtoDao;

    public void salva(Produto produto) {
        produtoDao.salva(produto);
    }

    public List pegaTodos() {
        return produtoDao.pegaTodos();
    }

    public void remove(Produto produto) {
        produtoDao.remove(produto);
    }

    public Produto pegaPorId(Long id) {
        return produtoDao.pegaPorId(id);
    }
}


Passo 6:


As classes da camada de pacotes view, criei mais 2 pacotes form e controller, no pacote Form eu criei uma classe que terá os dados das páginas JSP e no pacote Controller as classes que controlam as chamadas do JSP para a service (Leia Controller como Managed Bean do JSF ou as Actions do Struts).


Form:

Aqui podemos ver as anotações do Hibernate Validator.
@NotEmpty: Anotação para validar se o valor é vazio.

@NotNull: Anotação para validar se o valor é nulo.
Message: Você pode customizar as mensagens que por padrão são em inglês.

public class ProdutoForm {

    private Long id;
    @NotEmpty(message = "Valor não pode ser vazio")
    private String nome;
    @NotEmpty(message = "Valor não pode ser vazio")
    private String descricao;
    private double preco;
    @NotEmpty(message = "Valor não pode ser vazio")
    private String cor;
    @NotNull(message = "Valor não pode ser nulo")
    private Long quantidade;

    //getters and setters

}


Controller:
@Controller
@RequestMapping("/produto/**")
public class ProdutoController {

    @Autowired
    private ProdutoService    produtoService;

    private ProdutoForm        produtoForm;

    private Produto         produto;
   
    @RequestMapping("/produto/formulario")
    public ModelAndView formulario() {
        return new ModelAndView("formulario").addObject("produtoForm", new ProdutoForm());
    }
   
    @RequestMapping("/produto/adiciona")
    public ModelAndView adiciona(@Valid ProdutoForm produtoForm, BindingResult result) {
        if (result.hasErrors()) {
            return new ModelAndView("formulario").addAllObjects(result.getModel());
        }
        populaBean(produtoForm);
        produtoService.salva(produto);
        return new ModelAndView("lista").addObject("produtos", produtoService.pegaTodos());
    }

    @RequestMapping("/produto/lista")
    public ModelAndView lista() {
        return new ModelAndView("lista").addObject("produtos", produtoService.pegaTodos());
    }
   
    @RequestMapping(value = "/produto/remove", method = RequestMethod.GET)
    public ModelAndView remove(@Valid @RequestParam(value = "produto.id") long id) {
        produto = new Produto();
        produto.setId(id);
        produtoService.remove(produto);
        return new ModelAndView("lista").addObject("produtos", produtoService.pegaTodos());
    }
   
    @RequestMapping("/produto/consulta")
    public ModelAndView consulta() {
        return new ModelAndView("consulta").addObject("produtoForm", new ProdutoForm());
    }
   
    @RequestMapping("/produto/pesquisa")
    public ModelAndView pesquisa(@Valid ProdutoForm produtoForm, BindingResult result) {
        produto = produtoService.pegaPorId(produtoForm.getId());
        produtoForm = populaForm(produto, produtoForm);
        return new ModelAndView("exibeProduto").addObject("produtoForm", produtoForm);
    }
   
    private void populaBean(ProdutoForm produtoForm) {
        //implementação do método de/para
    }
   
    private ProdutoForm populaForm(Produto produto, ProdutoForm produtoForm) {
       //implementação do método de/para
    }

   //getters and setters
   
}

É aqui que acontece a atuação do Spring MVC, temos a anotação @Controller que diz que essa classe será a página que receberá os valores do formulário e depois irá passar um objeto ou redirecionar para outras páginas.


@Controller: Anotação que diz que aquela classe terá como função  transformar o dados do formulário em dados do modelo, ou seja, gerenciamento entre as camadas View e Model.

@RequestMapping: Essa anotação é onde definimos o caminho do HTTP que irá ser utilizado na nossa aplicação, sendo mapeado na classe, todas as chamadas que contém "/produto/*" serão analisadas pelo Controller.

@RequestParam(value = "produto.id"): Podemos receber tanto o Form completo como apenas o parametro que desejamos com a anotação @RequestParam como parametro do método no Controller.

Podemos também enviar e receber mais de um objeto do(para o) formulário através do ModelAndView, nos frameworks mais antigos enviávamos apenas um objeto no retorno, com o ModelAndView podemos enviar mais.
Exemplo:
return new ModelAndView("exibeProduto").addObject("produtoForm", produtoForm);
Na linha acima estamos dizendo, ModelAndView coloque na página exibeProduto o objeto produtoForm.
ou ModelAndView eu quero que na página lista você coloque a lista de produtos.

return new ModelAndView("lista").addObject("produtos", produtoService.pegaTodos());

OBS: repare que o que coloco dentro do ModelAndView("lista") é o JSP lista.jsp.
OBS 2: Spring 3 trabalha por convenção, então baseado em suas anotações, JSPs e métodos , o que está dentro do @RequestMapping é o que criará na uri o caminho que chamará sua página.
Exemplo:
@RequestMapping("/produto/consulta") chamará o JSP consulta e na url ficará: /produto/consulta

Para validar o formulário utilizamos o BindingResult, ele verifica as validações e podemos retornar a página em seu estado no momento que pegamos o erro (ao invés de salvar todos objetos em param ou hiddens, mantendo seu estado.

Para validar nos parametros do método do controller que queremos fazer a validação colocamos no objeto a anotação @Valid, por exemplo: @Valid @RequestParam(value = "produto.id") long id, verifica se o id é válido ou @Valid ProdutoForm produtoForm no caso de um formulário.
Dentro do método adicionamos:


        if (result.hasErrors()) {
            return new ModelAndView("formulario").addAllObjects(result.getModel());
        }

No retorno estamos dizendo: Hei, se houver erro ModelAndView, volta pra página e devolve os objetos que estavam populados com as respectivas mensagens de erro.

Passo 7:
Para configurar o Spring precisamos colocar alguns XMLs (acalme-se não será um caminhão de XML como era antigamente)

Dentro de WebContent -> WEB-INF -> spring econtraremos o servlet-spring.xml e o app-spring.xml

servlet-spring.xml
[?xml version="1.0" encoding="UTF-8"?]
[beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd"]

     
    [bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"]
      [property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/]
      [property name="prefix" value="/WEB-INF/jsp/"/]
      [property name="suffix" value=".jsp"/]
    [/bean]

[/beans]
ViewResolver: aqui ele irá caçar na pasta "WEB-INF/jsp/" os nossos arquivos com sulfixo ".jsp"

app-spring.xml
[?xml version="1.0" encoding="UTF-8"?]
[beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd]
       
    [mvc:annotation-driven /]
    [context:annotation-config /]
   
   [ mvc:resources location="/css/" mapping="/resources/"/]
   [ mvc:resources location="/images/" mapping="/resources/"/]
   [ mvc:resources location="/js/" mapping="/resources/"/]
       
    [context:component-scan base-package="br.com.possege.loja" /]
  
   
    [import resource="spring-servlet.xml"/]

    [bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /]
   
    [mvc:resources mapping="/resources/**" location="/resources/" /]

    [bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"]
        [property name="basename" value="classpath:application-message" /]
        [property name="defaultEncoding" value="UTF-8" /]
        [property name="fallbackToSystemLocale" value="false" /]
    [/bean]
    
    [bean id="localeChangeInterceptor"
        class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"]
        property name="paramName" value="lang" /]
    [/bean]
    [bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver"]
        [property name="defaultLocale" value="pt_BR" /]
    [/bean]
 [/beans]

mvc:annotation-driven: Permite enviar as requisições das classes anotadas com @Controller.
context:annotation-config: Procura todas as classes anotadas com @PersistenceContext, @Autowired, entre outros, fazendo automaticamente a injeção de dependência.
context:component-scan: Procura todas as classes anotadas no pacote definido, assim não precisamos mapeá-las em XML, quando o scan é feito as classes são passadas por um filtro e é criada a definição em um bean para cada uma delas, quem determina a definição do bean é a anotação.
mvc:resources: Serve para o acesso GET dos arquivos estáticos, como CSS, JS, etc.
import resource: Importa o outro XML de configuração do Spring.

Passo 8:

Vamos configurar o web.xml
[?xml version="1.0" encoding="UTF-8"?]
[web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"]
[display-name]projetoSpring[/display-name]

    [servlet]
        [servlet-name]spring[/servlet-name]
        [servlet-class]org.springframework.web.servlet.DispatcherServlet[/servlet-class]
        [init-param]
            [param-name]contextConfigLocation[/param-name]
            [param-value]/WEB-INF/spring/app-config.xml[/param-value]
        [/init-param]
        [load-on-startup]1[/load-on-startup]
    [/servlet]

    [!-- Spring MVC Dispatcher Servlet --]
    [servlet-mapping]
        [servlet-name]spring[/servlet-name]
        [url-pattern]/[/url-pattern]
    [/servlet-mapping]
   
    [!-- Permitir comandos HTTP RESTfull (GET, POST, PUT, DELETE) --]
    [filter]
        [filter-name]hiddenHttpMethodFilter[/filter-name]
        [filter-class]org.springframework.web.filter.HiddenHttpMethodFilter[/filter-class]
    [/filter]

    [filter-mapping]
        [filter-name]hiddenHttpMethodFilter[/filter-name]
        [servlet-name]spring[/servlet-name]
    [/filter-mapping]

    [session-config]
        [session-timeout]10[/session-timeout]
    [/session-config]

    [!--SiteMesh --]
    [filter]
        [filter-name]sitemesh[/filter-name]
        [filter-class]com.opensymphony.sitemesh.webapp.SiteMeshFilter[/filter-class]
    [/filter]

    [filter-mapping]
        [filter-name]sitemesh[/filter-name]
        [url-pattern]/*[/url-pattern]
    [/filter-mapping]
   
    [!-- Encoding --]
    [filter]
        [filter-name]encodingFilter[/filter-name]
        [filter-class]org.springframework.web.filter.CharacterEncodingFilter[/filter-class]
        [init-param]
            [param-name]encoding[/param-name]
            [param-value]UTF-8[/param-value]
        [/init-param]
        [init-param]
            [param-name]forceEncoding[/param-name]
            [param-value]true[/param-value]
        [/init-param]
    [/filter]
    [filter-mapping]
        [filter-name]encodingFilter[/filter-name]
        [url-pattern]*[/url-pattern]
    [/filter-mapping]
   
    [error-page]
        [error-code]405[/error-code]
        [location]/erro[/location]
    [/error-page]
    [error-page]
        [error-code]500[/error-code]
        [location]/erro[/location]
    [/error-page]
    [error-page]
        [error-code]404[/error-code]
        [location]/erro[/location]
    [/error-page]
    [error-page]
        [error-code]400[/error-code]
        [location]/erro[/location]
    [/error-page]
[/web-app]

 Aqui configuramos o Spring, uma pog para permitir comandos HTTP Restfull, os filtros, a configuração do SiteMesh, Encoding e páginas de erro.

O redirecionamento de um 404, 500, etc, particularmente achei bizarro a solução que encontrei foi criar um ErroController e apontar para um JSP chamado erro.
Até cheguei abrir uma discussão no GUJ mas não obtive resposta.

ErroController:
@Controller
@RequestMapping("/")
public class ErroController {

    @RequestMapping("/**")
    public ModelAndView erro() {
        return new ModelAndView("erro");
    }
}

JSP:
[%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%]
[html]
    [head]
        [title][spring:message code="produto.erro.titulo" /][/title]
    [/head]
    [body]
        [p]
            [spring:message code="produto.erro.msg_default_erroGenerico" /]
        [/p]
    [/body]
 [/html]

Passo 9:

Configurando o SiteMesh, já adianto que não fiz CSS para esse exemplo, mas o SiteMesh é um ótimo template e já o deixei configurado.

Para configurar o SiteMesh eu criei na pasta WEB-INF o decorators.xml e uma sub pasta chamada decorators com o principal.jsp dentro.

decorators.xml
[xml]
[?xml version="1.0" encoding="UTF-8"?]
[decorators defaultdir="/decorators/principal.jsp"]

    [decorator name="principal"]
        [pattern]/*[/pattern]
    [/decorator]
   
[/decorators]
[/xml]

principal.jsp
[!DOCTYPE HTML]
[%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator"%]
[%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%]
[%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%]
[html]
    [head]
        [title][decorator:title default="Possege"/][/title]
        [meta charset="utf-8" /]
        [meta http-equiv="pragma" content="no-cache" /]
        [meta http-equiv="expires" content="-1" /]
        [meta http-equiv="cache-control" content="no-cache" /]
       
        [meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" /]       
        [meta name="format-detection" content="telephone=no" /]

        [meta name="apple-mobile-web-app-capable" content="yes" /]
        [meta name="apple-mobile-web-app-status-bar-style" content="black" /]       
       
       
        [decorator:head /]
    [/head]
    [body]
        [div]
            [div]
                [decorator:body/]
            [/div]
        [/div]
        [script src="http://www.google.com/jsapi"][/script]
       [script type="text/javascript" src="[c:url value="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" /]"][/script]
  [/body]
[/html]

Passo 10:

Criei uma pasta na raiz do projeto chamada resources que leva meu application-message_pt_BR.properties para internacionalização.
produto.lista.titulo=Lista de Produtos

produto.novo.titulo=Novo Produto
produto.novo.nome=Nome
produto.novo.descricao=Descri\u00E7\u00E3o
produto.novo.preco=Pre\u00E7o
produto.novo.cor=Cor
produto.novo.quantidade=Quantidade

produto.consulta.titulo=Consulta Produto
produto.consulta.codigo=C\u00F3digo
produto.consulta.lista=Listar Todos Produtos
produto.consulta.consulta=Consultar

produto.exibe.titulo=Produto Encontrado
produto.exibe.codigo=C\u00F3digo:
produto.exibe.nome=Nome:
produto.exibe.descricao=Descri\u00E7\u00E3o:
produto.exibe.preco=Pre\u00E7o:
produto.exibe.cor=Cor:
produto.exibe.quantidade=Quantidade:

produto.erro.titulo=Erro
produto.erro.msg_default_erroGenerico=Ocorreu um erro.

Passo 11:

Por fim criei todos os JSPs, não vou colocá-los aqui no blog mas vou colocar algumas tags que são essênciais e úteis.

As tag libs que mais utilizei:
[%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%]
[%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%]
[%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%]
[%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%]

Tags úteis:
[spring:message code="produto.exibe.preco" /]
[c:url var="pesquisa" value="/produto/pesquisa" /]
[form:form action="${pesquisa}" id="produtoForm" modelAttribute="produtoForm" method="post"]
[form:input path="nome" /] 
[form:errors path="nome"  /]
[fmt:formatNumber value="${produtoForm.preco }" type="currency"/]
[fmt:formatDate pattern="dd/MM/yyyy" value="${produtoForm.algumaData}"/]

spring:message: Coloca as mensagens, quando code ele pega do properties, quando text você digita o texto.
c:url: Submeter a página por um link, no caso estou passando o valor para o form:form
form:form: Nosso formulário, passo a ação, id e o modelAttribute que o Controller irá mandar, posso escolher enviar por get ou post.
for:input: Criar os campos texto para digitação no formulário.
form:errors: Pegar as mensagens de erro enviadas pelo BindingResult.
fmt:formatNumber: Formatar o valor no caso em moeda, há porcentagem e outros valores.
fm:formatDate: Formatar as datas no padrão que defini.

Fiz também um remove ajax utilizando JQuery dentro da aplicação:


[a href="javascript:void(0);" onclick="remove(${produto.id}); return false;"]Remove[/a]

[script type="text/javascript" src="[c:url value="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" /]"][/script]
[script type="text/javascript"]
    function remove(id){
        $.get('remove?produto.id='+id,function(){
            $('#produtoRemove-' + id).hide();
            alert('produto removido com sucesso');
            $('#produtoRemove-' + id).remove();
        });
    }
[/script]

Bom todo o fonte disponibilizei o download no GitHub.

Espero que este tutorial o ajude nos pontos que tive problemas, a ideia era mostrar uma solução com o ótimo framework MVC que os Spring nos dá.

Aconselho também estudar VRaptor é muito parecida a forma de programar e é um excelente framework MVC.

Agradecimenos especiais para Caelum e ao Christian Reichel por ter me ajudado com as dúvidas que surgiram quando comecei a programar com Spring MVC.

Comentários são bem vindos e as referências para deixar o seu template mais bonito e mais detalhes sobre Spring MVC e o VRaptor estão abaixo:


Washington Botelho - SiteMesh
Edson Gonçalves - Spring MVC
Rodolfo Chaves - Anotações do Spring
Valdemar Junior - Spring MVC com Tiles
Spring Source - Documentação Oficial
Jérôme Jaglale - Spring MVC Fast Tutorial
NetBeans - Tutorial Spring
Mkyoung - Hello World Spring
Caelum - FJ 27 Spring Framework
Caelum - FJ 28 VRaptor
Caelum - VRaptor online


Um Feliz Natal para todos. =D

4 de dezembro de 2011

Café com Java dia 10/12


O que é Café com Java?

Organizado há algum tempo por eu e o Marky Vasconcelos com extrema ajuda do Paulo Silveira, era simplesmente um encontro para o pessoal fazer um networking. Recentemente tomou um outro formato para atender mais pessoas, com mais temas. 


Porém como mês de Dezembro tem Natal, preparativos para o Ano Novo e etc, faremos o Café com Java Especial de Natal, no Blue Pub a partir das 16:00 hrs.


A entrada será de R$ 20,00 consumiveis e o que passar disso.


Vamos falar de Java, Tecnologia, Metodologias e nos divertir nesse fim de ano.


Horário: 16:00 em diante no Pub
Site do Pub: http://www.thebluepub.com.br/
R. do Pub: Alameda Campinas, 105, travessa da paulista.
Fotos dos outros Cafés com Java: Flickr
GUJ: Link do tópico
Twitter Tag: #CafeComJava

6 de outubro de 2011

Adeus Steve Jobs - #ISad


O mundo chora a perda de Steve Jobs (* 24/02/1955 - + 05/10/2011).
É assim que vou começar esse post, pois é assim que o mundo de TI se sente, estamos tristes pois perdemos uma das pessoas mais geniais que já existiram, se hoje temos nossos computadores do jeito que são devemos a ele.
Steve Jobs foi um inventor, um artista, um visionário e um grande empresário, criou uma das empresas mais valiosas do mundo a Apple Inc.
Steve influenciou milhões de pessoas no mundo inclusive eu, assisti no começo da minha carreira de TI o filme da TNT Piratas do Vale do Silício e o vídeo que ele fez na universidade de Stanford e com certeza isso me serviu muito, o sonho de trabalhar numa empresa visionária, que faz as coisas mais legais do mundo e sempre acreditando no crescimento da empresa, o que mais me tocou foi a paixão e o amor pelo seu trabalho, coisa que sempre falo até hoje inclusive até fiz um post aqui.
Nem tudo na vida dele foi um mar de rosas, não era rico, passou por problemas pessoais, mas deu a volta por cima com a Apple e quando teve que sair da companhia que amava foi um dos fundadores da Pixar outro enorme salto em sua vida.
Em 2003 na Sun Tech Days eu toquei pela primeira vez num PowerBook, na época os macs eram caros e quase ninguém tinha um, este Macbook que pude mexer era um que no Brasil haviam acabado de lançar com a propaganda de um homem grande com um Apple PowerBook de 17" e um cara pequeno com um PowerBook Apple de 20" (vídeo), Steve sempre lançou suas propagandas extravagantes e algumas polêmicas (engraçadas também como do IMac), via na época a IBM como seu inimigo, chamando-a de Big Brother em seu primeiro vídeo de lançamento da Apple faz essa referência ao Big Brother (vídeo), ele tinha uma visão do que os usuários querem, de como eles querem e com qualidade que um produto deve ser, além de um design lindo e inovador, nem todos seus produtos foram para frente, mas o Macintosh colorido e sem fios, o PowerBook, o IMac, o Macbook, o IPod, o IPod Touch, o IPhone e por último o IPad foram produtos que fizeram da Apple o que ela é hoje.
Fiquei super feliz quando comprei meu MacBook White, depois meu IPod Touch, meu IPhone, sempre admirei a qualidade da Apple com seus produtos inovadores, totalmente integrados entre si e simples, práticos e sem problemas.
A notícia sobre sua morte ontem, e depois de muito tempo ver o Twitter baleiando, as homenagens em suas homes do Google, da sua rival a Microsoft, todos os maiores jornais do mundo, blogs técnicos, revistas, as redes sociais, todos desenvolvedores, as pessoas mais importantes de TI entre elas Bill Gates, Wozniak (Fundou a Apple com Jobs), Mark Zuckerberg, Steve Ballmer, Paul Allen, James Gosling, Jack Dorsey (Twitter), Larry Page (Google), Eric Schmidt (Google), os fãs da Apple desejando que ele descansasse em paz nas HashTags (#RIPSteveJobs, #ThankYouSteve, #SteveJobs, #Apple e #ISad) foi realmente muito triste, ele nos serviu de inspiração e com certeza servirá a todas futuras gerações, o homem se foi mas o seu legado a sua marca foi deixada para todos que virão, nunca vamos esquecer a grandiosidade que Steve Jobs foi, o jeito que ele falava deixando as pessoas loucas e apaixonadas por sua empresa e seus produtos, uma pessoa assim hoje em dia é raro e com certeza ele fez um excelente trabalho.
Steve vai deixando um enorme vazio no mundo que dificilmente será preenchido, sentiremos sua falta.

Descanse em paz Steve Jobs .

Homenagem feita por Marcelo Braga.

5 de outubro de 2011

Café com Java - 08/10/2011

 

Mais uma vez tenho o imenso prazer de anunciar o Café com Java que será realizado novamente na Caelum.


O que é Café com Java?

Organizado há algum tempo por eu e o Marky Vasconcelos com extrema ajuda do Paulo Silveira, era simplesmente um encontro para o pessoal fazer um networking. Recentemente tomou um outro formato para atender mais pessoas, com mais temas.

Esse evento contará com 4 palestras de 30 minutos, e será realizado no auditório da Caelum próximo da estação Vila Mariana do metrô, em São Paulo.

Apresentações

10:00 - 10:40 - Lucas Cavalcanti (Começando com VRaptor e as novidades da versão 3.4 - Caelum)
10:40 - 11:00 - lanche
11:00 - 11:40 - Henrique Lima (Arquitetura do MoIP - Passado, Presente e Futuro)
11:40 - 12:20 - Washington Botelho (Testes de integração com DbUnit - Concrete Solutions) 

12:20 - Confraternização

Onde?

Dia: sábado, 08/10/2011 10:00 as 12:20.
Auditorio Caelum - Rua Vergueiro, 3185 - Próximo da estação Vila Mariana do metro.
Inscreva-se, vagas limitadas:
http://www.caelum.com.br/evento/cafecomjava/



Valor?

Entrada franca, mas é obrigatório a inscrição.

Quem pode ir?

Todos! É uma confraternização, um networking, nada formal, também não é algo focado apenas em Java, se você programa em outra linguagem vá também. 

  
Fotos dos outros encontros:

As fotos podem ser encontradas no meu Flickr: Fotos do Café com Java



Twitter HashTag: #CafeComJava
GUJ: Café com Java no GUJ