Vaadin: Programação para a web com jeito de desktop - Parte 2
Neste artigo veremos o Vaadin, uma ferramenta para a construção de interfaces web elegantes e que fornece um estilo de programação diferente daquele já bastante difundido pelo JSF. Vamos demonstrar os principais conceitos que envolvem esta tecnologia e apresentá-la através de um exemplo prático que irá explorar as diferenças entre a forma de desenvolvimento Vaadin e JSF.
Em que situação o tema é útil:
Diversas ferramentas já buscaram abstrair ao máximo as peculiaridades do ambiente web para os desenvolvedores. Contudo, nenhuma o conseguiu de forma tão elegante como o Vaadin. Esta ferramenta permite focar-se no principal, que é a construção da aplicação. Os detalhes de comunicação cliente/servidor são praticamente abstraídos, sobrando raríssimas situações em que serão necessárias intervenções desta natureza.
Resumo DevMan:
O segredo do Vaadin está em seu mecanismo de comunicação entre cliente e servidor. Uma aplicação pode ser totalmente desenvolvida sem se preocupar com estas peculiaridades comuns no mundo web. As aplicações são desenvolvidas em um novo paradigma, muito semelhante ao Swing, utilizando a composição de componentes, normalmente adotando painéis para realizar este agrupamento.
Devido a sua natureza voltada para a criação de sistemas, e não de sites web comuns, o Vaadin já nos brinda com alguns componentes que simplificam bastante nosso código, como os componentes de formulário e de tabela. Todo desenvolvedor que entra neste novo mundo, também não pode deixar de conferir os diversos componentes disponibilizados no site oficial, através da opção Add-ons!
O desenvolvimento de aplicações web tem hoje como grande protagonista o JSF, seguido por opções como GWT, Spring MVC, o saudoso Struts (ver Links), entre outros. Contudo, não devemos fechar os olhos para as demais opções existentes no mercado. Cada uma possui suas características e é importante analisar com calma aquela que melhor se encaixa no perfil de seu projeto. Neste artigo, vamos tentar complicar ainda mais a sua escolha e apresentar-lhes o Vaadin. Assim como o JSF, trata-se de um framework voltado para a construção de aplicações web e que possui algumas peculiaridades que o tornam bastante interessante.
Primeiro, cabe destacar que ele deve ser usado para a construção de sistemas web. Isto quer dizer que ele não foi projetado para o desenvolvimento de websites comuns, como portais. Outro detalhe que chama a atenção no Vaadin é o uso do GWT como motor de exibição de seus componentes. Mas não é só neste detalhe que estas duas últimas ferramentas são semelhantes: a forma de programação é muito próxima daquela adotada na construção de aplicações Swing.
A primeira questão que deve surgir em sua mente é: por que usar o primeiro, ao invés do segundo? É simples, apesar das semelhanças, existem detalhes marcantes que certamente vão influenciar em sua escolha. Inicialmente, lembre-se que o GWT trabalha traduzindo seu código Java para JavaScript. Assim, você tem limitações sobre quais bibliotecas poderão ser usadas em seu projeto, pois existem classes que não podem ser convertidas para um código JavaScript equivalente. Segundo, o número de classes que é necessário para que haja a comunicação remota é grande.
O Vaadin resolve estes dois problemas de uma forma bem simples. Todo o ciclo de vida de seus componentes de tela está no servidor. E você verá como este pequeno detalhe muda muita coisa. Com este paradigma, não há impedimento em usar qualquer biblioteca e muito menos há a necessidade de se criar classes para comunicação remota. O objetivo deste artigo, contudo, não é comparar o Vaadin ao GWT, pois o estilo de desenvolvimento entre ambos é muito semelhante (veja o tópico “Quebrando Paradigmas”). Ao contrário, vamos comparar o seu estilo de desenvolvimento com o JSF. Desta forma, você terá mais subsídios para decidir entre ambos.
Quebrando Paradigmas
Diversos frameworks já tentaram trazer o modelo de programação desktop para o mundo web. No entanto, nenhum deles conseguiu de forma tão simples e elegante como o Vaadin. Você observará que em casos raríssimos será necessário se preocupar com detalhes comuns ao ambiente web, como trabalhar com Session e/ou Request. Tudo é tratado de forma transparente, usando comunicação AJAX. Também esqueça os diversos namespaces de tags e expression language, comuns em JSF. Nada disso é mais necessário.
O modelo de construção da interface também mudou completamente. Não devemos mais pensar em construir sistemas com a ideia de navegação entre páginas. O botão Voltar do navegador perde muito de sua utilidade. Devemos construir sistemas da mesma forma como construímos em Swing: um menu, uma barra de ferramentas, janelas modais que se abrem para a edição de dados e daí em diante.
Breve História
Apesar de parecer novato no cenário Java, o Vaadin é um velho conhecido e existe desde o ano 2000. Contudo, nesta época, seu nome era IT Mill Toolkit, produzido pela empresa IT Mill. Passados nove anos desde sua concepção, a ferramenta foi rebatizada e passou a se chamar Vaadin. Mas não foi apenas o nome que mudou. Ocorreram mudanças internas, sendo a troca do motor de exibição de componentes a mais importante: sai um mecanismo próprio e entra o GWT.
Arquitetura
Os dois principais blocos que formam esta ferramenta são o framework web (servidor) e o motor de exibição de componentes. A Figura 1 fornece uma visão geral desta arquitetura e foi retirada do próprio site dos criadores (ver seção Links).
Figura 1. Arquitetura do Vaadin – retirado do site oficial.
O motor de exibição (Client-Side Engine) é o responsável em realizar o trabalho necessário para apresentar visualmente os componentes e tratar a interação do usuário com a tela. A comunicação deste motor com o servidor de aplicação é realizada através da linguagem User Interface Definition Language (UIDL), que é baseada em JSON.
["button", {"id": "PID2", "immediate":true, "caption": "My Button", "focusid":1,"v":{"state":false} } ]
A partir dos dados retornados pelo servidor, o motor realiza as alterações necessárias na exibição da tela. É importante fixar que o ciclo de vida dos componentes é gerenciado no servidor e não no cliente (navegador). Isto significa que todo seu estado e comportamento estão no servidor, que envia para o cliente somente os dados que são necessários para alterar a visualização dos componentes.
Ainda temos uma entidade específica para tratar o ciclo de vida destes componentes: Terminal Adapter. Os componentes não são responsáveis em gerenciar diretamente qual tecnologia será usada para sua exibição e seu tratamento de eventos. Esta separação permite que no futuro você continue construindo sua aplicação com a API do Vaadin e possa exibi-la com diferentes tecnologias de apresentação, precisando apenas implementar seu próprio Terminal Adapter.
No lado servidor ainda temos os temas, que permitem separar do seu código o CSS e as imagens, além da própria lógica de sua aplicação. O Vaadin já provê alguns temas e que você pode estender para adicionar aspectos visuais específicos de seu projeto.
Preparação Inicial
A instalação segue o roteiro padrão da maioria dos frameworks Java. Baixe, do site oficial do projeto, a versão que consta apenas com o arquivo no formato JAR. Este arquivo deve seguir o modelo vaadin-<versao>.jar, por exemplo, vaadin-6.6.1.jar. Na sua IDE preferencial, é necessário criar um projeto nos moldes de um aplicativo para a web. Feito isto, seu projeto deve contar com uma pasta chamada WEB-INF. Agora copie o arquivo baixado para a subpasta lib.
Neste momento ainda precisamos configurar nosso arquivo web.xml, informando a ele a Servlet do Vaadin e também uma classe específica que sua aplicação precisa ter, que herda de com.vaadin.Application. Criaremos esta classe nas próximas seções. Para este primeiro momento, use as configurações conforme a Listagem 1.
Listagem 1. Descritor WEB-INF/web.xml para o servlet.
<web-app id="WebApp_ID" version="2.4">
<display-name>JavaMagazine</display-name>
<context-param>
<param-name>productionMode</param-name>
<param-value>false</param-value>
</context-param>
<servlet>
<servlet-name>JavaMagazine</servlet-name>
<servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
<init-param>
<param-name>application</param-name>
<param-value>com.javamagazine.JMApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>JavaMagazine</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Plugin para Eclipse
Para quem prefere a IDE Eclipse, sugerimos que use o plugin oficial, pois facilitará bastante algumas tarefas. Para ter um projeto pronto para deploy no Tomcat, use a opção File | New > Project > Vaadin Project, conforme a Figura 2.
Figura 2. Seleção do tipo de projeto no Eclipse.
Agora resta apenas informar alguns detalhes, como o nome do projeto, o servidor que será usado para rodar a aplicação, a versão do Java e do Servlet e, por último, a versão do Vaadin desejada. Todas estas configurações podem ser vistas na Figura 3.
Figura 3. Preenchendo as informações sobre o projeto Vaadin.
Nos passos seguintes do Wizard, você será questionado sobre o nome da sua classe de aplicação. Informe o nome que desejar e pronto!
Primeiros Passos
Caso você não tenha usado o plugin para Eclipse, precisará criar uma classe que estende de com.vaadin.Application. Chamaremos esta classe de JMApplication. Ela é o ponto de entrada de nossa aplicação. Aqui, já podemos identificar a primeira diferença com relação ao JSF, pois não precisamos de arquivos XHTML ou JSP. Ao estender a classe Application, você será forçado a implementar o método init(). Este é o lugar no qual começamos a definir a parte visual da aplicação.
Vamos avançar passo a passo e implementar primeiro uma tela simples, contendo apenas um botão que exibirá uma mensagem para o usuário. Para isto, use o código da Listagem 2 que simplesmente adiciona um botão na tela e um comportamento para que quando ocorra um clique, seja exibida uma mensagem.
Listagem 2. JMApplication.java: primeiros passos com o Vaadin.
public class JMApplication extends Application {
public void init() {
final Window mainWindow = new Window("JavaMagazine");
Button button = new Button("Clique-me");
button.addListener(new ClickListener() {
public void buttonClick(ClickEvent event) {
mainWindow.showNotification("Olá!");
}
});
mainWindow.addComponent(button);
setMainWindow(mainWindow);
}
}
Para atingir o mesmo objetivo deste código, usando JSF, você certamente criou uma página, usou as tags específicas da implementação JSF de sua escolha e precisou também de uma classe de Managed Bean para tratar a interação do usuário. Vamos evoluir este código para chegarmos à nossa aplicação.
Agenda de Contatos
Faremos uma aplicação muito simples, consistindo apenas nas operações de CRUD de uma agenda de contatos. Para isso, precisaremos de apenas uma entidade, que chamaremos de Contato. Não entraremos em detalhes sobre como esta entidade será persistida. Para simplificar, vamos guardá-la em memória, usando um java.util.Map. Nossa entidade está na Listagem 3.
Listagem 3. Classe Contato.java.
public class Contato {
private String nome;
private String email;
private String site;
private String categoria;
private String telefone;
// Métodos GET e SET omitidos.
}
Também teremos uma classe chamada ContatoNegocio para gerir os contatos. Esta classe terá os métodos comuns a todo sistema baseado em CRUD: inserir, editar, excluir, localizar uma entidade e localizar todas as entidades. Este código você encontra na Listagem 4.
Listagem 4. Classe ContatoNegocio.java.
public class ContatoNegocio {
private Map<String, Contato> contatos = new HashMap<String, Contato>();
public void inserir(Contato contato) {
contatos.put(contato.getNome(), contato);
}
public void atualizar(Contato contato) {
contatos.put(contato.getNome(), contato);
}
public void remover(Contato contato) {
contatos.remove(contato.getNome());
}
public Collection<Contato> listar() {
return contatos.values();
}
public Contato obter(String nome) {
return contatos.get(nome);
}
}
Até este ponto, temos uma aplicação estruturada conforme a Figura 4.
Figura 4. Estrutura do projeto.
Embora as camadas de persistência e de negócio não sejam o foco deste artigo, é interessante observar que a arquitetura do Vaadin lhe permite eliminar a necessidade de se ter objetos do tipo Data Transfer Objects (DTO). Não há a necessidade de se fazer transferências de dados remotas, pois no servidor você apenas preenche os componentes com dados e o framework se preocupa em transferir esses dados, via AJAX, para o navegador de forma totalmente transparente para o desenvolvedor. Toda interação entre o usuário e a tela (eventos) também é tratada no servidor, sempre através de chamadas remotas.
Para resolver este problema foi definido o padrão de projeto chamado Data Transfer Object, cujo objetivo era encapsular todos os dados necessários de um objeto de negócio em um único objeto serializável e que era transferido através de apenas uma chamada remota.
Editando Dados: Formulários
Como nossa entidade Contato possui cinco atributos, sendo eles nome, telefone, email, site e categoria, teremos também cinco campos de tela para representá-los. O Vaadin fornece uma classe muito interessante para a construção de formulários. Lembre-se do que dissemos logo no início do artigo: este framework é voltado para a criação de sistemas, portanto, nada mais sensato do que facilitar procedimentos comuns como este.
Para este trabalho, precisamos de uma instância de com.vaadin.ui.Form, definir quem será o seu “fornecedor” de campos e o objeto que será usado como fonte de dados. Funciona assim: você cria um formulário e passa como parâmetro para o método setItemDataSource() o objeto que será usado para preencher os dados do formulário. O Form vai iterar em todos os atributos deste objeto e perguntar para o nosso “fornecedor” qual campo deve ser criado para cada atributo encontrado. Veja o código que materializa o que descrevemos na Listagem 5.
Listagem 5. Classe JMApplication.java: criando formulários.
public class JMApplication extends Application implements FormFieldFactory {
private Form form;
public void init() {
final Window mainWindow = new Window("JavaMagazine");
setMainWindow(mainWindow);
form = new Form();
form.setCaption("Contato");
form.setFormFieldFactory(this);
form.setItemDataSource(new BeanItem<Contato>(new Contato()));
mainWindow.addComponent(form);
}
public Field createField(Item item, Object propertyId, Component uiContext) {
Field field = null;
if (propertyId.equals("nome")) {
field = new TextField();
field.setCaption("Nome:");
} else if (propertyId.equals("email")) {
field = new TextField();
field.setCaption("E-mail:");
} else if (propertyId.equals("site")) {
field = new TextField();
field.setCaption("Site:");
} else if (propertyId.equals("telefone")) {
field = new TextField();
field.setCaption("Telefone:");
} else if (propertyId.equals("categoria")) {
field = new ComboBox();
((ComboBox) field).addItem("Família");
((ComboBox) field).addItem("Amigos");
((ComboBox) field).addItem("Trabalho");
}
return field;
}
}
Esta é a forma mais trivial para se criar formulários. Observe que caso sua aplicação tenha muitos formulários de cadastro, a separação destes em classes específicas apresenta-se como uma boa prática. Classes abstratas de formulário que pré-estabelecem comportamentos comuns a todos os seus formulários também são interessantes e devem ser analisadas. Toda a mágica ocorre no método createField(), que vem da interface FormFieldFactory.
Este método tem o parâmetro propertyId, que informa o nome do atributo encontrado no objeto que serviu de fonte de dados. De posse da propriedade do objeto, cabe agora retornar um componente de tela que o representa, como um TextField, ComboBox ou CheckBox. Observe que um formulário pode ser construído de diversas formas, inclusive sem utilizar uma instância de Form. Neste caso, você teria que criar todos os campos e adicioná-los diretamente na janela, assim como será feito com os botões, que explicaremos nas próximas seções.
Add-ons
Ao acessar a página oficial do Vaadin, você verá uma opção chamada Add-ons. Caso surjam necessidades específicas, sempre procure por uma solução primeiro neste local. Aliás, mesmo que não tenha necessidades específicas, vale a pena navegar pelos componentes que estão publicados lá. Esta é uma área onde desenvolvedores criam e publicam seus componentes para o público. Existem muitos componentes, cada um para resolver problemas específicos, como: geração de gráficos, integração com Google Maps, Testes, Temas, etc.
Caso você tenha interesse em criar seus próprios componentes, a documentação é muito boa e ajudará bastante.
Tratando Eventos
Uma vez que o formulário está pronto, precisamos adicionar comportamentos para que o usuário possa interagir com nossas telas. Em JSF, novamente precisaremos ter uma classe de Managed Bean, uma página XHTML e uma tag, possivelmente a commandButton. Nesta tag, informamos, através do atributo action, qual método a ser chamado no Managed Bean, assim que o usuário clicá-lo.
O equivalente a isto no Vaadin está na Listagem 6. Temos apenas uma instância de com.vaadin.ui.Button e adicionamos a ela um Listener do tipo ClickListener.
Listagem 6. Classe JMApplication.java: adicionando o tratamento de eventos no método init().
public void init() {
final Window mainWindow = new Window("JavaMagazine");
setMainWindow(mainWindow);
salvar = new Button("Salvar");
salvar.addListener(new ClickListener() {
public void buttonClick(ClickEvent event) {
form.commit();
BeanItem<Contato> beanItem = (BeanItem<Contato>) form.getItemDataSource();
Contato contato = beanItem.getBean();
negocio.inserir(contato);
mainWindow.showNotification("Contato cadastrado!");
}
});
form = new Form();
form.getFooter().addComponent(salvar);
form.setCaption("Contato");
form.setFormFieldFactory(this);
form.setItemDataSource(new BeanItem<Contato>(new Contato()));
mainWindow.addComponent(form);
}
Note que quando fazemos form.commit(), estamos pedindo para que o formulário obtenha os valores digitados pelo usuário e repasse-os para o objeto que será obtido através da chamada beanItem.getBean(). Ao chamar commit(), você também estará instruindo o Form a realizar a validação dos campos, caso existam.
Exibindo Dados em Listas
Feito o cadastro de contatos, precisamos exibi-los para que o usuário possa ter as opções de visualizar, excluir e editar. Para este objetivo, vamos usar o componente com.vaadin.ui.Table. Você sempre usará uma instância desta classe para exibir dados em formato de lista (também conhecidos como grids) para os seus usuários. Assim, primeiro, criamos uma instância de Table e depois informamos quais dados deverão preenchê-lo. O código necessário para alcançar este objetivo está na Listagem 7.
Listagem 7. Classe JMApplication.java: método para preencher os dados na tabela.
public void preencherTabela() {
BeanItemContainer<Contato> container = new BeanItemContainer<Contato>(Contato.class);
container.addAll(negocio.listar());
tabela.setContainerDataSource(container);
}
O Table usa um Container como fonte de dados. Ele é apenas um conjunto de itens, enquanto itens são objetos que implementam a interface com.vaadin.data.Item. Os containers são usados por componentes como o Table e o ComboBox para exibir conjuntos de dados. Um item é simplesmente um conjunto de propriedades não-nulas, no formato chave=valor.
Para facilitar, o Vaadin já provê algumas especializações da interface Container que permite tratar objetos de negócio como um conjunto de propriedades (Item). No nosso exemplo, estamos usando a classe com.vaadin.data.BeanItemContainer, que já transforma todas as propriedades do objeto Contato no formato de chave/valor.
Um problema comum em sistemas web é a apresentação de grandes quantidades de dados. O JSF, estando neste leque, sofre também deste mal. No Vaadin, contudo, você observará que é possível fazer uma paginação totalmente transparente e de forma simples, baseada apenas na barra de rolagem. Para alcançar este objetivo, sugerimos que procure o Add-on chamado LazyQueryContainer. Existem também especializações deste container para trabalhar com JPA e Hibernate: JPAContainer e HbnContainer. Caso precise de uma paginação mais simples, lembrando o formato do JSF (com setas “Próximo”, “Anterior” e etc.) procure o Add-on chamado PagedTable.
Observe na Listagem 8, que apresenta todo o código da aplicação de exemplo, que precisamos apenas de uma classe que estende de com.vaadin.Application. Uma vez estendida, basta implementar o método init(), construindo toda a interface a partir dos componentes disponibilizados pela ferramenta, como a com.vaadin.ui.TextField. O Vaadin ainda fornece facilidades para a criação de sistemas, como a classe com.vaadin.ui.Form para a definição de formulários de forma bastante simples. A Listagem 8 também demonstra como usar a classe com.vaadin.ui.Table para exibir os dados em forma de listagem.
Note como precisamos de poucas linhas de código para ter uma aplicação mínima já executando e funcional. A Figura 5 apresenta como nossa pequena aplicação se parece. Isto é Vaadin!
Figura 5. Nossa aplicação de contatos feita em Vaadin.
Listagem 8. JMAplication.java: Código completo da aplicação.
public class JMApplication extends Application implements FormFieldFactory {
private Form form;
private Table tabela;
private Button salvar;
private Button excluir;
private ContatoNegocio negocio = new ContatoNegocio();
@Override
public void init() {
final Window mainWindow = new Window("JavaMagazine");
setMainWindow(mainWindow);
salvar = new Button("Salvar");
salvar.addListener(new ClickListener() {
@SuppressWarnings("unchecked")
@Override
public void buttonClick(ClickEvent event) {
form.commit();
BeanItem<Contato> beanItem = (BeanItem<Contato>) form.getItemDataSource();
Contato contato = beanItem.getBean();
negocio.inserir(contato);
preencherTabela();
mainWindow.showNotification("Contato cadastrado!");
limparCampos();
}
});
excluir = new Button("Excluir");
excluir.addListener(new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
negocio.remover((Contato) tabela.getValue());
preencherTabela();
}
});
form = new Form();
form.getFooter().addComponent(salvar);
form.getFooter().addComponent(excluir);
form.setCaption("Contato");
form.setFormFieldFactory(this);
limparCampos();
tabela = new Table("Contatos");
tabela.setSelectable(true);
preencherTabela();
tabela.addListener(new ItemClickListener() {
@Override
public void itemClick(ItemClickEvent event) {
if (tabela.getValue() != null) {
form.setItemDataSource(new BeanItem<Contato>((Contato) tabela.getValue()));
}
}
});
mainWindow.addComponent(tabela);
mainWindow.addComponent(form);
}
public void limparCampos() {
form.setItemDataSource(new BeanItem<Contato>(new Contato()));
}
public void preencherTabela() {
BeanItemContainer<Contato> container = new BeanItemContainer<Contato>(Contato.class);
container.addAll(negocio.listar());
tabela.setContainerDataSource(container);
}
@Override
public Field createField(Item item, Object propertyId, Component uiContext) {
Field field = null;
if (propertyId.equals("nome")) {
field = new TextField();
field.setCaption("Nome:");
((TextField) field).setNullRepresentation("");
((TextField) field).setInputPrompt("Informe o Nome");
} else if (propertyId.equals("email")) {
field = new TextField();
field.setCaption("E-mail:");
((TextField) field).setNullRepresentation("");
((TextField) field).setInputPrompt("Informe o E-mail");
} else if (propertyId.equals("site")) {
field = new TextField();
field.setCaption("Site:");
((TextField) field).setNullRepresentation("");
((TextField) field).setInputPrompt("Informe o Site");
} else if (propertyId.equals("telefone")) {
field = new TextField();
field.setCaption("Telefone:");
((TextField) field).setNullRepresentation("");
((TextField) field).setInputPrompt("Informe o Telefone");
} else if (propertyId.equals("categoria")) {
field = new ComboBox();
((ComboBox) field).addItem("Família");
((ComboBox) field).addItem("Amigos");
((ComboBox) field).addItem("Trabalho");
((ComboBox) field).setInputPrompt("Informe a Categoria");
}
return field;
}
}
Conclusão
Neste artigo, focamos em apresentar o framework Vaadin. Trata-se de uma ferramenta para a criação de interfaces para o usuário, assim como o JSF. Entretanto, o primeiro apresenta uma forma diferente de programação para alcançar o mesmo objetivo do segundo. Neste contexto, focamos em algumas diferenças básicas entre ambos e que podem ajudá-lo a decidir entre o uso de um ou de outro.
O Vaadin tem despertado um imenso interesse da comunidade Java devido a este novo modelo de programação e às facilidades que trouxe. Desenvolver uma aplicação web tornou-se mais natural e fácil. Você não precisa mais se preocupar com tantos detalhes que normalmente teria com o JSF, como tratar a sessão do usuário, ser forçado a aprender outras linguagens, como XHTML, Expression Language, etc. Com Vaadin, basta conhecer uma única linguagem: Java. Com apenas isto, você conseguirá construir interfaces elegantes e com pouco código.
http://www.vaadin.com/
Site oficial do Vaadin.
http://www.json.org/
Site oficial da especificação do
formato JSON.
http://code.google.com/webtoolkit/
Site oficial do Google Web Toolkit
http://www.springframework.org/
Site oficial do framework Spring.
http://struts.apache.org/
Site oficial do framework Struts.
http://www.hibernate.org/
Site oficial do framework Hibernate.
http://www.frameworkdemoiselle.gov.br/
Site oficial do framework
Demoiselle. [ /nota]
Confira outros conteúdos:
Introdução ao JDBC
Novidades do Java
Teste unitário com JUnit
Promoção de Natal
Oferta exclusiva de Natal!
Pagamento anual
12x no cartão
De: R$ 69,00
Por: R$ 59,90
Total: R$ 718,80
Garanta o desconto
- Formação FullStack Completa
- Carreira Front-end I e II, Algoritmo e Javascript, Back-end e Mobile
- +10.000 exercícios gamificados
- +50 projetos reais
- Comunidade com + 200 mil alunos
- Estude pelo Aplicativo (Android e iOS)
- Suporte online
- 12 meses de acesso
Pagamento recorrente
Cobrado mensalmente no cartão
De: R$ 79,00
Por: R$ 59,90 /mês
Total: R$ 718,80
Garanta o desconto
- Formação FullStack Completa
- Carreira Front-end I e II, Algoritmo e Javascript, Back-end e Mobile
- +10.000 exercícios gamificados
- +50 projetos reais
- Comunidade com + 200 mil alunos
- Estude pelo Aplicativo (Android e iOS)
- Suporte online
- Fidelidade de 12 meses
- Não compromete o limite do seu cartão
<Perguntas frequentes>
Nossos casos de sucesso
Eu sabia pouquíssimas coisas de programação antes de começar a estudar com vocês, fui me especializando em várias áreas e ferramentas que tinham na plataforma, e com essa bagagem consegui um estágio logo no início do meu primeiro período na faculdade.
Estudo aqui na Dev desde o meio do ano passado!
Nesse período a Dev me ajudou a crescer muito aqui no trampo.
Fui o primeiro desenvolvedor contratado pela minha
empresa. Hoje eu lidero um time de desenvolvimento!
Minha meta é continuar estudando e praticando para ser um
Full-Stack Dev!
Economizei 3 meses para assinar a plataforma e sendo sincero valeu muito a pena, pois a plataforma é bem intuitiva e muuuuito didática a metodologia de ensino. Sinto que estou EVOLUINDO a cada dia. Muito obrigado!
Nossa! Plataforma maravilhosa. To amando o curso de desenvolvimento front-end, tinha coisas que eu ainda não tinha visto. A didática é do jeito que qualquer pessoa consegue aprender. Sério, to apaixonado, adorando demais.
Adquiri o curso de vocês e logo percebi que são os melhores do Brasil. É um passo a passo incrível. Só não aprende quem não quer. Foi o melhor investimento da minha vida!
Foi um dos melhores investimentos que já fiz na vida e tenho aprendido bastante com a plataforma. Vocês estão fazendo parte da minha jornada nesse mundo da programação, irei assinar meu contrato como programador graças a plataforma.
Wanderson Oliveira
Comprei a assinatura tem uma semana, aprendi mais do que 4 meses estudando outros cursos. Exercícios práticos que não tem como não aprender, estão de parabéns!
Obrigado DevMedia, nunca presenciei uma plataforma de ensino tão presente na vida acadêmica de seus alunos, parabéns!
Eduardo Dorneles
Aprendi React na plataforma da DevMedia há cerca de 1 ano e meio... Hoje estou há 1 ano empregado trabalhando 100% com React!
Adauto Junior
Já fiz alguns cursos na área e nenhum é tão bom quanto o de vocês. Estou aprendendo muito, muito obrigado por existirem. Estão de parabéns... Espero um dia conseguir um emprego na área.
Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.