Tutorial Hibernate 3 with JPA 2

Hello, how are you?

Today we will study about an important framework to persist your model: “Hibernate”.
To do the Hibernate more powerful in this “HelloWorld” we will be integrating it with JPA.
When we mix this two APIs we do not have the need of mapping each model class in some xml file, but the EntityManager will handle it.

To start our work today we need to do some downloads.

Our first download will be the MySQL.
The download link is: http://dev.mysql.com/downloads/mysql/.

MySQL Site Image

To install the MySQL software you just have to apply the Microsoft installation pattern: “Next, Next, Finish”. Be aware about the password that you will type to your database. This password is needed to our XML configuration file.

Let us create a schema to the database by opening the “MySQL Command Line Client” that will be displaying in your Windows/Linux menu.

Hibernate JPA

Type the user/password that you typed in the MySQL installation. Type the command line below:

create database hello;

Push “Enter” and it is done.

Hibernate JPA

Our next download will be the Hibernate 3 library (click here if you want to find another versions to download).

Now we need to download the MySQL database connector (in here you can find other host to download).

The connector is the responsible to do the “talk” between the Hibernate and the database. We will use the MySQL database, but if you want to do with another database, you just have to do the download of the desired connector to your chosen database.

Hibernate API: Inside the file you have downloaded from the website you will find all the libraries that we need. Some of the libraries are: “Hibernate 3”, “JPA 2” and some others are required, soon you will see the libraries required list.
First create a java project of the type “Java Project”, then create a folder named “lib”to put in our downloaded libraries. To our application work correctly we will need the files listed bellow:

  • hibernate-distribution-3.6.0.Final/hibernate3.jar
  • hibernate-distribution-3.6.0.Final/lib/jpa/hibernate-jpa-2.0-api-1.0.0.Final.jar
  • hibernate-distribution-3.6.0.Final/lib/required/*” (All files are required)

Be aware of: The files that you will find inside the folder “required” are obligatory to the Hibernate 3. Copy all files listed above (and do not forget the files in the required folder) to the lib folder.

MySQL connector: As we did with Hibernate 3 library files we will do the same with the connector file. Inside the zip file, that you downloaded, there is a library named “mysql-connector-java-5.1.14-bin.jar”, copy this file into the lib folder.

In the end we will have our lib folder like the image bellow:

Hibernate JPA

We need to create a configuration file named “persistence.xml”. This file is mandatory for Hibernate configuration and it must be inside the folder “src/META-INF”. Take a look at the file dir and the folder structure (if you are reading this tutorial and you have searched other sources but your code still not working, your problem might be the xml headers. Some tutorials have an invalid “header” typed):

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0"
    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">
    
    <persistence-unit name="Hello" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        
        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/Hello"/>
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="root" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

I will talk about each line of above code:

  • <persistence-unit name=”Hello” transaction-type=”RESOURCE_LOCAL”>” Two important configurations are present in this line: “unit name” defines to the application the name of the persistence configuration that we will use. In the same file, we are able to have more than one unit name. “transaction-type” sets our transaction type, in our case local. If we were doing a web application we would not need to control the transaction, the container (JBoss, Glassfish …) would do this job for us.
  • <provider>org.hibernate.ejb.HibernatePersistence</provider>” indicates which provider will “work” in our application. In our case we will use Hibernate.
  • “hibernate.show_sql” enables the SQL log to be shown in the console.
  • “javax.persistence.jdbc.driver” which “agent” will handle the database connection, we will use MySQL.
  • “javax.persistence.jdbc.url” our database url with the created schema.
  • “javax.persistence.jdbc.user” and “javax.persistence.jdbc.password” The database user and password. This attributes were defined when you installed the MySQL database. When I did the installation I typed the values “root”/“root”.
  • “hibernate.dialect” Dialect that the Hibernate will use. We will study more about this subject in a future post, by example, how to generate a database script.
  • “hibernate.hbm2ddl.auto” when this option has the true value, the Hibernate will update your tables when needed. If the table do not exist the Hibernate will create it (“CREATE TABLE…”), if you added a column (“ALTER TABLE…”). Just because this is a tutorial we will leave this option enabled, but it is not a good idea leave it activated in a real application. Again I say that it is not a good idea leave this option enabled for a real application. Turn it on only for local test or study.

One last step before we start to write our code. Add the libraries that we downloaded to the project build path. We need to do it so our application can use the libraries benefits.

Right mouse button click on the project: “Properties > Java Build Path”.

Click on Libraries tab and then “Add Jars”.

To finish this configuration, select all files that are inside the lib folder and click the button “Ok”.

Let us create the class “User” in the package “com”. With this model class we will do the CRUD (Create, Read, Update and Delete) operations.

package com;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    
    @Column
    private String name;
    
    @Column
    private String password;
    
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof User){
            User user = (User) obj;
            return user.getId() == this.getId();
        }
        
        return false;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Some details about the above code:

  • “@Entity” will indicate to our Provider that this class should be persisted in our database.
  • “@Table” defines the table name that will be written in the database. If you do not define an attribute value to the field “name”, the default will be the same name of the class.
  • “@Id” defines the Id of the class.
  • “GeneratedValue” It is a key that defines that our Id will have a value created automatically using some pattern. In our sample code above we use the pattern AUTO.
  • “@Column” defines the attribute as a database table column. We could also define a name to the database table column by the attribute “name”, just like we did to the “@Table” annotation.

Now we need a class that will create the connection with the database and manager our model class User. Let us create a class named “Main” in the package “com”.

package com;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
        EntityManager em = emf.createEntityManager();

        try {
            em.getTransaction().begin();
            
            User user = new User();
            user.setName("abc123");
            user.setPassword("abc123");
            
            em.persist(user);
            
            em.getTransaction().commit();
        }
        catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
        finally{
            emf.close();
        }
        
        System.out.println("It is over");
    }
}

Some details about the code above:

  • Notice that our application is a local application; we will need to control the connection manually. That is the reason of the method “beginTransaction”; we need also commit the changes and close the connection.
  • To persist our object User we use the method “em.persist(user);”

Just run the code and you will see a message indication success. To confirm just run a query into the database just like the images below:

Hibernate JPA

Hibernate JPA

Notice that, in the image above, the Hibernate created the insert sql script for us.

One of the greatest advantages of the Hibernate is that when you read an object from your database, it gives to you an object instead line strings. We use the method “find” to locate a database record by its Id:

package com;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
        EntityManager em = emf.createEntityManager();

        try {
            em.getTransaction().begin();
            
            User user = em.find(User.class, 1);
            
            System.out.println(user.getName());
            
            em.getTransaction().commit();
        }
        catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
        finally{
            emf.close();
        }
        
        System.out.println("It is over");
    }
}

What do we must to do to update our user data? Let us change the user name, take a look how simple it is:

package com;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
        EntityManager em = emf.createEntityManager();

        try {
            em.getTransaction().begin();
            
            User user = em.find(User.class, 1);
            
            user.setName("123abc");            
            
            em.getTransaction().commit();
        }
        catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
        finally{
            emf.close();
        }
        
        System.out.println("It is over");
    }
}

Hibernate JPA

To remove a record from the database, you just need to use the implemented method of the entity manager named “remove”. In our case you will invoke the method “find” again and then “em.remove (user);

I know this was a long post, but a hope it might help you.

In future posts we will be able to see about relationships and how to do the Ant + Hibernate generate database scripts.

If you have any doubt or any question, just post it.
See you later. o_

Tutorial Hibernate 3 com JPA 2

Olá pessoal, tudo bem?

Hoje vamos falar sobre um importante framework para tratar os dados do seu modelo: “Hibernate”.
Para fazer o Hibernate mais poderoso nesse “HelloWord” faremos com que ele trabalhe em conjunto com a API do JPA.
Trabalhando junto com o JPA não precisaremos mapear cada classe que for criada, mas deixaremos que o “EntityManager” tome conta do assunto.

Para começar precisamos fazer alguns downloads.

O primeiro será do MySQL.
O link para download é: http://dev.mysql.com/downloads/mysql/.

Imagem do Site MySQL

Basta instalar com padrão Microsoft: “Next, Next, Finish”. Apenas fique atento para a senha que você irá colocar no banco de dados. Ela será utilizada em nosso arquivo XML de configuração.

Precisamos criar um schema e para isso vamos abrir o “MySQL Command Line Client” que vai aparecer no seu menu do MySQL instalado.

Hibernate JPA

Digite o usuário e a senha colocados na hora da instalação. Digite o comando abaixo:

create database hello;

Aperte “Enter” e pronto.

Hibernate JPA

O próximo download será das bibliotecas do Hibernate 3 (aqui você poderá encontrar outras versões).

Vamos fazer o download do conector do MySQL (aqui você poderá escolher outro servidor para download).

O conector é o responsável por “ligar/intermediar” o Hibernate ao banco de dados. Estaremos utilizando o MySQL, mas caso queira fazer o teste com outro banco de dados basta fazer o download o conector do banco desejado.

API do Hibernate: Dentro do arquivo baixado encontraremos as bibliotecas do Hibernate 3, JPA 2 e algumas outras que são obrigatórias para o funcionamento do framework.
Após criar um projeto java do tipo “Java Project”, vamos criar criar um folder chamado “lib” para colocar as bibliotecas necessárias para funcionamento de nossa aplicação.

Iremos utilizar:

  • hibernate-distribution-3.6.0.Final/hibernate3.jar
  • hibernate-distribution-3.6.0.Final/lib/jpa/hibernate-jpa-2.0-api-1.0.0.Final.jar
  • hibernate-distribution-3.6.0.Final/lib/required/* ” (Todos os arquivos)

Atenção: Os arquivos da pasta “required” são obrigatórios. Copie todos os arquivos (inclusive os arquivos da pasta "required") listados acima para a pasta lib.

Conector MySQL: Assim como fizemos com o as bibliotecas do Hibernate faremos com o conector. Dentro do arquivo ZIP, que você baixou, existe uma biblioteca chamada “mysql-connector-java-5.1.14-bin.jar” basta copiá-la para dentro da pasta lib.

Ao final teremos os seguintes arquivos dentro da pasta lib:

Hibernate JPA

Precisamos criar um arquivo de configuração chamado “persistence.xml”. Esse arquivo é padrão do Hibernate e a pasta onde o arquivo deve estar obrigatoriamente é “src/META-INF”. Veja como nosso arquivo ficará (se você está lendo este tutorial mas já procurou em outras fontes e seu código não funciona, pode ser a declaração do “persistence.xml”. Alguns tutoriais apresentam um “header” inválido para ele):

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0"
    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">
    
    <persistence-unit name="Hello" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        
        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/Hello"/>
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="root" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

Vou explicar qual a utilidade de cada linha do arquivo descrito acima:

  • <persistence-unit name=”Hello” transaction-type=”RESOURCE_LOCAL”>” Duas configurações importantes são definidas aqui. “unit name” define para a aplicação a configuração que será utilizada. No mesmo arquivo podemos ter vários tipos diferentes. “transaction-type” define como será nosso tipo de transação, em nosso caso “local”. Caso fosse uma aplicação web não iríamos precisar controlar a transação, o containner (JBoss, GlassFish, …) faria esse trabalho.
  • <provider>org.hibernate.ejb.HibernatePersistence</provider>” indica qual será o provider de nossa aplicação. Em nosso caso, o Hibernate.
  • hibernate.show_sql” habilita a exibição do SQL gerado no console.
  • javax.persistence.jdbc.driver” qual será o agente de conexão com o banco de dados que estaremos utilizando, vamos utilizar o MySQL.
  • javax.persistence.jdbc.url” a URL de nosso banco de dados juntamente com o schema de nosso banco de dados.
  • javax.persistence.jdbc.user” e “javax.persistence.jdbc.password” usuário e senha do banco de dados. Esses atributos foram definidos na instalação do MySQL. Utilizei os valores “root” e “root”.
  • hibernate.dialect” o dialeto que o Hibernate irá utilizar. Vamos discutir mais sobre essa opção em posts futuros, por exemplo, como gerar script do banco de dados de modo automático.
  • hibernate.hbm2ddl.auto” com essa opção ativada, o Hibernate atualizará suas tabelas quando necessário. Por exemplo, se a tabela não existir ela irá criar (“CREATE TABLE…”), se você adicionou uma coluna (“ALTER TABLE…”). Para testes vou deixar ativo, mas não aconselho a deixar essa opção ativada quando se trata de uma aplicação real. Não é uma boa escolha deixar essa alteração acontecer de modo automático em uma aplicação real. Deixe-a ativa apenas para teste local ou estudo.

Falta um último passo antes de começar a codificar. Adicionar as bibliotecas que baixamos ao build path do projeto. Precisamos fazer isso para que nossa aplicação as reconheça.

Botão direito do mouse em cima do projeto > “Properties > Java Build Path”.

Clique na aba Libraries e depois em “Add JARs”.

E por último, selecione os arquivos que estão dentro da pasta lib e click em Ok.

Finalmente vamos criar nossa classe “User” no package “com”. Com essa classe iremos realizar um CRUD (Create, Read, Update, Delete) básico.

package com;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    
    @Column
    private String name;
    
    @Column
    private String password;
    
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof User){
            User user = (User) obj;
            return user.getId() == this.getId();
        }
        
        return false;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Alguns detalhes sobre o código acima:

  • “@Entity” indica para nosso Provider que essa classe deve ser persistida em nosso banco de dados.
  • “@Table” define o nome da tabela a ser utilizada no banco de dados. Caso não tenha definida nenhum nome utilizando a chave “name”, o padrão será o nome exato da classe.
  • “@Id” mostra qual o nome do id de nossa classe.
  • “GeneratedValue” é a chave utilizada para que o valor do nosso id seja gerada por algum tipo de padrão. Em nosso exemplo estamos utilizando o tipo “AUTO”.
  • “@Column” define o atributo como uma coluna. Poderíamos também definir um nome pelo atributo “name”, como foi feito com a chave da tabela (“@Table”).

Por último precisamos de uma classe que irá criar a conexão com o banco de dados e gerenciar nossa classe de modelo User. Vamos criar uma classe chamada Main no package “com”.

package com;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
        EntityManager em = emf.createEntityManager();

        try {
            em.getTransaction().begin();
            
            User user = new User();
            user.setName("abc123");
            user.setPassword("abc123");
            
            em.persist(user);
            
            em.getTransaction().commit();
        }
        catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
        finally{
            emf.close();
        }
        
        System.out.println("It is over");
    }
}

Alguns detalhes sobre o código acima:

  • Como estamos utilizando uma aplicação local precisamos controlar a conexão de modo manual. Por isso utilizamos o comando para abrir transação (“begin”), realizar commit e fechar a conexão (“close”).
  • Para informar que nosso objeto precisa ser salvo, utilizamos o comando “em.persist(user);”.

Basta executar nosso código e ver que a mensagem de execução com sucesso. Para confirmar, basta executar uma consulta em nosso banco de dados conforme imagens abaixo:

Hibernate JPA

Hibernate JPA

Note que, na imagem do console acima, o próprio Hibernate gerou o comando insert.

A grande vantagem do Hibernate é que ele traz um registro do banco de dados já como uma classe. E para fazer isso basta executar o código abaixo. Utilizamos o método “find” para localizar um registro do banco de dados pelo seu Id:

package com;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
        EntityManager em = emf.createEntityManager();

        try {
            em.getTransaction().begin();
            
            User user = em.find(User.class, 1);
            
            System.out.println(user.getName());
            
            em.getTransaction().commit();
        }
        catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
        finally{
            emf.close();
        }
        
        System.out.println("It is over");
    }
}

E para realizar uma alteração? Vamos alterar o nome do nosso usuário, veja como é simples.

package com;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
        EntityManager em = emf.createEntityManager();

        try {
            em.getTransaction().begin();
            
            User user = em.find(User.class, 1);
            
            user.setName("123abc");            
            
            em.getTransaction().commit();
        }
        catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
        finally{
            emf.close();
        }
        
        System.out.println("It is over");
    }
}

Hibernate JPA

E para remover basta utilizar o comando remove implementado pela classe EntityManager. Basta realizar novamente o comando find e depois “em.remove(user)“.

Bem pessoal, o post foi longo, mas espero que possa ser útil.

Em um próximo post poderemos ver questões de relacionamentos e como fazer com que o Hibernate + Ant gere o script do banco de dados.

Qualquer dúvida ou comentário basta postar.
Até mais! o_

Review: João Luiz Silva Silvestre

Design Pattern – Strategy

Hello, how are you?

I will post here some design patterns of the study I am doing about this subject. The base book to this study will be Head First – Design Patterns. I will describe in here the same patterns that we can find in the book, but I will be using different samples and adding more material about this subject as soon it is possible.

Let us use this user case: “An internet site that sells toys cars is receiving a lot of customer visitors every day and becoming more famous. Its investors want more; they want that the site provides to the customers the simulations of the toy car actions.”

Check below our class model (there are others sub classes of ToyCar that are not described below):

Design Pattern - Strategy

The investors want that the car perform the action of starting the engine, to the customers may hear the engine sound. To accomplish this, the solution that it is “the most useful, fastest and quickest” may be to apply some changing in the super class. What of bad could come of using this solution that the Java gives us? Any change in the super class ToyCar will be reflected to all sub classes, and all sub classes will have the same behavior! We just have to create a method to start the engine (“startEngine()”) and our problem will be solved:

Design Pattern - Strategy

The team was very happy with the result of this new functionality that was delivered on time. Now the customers can hear the engine sound. BUT, after a phone call it was possible to see that something bad happened. One of the investors saw something in our application that should never happen, a wood car starting its engine. Why this happened? Let us see our model:

Design Pattern - Strategy

Our wood car, that also has ToyCar as super class, received the method to start the engine when a wood car does not have an engine. What could we do to solve this problem? We could just override the method:

    @Override
    public boolean startEngine() {
        // Do nothing
    }

Would the above code be the best solution? Let us suppose that we have a sub class of ToyCar, a metal car (“MetalCar”) where we would have to override the method too. By doing this method overriding in all classes methods we are increasing our project complexity. And each time, that a new ToyCar sub class is created and this sub class should not have the method startEngine() implemented, we would have to override this method also.

So, which solution would be the best one here? Let us apply the first pattern principle of this study:
“Identify everything that changes and isolate it from what does not change.”
What is the meaning of this? Think about an engine behavior that will be present in one class and other different engine behavior that should be present in another class; we could isolate this behavior from our ToyCar class. Instead of letting our class ToyCar handling this behavior, why do not delegate it? Here it come our second pattern principle:
“Program to an interface”
This principle is nothing more than: use all benefits from super class. Imagine if we have an interface with a visible method, our class will not care with which behavior the interface method has. Let us create an interface to handle this engine behavior:

Design Pattern - Strategy

Bellow you can check how our classes will be implemented. First the class ToyCar, then Mercedes and WoodCar:

// Interface and Engine Behavior implementations

public interface EngineBehavior {
    public boolean startEngine();
}

public class NoEngineBehavior implements EngineBehavior {

    @Override
    public boolean startEngine() {
        System.out.println("No engine to turn on");
        return true;
    }
}

public class RegularEngineBehavior implements EngineBehavior {

    @Override
    public boolean startEngine() {
        System.out.println("Engine On");
        return true;
    }
}

public class PowerfulEngineBehavior implements EngineBehavior {
    
    @Override
    public boolean startEngine() {
        System.out.println("Powerfull Engine On");
        return true;
    }
}

// Our Classes Implmentatioins
public class ToyCar {
    private int doorTotal;
    private int maxSpeed;
    protected EngineBehavior engineBehavior;
    // Others attributes
    
    public ToyCar(){
        engineBehavior = new RegularEngine();
    }
    
    public void startEngine(){
        engineBehavior.startEngine();
    }
    
    // Others methods
}

public class Mercedes extends ToyCar {
    
    public Mercedes(){
        engineBehavior = new PowerfulEngineBehavior();
    }
    
    @Override
    public void startEngine(){
        engineBehavior.startEngine();
    }    
}

public class WoodCar extends ToyCar {
    
    public WoodCar(){
        engineBehavior = new NoEngineBehavior();
    }
    
    @Override
    public void startEngine(){
        engineBehavior.startEngine();
    }
}

I know that we could change the way that our interface is receiving its implementation (“engineBehavior = new NoEngineBehavior();”) and another “upgrades” about patterns, but this refactoring is subject to another posts.

You may think: “Wait a minute, even if I do comment the method startEngine() or put the code engineBehavior = new NoEngineBehavior(); I still have “duplicated code” in my system!” Think with me about this next investor requirement: “When we call the method startEngine() in a type of ToyCar that does not have an engine, we would have to register this action in a log”. If you notice how our classes are implemented now (WoodCar, and all others MetalCar, BambooCar), we would have to change only the method startEngine() in our class NoEngineBehavior. All classes that do not have an engine behavior would be with a correct functioning.

Final considerations:

  • The class name should indicate a noun. Things like: “Car”, “House”, “Computer”, etc. In the user case that we simulated today this behavior is like our noun. It is a class that handles a behavior pattern.
  • Program to an interface – this principle does not necessarily means that we have to create an Interface, but it means always program to a super type. You should always program to a super type like a regular Class (POJO), Abstract Class and Interface. You must decide the best type for your system and implement it. In the book Head First – Design Patterns the authors make this explanation very clear. Do not mistake this principle that says: “always code for a super type” with “always create an interface”. A super type will be the best solution to your design problems in like 99% of the situations.
  • We just studied another project Principle:
    “Give priority to composition rather than inheritance”.

As we saw in our user case today, we used an interface to create the composition. Using composition in our system will make our job easier.

    Design Pattern: Strategy
    Studied Principles:

  • Identify everything that changes and isolate it from what does not change.
  • Program to an interface.
  • Give priority to composition rather than inheritance.

I hope this post might be able to help you.

If you have any questions or ideas to share just leave your comment.

See you soon.

Design Pattern – Strategy

Olá, tudo bem?

Vou aproveitar que estou estudando sobre design patterns e colocar aqui alguns padrões encontrados atualmente. O livro base é o Design Patterns – Head First. Vou descrever aqui os mesmos padrões encontrados no livro, mas estarei utilizando exemplos diferentes e acrescendo mais material na medida do possível.
Esse estudo para patterns serve para a certificação OCJD. Essa certificação exige a entrega de um sistema onde você deverá explicar o porquê de cada escolha sobre o seu design.

Vamos utilizar o seguinte caso de uso: “Um site de carros de brinquedos está recebendo bastantes visitas e se tornando famoso. Mas seus investidores querem mais, querem que agora seja possível fazer simulações das ações dos carros de brinquedo na web.”

Atualmente nosso modelo se divide da seguinte forma (existem várias outras subclasses de ToyCar que não foram descritas na imagem abaixo):

Design Pattern - Strategy

Agora os investidores desejam que todos os carros de brinquedo exerçam a função de ligar o motor, para que os clientes possam ouvir seu ronco. Para isso, a solução mais “simples, rápida e prática” teoricamente seria aplicar uma herança. Que mal há em utilizar esse ótimo artifício fornecido pelo Java? Basta criar o método ligar motor (“startEngine()”) em nosso modelo e tudo estará resolvido.

Design Pattern - Strategy

Após a entrega da nova funcionalidade, a equipe de desenvolvimento vibrava com o bom funcionamento ao ouvirem o ronco dos motores dos carros de brinquedo. MAS, uma ligação é recebida e um pequeno stress começa a aparecer. Um dos investidores ao navegar pela aplicação encontra algo que nunca deveria acontecer, um carro de madeira ligando motor. Por que isso aconteceu? Vejamos algo que passou despercebido:

Design Pattern - Strategy

Nosso carro de madeira, que também tem como superclasse a classe ToyCar, acabou por herdar essa função que não cabia a ele. O que fazer para resolver esse problema? Poderíamos sobrescrever o método herdado:

    @Override
    public boolean startEngine() {
        // Do nothing
    }

Seria essa a melhor saída? Supondo que temos uma classe para um carro de metal (“MetalCar”) também iríamos ter que sobrescrever esse método. Cada hora nosso projeto fica mais complexo, pois à medida que criarmos mais modelos de carros que não precisam ter o motor ligado, a sobrescrita do método de ligar o motor será obrigatória.

Qual outra solução seria possível aqui? Vamos aplicar um primeiro princípio a ser tratado nessa série de artigos:
Identifique tudo o que varia e separe do restante que não irá variar.”
O que isso significa? Veja que o comportamento de ligar motor pode ou não aparecer para determinadas classes, com isso poderíamos separar esse comportamento da nossa classe ToyCar. Ao invés de deixar nossa classe ToyCar controlando esse comportamento por que não delegamos essa função? Hora de ver, um segundo princípio de padrão de projeto:
Programe para interface.”
Esse conceito nada mais é do que: utilizar todo o benefício de herança. Imagine que se tivermos uma interface com um método conhecido, não iria fazer qualquer diferença para nossa classe qual a implementação de motor estiver sendo relacionada a ele. Vamos criar uma Interface para tratar o comportamento do motor?

Design Pattern - Strategy

E como ficariam nossas classes? Primeiramente a classe ToyCar, depois a classe Mercedes e por último, nossa classe carro de Madeira:

// Interface and Engine Behavior implementations

public interface EngineBehavior {
    public boolean startEngine();
}

public class NoEngineBehavior implements EngineBehavior {

    @Override
    public boolean startEngine() {
        System.out.println("No engine to turn on");
        return true;
    }
}

public class RegularEngineBehavior implements EngineBehavior {

    @Override
    public boolean startEngine() {
        System.out.println("Engine On");
        return true;
    }
}

public class PowerfulEngineBehavior implements EngineBehavior {
    
    @Override
    public boolean startEngine() {
        System.out.println("Powerfull Engine On");
        return true;
    }
}

// Our Classes Implmentatioins
public class ToyCar {
    private int doorTotal;
    private int maxSpeed;
    protected EngineBehavior engineBehavior;
    // Others attributes
    
    public ToyCar(){
        engineBehavior = new RegularEngine();
    }
    
    public void startEngine(){
        engineBehavior.startEngine();
    }
    
    // Others methods
}

public class Mercedes extends ToyCar {
    
    public Mercedes(){
        engineBehavior = new PowerfulEngineBehavior();
    }
    
    @Override
    public void startEngine(){
        engineBehavior.startEngine();
    }    
}

public class WoodCar extends ToyCar {
    
    public WoodCar(){
        engineBehavior = new NoEngineBehavior();
    }
    
    @Override
    public void startEngine(){
        engineBehavior.startEngine();
    }
}

Claro que poderíamos alterar o modo em que a Interface está recebendo sua classe implementada (“engineBehavior = new NoEngineBehavior();”) e outras questões relacionadas a patterns, mas isso será assunto para próximos artigos.

Talvez você possa pensar: “Espera aí, dá no mesmo se eu comentar o código “startEngine()” em todas as classes ou colocar o código engineBehavior = new NoEngineBehavior(); pois terei essa “repetição” em toda classe.” Pense comigo, e se ao chamar o método “startEngine()” para um tipo de ToyCar que não tenha motor, fosse necessário uma ação como registrar no log essa tentativa? Do modo como nossas classes estão implementadas, bastaria alterar o método da classe NoEngineBehavior e pronto. Todas nossas classes de carros que não tem motor já estarão com esse comportamento ativo.

Três considerações finais:

  • O nome de uma classe deve indicar um substantivo. Coisas em geral: “Carro”, “Casa”, “Computador”. Em nosso caso o comportamento (behavior) virou um substantivo. Ele é uma classe que determina um padrão de comportamento.
  • Programar para Interface: Não significa necessariamente criar sempre uma interface (“Interface”). Significa programar para um super tipo, ou seja, você poderia estar usando uma Classe normal, Classe Abstrata ou Interface. Você tem que adaptar sua necessidade à melhor opção possível. No livro do Use a Cabeça (Head First), os autores deixam isso claro. Não confundir esse conceito com sempre criar uma interface para qualquer situação, mas sim um super tipo que venha a solucionar o seu problema.
  • Acabamos por ver mais um princípio de projeto:
    "Dar prioridade à composição."

Como vimos no exemplo acima, colocamos nossa interface como composição, isso facilitou e muito nosso trabalho.
Padrão de Projeto: Strategy
Princípios vistos:

  • Identifique tudo o que varia e separe do restante que não irá variar.
  • Programe para interface.
  • Dar prioridade à composição.

Espero que esse post possa te ajudar. Qualquer dúvida ou colocação basta postar abaixo.

Até a próxima.
Revisores: João Luiz Silva Silvestre / Diego Prado

JSF – Hello World, Auto Complete

Hello, how are you?

Let us talk about a framework that is a precious helper as a web “front-end”: “JSF – Java Server Faces”.
We will see here a “Hello World” of JSF and in the end of this post, how to activate the Eclipse auto complete option. Notice that, except by the auto complete option, this tutorial can be done using just a notepad.
In case you have doubts about how to create a basic webserver you can check here: Creating a WebServer. There are others subjects here in this blog talking about webserver: Handling Exceptions on a WebApp, User Authentication (Filter/Servlet).

We need to start with some downloads:

Let us create a new Dynamic Web Project, adding Tomcat 6 as our server. If you have any doubts about how to install and configure the Tomcat, you can see a tutorial here: Creating a WebServer.

New Dynamic Project

We need to copy the “*.jar” files that we have downloaded from the internet to the folder “WebContent/WEB-INF/lib”. You will find the JSF Mojarra “*.jar” files at the path: “mojarra-2.0.3-FCS/lib”, inside the file you downloaded. After copy all the files, the folder must have these three files in lib folder: “jsf-api.jar”, “jsf-impl.jar” and “jstl-1.2.jar”.

Let us change the web.xml file:

<?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"
    version="2.5">
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

We have to create the faces-config.xml, but we will not use it.

<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
   version="2.0">
  <!--
      Let's keep it empty. In JSF 2.0 we use annotations.
  -->
</faces-config>

It is time to create a class that will work as our controller. In this class we will put a welcome message. In a complete company system this message could be the user name, some message from a database, etc. Our class should be created in a package named “com” and will have the word “Hello” as its name.

package com;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Hello {

    private final String youAreWelcome = "You finished a simple hello world. Let's navigate?";

    public String getYouAreWelcome() {
        return youAreWelcome;
    }
}

As our last action before the first test, we need to create our welcome page named “index.xhtml”:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Hellow World JSF 2.0</title>
    </h:head>

    <h:body>
            <h:form>
                    <h:outputText value="#{hello.youAreWelcome}"/>
            </h:form>
    </h:body>
</html>

Pay attention to this: “Our page must be created inside WebContent folder”.

After adding our system to Tomcat, start it. To access our system we will use the link: http://localhost:8080/ProjectJSF/index.jsf. If you have any doubts about how to work with Tomcat Application, take a look at this link: Creating a WebServer. I’m doing this step by step while I am writing this tutorial, so if you did not see our first page without an error, go back and review your code.

Let us create some navigation in our system by doing a simple addition. To start with this change our Hello class will have three more fields to do the addition, another field will keep the user name.

package com;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Hello {
    private String userName;
    private int valueA;
    private int valueB;
    private int total;

    private final String youAreWelcome = "You finished a simple hello world. Let's navigate?";

    public String getYouAreWelcome() {
        return youAreWelcome;
    }
    
    public String mathIt(){
        total = valueA + valueB;
        
        return "result.xhtml";
    }
    
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getValueA() {
        return valueA;
    }

    public void setValueA(int valueA) {
        this.valueA = valueA;
    }

    public int getValueB() {
        return valueB;
    }

    public void setValueB(int valueB) {
        this.valueB = valueB;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public int getTotal() {
        return total;
    }    
}

We will need to change our “index.xhtml” file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Hellow World JSF 2.0</title>
    </h:head>

    <h:body>
            <h:form>
                <h:outputText value="#{hello.youAreWelcome}"/><br/>
                Your Name: <h:inputText id="userName" value="#{hello.userName}"/><br/>
                First Value: <h:inputText id="valueA" value="#{hello.valueA}"/><br/>
                Second Value: <h:inputText id="valueB" value="#{hello.valueB}"/><br/>
                  <h:commandButton value="Math It" title="Math It" action="#{hello.mathIt}"/>
            </h:form>
    </h:body>
</html>

The “result.xhtml” will be our last page to be created (it must be created in “WebContent” folder):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Hellow World JSF 2.0</title>
    </h:head>

    <h:body>
        <h:form>
            Thanks for passing by: <h:outputText value="#{hello.userName}"/><br/>
            Total: <h:outputText value="#{hello.total}"/>
        </h:form>
    </h:body>
</html>

Accessing again our system using the link http://localhost:8080/ProjectJSF/index.jsf we will see that our work is complete.

An Eclipse resource that helps us a lot is the text auto complete. When I was creating this post, I noticed that JSF uses the file type “*.xhtml” and the text auto complete did not work with this file type. I found tons of solutions on the internet that work for some people and did not to others. I found a very simple solution that worked on each different computer that I tested. Right button click on the project and go to: “Properties > Project Facets”:Project properties Project Facetes Check the option “JavaServer Faces”, and it is done. Go to the “index” or “result” file and you will see the auto complete working. Project Facetes Autocompletar
In some future posts about JSF we will be talking about Ajax, validations, PrimeFaces, etc. This subject is huge.

I hope this post might help you.

If you want to comment or to ask about anything just post it.

See you later.

JSF – Hello World, AutoComplete

Olá, tudo bem?

Vamos tratar sobre um framework que tem sido uma mão na roda como “front end” para web: “JSF – Java Server Faces”.

Veremos aqui um tutorial do JSF 2.0 e ao final como fazer um “autocompletar” do eclipse. Lembro que, exceto pelo autocompletar ao final, esse exemplo pode ser feito em um bloco de notas.

Caso você tenha dúvidas de como criar um WebServer básico, você pode visitar esse link: Criando um WebServer. Existem também outros assuntos tratados para WebServer que você pode encontrar aqui: Tratando Exceções em uma Aplicação Web, Autenticação de Usuários (Filter/Servlet).

Vamos começar pelos downloads?

Vamos criar um novo projeto do tipo Dynamic Web Project já adicionando como servidor o Tomcat 6.0. Caso você tenha alguma dúvida de como instalar o container Tomcat você poderá ver o passo a passo aqui: Criando um WebServer. New Dynamic Project

Precisamos também copiar os arquivos “*.jar” que nós acabamos de baixar para dentro da pasta “WebContent/WEB-INF/lib”. Você irá encontrar os arquivos do JSF Mojarra dentro do arquivo que você baixou, pelo seguinte caminho “mojarra-2.0.3-FCS/lib”. Ao final teremos dentro da pasta “WebContent/WEB-INF/lib” três arquivos do tipo jar: “jsf-api.jar“, “jsf-impl.jar“, “jstl-1.2.jar“.

Vamos alterar o arquivo “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"
    version="2.5">
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

Mesmo que não utilizemos o “faces-config.xml”, será necessária sua criação.

<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"

   version="2.0">
  <!--  
      Let's keep it empty. In JSF 2.0 we use annotations. 
  -->
</faces-config>

Vamos criar a classe Java que funcionará como nosso controlador. Nela iremos colocar uma mensagem de boas vindas. Em uma aplicação de grande porte, poderia ser o nome do usuário, alguma mensagem do banco de dados, etc. Nossa classe será colocada em um pacote chamado “com” e terá o nome de “Hello”:

package com;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Hello {
    
    private final String youAreWelcome = "You finished a simple hello world. Let's navigate?";

    public String getYouAreWelcome() {
        return youAreWelcome;
    }    
}

E por último vamos criar uma página chamada “WebContent/index.xhtml”:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />        
        <title>Hellow World JSF 2.0</title>
    </h:head>
    
    
    <h:body>
            <h:form>
                    <h:outputText value="#{hello.youAreWelcome}"/>
            </h:form>
    </h:body>
</html>

Atenção, nossa página tem que ficar dentro da pasta WebContent.

Após adicionar nosso sistema ao Tomcat, basta iniciá-lo para acessar nosso programa pelo link: “http://localhost:8080/ProjectJSF/index.jsf”. Caso você tenha alguma dúvida de como manejar o Tomcat, visite esse link: Criando um WebServer. Eu estou fazendo o passo a passo enquanto escrevo esse tutorial, então caso você não tenha conseguido visualizar a página inicial, volte e revise seu código.

E por último, vamos simular uma navegação? Vamos realizar uma soma simples, iremos alterar nossa classe “Hello” adicionando dois números onde iremos realizar uma soma. Outro campo irá registrar o nome do usuário:

package com;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Hello {
    private String userName;
    private int valueA;
    private int valueB;
    private int total;

    private final String youAreWelcome = "You finished a simple hello world. Let's navigate?";

    public String getYouAreWelcome() {
        return youAreWelcome;
    }
    
    public String mathIt(){
        total = valueA + valueB;
        
        return "result.xhtml";
    }
    
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getValueA() {
        return valueA;
    }

    public void setValueA(int valueA) {
        this.valueA = valueA;
    }

    public int getValueB() {
        return valueB;
    }

    public void setValueB(int valueB) {
        this.valueB = valueB;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public int getTotal() {
        return total;
    }    
}

Precisamos também alterar nossa JSP inicial “index.xhtml”:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />        
        <title>Hellow World JSF 2.0</title>
    </h:head>
    
    
    <h:body>
            <h:form>
                <h:outputText value="#{hello.youAreWelcome}"/><br/>
                Your Name: <h:inputText id="userName" value="#{hello.userName}"/><br/>
                First Value: <h:inputText id="valueA" value="#{hello.valueA}"/><br/>
                Second Value: <h:inputText id="valueB" value="#{hello.valueB}"/><br/>
                  <h:commandButton value="Math It" title="Math It" action="#{hello.mathIt}"/>                
            </h:form>
    </h:body>
</html>

E vamos criar uma página para exibir nosso resultado “result.xhtml” (que deve ficar dentro da pasta WebContent).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />        
        <title>Hellow World JSF 2.0</title>
    </h:head>
        
    <h:body>
        <h:form>
            Thanks for passing by: <h:outputText value="#{hello.userName}"/><br/>
            Total: <h:outputText value="#{hello.total}"/>
        </h:form>
    </h:body>
</html>

Acessando novamente a página inicial veremos que a navegação está pronta. “http://localhost:8080/ProjectJSF/index.jsf

Um recurso que pesa muito é o “autocompletar”. E enquanto criava esse artigo eu notei que pelo fato do JSF utilizar o tipo de arquivo “xhtml” o eclipse não ativou o autocompletar. Achei diversas soluções que funcionavam para uns e não para outros. Encontrei uma bem simples que funcionou em diversos lugares que testei. Clique botão direito em cima do projeto e vá em “Properties > Project Facets”.Project properties Project Facetes Marque a opção JavaServer Faces, e pronto. Pode ir para a página index ou result que você já terá seu autocompletar funcionando. Project Facetes Autocompletar

Nos próximos posts sobre JSF iremos ver Ajax, validações, PrimeFaces, etc. O assunto é longo.

Espero que o post de hoje possa ter lhe ajudado.

Qualquer coisa, poste sua dúvida/comentário que irei responder.

Até a próxima.

Clean Code – Part 5

Hello, how are you?

My last post was too long ago because my pos graduation is taking all my time. I was doing a project and I had o hard time coding a full system. That is why I am without time to post.
Let us keep talking about clean code? The older posts you will find here: Part 01, Part 02, Part 03, Part 04

  • Copy and Paste (even in non OO codes) -> Avoid doing this copy and paste. When you got a task there is an easy way to finish it, it is very easy to copy a code from a place and past it to where we have to use it. By doing this code replication we are increasing the difficult of the code maintenance, breaking good coding patterns and even worst, propagating some bugs.Imagine if we got a complex method, and we need to use it in another place of our software; instead of doing a change to transforme the code to be more generic and apply it to every situation, some developers choose the easiest way to finish the task that is coping and pasting the method. After pasting the code the developer just have to do small changes to complete the task. Imagine now that we have a bug in this pasted code, so we fix the pasted and the original code. The problem is that the older developer did not tell us that this code was replicated more three times. Can you see the problem of replication?

    It would be easier create just one method to be invoked in all parts of the system.

    When writing your code, if you think something like: “I have done/seen something like this before…” it means that is time to you to stop and think. Be aware of any kind of replication:

    • Non OO codes -> Create just one method and use it in any place of your code.
    • OO codes -> Time to apply super-class, abstract class, etc.
  • Remove unnecessary code -> Have you notice the large amount of commented code on legacy software? By example:
    // user.setCreditCardByDate(credidCard, new Date());
    user.setCreditCard(credidCard);
    list.add(user);
    //for(int a = 0; i < list.size(); i++){
        //daoUser.deleteCredidCardHistory(list.get(i));
        //Logger.debug("im here!!!!");
    //}
    daoUser.deleteCredidCardHistory(list);

    If the commented code has no more use, why will you keep it? Sometimes it is normal keep the older code while you test the new one, but saving it? If you are not so sure about the code you wrote, it is better think twice before saving it.
    If we have a tool to control our software version, what is the purpose of saving a commented code? With this kind of versioning tool we can always check the older code.
    The committed code must be clean, easy to understand and with a straight objective. When your code has a lot of old commented code, the current code might lose its focus because the developer might try to understand the commented code and forget about the current code.
    Take a look on how the above code would be so much easier to read:

    user.setCreditCard(credidCard);
    list.add(user);
    daoUser.deleteCredidCardHistory(list);
  • Knowledge of the development language -> Always seeks to upgrade the knowledge you got in your development language. Sometimes your development language already has the method that you are trying to create. “There is no need to re-create the wheel”. Keep updated about your development language. When some task demands you to do something you never done before, research.
    Someday I found this code on certain software and became a joke on the company:

    for(int i = 0; i < 10; i++){
        //... Do stuff
        // Get inside the if when finds the condition
        if (...){
            i = 13;
        }
        // Do stuff
    }

    You can see that instead using the word break, the developer changed the counter value. That task could be done in an easier way and with more style:

    for(int i = 0; i < 10; i++){
        //... Do stuff
        // Get inside the if when finds the condition
        if (...){
            break;
        }
        // Do stuff
    }

    Maybe you think: “Well, at least was working right?!” I will answer your “Yes”, but I will also say that you will not become a joke at your company if you keep updated about your working tool. Another thing to think about the code above is: “What if we must change the counter value”? “What if we have to change the counter value?” “What if we have to change the counter value from 10 up to 100?” You would have to change at the “for” declaration and in the “if”. It’s not worth it.;

  • TODO -> The IDEs that we can find today help us with this reminder. We can easily write “// TODO”, and see this reminder all over the class/system. It is really easy to put this tag TODO in all system code, and it can remember us of everything that we have to do.

TODO

  • The problem is “as easy is to create it, the TODO will be easy to forget about it”. Once this is usual to all company, tons of TODOs codes might appear at the Task view in a short a time, doing your code dirty.One way out to avoid this kind of problem, once you know that the problem will not be fixed in a short time you will not write the tag TODO in your code (To more information about this approach: Watch out for TODO comments! By Alexandre Gazola).
    Other way out it would be to create your own tags. In your company you could agree in use the task TODO just to codes that will be fixed before the end of the task. We could use like: “// REMAKE” or “// REFACTOR” and by the IDEs we can filter by created TAGs.
  • Lose your ego -> I believe that one of the most difficulties of the human being is to lose the ego. Maybe you got a task to do, trusting in your 30 years of experience you will not talk with anyone about your task and will not gather ideas to do that. Ego it is something that only harm the human being. The best thing to do is to have a quick chat with a few people of your team to gather ideas, put them all together, and you can be sure that you code will have everything to get good design patterns, the right technologies and a good OO modeling.
    Just because someone was recently hired to the team, would mean that he does not have any knowledge. Talking and gathering ideas will take your project to another level.
    Leave your ego away; it will not take you anywhere.

That is all for today.

If you have any question, just post it. I do not know when I will post again because the Pos Graduation is taking a lot of time, but soon I will have more tutorials to post here.

See you later! o_

Código Limpo – Parte 05

Oi pessoal, tudo bem?

Realmente faz tempo que não postava algo, mas é por que o projeto de bloco da Pós-Graduação está tomando muito tempo. Então está complicado criar os posts.

Vamos continuar falando sobre Código Limpo? Os antigos posts você encontra aqui: Parte 01, Parte 02, Parte 03, Parte 04.

  • Copiar e Colar (mesmo em códigos não OO) -> Evitem isso ao máximo. Ao realizar uma tarefa existe uma enorme facilidade em copiar código de um lugar, e aplicar onde precisamos alterar. Com essa replicação de código estamos aumentando a dificuldade de manutenção, quebrando bons padrões de programação e talvez até propagando bugs.

    Imagine que existe um método com um complexo cálculo, onde é necessário aplicá-lo a outras partes do sistema. Ao invés de fazer alterações bem pensadas para deixar o método mais genérico, alguns desenvolvedores, acabam por escolher o mais fácil que seria copiar, colar. Após copiar e colar basta fazer pequenos ajustes. Imagine agora que após certo tempo nota-se que existe um erro no cálculo e alteramos o método inicial e o que foi replicado, mas o antigo programador não falou que esse código foi replicado mais 3x. Imaginou? Seria mais fácil ter criado apenas um método que fosse invocado em todas as partes do sistema.Reflita nisso. Quando você pensar “Eu já fiz esse código antes…”, quer dizer que é hora de parar, pensar e ver que está acontecendo uma provável duplicação:
    • Códigos não OO -> Crie apenas uma função e utilize-a de qualquer lugar do sistema.
    • Códigos OO -> Hora de aplicar super classes, classes abstrata, etc.
  • Remover código desnecessário -> Já reparou a quantidade códigos comentados existem em programas legados? Por exemplo:
    // user.setCreditCardByDate(credidCard, new Date());
    user.setCreditCard(credidCard);
    list.add(user);
    //for(int a = 0; i < list.size(); i++){
        //daoUser.deleteCredidCardHistory(list.get(i));
        //Logger.debug("im here!!!!");
    //}
    daoUser.deleteCredidCardHistory(list);

    Se esse método já está ultrapassado, por que mantê-lo? As vezes é normal deixar o código antigo enquanto se faz testes, mas salvá-los? Se você está incerto de sua alteração, é melhor pensar duas vezes antes de salvá-la por definitivo.
    Se tivermos um versionador qual seria o propósito de salvar um código comentado? Uma vez que temos essa ferramenta para consultar o antigo código sempre.

    O código salvo tem que ser um código limpo, que seja fácil de entender, objetivo. Quando um código apresenta vários códigos antigos comentados, o código atual perde um pouco do foco pois o desenvolvedor pode querer entender o código antigo comentado.

    Olhe como ficaria mais limpo o código:

    user.setCreditCard(credidCard);
    list.add(user);
    daoUser.deleteCredidCardHistory(list);
  • Conhecimento da linguagem -> Procure sempre aprimorar seu conhecimento na linguagem. Algumas vezes a própria linguagem já contém métodos prontos e já funcionais para você. “Não existe a necessidade reinventar a roda”. Mantenha-se informado sobre sua linguagem de desenvolvimento, se informe das novidades. Quando você receber uma tarefa que exige algo que você não fez ainda, pesquise.
    Um exemplo que uma vez encontrei, e virou piada na empresa, está no pedaço de código abaixo:

    for(int i = 0; i < 10; i++){
        //... Do stuff
        // Get inside the if when finds the condition
        if (...){
            i = 13;
        }
        // Do stuff
    }

    Vocês podem ver que ao invés de usar a palavra break, o desenvolvedor alterou o valor do contador. Sendo que poderia ser feito de forma mais fácil e com mais estilo:

    for(int i = 0; i < 10; i++){
        //... Do stuff
        // Get inside the if when finds the condition
        if (...){
            break;
        }
        // Do stuff
    }

    Talvez você pense: “Bem, estava funcionando não estava?” Eu te responderei que sim, mas também acrescento que você não irá virar piada se você estiver sempre querendo conhecer sua ferramenta de trabalho. Outra coisa a se pensar é, e se realmente fosse necessário alterar o valor do contador? Se o total subisse para 100 ao invés de 10? Teria que aumentar o valor do contador junto com o valor total de loops. Não vale a pena.

  • TODO – As IDEs de hoje nos ajudam muito com esse lembrete. Facilmente podemos escrever “// TODO” (em português “A Fazer”), e ver essas referências que estão por todo classe/sistema. Realmente é muito simples colocar esse lembrete em meio ao nosso código, pode nos lembrar de tudo que realmente está pendente.TODO
    O problema é que assim como é fácil criar é fácil esquecer. Uma vez que isso vire prática na empresa, milhares de TODOs poderão aparecer na view de Tasks em pouco tempo, com isso, vão ficar poluídos a view e seu código.
    Uma saída seria evitar esse tipo de abordagem, uma vez que você sabe que não existe previsão para realizar a alteração marcada no TODO. (Para mais informações dessa abordagem: Watch out for TODO comments! By Alexandre Gazola).
    Outra saída seria criar tags personalizadas. Para isso, a tag TODO poderia ter seu uso definido apenas para ações rápidas e que serão finalizadas antes do código ser salvo no versionador. Poderíamos criar, por exemplo: “// REMAKE …” ou então “// REFACTOR …” E pelas IDEs é possível filtrar por tags customizadas.
  • Perca seu orgulho – Creio que uma das maiores barreiras do ser humano é essa, perder o orgulho. Talvez você tenha uma tarefa a fazer, tenha 30 anos como desenvolvedor e com isso acaba por não comentar com ninguém ou trocar idéias sobre sua tarefa. Orgulho é algo que apenas prejudica o ser humano. A melhor coisa a se fazer é ter um bate papo rápido com algumas pessoas da equipe para coletar idéias, mescle todas, e pode ter certeza que seu código tem tudo para ter bons padrões de projeto, as corretas tecnologias e uma boa modelagem OO.
    Não é só por que alguém acabou de entrar na equipe que ele não irá ter conhecimento algum. Conversar e trocar idéias irá levar seu projeto a um novo patamar.
    Deixe seu orgulho de lado, ele não irá te levar a lugar algum.

Por hoje é só qualquer observação basta colocar. Não sei quando irei postar novamente por causa da Pós-Graduação, mas em breve terei várias tutoriais para colocar aqui.

Até mais! o_

User Authentication (Filter/Servlet)

Hello, how are you?

Let’s talk today about how to control user authentication manually? To do this authentication we will be using a simple but powerful Java class: “Filter”. We will be using the code developed in the others posts about Web Applications: Creating a WebServer, Handling Exceptions on a WebApp.

I will write bellow, the code that we will be using for this Filter article. The files that will be described bellow are: one Servlet, two JSPs and a “web.xml” file (we will be able to do a Hello World Filter with these files). If you have any problem running the Web Application with the codes bellow, take a look at this article (Creating a WebServer) that will help you (with these codes bellow you will be able to run your WebServer and navigate on it).
Our project name is Servlet. The web.xml file will stay inside the folder WebContent/WEB-INF

<?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>Servlet</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>  
    </welcome-file-list>
  
    <servlet>
        <servlet-name>hello</servlet-name>
        <jsp-file>/index.html</jsp-file>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>final</servlet-name>
        <servlet-class>com.Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>final</servlet-name>
        <url-pattern>/mathit</url-pattern>
    </servlet-mapping>     
</web-app>

com.Servlet.java

package com;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet extends HttpServlet {
    public void doPost(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {
        int value1;
        int value2;
        int total = 0;
        String name = (String) req.getParameter("name");
        String warning = "";
        
        try {
            value1 = Integer.parseInt((String) req.getParameter("value1"));
            value2 = Integer.parseInt((String) req.getParameter("value2"));
        } catch (NumberFormatException e) {
            value1 = 0;
            value2 = 0; 
            warning = "We got some bad value(blank or non numerics values, we set 0 instead";
        }
        
        req.setAttribute("name", name);
        req.setAttribute("warning", warning);
        
        total = value1 + value2;
        
        req.setAttribute("total", total);
        
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/show.jsp");
        
        requestDispatcher.forward(req, res);
    }
}

File code: /WebContent/index.html

<html>
    <body>
        <form action="/Servlet/mathit" method="post">
            <h1>Hello</h1>
            Type your name: <input type="text" name="name"/> <br/><br/>
            Lets do some math?<br/>
            Type the first value to be added: <input type="text" name="value1"/> <br/>
            Type the second value to be added: <input type="text" name="value2"/> <br/><br/>
            <input type="submit" value="Do some math"/>
        </form>
    </body>
</html>

File code: /WebContent/WEB-INF/show.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <body>
        Thanks ${name} for passing by. <br/>
        The total is: ${total}. <br/>
        
        <br/>${warning}
    </body>
</html>

To access the application, start the Tomcat and access through the address http://localhost:8080/Servlet/hello.

Filter is a Java class able to intercept requests done by a client; you just have to map a request pattern (as URL, Servlet, etc). To start with it, let’s create a Filter class and put it to work.
That’s how our Filter code class will be:

package com;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * Servlet Filter implementation class UserCheckFilter
 */
public class UserCheckFilter implements Filter {
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        System.out.println("Hello World");
        
        chain.doFilter(request, response);
    }
}

The init and destroy methods belongs to the Filter interface and they must be implemented. In this sample code we are just printing “Hello World”, we need to be sure that our Filter class is being invoked.

We must add some Filter tags to our web.xml file.

<filter>
    <filter-name>UserCheckFilter</filter-name>
    <filter-class>com.UserCheckFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserCheckFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

About the tags: “url-pattern” it tells witch url address we are mapping, and in our sample we are catching any requested url. “filter-name” defines the Filter name that will be invoked.

Start the Tomcat and access the application through the link: http://localhost:8080/Servlet/hello (If you still have some trouble accessing the first page of our tutorial, visit this link to clear your doubts: Creating a WebServer).
Look at the Console to see our message there:
Hello World Screen

With our Filter already working, let’s create a User class. A simple POJO with name and password as it attributes. Our class will be like this:

package com;

public class User {
    private String name = "UNKNOW";
    private String password = "UNKNOW";
    
    public User(String name, String password){
        this.name = name;
        this.password = password;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

We need a Servlet to do the user authentication, let’s create it to validate the user name and the password. We will do this validation in our Servlet and we will not worry about patterns.

package com;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class UserValidator extends HttpServlet {
    private static final Map users = getUsers();
    
    /**
     * Creates valid users 
     * 
     * This User Map could be users returned from a database
     * or a simple select with the user.name
     * 
     * @return a Map of valid users
     */
    private static Map getUsers() {
        Map users = new HashMap();
        
        User userOne = new User("one","one");
        User userTwo = new User("two","TWO");
        
        users.put(userOne.getName(), userOne);
        users.put(userTwo.getName(), userTwo);
        
        return users;
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        doPost(req, res);
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        RequestDispatcher rd;
        String name = req.getParameter("name");
        String password = req.getParameter("password");
    
        User user = validateLogin(name, password);
        
        if (user == null){
            rd = req.getRequestDispatcher("/loginError.jsp");
        }
        else{
            HttpSession session = req.getSession();
            session.setAttribute("user", user);
            rd = req.getRequestDispatcher("/loginSuccess.jsp");
        }
        
        rd.forward(req, res);
    }

    /**
     * Validate the entered data
     * 
     * If there is no valid data, the method will return null
     * 
     * @param name given at the jsp
     * @param password given at the jsp
     * @return a user if one was found and validated
     */
    private User validateLogin(String name, String password) {
        // All parameters must be valid
        if (name == null || password == null){
            return null;
        }
        
        // Get a user by key
        User user = users.get(name);
        
        if (user == null){
            return null;
        }
        
        // Check if the password is valid
        if (!user.getPassword().equals(password.trim())){
            return null;
        }
        
        return user;
    }
}

The map “users” and the method “getUsers” exists only to create valid users. If our user is not validated the method “validateLogin” will return a null value. If the user entered a valid data, he will be redirected to a login success page otherwise he will be redirected to an error page.

We need to edit the “web.xml” file and add the Servlet mapping that we just created:

<servlet>
    <servlet-name>userValidator</servlet-name>
    <servlet-class>com.UserValidator</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>userValidator</servlet-name>
    <url-pattern>/userValidator</url-pattern>
</servlet-mapping>

We have to create three JSP files: login, login error and login success.
/WebContent/login.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Login</title>
    </head>
    <body>
        <form action="/Servlet/userValidator" method="post">
            Name: <input type="text" name="name"/>
            Password: <input type="password" name="password"/>
            <input type="submit" value="LogIn"/>
        </form>
    </body>
</html>

/WebContent/loginError.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Error</title>
    </head>
    <body>
        Wrong user/password
    </body>
</html>

/WebContent/loginSuccess.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Success</title>
    </head>
    <body>
        You have loged in.
    </body>
</html>

Let’s change our Filter file. This change will be very delicate, this code change will be responsible to determine if our user will be able to keep on in his request or not.

package com;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Servlet Filter implementation class UserCheckFilter
 */
public class UserCheckFilter implements Filter {
    private String LOGIN_ACTION_URI;
    
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        LOGIN_ACTION_URI = fConfig.getInitParameter("loginActionURI");
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        
        if (user == null && !LOGIN_ACTION_URI.equals(req.getRequestURI())){
            RequestDispatcher rd = req.getRequestDispatcher("/login.jsp");
            rd.forward(request, response);
            return;
        }
        
        chain.doFilter(request, response);
    }
}

Some details about the code above: “req.getSession()” – returns the user session, if there is no session the container will be responsible to create one. We get inside the session a User object, remember that in our Servlet when the user does the login we insert into the session a User object. If there is no User object in the session, the returned value will be null, and we redirect the user to the login jsp. We have in the code above too an attribute named LOGIN_ACTION_URI. This value is returned from the filter configurations, it will be configured in the web.xml very soon. We created the LOGIN_ACTION_URI just to be sure that if the user is trying to validate its login, he does not get stuck in the login jsp.

Now we just have to edit the “web.xml” and add our filter attribute there:

<filter>
    <filter-name>UserCheckFilter</filter-name>
    <filter-class>com.UserCheckFilter</filter-class>
    <init-param>
        <param-name>loginActionURI</param-name>
        <param-value>/Servlet/userValidator</param-value>
    </init-param>
</filter>

When we access the link http://localhost:8080/Servlet/hello, the user will be redirected to the login page. After the user type a valid name/password, it will have the session validated. It will be no longer needed to do this validation.

If you have any doubt, or question just post it.
See you soon.

Autenticação de Usuários (Filter/Servlet)

Olá, tudo bem?

Vamos falar hoje sobre como controlar autenticações de usuário de modo manual? Para fazermos isso, iremos utilizar uma ferramenta do Java bastante simples e poderosa – Filtro (Filter). Será usado como base o código desenvolvido nos outros post sobre Web Applications: Criando um WebServer, Tratando Exceções.

Vou colocar abaixo o código (resumido) que iremos utilizar, será um arquivo do tipo Servlet, dois arquivos JSPs e o arquivo web.xml (apenas com esses arquivos conseguiremos colocar o Filtro em uso). Caso tenha problemas em apenas criar um projeto web com o código abaixo, olhe esse link que mostra um passo a passo: Criando um WebServer (com esses três arquivos você já será capaz de iniciar um webserver e navegar).
Nosso projeto se chama Servlet. O arquivo web.xml ficará dentro da pasta WebContent/WEB-INF

<?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>Servlet</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>  
    </welcome-file-list>
  
    <servlet>
        <servlet-name>hello</servlet-name>
        <jsp-file>/index.html</jsp-file>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>final</servlet-name>
        <servlet-class>com.Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>final</servlet-name>
        <url-pattern>/mathit</url-pattern>
    </servlet-mapping>     
</web-app>

Código do arquivo com.Servlet.java

package com;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Servlet extends HttpServlet {
    public void doPost(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {
        int value1;
        int value2;
        int total = 0;
        String name = (String) req.getParameter("name");
        String warning = "";
        
        try {
            value1 = Integer.parseInt((String) req.getParameter("value1"));
            value2 = Integer.parseInt((String) req.getParameter("value2"));
        } catch (NumberFormatException e) {
            value1 = 0;
            value2 = 0; 
            warning = "We got some bad value(blank or non numerics values, we set 0 instead";
        }
        
        req.setAttribute("name", name);
        req.setAttribute("warning", warning);
        
        total = value1 + value2;
        
        req.setAttribute("total", total);
        
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/show.jsp");
        
        requestDispatcher.forward(req, res);
    }
}

Código do arquivo /WebContent/index.html

<html>
    <body>
        <form action="/Servlet/mathit" method="post">
            <h1>Hello</h1>
            Type your name: <input type="text" name="name"/> <br/><br/>
            Lets do some math?<br/>
            Type the first value to be added: <input type="text" name="value1"/> <br/>
            Type the second value to be added: <input type="text" name="value2"/> <br/><br/>
            <input type="submit" value="Do some math"/>
        </form>
    </body>
</html>

Código do arquivo /WebContent/WEB-INF/show.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <body>
        Thanks ${name} for passing by. <br/>
        The total is: ${total}. <br/>
        
        <br/>${warning}
    </body>
</html>

Para acessar, basta iniciar o Tomcat e acessar pelo endereço: http://localhost:8080/Servlet/hello.

O Filtro é uma classe do Java que pode interceptar as requisições feitas, apenas por mapear um padrão de requisição (URL, Servlet, etc…). Para começar, vamos criar uma classe de filtro e colocá-la para trabalhar.
O código da nossa classe filtro ficará assim:

package com;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * Servlet Filter implementation class UserCheckFilter
 */
public class UserCheckFilter implements Filter {
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        System.out.println("Hello World");
        
        chain.doFilter(request, response);
    }
}

Note que o método init e destroy pertencem à interface Filter e devem ser implementados. Estamos apenas exibindo “Hello World” para certificar que nosso filtro esteja correto e funcionando.

Temos agora que adicionar as seguintes tags ao arquivo web.xml:

<filter>
    <filter-name>UserCheckFilter</filter-name>
    <filter-class>com.UserCheckFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserCheckFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Explicando as tags: “url-pattern” define a url que estaremos mapeando, e em nosso caso estamos capturando qualquer url que for solicitada. “filter-name” define o nome do filtro mapeado que será acionado. O “filter-class” é a nossa classe Java que já foi criada.

Inicie o Tomcat e acesse pelo link: http://localhost:8080/Servlet/hello (caso você tenha problemas em visualizar a página, visite o primeiro post para tirar suas dúvidas: Criando um WebServer)
Olhe no console e veja que a nossa mensagem irá aparecer lá.
Hello World Screen

Com nosso filtro em pleno funcionamento, vamos criar uma classe de usuário. Um POJO simples, contendo nome do usuário e senha. Nossa classe ficará assim:

package com;

public class User {
    private String name = "UNKNOW";
    private String password = "UNKNOW";
    
    public User(String name, String password){
        this.name = name;
        this.password = password;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

Precisamos de um Servlet para fazer a validação de quem está acessando nosso servidor, vamos criá-lo de modo que valide nome/senha do usuário. Vamos criar nosso Servlet com um método para fazer essa validação (não vamos entrar em detalhes de patterns no momento).

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class UserValidator extends HttpServlet {
    private static final Map users = getUsers();
    
    /**
     * Creates valid users 
     * 
     * This User Map could be users returned from a database
     * or a simple select with the user.name
     * 
     * @return a Map of valid users
     */
    private static Map getUsers() {
        Map users = new HashMap();
        
        User userOne = new User("one","one");
        User userTwo = new User("two","TWO");
        
        users.put(userOne.getName(), userOne);
        users.put(userTwo.getName(), userTwo);
        
        return users;
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        doPost(req, res);
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        RequestDispatcher rd;
        String name = req.getParameter("name");
        String password = req.getParameter("password");
    
        User user = validateLogin(name, password);
        
        if (user == null){
            rd = req.getRequestDispatcher("/loginError.jsp");
        }
        else{
            HttpSession session = req.getSession();
            session.setAttribute("user", user);
            rd = req.getRequestDispatcher("/loginSuccess.jsp");
        }
        
        rd.forward(req, res);
    }

    /**
     * Validate the entered data
     * 
     * If there is no valid data, the method will return null
     * 
     * @param name given at the jsp
     * @param password given at the jsp
     * @return a user if one was found and validated
     */
    private User validateLogin(String name, String password) {
        // All parameters must be valid
        if (name == null || password == null){
            return null;
        }
        
        // Get a user by key
        User user = users.get(name);
        
        if (user == null){
            return null;
        }
        
        // Check if the password is valid
        if (!user.getPassword().equals(password.trim())){
            return null;
        }
        
        return user;
    }
}

O Map “users” e a função “getUsers” existem apenas para gerar usuários válidos. Caso nosso usuário não tenha seus dados válidos o método “validateLogin” retorna o valor null. Dependendo dos dados fornecidos pelo usuário, caso válido ele será redirecionado para a página de sucesso, caso contrário, irá para a página de erro.

Precisamos alterar o arquivo “web.xml” e adicionar o mapeamento do Servlet que acabamos de criar:

<servlet>
    <servlet-name>userValidator</servlet-name>
    <servlet-class>com.UserValidator</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>userValidator</servlet-name>
    <url-pattern>/userValidator</url-pattern>
</servlet-mapping>

Vamos criar 3 arquivos do tipo JSP, para: login, erro no login e login com sucesso:
/WebContent/login.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Login</title>
    </head>
    <body>
        <form action="/Servlet/userValidator" method="post">
            Name: <input type="text" name="name"/>
            Password: <input type="password" name="password"/>
            <input type="submit" value="LogIn"/>
        </form>
    </body>
</html>

/WebContent/loginError.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Error</title>
    </head>
    <body>
        Wrong user/password
    </body>
</html>

/WebContent/loginSuccess.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Success</title>
    </head>
    <body>
        You have loged in.
    </body>
</html>

Precisamos alterar agora nosso Filtro. Essa será a alteração mais delicada, pois será nosso filtro que irá definir se nosso usuário pode continuar em sua requisição ou não.

package com;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Servlet Filter implementation class UserCheckFilter
 */
public class UserCheckFilter implements Filter {
    private String LOGIN_ACTION_URI;
    
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        LOGIN_ACTION_URI = fConfig.getInitParameter("loginActionURI");
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        
        if (user == null && !LOGIN_ACTION_URI.equals(req.getRequestURI())){
            RequestDispatcher rd = req.getRequestDispatcher("/login.jsp");
            rd.forward(request, response);
            return;
        }
        
        chain.doFilter(request, response);
    }
}

Alguns detalhes sobre o código acima: “req.getSession()” – retorna a sessão do usuário, mas caso não tenha nenhuma sessão o próprio container fica encarregado de criar uma. Buscamos dentro da sessão o objeto usuário, em nosso servlet ao efetuar o login um objeto do tipo User é inserido na sessão. Caso não exista um objeto do tipo User na sessão, o valor retornado é null e com isso direcionamos o usuário para a tela de login. Note também que temos um atributo LOGIN_ACTION_URI que é retornado das configurações do filtro, ele será configurado daqui a pouco no arquivo web.xml. O atributo LOGIN_ACTION_URI existe para caso o usuário esteja tentando realizar a validação ele possa chegar ao nosso Servlet de validação de usuário, caso esse atributo não existisse, não seria possível realizar o login pois o objeto User nunca seria adicionado à sessão.

Falta agora colocar o parâmetro de inicialização do filtro no arquivo web.xml:

<filter>
    <filter-name>UserCheckFilter</filter-name>
    <filter-class>com.UserCheckFilter</filter-class>
    <init-param>
        <param-name>loginActionURI</param-name>
        <param-value>/Servlet/userValidator</param-value>
    </init-param>
</filter>

Ao acessar o link http://localhost:8080/Servlet/hello, o usuário será redirecionado para a página de login. Após digitar um usuário/senha que sejam válidos, ele terá sua sessão validada. E não será mais necessário realizar essa validação.

Caso tenha alguma dúvida/colocação a fazer, basta postar.

Até a próxima.