Prof. Rodrigo Noll - IFRS Canoas
JEE (Java Enterprise Edition) é um conjunto de padrões da indústria para desenvolvimento Java para Web que incluem diversas especificações.
Aqui trabalharemos com:
Baixe o servidor de aplicação Wildfly 11. Descompacte o arquivo baixado.
No Eclipse, encontre a visão Servers, onde estão todos os servidores de aplicação.
Na visão Servers, clique onde indicado...
... e selecione o WildFly 11.
Prossiga...
... e procure a pasta que descompactou o WildFly.
Finalize a criação...
Para executar o servidor, clique aqui.
A console deve exibir:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="webapp">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.jdbc.batch_size" value="0"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_sql_comments" value="false" />
<property name="hibernate.jdbc.wrap_result_sets" value="false" />
<property name="hibernate.hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
Dependências (JPA)
Dependências (JSF)
<build>
<directory>${project.basedir}/target</directory>
<sourceDirectory>/src/main/java</sourceDirectory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<resources>
<resource>
<directory>/src/main/resources</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<scriptSourceDirectory>src/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
Execute Maven > Update Project e Run As > Maven Install
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.edu.ifrs.canoas.jee</groupId>
<artifactId>webapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>5.0.1.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
<!-- CDI -->
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-junit4</artifactId>
<version>1.1.0.Final</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<!-- JSF -->
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.14</version>
</dependency>
<!-- PrimeFaces -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.1</version>
</dependency>
</dependencies>
<build>
<directory>${project.basedir}/target</directory>
<sourceDirectory>/src/main/java</sourceDirectory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<resources>
<resource>
<directory>/src/main/resources</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<scriptSourceDirectory>src/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
Após atualizar o projeto com o Maven, deve-se ficar como a imagem ao lado.
O projeto concluído pode ser encontrado aqui.
Clone o seguinte projeto https://github.com/aula-java/jee
Execute:
Acesse: http://localhost:8080/webapp
Name: Console
Project: jee
Main Class: org.h2.tools.Console
Acesso ao banco de dados: http://localhost:8082/
JDBC URL: jdbc:h2:file:~/webapp-db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE
User Name: sa
Password: sa
Esta conexão está configurada na aplicação aqui: /src/main/webapp/WEB-INF/webapp-ds.xml
package org.javaee7.servlet.web.fragment;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Arun Gupta
*/
@WebServlet(urlPatterns = "/TestServlet")
public class TestServlet extends HttpServlet {
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Web Fragment with output from Servlet Filter</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Web Fragment with output from Servlet Filter</h1>");
out.println("<br><br>Check server log for output from LoggingFilter");
out.println("</body>");
out.println("</html>");
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
Usando Servlets, tínhamos um unidade centralizadora com muitas responsabilidades, o que tornava muito complicado o desenvolvimento de aplicações de pequeno/médio porte, imagine de maior porte.
Levante a aplicação no Eclipse e acesse: http://localhost:8080/webapp/public/usuario.xhtml
Código: HTML, Managed Bean
A aplicação Java está organizada assim:
Tecnologia que permite criar aplicações Java para Web utilizando componentes visuais
pré-prontos, de forma que o desenvolvedor não se preocupe com Javascript e HTML.
Basta adicionar os componentes (calendários, tabelas, formulários) e eles
serão renderizados e exibidos em formato HTML
JSF é um framework Java MVC.
MVC (Model-View-Controller) é um dos padrões arquiteturais mais conhecidos que visa simplificar e distribuir as responsabilidades destes Servlets.
1. <html xmlns="http://www.w3.org/1999/xhtml"
2. xmlns:h="http://java.sun.com/jsf/html"
3. xmlns:f="http://java.sun.com/jsf/core"
4. xmlns:p="http://primefaces.org/ui">
As bibliotecas de tags que representam os componentes do JSF:
Comandos
Entradas
Saídas
Comandos
Entradas
Saídas
1. Restore View
2. Apply Request Values
3. Process Validation
@Entity
public class Usuario {
...
@NotNull(message="Nome nao pode ser vazio!")
private String nome;
...
}
<div class="form-group"<
<p:outputLabel for="nome" value="#{messages['user.name']}" />
<p:inputText id="nome" styleClass="form-control"
value="#{gerenciarUsuarioMB.usuario.nome}" required="true" />
<p:message for="nome" />
</div>
4. Update Model Values
5. Invoke Application
@Named
@RequestScoped
public class GerenciarUsuarioMB {
...
public String salva() {
gerenciarUsuarioService.salvaUsario(usuario);
this.init();
return "/public/usuario.jsf";
}
public void exclui() {
gerenciarUsuarioService.exclui(usuario);
}
...
}
6. Render Response
Analise o formulário no código
<h:form id="mainForm" >
<h:inputHidden value="#{gerenciarUsuarioMB.usuario.id}" id="hiddenId" />
<div class="form-group">
<p:outputLabel for="nome" value="#{messages['user.name']}" />
<p:inputText id="nome" styleClass="form-control"
value="#{gerenciarUsuarioMB.usuario.nome}" required="true" />
</div>
<div class="form-group">
<p:outputLabel for="sobrenome"
value="#{messages['user.lastname']}" />
<p:inputText id="sobrenome" styleClass="form-control"
value="#{gerenciarUsuarioMB.usuario.sobrenome}" required="true" />
</div>
<div class="form-group">
<p:outputLabel for="email" value="#{messages['user.email']}" />
<p:inputText id="email" styleClass="form-control"
value="#{gerenciarUsuarioMB.usuario.email}" required="true" />
</div>
<div class="form-group">
<p:outputLabel for="senha" value="#{messages['user.password']}" />
<p:password id="senha" styleClass="form-control"
value="#{gerenciarUsuarioMB.usuario.senha}" required="true">
</p:password>
</div>
<p:commandButton value="#{messages['clean']}"
action="#{gerenciarUsuarioMB.limpa}" styleClass="btn btn-default"
ajax="false" style="border: none;" immediate="true" />
<h:commandButton value="Salvar" action="#{gerenciarUsuarioMB.salva}"
styleClass="btn btn-primary pull-right">
</h:commandButton>
<form>
Analise a tabela no código
<h:form id="mainForm" >
<div class="box-footer">
<h:panelGroup rendered="#{ gerenciarUsuarioMB.usuarios}">
<em><p:output value="#{messages['users.empty']}" />.</em>
</h:panelGroup>
<p:dataTable var=" value="#{gerenciarUsuarioMB.usuarios}" id="tb-usuarios"
rendered="#{not empty gerenciarUsuarioMB.usuarios}">
<p:column headerText="Nome">
<h:outputText value="#{_usr.nome}" />
</p:column>
<p:column headerText="Sobrenome">
<h:outputText value="#{_usr.sobrenome}" />
</p:column>
<p:column headerText="Email">
<h:outputText value="#{_usr.email}" />
</p:colum
<p:column headerText="Ações">
<!-- EDITA -->
<h:commandButton value="#{messages['edi immediate="true" styleClass="btn btn-default"
action="#{gerenciarUsuarioMB.edita(_u update="form-usuario" >
<p:ajax update=":mainForm:user-content" />
</h:commandButton>
<!-- EXCLUI -->
<h:commandLink value="#{messages['delet immediate="true" styleClass="btn btn-default"
action="#{gerenciarUsuarioMB.exclui}" ajax=" update="tb-usuarios">
<f:setPropertyActionListener value="#{_usr}"
target="#{gerenciarUsuarioMB.usuario}" />
</h:commandLink>
</p:column>
</p:dataTable>
</div>
<form>
Os campos do formulário provém de simples classes Java (geralmente entidades, Beans, POJOs, DTOs) como a Usuario.java
@Entity
public class Usuario extends BaseEntity<Long> implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private ID id;
@NotNull
private String nome;
private String sobrenome;
private String telefone;
//Getters & Setters
}
A compreensão do tempo de vida de cada escopo disponível é um requisito de grande valor para o desenvolvedor de aplicações JSF. Uma escolha equivocada pode sobrecarregar o servidor, degradando o desempenho de toda a sua aplicação
A camada de visão recebe os dados de Usuario.java, por exemplo, a partir de ManagedBeans, como o GerenciarUsuarioMB.java
@Named
@RequestScoped
public class GerenciarUsuarioMB {
@Inject
private GerenciarUsuarioService gerenciarUsuarioService;
@Inject
private Usuario usuario;
private List<Usuario> usuarios;
public String salva() {...}
public void exclui() {...}
public void edita(Usuario u) {...}
public Usuario getUsuario() {...}
public void setUsuario(Usuario usuario) {...}
public List<Usuario> getUsuarios() {...}
public void setUsuarios(List<Usuario> usuarios) {...}
}
Obs.: para chamar os métodos usamos a sintaxe #{managedbean.método}
<h:commandButton value="Salvar" action="#{gerenciarUsuarioMB.salva}"/>
Para utilizar bibliotecas de componentes em sua camada de visão, adicione a dependência no pom.xml e taglib no header HTML de:
Veja o showcase e a integração dos componentes com o ManagedBean.
<p:outputLabel value="#{messages['menu.title']}" />
@Named
@RequestScoped
public class GerenciarUsuarioMB {
@Inject
private GerenciarUsuarioService gerenciarUsuarioService;
@Inject
private Usuario usuario;
}
@Entity
public class Usuario {
@NotNull(message="{validacao.nulo}") //Apresenta a mensagem de texto equivalente do arquivo de ValidationMessages.properties
@Email(message="Email inválido!") //Apresenta a mensagem de texto
private String email;
...
}
Modifique o THE CHALLENGE adicionando: