Java Enterprise Edition (JEE)

LPOO 2 - Java


Prof. Rodrigo Noll - IFRS Canoas



Versão para impressão

Introdução

Introdução ao JEE

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:

Configurando o ambiente

Configurando o ambiente

Baixe o servidor de aplicação Wildfly 11. Descompacte o arquivo baixado.

Configurando o ambiente

Na visão Servers, clique onde indicado...

Configurando o ambiente

Prossiga...

Configurando o ambiente

Finalize a criação...

Configurando o ambiente

A console deve exibir:

Criando um projeto

Criando um projeto

Criando um projeto

Criando um projeto

Criando um projeto

Configurando JPA

  • Substitua o conteúdo do arquivo persistence.xml gerado pelo descrito abaixo

<?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>

                

Convertendo para Maven

Convertendo para Maven

Convertendo para Maven

  • Adicione ao pom.xml após das 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>
                

Execute Maven > Update Project e Run As > Maven Install

Convertendo para Maven

  • O resultado do pom.xml deve ser:

<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>

                

Organizando as pastas

Organizando as pastas

Organizando as pastas

Organizando as pastas

Executando o projeto

Executando o projeto

Clone o seguinte projeto https://github.com/aula-java/jee

Execute:

  1. Maven > Select Maven Profiles, selecione arq-wildfly-remote e depois Activate
  2. Maven > Update Project

Executando o projeto

Executando o projeto

Acessando o Banco de Dados

Acessando o Banco de Dados

Name: Console

Project: jee

Main Class: org.h2.tools.Console

Acessando o Banco de Dados

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

THE CHALLENGE

The Challenge

  1. Faça a senha ter tamanho entre 6 e 8 caracteres e aceitar apenas letras e números
  2. Adicione no formulário e na tabela o campo endereço
    • Endereco deve ter logradouro, número, cep, cidade e estado e ser mapeado em outra entidade.
    • Cada Usuário tem apenas 1 endereço

JEE: Java Enterprise Edition

Java Enterprise Edition

  • Aplicações Web são por natureza distribuídas, de grande escala, com muitas camadas, confiáveis e seguras.
  • As primeiras aplicações Web em Java eram organizadas usando Servlets.
    • Servlets se baseiam em requisições e respostas HTTP, geralmente enviando HTML para o navegador do usuário.

Java Enterprise Edition

Analise este exemplo de Servlet. Como, por exemplo, você trabalharia com CSS ou bibliotecas JS?

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>
}
                        

Java Enterprise Edition

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.

Modelo de Aplicação JEE

  • Para prover uma solução de aplicações coorporativas (grandes, multiplas camadas, escalável, confiável e segura), JEE propõe um modelo de aplicação

Modelo de Aplicação JEE

  • O modelo anterior pode ser implantado em um Servidor JEE com as seguintes tecnologias organizados nas camadas Cliente, Web e Negócio.
  • Para as tecnologias que ficam no servidor JEE, especificamente na camada Web, iremos inicialmente focar no framework JSF, responsável pelas requisições e respostas da camada Web (navegadores)

Exemplo de Aplicação JEE (1/3)

Levante a aplicação no Eclipse e acesse: http://localhost:8080/webapp/public/usuario.xhtml


Código: HTML, Managed Bean

Exemplo de Aplicação JEE (2/3)

A aplicação Java está organizada assim:

Exemplo de Aplicação JEE (3/3)

Java Server Faces

O que é JSF?

O que é JSF?

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.

Características do JSF

  • Orientado a componentes
    • Não é baseado em request/response
    • Integra uma página a um componente (Backing Bean/Managed Bean)
    • É baseado em componentes(MB), eventos e beans (POJO)
  • Especificação do Padrão JEE
    • Implementado por vários fabricantes (ex. Mojarra, Apache MyFaces)
    • Todo servidor de aplicações Java tem que vir com uma implementação da especificação

Vantagens do JSF

  • Obriga um MVC limpo e organizado
  • Conjunto de componentes gráficos padrão e integrados a dados do servidor (primefaces, richfaces, etc.)
  • Validadores e conversores
  • Ajax, internacionalização e acessibilidade
  • Integração com EJBs
  • Injeção de Dependência (CDI): inversão de controle no qual o container mantém o ciclo de vida dos objetos Java marcados com anotações

Arquitetura JSF (1/2)

Arquitetura JSF (2/2)

Componentes JSF(1/2)


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:

    1. Contém os componentes necessários para montarmos a view gerando o HTML adequado
    2. Indica que estamos habilitando através do prefixo h as TAGs do JSF que renderizam HTML
    3. Indica a tag core e possui diversos componentes não visuais, como tratadores de eventos ou validadores
    4. Se refere aos componentes do Primefaces

Componentes JSF(2/2)

    Comandos

    • <h:commandButton>
    • <h:commandLink>

    Entradas

    • <h:inputHidden>
    • <h:inputSecret>
    • <h:inputText>
    • <h:inputTextarea>

    Saídas

    • <h:outputLabel>
    • <h:outputLink>
    • <h:outputText>

Ciclo de Vida JSF

  • O JSF cria o HTML lendo o arquivo XHTML
  • Com base nesse arquivo, ele monta a árvore de componentes (UIViewRoot)
  • Após montar a árvore, ela é passada ao renderizador
  • O JSF guarda na memória a árvore usada para gerar a tela através das requisições – JSF é considerado um framework statefull

Ciclo de Vida JSF

Ciclo de Vida JSF

Ciclo de Vida JSF

Ciclo de Vida JSF

Ciclo de Vida JSF

Ciclo de Vida JSF

Resumo do Ciclo de Vida JSF

Trabalhando com JSF

Formulários

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>
                

Listas

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>
                

Beans

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
}
                

Managed Beans

  • Possuem atributos para representar os componentes da view
  • Objetos UIInput, UIOutput e UICommand
  • Ligados aos componentes da view através do atributo biding das tags correspondentes
  • Escopos
    • @ApplicationScoped: Escopo de aplicação, permanece existente entre todas as interações de todos os usuários, ou seja possui vida útil durante todo o tempo em que a aplicação estiver funcionando (a partir do momento que o servidor iniciar até que a aplicação seja interrompida).
    • @SessionScoped: Escopo de sessão, permanece ativo em várias requisições HTTP enquanto durar a sessão do usuário. Terá seu ciclo de vida iniciado no momento em que o cliente o requisita e finaliza quando a sessão do cliente termina

Managed Beans

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}"/>
                

Biblioteca de Componentes

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.

CDI e Bean Validation

CDI: Injeção de Dependências

  • Fornece uma unificada injeção de dependência e ciclo de vida contextual para JEE
  • Um mecanismo para desacoplar componentes da aplicação a partir de uma API
  • Permite injetar bean nas views (messages.properties):
  • 
    <p:outputLabel value="#{messages['menu.title']}" />
                            
  • Torna muito mais fácil a integração aplicações com JSF e EJB:
  • 
    @Named
    @RequestScoped
    public class GerenciarUsuarioMB {
        @Inject
        private GerenciarUsuarioService gerenciarUsuarioService;
        @Inject
        private Usuario usuario;
    }
    
                    

Bean Validation

  • Promover a melhor separação de camadas (regras de dados permanecem nos dados e regras de negócio na camada de negócio/serviço)
  • Utilização de anotações (Constraints/Regras) para realização de validações
  • Baseado no framework Hibernate Validator (maduro)
  • Acesse aqui as restrições do Bean Validation.
  • Exemplo de uso:
  • 
    @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;
        ...
    }
                    

Exercício

Modifique o THE CHALLENGE adicionando:

  1. No menu de navegação a esquerda (MAIN NAVIGATION), adicione dois links para gerenciar (1) Usuários e (2) Automóveis
  2. Faça o CRUD para o gerenciamento de automóveis (marca, modelo, ano, placa, RENAVAN)
  3. No CRUD de usuário, faça com que seja possível vincular o usuário selecionado a um automóvel previamente cadastrado

Java Enterprise Edition (JEE)

Exercício


LPOO 2 - Java