Arquivo de dezembro, 2014

No ciência da computação, Data Access Object é um padrão para um objeto que fornece uma interface abstrata para algum tipo de banco de dados ou outro mecanismo de persistência e que permite separar regras de negócio das regras de acesso a banco de dados. A vantagem de usar objetos de acesso a dados é a separação simples e rigorosa entre duas partes importantes de uma aplicação que não devem e não podem conhecer quase que nada uma da outra, e que podem evoluir frequentemente e independentemente.

O DAO implementa o mecanismo de acesso necessário para trabalhar com a fonte de dados. A fonte de dados pode ser um armazenamento persistente como um RDBMS, um serviço externo, como uma troca de B2B, um repositório como um banco de dados LDAP, um serviço de negócios acessado via CORBA, Internet Inter-ORB Protocol (IIOP) ou soquetes de baixo nível. O componente de negócio que se baseia no DAO usa a interface mais simples exposta pelo DAO para seus clientes.

DAO e Python

O DAO é um Pattern da Oracle J2EE para Java, entretanto se tornou um padrão muito popular na programação orientada a objeto, pois separa a logica de negocio da logica do banco de dados e consequentemente da interface com o usuário. Apesar das diferenças entre a linguagem orientada a objeto Java e Python o DAO pode ser usado sem problemas com algumas variações e sendo um padrão flexível e intuitivo é bem possível que você já o utilize nos seus códigos orientados a objeto.

DAO - CRUD - Python

DAO – CRUD – Python

DAO Pattern

O DAO é um padrão flexível e não uma regra ele é utilizado em conjunto com Factory Pattern e Broker Pattern (veja Patterns relacionados no link abaixo) por isto é comum você encontrar algumas variações de sua implementação, o padrão possui quatro especificações para que possa ser utilizado corretamente elas são: DataAccessObject, DataSourceObject, BussinesObject e TransferObject.

  1. DataAccessObjecté o objeto principal desse padrão. O Data Access Object abstrai a implementação fundamental de acesso a dados para o Business Objects para permitir acesso transparente à fonte de dados.
  2. DataSourceObjectrepresenta uma implementação da fonte de dados. Uma fonte de dados pode ser uma base de dados tal como um RDBMS, repositório XML, e assim por diante.
  3. BussinesObject – o objeto de negócios representa o dados do cliente. É o objeto que requer acesso à fonte de dados para obter e armazenar dados.
  4. TransferObjectrepresenta um objeto de transferência usado como um suporte de dados. O Data Access Object pode usar um objeto de transferência para retornar dados para o cliente. O Data Access Object também pode receber os dados do cliente em um objeto de transferência para atualizar os dados na fonte de dados.

DAO Pattern: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

CRUD – DAO

CRUD acrónimo de Create, Read, Update e Delete, utiliza as quatro operações básicas  para criação, consulta, atualização e exclusão de dados.

Através do padrão DAO vamos utilizar as operações CRUD para manipular dados no banco de dados. O DAO é um Pattern J2EE, mas como ele separa as regras de negocio do acesso a dados também podemos utiliza-lo com qualquer tipo de interface, seja pela linha de comando, uma GUI desktop ou aplicações web.

Para usar o DAO você utiliza o Factory Pattern para criar uma abstração para o acesso a dados e uma classe concreta para seu tipo de acesso como por exemplo OracleDAOFactory, DB2DAOFactory e assim por diante. Então você pode criar a interface para seu objeto DAO chamada DAOFuncionario e a partir da interface (Python não possui interfaces)  você pode criar as classes DAO como, DAOFuncionarioOracle, DAOFuncionarioDB2 e utiliza o objeto de transferência para manipular dados.

Neste exemplo não criamos uma classe abstrata utilizando o Pattern Factory Method, cortamos caminho pois utilizamos apenas um objeto DAO para todos os bancos de dados, mas caso deseje criar uma abstração para classes concretas para cada banco de dados siga a especificação oficial do DAO Pattern no link logo acima.

DAO - Python Packages

DAO – Python Packages

Utilize a imagem acima para ver a organização das Packges para cada classe e atente-se aos drivers utilizados para cada banco de dados.

Exemplo:

Neste exemplo usamos o Pattern DAO para criar operações CRUD utilizando uma interface gráfica, como este exemplo não possuí uma tela de login mude o acesso ao banco e usuário e senha diretamente na classe DAConexaoFactory.

O DAO  pode ser utilizado para varias soluções como no exemplo abaixo para enfatizar sua eficiência utilizamos o DAO em uma interface gráfica escrita com Tkinter justamente para mostrar a independência do negocio e acesso a dados.

Este é o terceiro método que disponibilizamos para manipular dados através de um banco de dados, para ver este mesmo programa utilizando SQL direto da aplicação clique aqui.

Pare ver este programa usando objetos no banco de dados como Views e Triggers clique aqui ou procure na busca também por Stored Procedures e cursores.

Ainda veremos outros métodos para manipular dados através de frameworks específicos.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

DB2

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2));

MSSQL

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

Python

Objeto – Negócio

# coding=utf-8
# Desenvolvimento Aberto
# Funcionario.py

__author__ = 'Desenvolvimento Aberto'

class Funcionario():

    # Define atributos privados
    def __init__(self):
        self.__id = None
        self.__nome = None
        self.__sobrenome = None
        self.__cargo = None
        self.__salario = None

    # Define métodos Getter e Setter
    # Você também pode optar por propriedades
    def getId(self):
        return self.__id

    def setId(self, id):
        self.__id = id

    def getNome(self):
        return self.__nome

    def setNome(self, nome):
        self.__nome = nome

    def getSobrenome(self):
        return self.__sobrenome

    def setSobrenome(self, sobrenome):
        self.__sobrenome = sobrenome

    def getCargo(self):
        return self.__cargo

    def setCargo(self, cargo):
        self.__cargo = cargo

    def getSalario(self):
        return self.__salario

    def setSalario(self, salario):
        self.__salario = salario

Factory Pattern – DAConexaoFactory

# coding=utf-8
# Desenvolvimento Aberto
# DAConexaoFactory.py

__author__ = 'Desenvolvimento Aberto'

# Importa fonte de dados
import cx_Oracle
import ibm_db
import odbc

class DAConexaoFactory():

    # Define atributos privados

    def __init__(self):
        self.__ORACLE = 1
        self.__DB2 = 2
        self.__MSSQL = 3
        self.__erroCon = None
        self.__factory = None
        self.__IBMDriver = None # IBM DB2 driver (ibm_db)

    # Cria Factory para objetos
    def getConexao(self, banco):

        # Define conexão e fonte de dados
        con = None
        self.__factory = banco

        # Cria string de conexão Oracle
        if (banco == self.__ORACLE):
            sconexao = "user/pass@localhost/XE"
            try:
                con = cx_Oracle.connect(sconexao)
            except Exception, e:
                self.__erroCon = str(e)

        # Cria string de conexão IBM DB2
        if (banco == self.__DB2):
            sconexao = "DATABASE=DEVA" + \
                       ";HOSTNAME=localhost;PORT=50000;PROTOCOL=TCPIP;" + \
                       "UID=user;" + \
                       "PWD=pass"
            try:
                self.__IBMDriver = ibm_db
                con = ibm_db.connect(sconexao, "", "")
            except Exception, e:
                self.__erroCon = str(e)

        # Cria string de conexão MSSQL
        if (banco == self.__MSSQL):
            sconexao = "MSSQLSERVER/user/pass"
            try:
                con = odbc.odbc(sconexao)
            except Exception, e:
                self.__erroCon = str(e)

        return con

    # Retorna Erros
    def getErros(self):
        return self.__erroCon

    # Retorna Factory da conexão
    def getFactory(self):
        return self.__factory

    # Retorna Driver da IBM (Oracle e MSSQL possui outro padrão)
    def getIbmDriver(self):
        return self.__IBMDriver

Objeto DAO – FuncionarioDAO

# coding=utf-8
# Desenvolvimento Aberto
# FuncionarioDAO.py

__author__ = 'Desenvolvimento Aberto'

# Importa pacotes DAO
from DesenvolvimentoAberto.Modelo.Funcionario import Funcionario
from DesenvolvimentoAberto.Conexao.DAConexaoFactory import DAConexaoFactory

class FuncionarioDAO():

    # Construtor da classe
    def __init__(self):
        self.__erro = None
        self.__con = None
        self.__factory = None
        self.__IBMDriver = None
        try:
            # Cria Conexão com o Factory Method Pattern
            # Você pode ter uma classe para cada fonte de dados
            # Unimos as três fontes para o exemplo
            conexao = DAConexaoFactory()
            self.__con = conexao.getConexao(3)
            self.__factory = conexao.getFactory()
            self.__IBMDriver = conexao.getIbmDriver()
        except Exception, e:
            self.__erro = str(e)

    # Metodo de Manipulação de dados

    def buscaFuncionario(self, id):

        # Cria instancia do objeto
        funcionario = Funcionario()

        # Define SQL
        sql = "SELECT * FROM FUNCIONARIOS WHERE ID_FUNCIONARIO = " + str(id)

        # Executa SQL
        try:
            if (self.__factory != 2):
                cursor= self.__con.cursor()
                cursor.execute(sql)
                dados = cursor.fetchone()

            else:
                cursor = self.__IBMDriver.exec_immediate(self.__con, sql)
                dados  = self.__IBMDriver.fetch_tuple(cursor)

        except Exception, e:
            self.__erro = str(e)

        # Alimenta objeto
        funcionario.setId(dados[0])
        funcionario.setNome(dados[1])
        funcionario.setSobrenome(dados[2])
        funcionario.setCargo(dados[3])
        funcionario.setSalario(dados[4])

        # Retorna Objeto
        return funcionario

    def insereFuncionario(self, funcionario ):

        # Define SQL
        # Troca decimal é requerido se Oracle/DB2 for ptbr.
        sql = "INSERT INTO FUNCIONARIOS VALUES (" + \
              funcionario.getId() + ", '" + \
              funcionario.getNome() + "', '" + \
              funcionario.getSobrenome() + "', '" + \
              funcionario.getCargo() + "', " + \
              str(funcionario.getSalario()).replace(",",".") + ")"

        # Executa SQL
        try:
             if (self.__factory != 2):
                 cursor=self.__con.cursor()
                 cursor.execute(sql)
                 self.__con.commit()
                 return True
             else:
                 cursor = self.__IBMDriver.exec_immediate(self.__con, sql)
                 return True

        except Exception, e:
            self.__erro = str(e)
            return False

    def alteraFuncionario(self, funcionario):

       #  Define SQL
       sql = "UPDATE FUNCIONARIOS SET " + \
             "ID_FUNCIONARIO = " + funcionario.getId() + ", " + \
             "NOME = '" + funcionario.getNome() + "', " + \
             "SOBRENOME = '" + funcionario.getSobrenome() + "', " + \
             "CARGO = '" + funcionario.getCargo() + "', " + \
             "SALARIO = " + str(funcionario.getSalario()).replace(",",".") + \
             " WHERE ID_FUNCIONARIO = " + funcionario.getId()

       # Executa SQL
       try:
           if (self.__factory != 2):
               cursor=self.__con.cursor()
               cursor.execute(sql)
               self.__con.commit()
               return True
           else:
               cursor = self.__IBMDriver.exec_immediate(self.__con, sql)
               return True

       except Exception, e:
           self.__erro = str(e)
           return False

    def apagarFuncionario(self, funcionario):

        # Define SQL
        sql = "DELETE FROM FUNCIONARIOS WHERE ID_FUNCIONARIO = " + funcionario.getId()

        # Executa SQL
        try:
            if (self.__factory != 2):
                cursor=self.__con.cursor()
                cursor.execute(sql)
                self.__con.commit()
                return True
            else:
                cursor = self.__IBMDriver.exec_immediate(self.__con, sql)
                return True

        except Exception, e:
            self.__erro = str(e)
            return False

    # Retorna Erro
    def getErro(self):
        return self.__erro

GUI – DADaoApp

#!/usr/bin/env python
# coding=utf-8
# Desenvolvimento Aberto
# DADaoApp.py

# importa modulos
from Tkinter import *
from DesenvolvimentoAberto.Modelo.Funcionario import Funcionario
from DesenvolvimentoAberto.Dao.FuncionarioDAO import FuncionarioDAO
import tkMessageBox

class DADaoApp(Frame):

    def __init__(self, formulario=None):

        # Define formulario
        Frame.__init__(self, formulario)

        # Cria Widgets
        self.titulo = Label(formulario, text="DAO - Pattern")
        self.separador1 = Frame(height=2, bd=1, relief=SUNKEN)
        self.separador2 = Frame(height=2, bd=1, relief=SUNKEN)

        # labels
        self.lcodigo = Label(formulario, text="Codigo:")
        self.lpnome = Label(formulario, text="Nome:")
        self.lsnome = Label(formulario, text="Sobrenome:")
        self.lcargo = Label(formulario, text="Cargo:")
        self.lsalario = Label(formulario, text="Salario:")

        # Entry
        self.tcodigo = Entry(formulario, width=20)
        self.tpnome = Entry(formulario, width=50)
        self.tsnome = Entry(formulario, width=45)
        self.tcargo = Entry(formulario, width=35)
        self.tsalario = Entry(formulario, width=30)

        # Pesquisa
        self.lpesquisa = Label(formulario, text="Pesquisa:")
        self.tpesquisa = Entry(formulario)
        self.botao = Button(formulario, text="Pesquisar", command=self.on_Pesquisar)

        # Ações
        self.painel = Frame()
        self.bnovo = Button(self.painel, text="Novo", command=self.on_novo, width=8)
        self.binserir = Button(self.painel, text="Inserir", command=self.on_inserir, width=8)
        self.balterar = Button(self.painel, text="Alterar", command=self.on_alterar, width=8)
        self.bapagar = Button(self.painel, text="Apagar", command=self.on_apagar, width=8)

        # Cria janela para menssagem
        self.janela = Tk()
        self.janela.wm_withdraw()

        # Define Layout
        self.titulo.grid(row=0, sticky=W+E+N+S, pady=20)
        self.separador1.grid(row=1, sticky=W+E+N+S, columnspan=3)

        # Define Layout Dados
        self.lcodigo.grid(row=3, sticky=W, padx=20)
        self.tcodigo.grid(row=3, column=1, pady=5, sticky=W)
        self.lpnome.grid(row=4, sticky=W, padx=20)
        self.tpnome.grid(row=4, column=1, pady=5, sticky=W)
        self.lsnome.grid(row=5, sticky=W, padx=20)
        self.tsnome.grid(row=5, column=1, pady=5, sticky=W)
        self.lcargo.grid(row=6, sticky=W, padx=20)
        self.tcargo.grid(row=6, column=1, pady=5, sticky=W)
        self.lsalario.grid(row=7, sticky=W, padx=20)
        self.tsalario.grid(row=7, column=1, pady=5, sticky=W)

        # Layout pesquisa
        self.lpesquisa.grid(row=2, column=0, pady=20)
        self.tpesquisa.grid(row=2, column=1, pady=20)
        self.botao.grid(row=2, column=2, padx=10, pady=20)

        # Loayout Ações
        self.bnovo.grid(row=1, column=0, pady=10, padx=5)
        self.binserir.grid(row=1, column=1, pady=10, padx=5)
        self.balterar.grid(row=1, column=2, pady=10, padx=5)
        self.bapagar.grid(row=1, column=3, pady=10, padx=5)
        self.separador2.grid(row=9, sticky=W+E, columnspan=3, pady=10)
        self.painel.grid(row=10, sticky=W+E+S, column=1, columnspan=1)

    # Limpa campo
    def limpar(self):
        self.tcodigo.delete(0, END)
        self.tpnome.delete(0, END)
        self.tsnome.delete(0, END)
        self.tcargo.delete(0, END)
        self.tsalario.delete(0, END)

    # Evento do botão
    def on_Pesquisar(self):

        # Cria objetos Modelo e DAO
        funcionario = Funcionario()
        pesquisar = FuncionarioDAO()

        # Executa trasferencia de Objetos
        try:
            funcionario = pesquisar.buscaFuncionario(self.tpesquisa.get())
        except ValueError:
            tkMessageBox.showinfo(title="Erro", message=pesquisar.getErro(), parent=self.janela)

        # Exibe dados
        self.limpar()
        self.tcodigo.insert(0, str(funcionario.getId()))
        self.tpnome.insert(0, funcionario.getNome())
        self.tsnome.insert(0, funcionario.getSobrenome())
        self.tcargo.insert(0, funcionario.getCargo())
        self.tsalario.insert(0, str(funcionario.getSalario()))

    # limpa widgets
    def on_novo(self):
        self.limpar()
        self.tcodigo.focus()

    # Insere dados
    def on_inserir(self):

        # Cria objeto Modelo
        funcionario = Funcionario()

        # Alimenta dados ao objeto
        funcionario.setId(self.tcodigo.get())
        funcionario.setNome(self.tpnome.get())
        funcionario.setSobrenome(self.tsnome.get())
        funcionario.setCargo(self.tcargo.get())
        funcionario.setSalario(self.tsalario.get())

        # Cria objeto DAO
        inserir = FuncionarioDAO()

        # Executa trasferencia de Objetos
        resultado = inserir.insereFuncionario(funcionario)

        # Exibe Resultado
        if (resultado):
            tkMessageBox.showinfo(title="Menssagem", message="Dados inseridos com suscesso!", parent=self.janela)
        else:
            tkMessageBox.showinfo(title="Erro", message=inserir.getErro(), parent=self.janela)

    # Altera dados
    def on_alterar(self):
        # Cria objeto Modelo
        funcionario = Funcionario()

        # Alimenta objeto
        funcionario.setId(self.tcodigo.get())
        funcionario.setNome(self.tpnome.get())
        funcionario.setSobrenome(self.tsnome.get())
        funcionario.setCargo(self.tcargo.get())
        funcionario.setSalario(self.tsalario.get())

        # Cria objeto DAO
        alterar = FuncionarioDAO()

        # # Executa trasferencia de Objetos
        resultado = alterar.alteraFuncionario(funcionario)

        # Exibe resultado
        if (resultado):
            tkMessageBox.showinfo(title="Menssagem", message="Dados alterados com suscesso!", parent=self.janela)
        else:
            tkMessageBox.showinfo(title="Erro", message=alterar.getErro(), parent=self.janela)

    # Exclui dados
    def on_apagar(self):

        # Cria objeto Modelo
        funcionario = Funcionario()

        # Alimenta objeto
        funcionario.setId(self.tcodigo.get())
        funcionario.setNome(self.tpnome.get())
        funcionario.setSobrenome(self.tsnome.get())
        funcionario.setCargo(self.tcargo.get())
        funcionario.setSalario(self.tsalario.get())

        #Cria objeto DAO
        apagar = FuncionarioDAO()

        # Executa trasferencia de Objetos
        resultado = apagar.apagarFuncionario(funcionario)

        # Exibe resultado
        if (resultado):
            tkMessageBox.showinfo(title="Menssagem", message="Dados apagados com suscesso!", parent=self.janela)
            self.limpar()
        else:
            tkMessageBox.showinfo(title="Erro", message=apagar.getErro(), parent=self.janela)

# loop do tcl
root = Tk()
root.title('DA - DAO - Data Access Object')
app = DADaoApp(formulario=root)
app.mainloop()
root.destroy()

 

No ciência da computação, Data Access Object é um padrão para um objeto que fornece uma interface abstrata para algum tipo de banco de dados ou outro mecanismo de persistência e que permite separar regras de negócio das regras de acesso a banco de dados. A vantagem de usar objetos de acesso a dados é a separação simples e rigorosa entre duas partes importantes de uma aplicação que não devem e não podem conhecer quase que nada uma da outra, e que podem evoluir frequentemente e independentemente.

O DAO implementa o mecanismo de acesso necessário para trabalhar com a fonte de dados. A fonte de dados pode ser um armazenamento persistente como um RDBMS, um serviço externo, como uma troca de B2B, um repositório como um banco de dados LDAP, um serviço de negócios acessado via CORBA, Internet Inter-ORB Protocol (IIOP) ou soquetes de baixo nível. O componente de negócio que se baseia no DAO usa a interface mais simples exposta pelo DAO para seus clientes.

Microsoft, C# e DAO

O DAO Pattern J2EE não deve ser confundido com o DAO método de acesso a dados da Microsoft . O DAO (Microsoftfornece um quadro para a utilização de código para criar e manipular bancos de dados através de um conjunto hierárquico de objetos que usam o mecanismo de banco de dados Microsoft Jet para arquivos MDB, ou através de ODBC ou também banco de dados IASM como o antigo DBase, Paradox entre outros. O DAO Microsoft é considerado obsoleto e não é suportado pelo .NET Framework.

Devido a similaridade do C# com o Java é possível utilizar integralmente o DAO Pattern que é um padrão já consagrado por desenvolvedores Java para separar a camada de negocio da camada do banco de dados. O DAO é um célebre Pattern utilizado sozinho ou também em conjunto com outros frameworks, provavelmente alguns desenvolvedores C# já o utilizaram de algum modo, implicitamente ou explicitamente, mesmo sem o conhecer em detalhes.

DAO - CRUD - C#

DAO – CRUD – C#

DAO Pattern

O DAO é um padrão flexível e não uma regra ele é utilizado em conjunto com Factory Pattern e Broker Pattern (veja Patterns relacionados no link abaixo) por isto é comum você encontrar algumas variações de sua implementação, o padrão possui quatro especificações para que possa ser utilizado corretamente elas são: DataAccessObject, DataSourceObject, BussinesObject e TransferObject.

  1. DataAccessObjecté o objeto principal desse padrão. O Data Access Object abstrai a implementação fundamental de acesso a dados para o Business Objects para permitir acesso transparente à fonte de dados.
  2. DataSourceObjectrepresenta uma implementação da fonte de dados. Uma fonte de dados pode ser uma base de dados tal como um RDBMS, repositório XML, e assim por diante.
  3. BussinesObject – o objeto de negócios representa o dados do cliente. É o objeto que requer acesso à fonte de dados para obter e armazenar dados.
  4. TransferObjectrepresenta um objeto de transferência usado como um suporte de dados. O Data Access Object pode usar um objeto de transferência para retornar dados para o cliente. O Data Access Object também pode receber os dados do cliente em um objeto de transferência para atualizar os dados na fonte de dados.

DAO Pattern: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

CRUD – DAO

CRUD acrónimo de Create, Read, Update e Delete, utiliza as quatro operações básicas  para criação, consulta, atualização e exclusão de dados.

Através do padrão DAO vamos utilizar as operações CRUD para manipular dados no banco de dados. O DAO é um Patter J2EE, mas como ele separa as regras de negocio do acesso a dados também podemos utiliza-lo com qualquer tipo de interface, seja pela linha de comando, uma GUI desktop ou aplicações web.

Para usar o DAO você utiliza o Factory Pattern para criar uma abstração para o acesso a dados e uma classe concreta para seu tipo de acesso como por exemplo OracleDAOFactory, DB2DAOFactory e assim por diante. Então você pode criar a interface para seu objeto DAO chamada DAOFuncionario e a partir da interface você pode criar as classes DAO como, DAOFuncionarioOracle, DAOFuncionarioDB2 e utilizar o objeto de transferência para manipular os dados.

Neste exemplo não criamos uma classe abstrata utilizando o Pattern Factory, cortamos caminho pois utilizamos apenas um objeto DAO para todos os bancos de dados, mas caso deseje criar uma abstração para classes concretas para cada banco de dados siga a especificação oficial do DAO Pattern no link logo acima.

Visual Studio

Crie um design como na figura abaixo, utilizando 3 Panels, 7 Labels, 6 TextBox e 5 Buttons:

Design Time

Design Time

Atente-se a organização dos Namespaces para cada classe e os drivers utilizados para cada banco de dados.

Exemplo:

Neste exemplo usamos o Pattern DAO para criar operações CRUD utilizando uma interface gráfica, como este exemplo não possuí uma tela de login mude o acesso ao banco e usuário e senha diretamente na classe FuncionarioDAO.

Este é o terceiro método que disponibilizamos para manipular dados através de um banco de dados, para ver este mesmo programa utilizando SQL direto da aplicação clique aqui.

Pare ver este programa usando objetos no banco de dados como Views e Triggers clique aqui ou procure na busca também por Stored Procedures e cursores.

Ainda veremos outros métodos para manipular dados através de frameworks específicos como Entity Framework e outros.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

DB2

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2));

MSSQL

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

C#

Objeto – Funcionario

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesenvolvimentoAberto.Modelo
{
    class Funcionario
    {
        // Declara atributos
        private long id;
        private string nome;
        private string sobrenome;
        private string cargo;
        private double salario;

        // Declara construtor padrão
        public Funcionario()
        {

        }

        // Declara construtor overload
        public Funcionario(long id, string nome, string sobrenome,
            string cargo, double salario)
        {
            this.id = id;
            this.nome = nome;
            this.sobrenome = sobrenome;
            this.cargo = cargo;
            this.salario = salario;
        }

        // Declara propriedades
        // Caso deseje pode utilizar metodos Getter e Setters
        public long Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }
        public string Nome
        {
            get
            {
                return nome;
            }
            set
            {
                nome = value;
            }
        }
        public string Sobrenome
        {
            get
            {
                return sobrenome;
            }
            set
            {
                sobrenome = value;
            }
        }
        public string Cargo
        {
            get
            {
                return cargo;
            }
            set
            {
                cargo = value;
            }
        }
        public double Salario
        {
            get
            {
                return salario;
            }
            set
            {
                salario = value;
            }
        }

    }
}

Factory Pattern – DAConexaoFactory

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Data.SqlClient;    // ADO.NET
using Oracle.DataAccess.Client; // ODAC 12c
using IBM.Data.DB2;             // IBM Data Server Provider

using System.Data.Common;       // DbProviderFactory

namespace DesenvolvimentoAberto.Conexao
{

    class DACconexaoFactory : DbProviderFactory
    {
        // Cria objetos de conexão
        private static string connectionString;
        private static DbConnection connUnica = null;
        private static Exception erro;

        // Define tipos de datasource
        public static readonly int ORACLE = 1;
        public static readonly int DB2 = 2;
        public static readonly int MSSQL = 3;

        // Define Driver
        private static System.Data.Common.DbProviderFactory factory;

        // cria conexões
        // você pode alimentar o nome do servidor, timeout e banco de dados
        // de alguma configuração global ou como achar melhor.

        public static DbConnection getConexao(int fabrica, string usuario, string senha)
        {
           factory = new DACconexaoFactory();

           if (fabrica == ORACLE)
            {
                try
                {
                    // String de Conexao
                    connectionString = 

                    // Usuario
                    "User Id=" + usuario + 

                    // Senha
                    ";Password=" + senha + 

                    // TNSnames
                    ";Data Source=xe";

                    // ODAC 12c
                    factory =  DbProviderFactories.GetFactory("Oracle.DataAccess.Client");

                    connUnica = factory.CreateConnection();
                    connUnica.ConnectionString = connectionString;
                    connUnica.Open();
                }

                 catch (Exception ex)
                {
                    erro = ex;
                }
            }

           if (fabrica == DB2)
           {
               try
               {
                   // String de Conexao
                   connectionString =

                   // Servidor
                   "Server=localhost" +

                   // Banco de dados
                   ";Database=DEVA" + 

                   // Usuario
                   ";UID=" + usuario +

                   // Senha
                   ";PWD=" + senha +

                   // TNSnames
                   ";Connect Timeout=40";

                   // IBM DATA Server Provider
                   factory = DbProviderFactories.GetFactory("IBM.Data.DB2");

                   connUnica = factory.CreateConnection();
                   connUnica.ConnectionString = connectionString;
                   connUnica.Open();
               }

               catch (Exception ex)
               {
                   erro = ex;
               }
           }

           if (fabrica == MSSQL)
           {
               try
               {
                   // String de Conexao
                   connectionString =

                   // Servidor
                   "Server=localhost" + 

                   // Banco de dados
                   ";Database=DevAberto" + 

                   // Usuario
                   ";UID=" + usuario +

                   // Senha
                   ";PWD=" + senha +

                   // TNSnames
                   ";Connect Timeout=40";

                   // ADO NET Nativo - MSSQL Server
                   factory = DbProviderFactories.GetFactory("System.Data.SqlClient");

                   connUnica = factory.CreateConnection();
                   connUnica.ConnectionString = connectionString;
                   connUnica.Open();
               }

               catch (Exception ex)
               {
                   erro = ex;
               }
           }
            return  connUnica;
        }

        // Recupera Driver
        public static DbProviderFactory getFactory()
        {
            return factory;
        }
        // Recupera Erro
        public static Exception getErro()
        {
            return erro;
        }

    }
}

Interface – IFuncionarioDAO

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using DesenvolvimentoAberto.Modelo;

namespace DesenvolvimentoAberto.Dao
{
    interface IFuncionarioDAO
    {
        // Cria interface
        // A interface propricia os retornos corretos de cada operação.

        Funcionario buscaFuncionario(string id);

        Boolean insereFuncionario(Funcionario funcionario);

        Boolean updateFuncionario(Funcionario funcionario);

        Boolean deletaFuncionario(Funcionario funcionario);

        // TODO: Insira outros metodos que você deseje que sejam obrigatorios.

    }
}

Objeto DAO – FuncionarioDAO

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Common;
using System.Data.SqlTypes;

using DesenvolvimentoAberto.Conexao;
using DesenvolvimentoAberto.Modelo;

namespace DesenvolvimentoAberto.Dao
{
    class FuncionarioDAO : IFuncionarioDAO
    {
        // Declara objetos
        private DbConnection conn;
        private Exception erro;
        private string sql;

        public FuncionarioDAO()
        {
            // Como o exemplo não possui uma tela de login
            // utilizamos uma adaptação no construtor da classe
            // você pode utilizar um login para que o factory da conexão
            // use a string de conexão completa.

            try
            {
                this.conn = DACconexaoFactory.getConexao(1, "user", "password");
            }
            catch
            {
                erro = DACconexaoFactory.getErro();
            }

        }
        public Modelo.Funcionario buscaFuncionario(string id)
        {
            // Cria objeto
            Funcionario funcionario = new Funcionario();

            sql = sql = "SELECT * FROM FUNCIONARIOS WHERE ID_FUNCIONARIO = " + id;

            try
            {
                // Cria Conexão Driver especifico
                DbCommand cmd = DACconexaoFactory.getFactory().CreateCommand();
                cmd.Connection = conn;
                cmd.CommandText = sql;
                cmd.ExecuteNonQuery();

                // Cria set de dados
                DbDataReader dados = cmd.ExecuteReader();

                // Converte Decimal para Double para IBM DB2 e MSSQL
                if (dados.HasRows)
                {
                    while (dados.Read())
                    {
                        funcionario.Id = dados.GetInt32(0);
                        funcionario.Nome = dados.GetString(1);
                        funcionario.Sobrenome = dados.GetString(2);
                        funcionario.Cargo = dados.GetString(3);
                        funcionario.Salario = Convert.ToDouble(dados.GetDecimal(4));
                    }
                }

            }
            catch (Exception ex)
            {
                // Retorna erro
                erro = ex;
            }
            return funcionario;
        }

        public bool insereFuncionario(Modelo.Funcionario funcionario)
        {
            // Define SQL
            // Troca decimal é requerido se Oracle/DB2 for ptbr.
            sql = "INSERT INTO FUNCIONARIOS VALUES ("
                + funcionario.Id + ", '" +
                  funcionario.Nome + "', '" +
                  funcionario.Sobrenome + "', '" +
                  funcionario.Cargo + "', " +
                  trocaDecimal(Convert.ToString(funcionario.Salario)) + ")";

            try
            {
                // Cria Conexão Driver especifico
                DbCommand cmd = DACconexaoFactory.getFactory().CreateCommand();
                cmd.Connection = conn;
                cmd.CommandText = sql;

                cmd.ExecuteNonQuery();
                conn.Close();
                return true;
            }
            catch (Exception ex)
            {
                // Retorna erro
                erro = ex;
            }

            return false;
        }

        public bool updateFuncionario(Modelo.Funcionario funcionario)
        {
            // Define SQL
            sql = "UPDATE FUNCIONARIOS SET " +
                "ID_FUNCIONARIO = " + funcionario.Id + ", " +
                "NOME = '" + funcionario.Nome + "', " +
                "SOBRENOME = '" + funcionario.Sobrenome + "', " +
                "CARGO = '" + funcionario.Cargo + "', " +
                "SALARIO = " + trocaDecimal(Convert.ToString(funcionario.Salario)) +
                "WHERE ID_FUNCIONARIO = " + funcionario.Id;
            try
            {
                // Cria Conexão Driver especifico
                DbCommand cmd = DACconexaoFactory.getFactory().CreateCommand();
                cmd.Connection = conn;
                cmd.CommandText = sql;

                cmd.ExecuteNonQuery();
                conn.Close();
                return true;
            }
            catch (Exception ex)
            {
                // Retorna erro
                erro = ex;
            }

            return false;
        }

        public bool deletaFuncionario(Modelo.Funcionario funcionario)
        {
            // Define SQL
            sql = "DELETE FROM FUNCIONARIOS WHERE ID_FUNCIONARIO = " + funcionario.Id;

            try
            {
                // Cria Conexão Driver especifico
                DbCommand cmd = DACconexaoFactory.getFactory().CreateCommand();
                cmd.Connection = conn;
                cmd.CommandText = sql;

                cmd.ExecuteNonQuery();
                conn.Close();
                return true;
            }
            catch (Exception ex)
            {
                // Retorna erro
                erro = ex;
            }

            return false;
        }

        private static String trocaDecimal(string conteudo)
        {
            // Substitui decimal na manipulação de SQL
            return conteudo.Replace(",", ".");
        }

        // Retorna erro
        public string getErro()
        {
            return erro.ToString();
        }
    }
}

GUI – Aplicação – Windows Form

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using DesenvolvimentoAberto.Modelo;
using DesenvolvimentoAberto.Dao;

namespace DACampos
{

    public partial class Campos : Form
    {

        public Campos()
        {
            InitializeComponent();
        }

        // Utiliza DAO

        // Evento de clique do botão Pesquisar
        private void button1_Click(object sender, EventArgs e)
        {
            // Cria objeto
            Funcionario funcionario = new Funcionario();

            // Executa busca
            funcionario = new FuncionarioDAO().buscaFuncionario(textBox6.Text);

            // Verifica resultado
            long resultado = funcionario.Id;

            if (resultado != 0)
            {
                textBox1.Text = Convert.ToString(funcionario.Id);
                textBox2.Text = funcionario.Nome;
                textBox3.Text = funcionario.Sobrenome;
                textBox4.Text = funcionario.Cargo;
                textBox5.Text = Convert.ToString(funcionario.Salario);
            }
            else
            {
                MessageBox.Show("Funcionário não encontrado!");
                textBox6.Focus();
                textBox6.SelectAll();
            }

        }

        private static String trocaDecimal(string conteudo)
        {
            // Substitui decimal na manipulação de SQL
            return conteudo.Replace(".", ",");
        }

        // Novo registro
        private void button2_Click(object sender, EventArgs e)
        {
            // Limpa componentes
            textBox1.Text = null;
            textBox2.Text = null;
            textBox3.Text = null;
            textBox4.Text = null;
            textBox5.Text = null;

            // Define foco
            textBox1.Focus();
        }

        // Insere registro
        private void button3_Click(object sender, EventArgs e)
        {
            // Cria objeto do modelo usando o construtor overload
            Funcionario funcionario = new Funcionario(Convert.ToInt32(textBox1.Text),
                textBox2.Text, textBox3.Text, textBox4.Text, Convert.ToDouble(trocaDecimal(textBox5.Text)));

            // cria objeto DAO
            FuncionarioDAO inserir = new FuncionarioDAO();

            // Insere objeto
            Boolean resultado = inserir.insereFuncionario(funcionario);

            // Verifica resultado
            if (resultado)
            {
                MessageBox.Show("Dados inseridos com sucesso");
            }
            else
            {
                MessageBox.Show("Erro ao inserir dados:" + Environment.NewLine +
                    Environment.NewLine +
                    inserir.getErro());
            }

        }

        // Altera registro
        private void button4_Click(object sender, EventArgs e)
        {
            // Cria objeto do modelo usando o construtor overload
            Funcionario funcionario = new Funcionario(Convert.ToInt32(textBox1.Text),
               textBox2.Text, textBox3.Text, textBox4.Text, Convert.ToDouble(trocaDecimal(textBox5.Text)));

            // Cria objeto DAO
            FuncionarioDAO alterar = new FuncionarioDAO();

            // Altera Objeto
            Boolean resultado = alterar.updateFuncionario(funcionario);

            // Verifica resultado
            if (resultado)
            {
                MessageBox.Show("Dados alterados com sucesso");
            }
            else
            {
                MessageBox.Show("Erro ao alterar dados:" + Environment.NewLine +
                    Environment.NewLine +
                    alterar.getErro());
            }
        }

        // Deleta registro
        private void button5_Click(object sender, EventArgs e)
        {
            // Cria objeto do modelo usando o construtor overload
            Funcionario funcionario = new Funcionario(Convert.ToInt32(textBox1.Text),
               textBox2.Text, textBox3.Text, textBox4.Text, Convert.ToDouble(trocaDecimal(textBox5.Text)));

            // Cria objeto DAP
            FuncionarioDAO apagar = new FuncionarioDAO();

            // Deleta objeto
            Boolean resultado = apagar.deletaFuncionario(funcionario);

            // verifica resultado
            if (resultado)
            {
                MessageBox.Show("Dados apagados com sucesso");
                button2.PerformClick();
                textBox6.Focus();
            }
            else
            {
                MessageBox.Show("Erro ao alterar dados:" + Environment.NewLine +
                    Environment.NewLine +
                    apagar.getErro());
            }
        }
    }
}

 

No ciência da computação, Data Access Object é um padrão para um objeto que fornece uma interface abstrata para algum tipo de banco de dados ou outro mecanismo de persistência e que permite separar regras de negócio das regras de acesso a banco de dados. A vantagem de usar objetos de acesso a dados é a separação simples e rigorosa entre duas partes importantes de uma aplicação que não devem e não podem conhecer quase que nada uma da outra, e que podem evoluir frequentemente e independentemente.

O DAO implementa o mecanismo de acesso necessário para trabalhar com a fonte de dados. A fonte de dados pode ser um armazenamento persistente como um RDBMS, um serviço externo, como uma troca de B2B, um repositório como um banco de dados LDAP, um serviço de negócios acessado via CORBA, Internet Inter-ORB Protocol (IIOP) ou soquetes de baixo nível. O componente de negócio que se baseia no DAO usa a interface mais simples exposta pelo DAO para seus clientes.

CRUD - DAO

CRUD – DAO

DAO Pattern

O DAO é um padrão flexível e não uma regra ele é utilizado em conjunto com Factory Pattern e Broker Pattern (veja Patterns relacionados no link abaixo) por isto é comum você encontrar algumas variações de sua implementação, o padrão possui quatro especificações para que possa ser utilizado corretamente elas são: DataAccessObject, DataSourceObject, BussinesObject e TransferObject.

  1. DataAccessObjecté o objeto principal desse padrão. O Data Access Object abstrai a implementação fundamental de acesso a dados para o Business Objects para permitir acesso transparente à fonte de dados.
  2. DataSourceObjectrepresenta uma implementação da fonte de dados. Uma fonte de dados pode ser uma base de dados tal como um RDBMS, repositório XML, e assim por diante.
  3. BussinesObject – o objeto de negócios representa o dados do cliente. É o objeto que requer acesso à fonte de dados para obter e armazenar dados.
  4. TransferObjectrepresenta um objeto de transferência usado como um suporte de dados. O Data Access Object pode usar um objeto de transferência para retornar dados para o cliente. O Data Access Object também pode receber os dados do cliente em um objeto de transferência para atualizar os dados na fonte de dados.

DAO Pattern: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

CRUD – DAO

CRUD acrónimo de Create, Read, Update e Delete, utiliza as quatro operações básicas  para criação, consulta, atualização e exclusão de dados.

Através do padrão DAO vamos utilizar as operações CRUD para manipular dados no banco de dados. O DAO é um Patter J2EE, mas como ele separa as regras de negocio do acesso a dados também podemos utiliza-lo com qualquer tipo de interface, seja pela linha de comando, uma GUI desktop ou aplicações web.

Para usar o DAO você utiliza o Factory Pattern para criar uma abstração para o acesso a dados e uma classe concreta para seu tipo de acesso como por exemplo OracleDAOFactory, DB2DAOFactory e assim por diante. Então você pode criar a interface para seu objeto DAO chamada DAOFuncionario e a partir da interface você pode criar as classes DAO como, DAOFuncionarioOracle, DAOFuncionarioDB2 e utilizar o objeto de transferência para manipular dados.

Neste exemplo não criamos uma classe abstrata utilizando o Pattern Factory, cortamos caminho pois utilizamos apenas um objeto DAO para todos os bancos de dados, mas caso deseje criar uma abstração para classes concretas para cada banco de dados siga a especificação oficial do DAO Pattern no link logo acima.

Eclipse IDE - Drivers - Oracle - DB2 - MSSQL

Eclipse IDE – Drivers – Oracle – DB2 – MSSQL

Utilize a imagem acima para ver a organização das Packges para cada classe e os drivers utilizados para cada banco de dados.

Exemplo:

Neste exemplo usamos o Pattern DAO para criar operações CRUD utilizando uma interface gráfica, como este exemplo não possuí uma tela de login mude o acesso ao banco e usuário e senha diretamente na classe FuncionarioDAO.

Este é o terceiro método que disponibilizamos para manipular dados através de um banco de dados, para ver este mesmo programa utilizando SQL direto da aplicação clique aqui.

Pare ver este programa usando objetos no banco de dados como Views e Triggers clique aqui ou procure na busca também por Stored Procedures e cursores.

Ainda veremos outros métodos para manipular dados através de frameworks específicos como JPA e outros.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

DB2

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2));

MSSQL

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

Java

JavaBean – Funcionario

package org.desenvolvimento.aberto.modelo;

// Modelos utilizam JavaBean
public class Funcionario {

	// Declara atributos
	private long Id;
	private String nome;
	private String sobrenome;
	private String cargo;
	private double salario;

	// Método construtor padrão do JavaBean
	public Funcionario() {

	}

	// Método construtor Overload
	public Funcionario(long id, String nome, String sobrenome, String cargo,
			double salario) {
		this.Id = id;
		this.nome = nome;
		this.sobrenome = sobrenome;
		this.cargo = cargo;
		this.salario = salario;
	}

	// Declara métodos Getters e Setters
	public long getId() {
		return Id;
	}

	public void setId(long id) {
		Id = id;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getSobrenome() {
		return sobrenome;
	}

	public void setSobrenome(String sobrenome) {
		this.sobrenome = sobrenome;
	}

	public String getCargo() {
		return cargo;
	}

	public void setCargo(String cargo) {
		this.cargo = cargo;
	}

	public double getSalario() {
		return salario;
	}

	public void setSalario(double salario) {
		this.salario = salario;
	}

}

Factory Pattern – DAConexaoFactory

package org.desenvolvimento.aberto.conexao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DAConexaoFactory {

	// Cria string de conexão de banco de dados
	private static String conexao;

	// cria conexões
	// você pode alimentar o nome do servidor, porta e banco de dados
	// de alguma configuração global ou como achar melhor.

	public static Connection getConexao(int fabrica, String usuario,
			String senha) throws ClassNotFoundException, SQLException {

		if (fabrica == 1) {
			conexao = "jdbc:oracle:thin:@localhost:1521:xe";
			Class.forName("oracle.jdbc.driver.OracleDriver");
		}

		if (fabrica == 2) {
			conexao = "jdbc:derby:net://localhost:50000/deva";
			Class.forName("com.ibm.db2.jcc.DB2Driver");
		}

		if (fabrica == 3) {
			conexao = "jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=devaberto";
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
		}

		// Retorna driver pronto para login
		return DriverManager.getConnection(conexao, usuario, senha);

	}

}

Interface – FuncionarioDAOInterface

package org.desenvolvimento.aberto.dao;

import org.desenvolvimento.aberto.modelo.Funcionario;

public interface FuncionarioDAOInterface {

	// Cria interface
	// A interface propricia os retornos corretos de cada operação.

	public Funcionario buscaFuncionario(String id);

	public boolean insereFuncionario(Funcionario funcionario);

	public boolean updateFuncionario(Funcionario funcionario);

	public boolean deletaFuncionario(Funcionario funcionario);

	// TODO: Insira outros metodos que você deseje que sejam obrigatorios.
}

Objeto DAO – FuncionarioDAO

package org.desenvolvimento.aberto.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.desenvolvimento.aberto.conexao.DAConexaoFactory;
import org.desenvolvimento.aberto.modelo.Funcionario;

public class FuncionarioDAO implements FuncionarioDAOInterface {

	// Cria componentes
	private Connection conn = null;
	private Statement query;
	private String sql;

	public FuncionarioDAO() {

		// Como o exemplo não possui uma tela de login
		// utilizamos uma adaptação no construtor da classe
		// você pode utilizar um login para que o factory da conexão
		// use a string de conexão completa.

		try {

			this.conn = DAConexaoFactory
					.getConexao(1, "user", "password");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public Funcionario buscaFuncionario(String id) {

		// Cria novo objeto
		Funcionario funcionario = new Funcionario();

		// Define SQL
		sql = "SELECT * FROM FUNCIONARIOS WHERE ID_FUNCIONARIO = " + id;

		try {

			// Associa conexão e executa SQL
			query = conn.createStatement();
			ResultSet rs = query.executeQuery(sql);

			// Recupera dados do set
			while (rs.next()) {
				funcionario.setId(rs.getInt("ID_FUNCIONARIO"));
				funcionario.setNome(rs.getString("NOME"));
				funcionario.setSobrenome(rs.getString("SOBRENOME"));
				funcionario.setCargo(rs.getString("CARGO"));
				funcionario.setSalario(rs.getDouble("SALARIO"));
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Retorna objeto
		return funcionario;
	}

	@Override
	public boolean insereFuncionario(Funcionario funcionario) {

		// Define SQL
		sql = "INSERT INTO FUNCIONARIOS VALUES (?, ?, ?, ?, ?)";

		try {

			// Prepara SQL e alimenta parametros
			PreparedStatement query = conn.prepareStatement(sql);
			query.setLong(1, funcionario.getId());
			query.setString(2, funcionario.getNome());
			query.setString(3, funcionario.getSobrenome());
			query.setString(4, funcionario.getCargo());
			query.setDouble(5, funcionario.getSalario());

			// Executa SQL
			query.execute();
			query.close();
			return true;

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return false;
	}

	@Override
	public boolean updateFuncionario(Funcionario funcionario) {

		// Define SQL
		sql = "UPDATE FUNCIONARIOS SET ID_FUNCIONARIO = ?, NOME = ?, SOBRENOME = ?,"
				+ " CARGO = ?, SALARIO = ? WHERE ID_FUNCIONARIO = ?";

		try {

			// Prepara SQL e alimenta parametros
			PreparedStatement query = conn.prepareStatement(sql);
			query.setLong(1, funcionario.getId());
			query.setString(2, funcionario.getNome());
			query.setString(3, funcionario.getSobrenome());
			query.setString(4, funcionario.getCargo());
			query.setDouble(5, funcionario.getSalario());
			query.setLong(6, funcionario.getId());

			// Executa SQL
			query.execute();
			query.close();
			return true;

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return false;
	}

	@Override
	public boolean deletaFuncionario(Funcionario funcionario) {

		// Define SQL
		sql = "DELETE FROM FUNCIONARIOS WHERE ID_FUNCIONARIO = ?";

		// Prepara SQL e alimenta parametros
		PreparedStatement query;
		try {
			// Executa SQL
			query = conn.prepareStatement(sql);
			query.setLong(1, funcionario.getId());
			query.execute();
			query.close();

			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return false;

	}

}

GUI – DAApp

package org.desenvolvimento.aberto;

import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;

import org.desenvolvimento.aberto.dao.FuncionarioDAO;
import org.desenvolvimento.aberto.modelo.Funcionario;

public class DAApp implements ActionListener {
	// Declara componentes
	private JLabel ltitulo;
	private JLabel lid;
	private JLabel lpnome;
	private JLabel lsnome;
	private JLabel lcargo;
	private JLabel lsalario;
	private JLabel lpesquisa;

	private JTextField tid;
	private JTextField tpnome;
	private JTextField tsnome;
	private JTextField tcargo;
	private JTextField tsalario;
	private JTextField tpesquisa;

	private JButton botao;
	private JButton alterar;
	private JButton inserir;
	private JButton deletar;
	private JButton novo;

	private Border borda;

	private JFrame menssagem;

	public Container criaPainel() {
		// cria painel
		JPanel painel = new JPanel();
		painel.setLayout(new FlowLayout());
		painel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
		painel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
		// Cria titulo
		ltitulo = new JLabel("Database - Fields -Sem conexão");

		painel.add(ltitulo);
		painel.add(Box.createVerticalStrut(60));

		// Cria painel de usuario
		JPanel painelDados = new JPanel(new GridLayout(0, 2, 10, 10));

		// Cria componentes
		lid = new JLabel("Código:");
		lpnome = new JLabel("Primeiro Nome:");
		lsnome = new JLabel("Sobrenome:");
		lcargo = new JLabel("Cargo:");
		lsalario = new JLabel("Salário:");

		tid = new JTextField();
		tpnome = new JTextField();
		tsnome = new JTextField();
		tcargo = new JTextField();
		tsalario = new JTextField();

		tid.setPreferredSize(new Dimension(150, 20));

		// Adiciona componentes no painel
		painelDados.add(Box.createVerticalStrut(10));
		painelDados.add(Box.createVerticalStrut(10));
		painelDados.add(lid);
		painelDados.add(tid);
		painelDados.add(lpnome);
		painelDados.add(tpnome);
		painelDados.add(lsnome);
		painelDados.add(tsnome);
		painelDados.add(lcargo);
		painelDados.add(tcargo);
		painelDados.add(lsalario);
		painelDados.add(tsalario);
		painelDados.add(Box.createVerticalStrut(10));
		painelDados.add(Box.createVerticalStrut(10));

		// Cria painel de pesquisa
		JPanel painelPesquisa = new JPanel(new GridLayout(0, 3, 10, 10));
		borda = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
		painelPesquisa.setBorder(borda);

		// Cria pesquisas
		lpesquisa = new JLabel("Pesquisa código:");
		tpesquisa = new JTextField();
		botao = new JButton("Pesquisar");
		botao.addActionListener(this);

		// Define foco do cursor no campo de pesquisa
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				tpesquisa.requestFocus();
			}
		});

		// Adiciona compoentes ao painel de pesquisa
		painelPesquisa.add(lpesquisa);
		painelPesquisa.add(tpesquisa);
		painelPesquisa.add(botao);

		// Cria painel de pesquisa
		JPanel painelAcao = new JPanel(new GridLayout(0, 4, 10, 10));
		borda = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
		painelAcao.setBorder(borda);

		// Cria botões de manipulação de banco
		novo = new JButton("Novo");
		inserir = new JButton("Inserir");
		alterar = new JButton("Alterar");
		deletar = new JButton("Apagar");

		// Cria ouvintes de eventos
		novo.addActionListener(this);
		inserir.addActionListener(this);
		alterar.addActionListener(this);
		deletar.addActionListener(this);

		// Insere componentes em um painel
		painelAcao.add(novo);
		painelAcao.add(inserir);
		painelAcao.add(alterar);
		painelAcao.add(deletar);

		// Adiciona paineis
		painel.add(painelPesquisa);
		painel.add(painelDados);
		painel.add(painelAcao);

		return painel;
	}

	// Clique do botão de pesquisa
	public void actionPerformed(ActionEvent arg0) {

		// Verifica pesquisa
		if (arg0.getSource() == botao) {

			// Cria funcionario
			Funcionario funcionario = new Funcionario();

			// Busca funcionario
			funcionario = new FuncionarioDAO().buscaFuncionario(tpesquisa
					.getText());

			// verifica resultado
			long resultado = funcionario.getId();

			// Alimenta dados na GUI
			if (resultado != 0) {
				tid.setText(String.valueOf(funcionario.getId()));
				tpnome.setText(funcionario.getNome());
				tsnome.setText(funcionario.getSobrenome());
				tcargo.setText(funcionario.getCargo());
				tsalario.setText(String.valueOf(funcionario.getSalario()));
			} else {

				JOptionPane.showMessageDialog(menssagem,
						"Funcionario não encontrado!");

				javax.swing.SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						tpesquisa.requestFocus();
						tpesquisa.selectAll();
					}
				});
			}
		}

		// Botão Novo
		if (arg0.getSource() == novo) {

			// Limpa GUI
			tid.setText(null);
			tpnome.setText(null);
			tsnome.setText(null);
			tcargo.setText(null);
			tsalario.setText(null);

			javax.swing.SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					tid.requestFocus();
				}
			});

		}

		// Insere dados
		if (arg0.getSource() == inserir) {

			// Cria funcionario usando o construtor Overload
			Funcionario funcionario = new Funcionario(Integer.parseInt(tid
					.getText()), tpnome.getText(), tsnome.getText(),
					tcargo.getText(), Double.parseDouble(tsalario.getText()));

			// Cria objeto DAO
			FuncionarioDAO inserir = new FuncionarioDAO();

			// Insere funcionario
			boolean resultado = inserir.insereFuncionario(funcionario);

			// Exibe resultado
			if (resultado) {
				JOptionPane.showMessageDialog(menssagem,
						"Dados inseridos com sucesso!");
			} else {
				JOptionPane.showMessageDialog(menssagem,
						"Erro ao inserir Dados!");
			}

		}

		// Altera dados
		if (arg0.getSource() == alterar) {

			// Cria funcionario usando o construtor overload
			Funcionario funcionario = new Funcionario(Integer.parseInt(tid
					.getText()), tpnome.getText(), tsnome.getText(),
					tcargo.getText(), Double.parseDouble(tsalario.getText()));

			// Cria objeto DAO
			FuncionarioDAO alterar = new FuncionarioDAO();

			// Altera funcionario
			boolean resultado = alterar.updateFuncionario(funcionario);

			if (resultado) {
				JOptionPane.showMessageDialog(menssagem,
						"Dados alterados com sucesso!");
			} else {
				JOptionPane.showMessageDialog(menssagem,
						"Erro ao alterar Dados!");
			}

		}

		// Deleta dados
		if (arg0.getSource() == deletar) {

			// Cria funcionario utilizando o construtor overload
			Funcionario funcionario = new Funcionario(Integer.parseInt(tid
					.getText()), tpnome.getText(), tsnome.getText(),
					tcargo.getText(), Double.parseDouble(tsalario.getText()));

			// Cria objeto DAO
			FuncionarioDAO apagar = new FuncionarioDAO();

			// Deleta funcionario
			boolean resultado = apagar.deletaFuncionario(funcionario);

			// Exibe resultado
			if (resultado) {
				JOptionPane.showMessageDialog(menssagem,
						"Dados apagados com sucesso!");

				javax.swing.SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						tpesquisa.requestFocus();
						tpesquisa.selectAll();
					}
				});

				novo.doClick();
			} else {

				JOptionPane.showMessageDialog(menssagem,
						"Erro ao apagar Dados!");

			}
		}

	}

	public static void criaGUI() {
		// Cria formulario
		JFrame formulario = new JFrame("Desenvolvimento Aberto");
		formulario.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// cria painel de conteudo
		DAApp app = new DAApp();

		formulario.setContentPane(app.criaPainel());

		// Exibe o formulario
		formulario.setSize(400, 450);
		formulario.setVisible(true);

	}

	public static void main(String[] args) {

		javax.swing.SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {

				// Mostra GUI
				criaGUI();

			}
		});

	}

}

 

O WAS Liberty Porfile é extremamente leve, fácil de instalar, e muito rápido de usar, portanto, fornece uma plataforma conveniente e capaz para desenvolver e testar suas aplicações web e OSGi. Permite que o servidor de aplicação tenha a disposição apenas os recursos necessários para o aplicativo ou conjunto de aplicações, você também pode estender os recursos do servidor de aplicação instalando um pacote de extensão para adicionar mais funcionalidades ao Liberty Profile como recursos de Web Service, JMS e suporte ao MongoDB entre outros. Você também pode adicionar um pacote de extras que permite utilizar um Embeddable EJB Container e um cliente JPA .

WAS Developer Edition: http://www-03.ibm.com/software/products/pt/appserv-wasfordev

Instalando Pacotes de Extensão e Extras

1 – Na pagina de download após o login escolha os seguintes softwares: IBM WebSphere Application Server for Developers Extended Archive e IBM WebSphere Application Server for Developers Extra Archive , são arquivos de extensão jar:

Download Extended e Extras

Download Extended e Extras

2 – Abra o prompt de comando no local onde instalou o servidor e utilize o seguinte comando para instalar a extensão:

java -jar wlp-developers-extended-8.5.5.4.jar
Extendes Archive

Extendes Archive

3 – Pressione Enter para exibir os termos de licença e digite 1 para confirmar a instalação:

Termos de Licença

Termos de Licença

4 – Pressione Enter para confirmar o local da instalação, você deve instalar no mesmo diretório do runtime do servidor WAS:

Local da Instalação

Local da Instalação

5 – Aguarde o andamento e validação da instalação:

Validação

Validação

6 – Repita o mesmo procedimento com o arquivo de extras porem você pode criar uma pasta chamada Extras para a instalação:

Exemplo: C:\Desenvolvimento Aberto\IBM\extras
java -jar wlp-developers-extras-8.5.5.4.jar

 Configurando o WAS Liberty Profile

 7 – Abra o Eclipse e a aba Servers e expanda o servidor Websphere Application Server Liberty Profile. Expanda a opção Server Configuration e em Feature Manager clique com o botão direito e escolha Open:

Server Configuration

Server Configuration

8 – Na opção Feature Manager clique no botão Add para adicionar mais funcionalidades ao servidor:

Feature Manager

Feature Manager

9 – Adicione a funcionalidade adequada a sua aplicação:

Estenção

Funcionalidades

Você pode adicionar somente as funcionalidades que você precisa para suas aplicações e utilizar vários recursos da já consagrada tecnologia JAVA EE e OSGI (Open Services Gateway Initiative) que permite a reutilização de componentes para construir e gerenciar sistemas altamente complexos. Tornando o código mais fácil de escrever, testar e reutilizar. Gerenciar implantação dinâmica. Detectar erros previamente. Implantar remotamente. Detectar e resolver problemas que ainda não aconteceram.

O conjunto de ferramentas para desenvolvedores WebSphere Develper Tools é um plug-in para a IDE Eclipse para a construção e implantação de aplicações Java EE, OSGi e aplicações Web 2.0 para o WebSphere Application Server Liberty Profile. As ferramentas proporcionam um meio fácil e leve para o desenvolvimento, montagem e implantação de aplicativos para o WebSphere Application Server.

Para instalar basta acessar o menu Help do Eclipse e escolher a opção Eclipse MarketPlace e digitar na busca a palavra WebSphere, selecione a versão da sua IDE, clique em instalar e você obterá ajuda do assistente de instalação:

WebSphere Developer Tools for Eclipse

WebSphere Developer Tools for Eclipse

Configurando o WAS Liberty Profile no Eclipse

1 – Abra janela de servidores crie um novo servidor, você pode fazer isto de varias maneiras no Eclipse uma delas é no menu Window->Show View->Server. Na janela de servidores, clique com o botão direito e escolha New Server:

New Server

New Server

2 – Caso ainda não tenha o adaptador para servidor WAS Liberty Profile, clique em Download additional servers adapter e escolha o adaptador para o servidor:

WAS Liberty Profile Adapter

WAS Liberty Profile Adapter

3 – Aceite os termos de licença e clique em instalar:

Was Adapter - Licença

Was Adapter – Licença

4 – Escolha a opção para seu servidor e clique em Next:

Novo Servidor

Novo Servidor

5 – Escolha o caminho da instalação do servidor WebSphere Application Server Liberty Profile na maquina local, o Java JRE e clique em Finish:

WASLF - Configuração

WASLF – Configuração

Testando o WAS Liberty Profile

6 – Para testar o servidor na aba Servers selecione o WAS Liberty Profile e crie um novo projeto do tipo Dynamic Web Project, crie um Servlet chamado DaWebSphereHelloWorld,  utilize o código abaixo, rode sua aplicação e selecione o servidor adequado:

Run - WAS

Run – WAS

7 – Pronto, sua aplicação já está rodando:

WebSphere Application Server

WebSphere Application Server

O conceito do WebSphere Application Server Liberty Profile é proporcionar um ambiente leve e rápido para aplicações Java e OSGI carregando somente os Containers e recursos necessários para as aplicações, entretanto caso queira utilizar outros recursos você precisa efetuar uma instalação adicional de extras para o servidor WebSphere Application Server.

WasDev: https://developer.ibm.com/wasdev/downloads/

Was for Developer e Extras: http://www-03.ibm.com/software/products/pt/appserv-wasfordev

WAS Extended e Extras: Instalação e configuração.

Exemplo:

Neste exemplo configuramos o instalamos as ferramentas WAS Liberty Profile para o Eclipse e configuramos o servidor na IDE para que possamos desenvolver aplicações Java para o IBM WebSphere.

Java

package org.desenvolvimento.aberto;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/DaWebSphereHelloWorld")
public class DaWebSphereHelloWorld extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public DaWebSphereHelloWorld() {
		super();

	}

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// Cria Página HTML Dinâmica
        response.setContentType("text/html");

        PrintWriter html = response.getWriter();

        html.println("<html>");
        html.println("<body>");
        html.println("<h1>Desenvolvimento Aberto - Java</h1>");
        html.println("<h2>IBM WebSphere Application Server for Developers Edition</h2>");
        html.println("<h3>WAS Liberty Profile Server - Instalação: Standalone</h3>");
        html.println("</form>");
        html.println("</body>");
        html.println("</html>");

	}

}

O WebSphere Application Server é um produto de software que executa o papel de um servidor de aplicativos web. Mais especificamente, é uma estrutura de software e middleware que hospeda aplicativos web baseados em Java. O WAS é o principal produto dentro da suíte de software IBM WebSphere.

O WAS Liberty Porfile é um perfil dinâmico do WebSphere Application Server que permite que o servidor de aplicação tenha a disposição apenas os recursos necessários para o aplicativo (ou conjunto de aplicações) implantadas no servidor WAS. Se uma aplicação requer apenas um mecanismo de Servlet, então tudo o que o servidor iniciará é o kernel, o transporte HTTP e o contêiner web.  O WAS é encontrado para download na versão WebSphere Application Server Full Profile e em uma versão de instalação Standalone do servidor Liberty Profile.

WAS Developer Edition: http://www-03.ibm.com/software/products/pt/appserv-wasfordev

Instalando e Configurando o WAS for Developers Liberty Profile

1 – Na pagina de download após o login (caso não tenha um ID da IBM crie um gratuitamente) escolha o seguinte software: IBM WebSphere Application Server for Developers Archive, ele é um arquivo de extensão jar:

WAS for Developers - Download

WAS for Developers – Download

2 – Abra o prompt de comando e utilize o seguinte comando para instalar o WAS:

java -jar wlp-developers-runtime-8.5.5.2.jar
Instalando - Jar

Instalando – Jar

3 – Pressione Enter para exibir os termos de licença e digite 1 para confirmar a instalação:

Termos de Licença

Termos de Licença

4 – Pressione Enter para confirmar o local da instalação ou entre o local desejado:

Local da instalação

Local da instalação

5 – Aguarde o andamento da instalação:

Andamento

Andamento

6 – Após a instalação precisamos criar e iniciar um servidor WAS, digite os seguintes comandos:

cd wpl\bin
server create DA001
server start DA001
Criando e Iniciando o Servidor

Criando e Iniciando o Servidor

7 – Para testar abra o navegado e digite a seguinte url: http://localhost:9080/

WebSphere Application Server Liberty Profile

WebSphere Application Server Liberty Profile

Agora você precisa instalar as ferramentas para desenvolvimento WAS Developer Tools para o Eclipse e programar aplicações Java baseadas no servidor de aplicação IBM WebSphere. Para instalar as ferramentas para o Eclipse e criar uma aplicação Hello World com WAS Liberty Profile clique aqui.

ASP.NET – Login – Logout – timeout – C#

Publicado: 6 de dezembro de 2014 em C#

Tarefas de gerenciamento de sessão típicas incluem manter o controle de quais aplicativos estão abertos e documentar cada aplicativo que abriu, para que o mesmo estado possa ser restaurado quando o usuário sair e entrar novamente mais tarde. Você também pode utilizar a Session para criar áreas restritas de um website que podem ser acessadas pela sessão de um usuário, você também pode definir um tempo para que esta sessão fique ativa no navegador do usuário autenticado.

Para um site, gerenciamento de sessão pode envolver e exigir que o usuário reinicie sessão se a sessão expirou ou seja, se um certo limite de tempo passou sem a atividade do usuário. A sessão também é usada para armazenar informações no lado do servidor entre solicitações HTTP. Este tipo de conceito básico é o principio do esquema de autenticação utilizado por vários websites, entretanto a partir deste esquema básico pode-se criar métodos mais eficientes para utilizar este conceito.

O uso do ambiente de Sessão do ASP.NET consome recursos do servidor. Atente-se ao utilizar o recurso de tempo de sessão, devemos ser cuidadosos ao definirmos o tempo de duração da sessão inativa, pois quanto maior o tempo, mais irá demorar para o ASP.NET liberar os recursos utilizados.

Session State: http://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.85).aspx

Utilizando Sessions – Login, Logout e Timeout

1- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DASessionTimeout, crie uma nova pagina WebForm chamada default e uma pagina chamada AreaComunitaria. Copie o código para a pagina e rode o programa.

Você pode tentar chamar a pagina AreaComunitaria sem utilizar o usuário e senha, digitando o nome da pagina na url do navegador e constatará que não pode acessar a pagina devido a inexistência da sessão para seu usuário. Efetue o Login para criar a sessão:

Session - Login

Session – Login

2 – Assim que efetuar o login você será direcionado a área comunitária podendo então acessar a pagina da comunidade, caso clique no link sair, a sessão será invalidada e você será redirecionado para a tela de login:

Session - Área Comunitária

Session – Área Comunitária

3 – Ao incluir as tags de configuração da sessão no arquivo web.config você pode definir o tempo em minutos que deseja que sessão seja valida. Use o código do arquivo xml abaixo para fazer com que a sessão dure 1 minuto, efetue o login, aguarde um minuto e atualize a pagina, com a sessão expirada você será redirecionado novamente para a pagina de login:

Session - Timeout

Session – Timeout

Gerenciamento de Sessão ASP.NET

Este é um modo simples de utilizar uma sessão em ASP.NET e é valido como um exercício, entretanto existem vários outras maneiras mais eficientes de gerenciar ambientes de sessão:

Ambientes de Sessão: http://msdn.microsoft.com/pt-br/library/gg454582.aspx

Exemplo:

Neste exemplo criamos uma pagina de login com a funcionalidade de autenticar em uma pagina somente para membros da comunidade e utilizamos o recurso de timeout da sessão para que ela expire assim que o usuário estiver autenticado por 1 minuto.

Obs: usuário: DevAberto e a senha: 1234

ASP.NET – C#

default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="DaSessionTimeout._default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Desenvolvimento Aberto - Login</title>
    <style type="text/css">
        .auto-style1 {
        }
        .auto-style2 {
            width: 103px;
            height: 23px;
        }
        .auto-style3 {
            height: 23px;
        }
        .auto-style4 {
            height: 30px;
        }
    </style>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h3>Login:</h3>
    <form id="form1" runat="server">
    <div>

        <table style="width:100%;">
            <tr>
                <td class="auto-style2">
                    <asp:Label ID="Label1" runat="server" Text="Usuário:"></asp:Label>
                </td>
                <td class="auto-style3">
                    <asp:TextBox ID="TextBox1" runat="server"  Width="207px"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="auto-style4">
                    <asp:Label ID="Label2" runat="server" Text="Senha:"></asp:Label>
                </td>
                <td class="auto-style4">
                    <asp:TextBox ID="TextBox2" runat="server" TextMode="Password" Width="207px"></asp:TextBox>
                    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Entrar" />
                </td>
            </tr>
            <tr>
                <td class="auto-style1" colspan="2">&nbsp;</td>
            </tr>
        </table>

    </div>
    </form>
</body>
</html>

default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaSessionTimeout
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // Recupera elementos do formulario
            string usuario = Request.Form["TextBox1"];
            string senha   = Request.Form["TextBox2"];

            // Neste exercicio usuario e senhas são fixos
            // Estes dados geralmente estão associados a um banco de dados
            if ( usuario.Equals("DevAberto") && senha.Equals("1234"))
            {
                Session["Usuario"] = usuario;
                Response.Redirect("AreaComunitaria.aspx");
            }
            else
            {
                Response.Redirect("default.aspx");
            }

        }
    }
}

AreaComunitaria.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AreaComunitaria.aspx.cs" Inherits="DaSessionTimeout.AreaComunitaria" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Desenvolvimento Aberto - ASP.NET - C#</title>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h3>Area da Comunidade - C# - ASP.NET</h3>
    <form id="form1" runat="server">
    <div>
       <div>
           <% string usuario = (string)Session["Usuario"];
               Response.Write("Bem Vindo: " + usuario); %>
           <br />
           <asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">Sair</asp:LinkButton>
       </div>
    </div>
    </form>
</body>
</html>

AreaComunitaria.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DaSessionTimeout
{
    public partial class AreaComunitaria : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Recupera usuario da sessão
            string usuario = (string)Session["Usuario"];

            // Sessão for invalida
            if (usuario == null)
            {
                Response.Redirect("default.aspx");
            }

        }

        protected void LinkButton1_Click(object sender, EventArgs e)
        {
            // Invalida Sessão
            Session.Abandon();
            Response.Redirect("default.aspx");
        }
    }
}

Web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

  <sessionState timeout="1" />

  </system.web>
</configuration>

ASP.NET – Cookies – C#

Publicado: 5 de dezembro de 2014 em C#

Um cookie é um pequeno pedaço de dados enviado de a partir de um website e armazenado em um arquivo de texto criado no computador do usuário enquanto ele está navegando em um site. Cada vez que o usuário carrega o website, o navegador envia o cookie de volta ao servidor para notificar o site da atividade prévia do usuário. Os cookies foram projetados para serem um mecanismo confiável para sites recordarem informações de estado ou para registrar a atividade de navegação do usuário.

Cookie é um assunto que trouxe e ainda levanta muita controvérsia no universo da computação para web, devido a questões de segurança quanto a manipular informações no computador local, fazem com que todos os tipos de usuários se preocupe com as informações utilizadas em websites principalmente se utilizar computadores que são compartilhados com varias pessoas como em lan houses ou outros.

C# possui a classe HttpCookie que permite que o desenvolvedor manipule cookies em suas aplicações web seguindo as especificações do RFC 2109, está classe representa os valores de um cookie HTTP.

Cookies: https://www.ietf.org/rfc/rfc2109.txt

HttpCookie: System.Web

Utilizando Cookies

1- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DACookie, crie uma nova pagina WebForm chamada default. Copie o código para a pagina e rode o programa:

Formulario - Cookie

Formulário – Cookie

2 –  Assim que o botão recebe o evento de clique o método Post cria o cookie no computador local guardando em seu arquivo o nome do usuário, a pagina é recarregada e o cookie é lido automaticamente, toda vez que você tentar recarregar esta página o cookie será lido e o nome guardado automaticamente preenchido:

Cookie

Cookie

Para ver o cookie e no seu navegador (Firefox) abra Opções no menu do Firefox e escolha a aba privacidade:

Firefox - Opções -  Privacidade

Firefox – Opções – Privacidade

4 – Clique no link excluir cookies em particular e digite no campo de busca, localhost. Selecione o cookie pelo seu nome e você pode ver os dados gravados no mesmo. Caso queira testar o exemplo outra vez você pode excluir o cookie e rodar a aplicação novamente:

Firefox - Cookie

Firefox – Cookie

Exemplo:

Neste exemplo criamos uma página que grava e lê um cookie no computador local.

C#

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="DACookies._default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h2>Cookies Memoriza Dados</h2>
    <form id="form1" runat="server">
    <div>
    
        <asp:Label ID="Label1" runat="server" Text="Nome: "></asp:Label>
        <asp:TextBox ID="TextBox1" runat="server" Width="292px"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Adicionar" />
    
    </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DACookies
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Recupera Cookie
            HttpCookie cookie = Request.Cookies.Get("DAMeuCookie");

            // Verifica se existe  Cookie 
            if (cookie != null)
            {            
                // Modifica pagina
                Label1.Text = cookie.Value;
                TextBox1.Visible = false;
                Button1.Visible = false;
            }

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // Recupera parametro 
            string nome = Request.Form["TextBox1"];
            
            // Cria objeto Cookie
            HttpCookie cookie = new HttpCookie("DAMeuCookie");
            cookie.Value = nome;

            // Adiciona cookie a coleção
            Response.Cookies.Add(cookie);

            // Redireciona pagina
            Response.Redirect("default.aspx");
        }
    }
}

 

SAP – Classes – Objetos e Coleções – Abap

Publicado: 4 de dezembro de 2014 em Abap

Desde que o ABAP Objects foi lançado há vários anos atrás a polemica se instalou na comunidade de desenvolvedores ABAP quanto a utilização do novo paradigma de programação orientado a objeto junto com o antigo paradigma da programação procedural, possibilitando então escrever códigos de múltiplos paradigmas. Varias instruções do antigo paradigma foram marcadas como obsoleta pela SAP que ainda as mantem a nível de compatibilidade com programas mais antigos.

A vinda do novo paradigma causa até hoje enorme e incontáveis batalhas e discussões entre os novos e novos, os novos e velhos e os velhos e velhos desenvolvedores ABAP a fim de chegar a uma argumentação final sobre o assunto que parece não ter solução. Enquanto alguns puristas declaram firmemente que você não pode utilizar instruções do antigo paradigma com instruções orientadas objetos, outros mais liberais não veem nenhum problema nisto já que deste modo a programação se torna muito mais fácil e rápida e ainda contam com o respaldo dos exemplos oficiais disponibilizados pela SAP contidos no NetWeaver que educam os novos desenvolvedores a utilizar os dois paradigmas (transação ABAPDOCU).

Com toda está polemica, é claro que não queremos nos meter no meio deste assunto e nossa opinião não poderia ser mais obvia. Ficar em cima do muro! Pode parecer uma posição meio frouxa, mas garanto que este não é o caso. Se por um lado a programação orientada a objeto é considerada superior a programação procedural, então um código orientado a objeto bem escrito deveria ter uma melhor qualidade, e tem! Mas os exemplos e vários códigos fornecidos, escritos e assinados pela própria SAP misturam os paradigmas, então eu também posso fazer isto, também concordamos!

Já que concordamos com ambas as partes temos que achar o verdadeiro ocasionador de tal desavenças, isto não é tão difícil assim, uma simples busca na documentação oficial e logo encontramos uma da muitas explicações plausíveis para o acontecimento (existem vários pontos que divergem a programação procedural da orientada a objeto e um deles é o próprio Open SQL e os Data Objects, mas isto é assunto para outra ocasião).  Voltando para linha do raciocínio, acontece que a SAP não terminou de implementar o framework de coleções para a linguagem de programação ABAP Objects e indica nos exemplos oficiais um workaround para simular uma LISTA no conceito de programação orientada a objeto, veja no código a implementação do método:  “METHOD WRITE_LIST”.

Isto acontece exatamente no tópico de métodos que são um dos mais importantes elementos que compõem uma classe que obviamente resultará em um objeto. E mais! Também afirma que o exemplo contem instruções obsoletas e não garante a compatibilidade com futuras versões:

“The ABAP statements used for list processing are not yet fully available in ABAP Objects. However, to produce a simple test output, you can use the following statements: WRITE [AT] /<offset>(<length>) <f>
ULINE
SKIP
NEW-LINE

Note: The behavior of formatting and interactive list functions in their current state are not guaranteed. Incompatible changes could occur in a future release.”

Classes: Métodos ABAP

O que é uma lista em programação orientada a objetos?

Em programação orientada a objeto a classe de Lista faz parte do framework de coleções e é equivalente genérico da classe ArrayList . Implementa a interface genérica de listas usando uma matriz cujo tamanho é gerado dinamicamente conforme necessário. Em ABAP podemos dizer que uma lista é semelhante a uma tabela interna que pode conter varias colunas ou linhas, porem é um objeto que pode conter (Container) um objeto criado pelo desenvolvedor e ser manipulado através de outro objeto chamado de iterador.

O ABAP disponibiliza algumas classes para manipular objetos utilizando as coleções porem estas classes ainda não fazem parte de um framework de coleções consistentes como encontramos em outras linguagem com o próprio STL para C++ ou JCF para Java que são as linguagens de programação no qual o ABAP OO foi baseado.

Classes - Manipulando Objetos e Coleções

Classes – Manipulando Objetos e Coleções

Analisando a Classe do Objeto e Utilizando Coleções

Utilizamos um Pattern básico para o objeto criado na classe do código abaixo baseado no que seria comum em qualquer linguagem orientada a objeto como Java e C++.

  1. A classe utiliza encapsulamento privado para os atributos que são os campos primitivos ou não que armazenam valores para o objeto.
  2. Estes campos privados são acessados através dos tradicionais métodos Getter e Setter que são o método Get para ler um atributo do objeto e o método Set para alimentar um atributo do objeto.
  3. Utilizamos um construtor padrão e um construtor Overload para a classe, em ABAP não podemos sobrecarregar os construtores através de métodos e precisamos criar está funcionalidade pela instrução OPTIONAL declarada nos parâmetros das variáveis no escopo do método construtor.
  4. Utilizamos a classe de coleção CL_OBJECT_COLLECTION para criar uma lista para o objeto.
  5. Utilizamos a classe de coleção CL_OBJECT_COLLECTION_ITERATOR  para iterar o objeto de lista.
  6. Para continuar em cima do muro, utilizamos uma instrução FORM-PERFORM para adicionar os objetos na lista e explicamos o motivo nos comentários do código abaixo.

Você ainda pode manipular os objetos da lista, adicionado, removendo, alterando os dados para seu objeto. Mas reiteramos que as coleções ainda não estão totalmente implementadas em ABAP Objetcs o que pode tornar mais difícil este tipo de programação a não ser que você mesmo herde e estenda as classes e implemente seu próprio framework para as coleções.

Mais Questões

Seria o ABAP Objects uma linguagem incompleta? Já que as coleções são de grande importância e essenciais na orientação a objeto uma implementação incompleta justificaria o uso de instruções procedurais para a manipulação de objetos? O Open SQL deixaria o ABAP Objects com um pé no paradigma da programação declarativa já que é utilizado de forma muito similar ao SQL que é uma linguagem declarativa? Manipular dados nos objetos através do Open SQL e Data Objects (Em geral utilizam a instrução DATA) como vemos no exemplo disponibilizado pela SAP no link acima e não através de Patterns de objetos como o DAO (Data Access Objects) para Java entre outros também não quebraria o paradigma da orientação a objeto? Podemos então afirmar que ABAP é uma linguagem exclusivamente de múltiplos paradigmas? Deixaremos que vocês tirem suas próprias conclusões.

DAO Pattern: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

ABAP: Data Objects

Até o momento não há documentação oficial no site da SAP sobre as classes de coleções.

Object Handling: Manipulando Objetos

Exemplo:

Neste exemplo criamos uma classe que contem alguns recursos básicos da programação orientada a objeto como atributos privados, construtor Overload, métodos Getter e Setter e utilizamos um objeto de lista para armazenar e manipular nosso objeto.

Métodos: Overload

Coleções: Collections Iterator e Collection Map

ABAP

*&---------------------------------------------------------------------*
*& Report  ZABAPOBJETO
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& Objetos Abap - Manipulando Objetos
*& Classe - Objeto - Lista - Iterador
*&---------------------------------------------------------------------*

REPORT  ZABAPOBJETO.

* Cria classe Participante
class ZPARTICIPANTE definition.

  public section.

* Declara construtor com efeito Overload
    methods CONSTRUCTOR IMPORTING
               pid    TYPE i      OPTIONAL
               pnome  TYPE string OPTIONAL
               pidade TYPE i      OPTIONAL.

* Declara métodos Getter e Setter

    methods SETID importing  !PID type i .
    methods GETID returning value(RESULTADO) type i .
    methods SETNOME importing  !PNOME type STRING .
    methods GETNOME returning value(RESULTADO) type STRING .
    methods SETIDADE importing !PIDADE type I .
    methods GETIDADE returning value(RESULTADO) type I .

* Declara atributos privados
  private section.

    data ID    type i.
    data NOME  type STRING .
    data IDADE type I .

ENDCLASS.

* Implementação da classe
CLASS ZPARTICIPANTE IMPLEMENTATION.

*  Construtor

  METHOD CONSTRUCTOR.
    me->ID = PID.
    me->NOME = PNOME.
    me->IDADE = PIDADE.
  ENDMETHOD.

*  Metodos Getter e Setter

  METHOD GETIDADE.
    RESULTADO = me->IDADE.
  ENDMETHOD.

  METHOD GETNOME.
    RESULTADO = me->NOME.
  ENDMETHOD.

  METHOD GETID.
    RESULTADO = me->ID.
  ENDMETHOD.

  METHOD SETIDADE.
    me->IDADE = PIDADE.
  ENDMETHOD.

  METHOD SETNOME.
    me->NOME = PNOME.
  ENDMETHOD.

  METHOD SETID.
    me->ID = PID.
  ENDMETHOD.

ENDCLASS.

* testa programa
START-OF-SELECTION.

* Testa Classe
  DATA: p1    TYPE REF TO ZPARTICIPANTE,
        p2    TYPE REF TO ZPARTICIPANTE,
        id    TYPE i,
        nome  TYPE String,
        idade TYPE i.

* Istancia Objeto usando Construtor Overload
  CREATE OBJECT P1
    EXPORTING
      PID    = 1
      PNOME  = 'José Pereira'
      PIDADE = 35.

* Métodos Getter
  id    = p1->GETID( ).
  nome  = P1->GETNOME( ).
  idade = P1->GETIDADE( ).

* Imprime valores P1
  WRITE: / 'Valor do Objeto P1: ', id, nome, idade.

*Instancia Objeto padrão

  CREATE OBJECT P2.
* Métodos Setter
  p2->SETID( 2 ).
  p2->SETNOME( 'Joao da Silva' ).
  p2->SETIDADE( 20 ).

* Métodos Getter
  id    = p2->GETID( ).
  nome  = P2->GETNOME( ).
  idade = P2->GETIDADE( ).

* Imprime valores P2
  WRITE: / 'Valor do Objeto P2: ', id, nome, idade.

SKIP 2.
WRITE : / 'Objetos da lista:'.
SKIP 1.

* ***********************************************
* ************* Manipulando Objetos *************
* ***********************************************
*
*
* Define Lista para iterar objetos
* Listas e iteradores fazem parte do framework de coleções
* São o meio padrão para manipular objetos
* No entanto em ABAP Objects as coleções não
* foram totalmente implementadas.

* Declara instancia da classe para a lista
  DATA ITEM TYPE REF TO ZPARTICIPANTE.

* Declara objeto de lista e iterador
  DATA LISTA TYPE REF TO CL_OBJECT_COLLECTION.
  DATA ITERADOR TYPE REF TO CL_OBJECT_COLLECTION_ITERATOR.

* Cria lista
  CREATE OBJECT LISTA.

* Adiciona Objeto a lista
  PERFORM ADD USING 3 'Mario Alvim' 27.
  PERFORM ADD USING 4 'Fernando Moraes' 45.
  PERFORM ADD USING 5 'Eduardo gonçalves' 38.

* Atribui objeto ao Iterador
  ITERADOR = LISTA->GET_ITERATOR( ).

* Usa iterator como um cursor de banco de dados
  WHILE ITERADOR->HAS_NEXT( ) IS NOT INITIAL.

    " Verifica objetos da lista
    ITEM ?= ITERADOR->GET_NEXT( ).

    " Alimenta objeto
    id = ITEM->GETID( ).
    nome = ITEM->GETNOME( ).
    idade = ITEM->GETIDADE( ).

    " Imprime dados do objeto
    WRITE : / id, nome, idade.

  ENDWHILE.

* Cria uma polemica instrução FORM-PERFORM
* Seria possivel criar uma classe com um método estatico
* para executar a mesma função desta sub-rotina
* mas encapsular os objetos criados daria muito mais trabalho
* do que mesclar Objetos e uma instrução procedural.
*
* Desde que as Coleções não estão totalmente implementadas em ABAP OO
* Exemplos utilizando o FORM-PERFORM para criar objetos
* são muito comuns mesmo nos exemplos disponibilizados pela SAP
* você pode conferir nos exemplos do NETWEAVER basta procurar na transação
* ABAPDOCU e vai encontrar varios exemplos utilizando objetos inicializados com FORM-PERFORM
* Este processo seria equivalente a uma VOID em C++ ou Def em Python ou Ruby que pode estar
* tanto dentro de uma classe como um método ou fora de uma classe como um procedimento.

FORM ADD USING VALUE(pid)  TYPE i
               VALUE(pnome) TYPE string
               VALUE(pidade) TYPE i.

* Cria objeto da classe como item
  CREATE OBJECT ITEM
    EXPORTING
      PID    = pid
      PNOME  = pnome
      PIDADE = pidade.

* Adiciona a lista
  LISTA->ADD( ITEM ).

ENDFORM.

ASP.NET – Responses – Status Code – C#

Publicado: 3 de dezembro de 2014 em C#

A cada solicitação do protocolo HTTP o servidor indica uma resposta provisória, consistindo somente da linha de status e cabeçalhos opcionaisencerrado por uma linha vazia. As respostas podem conter por exemplo erros de HTTP que são enviados para o navegador da Web pelo servidor se um problema for encontrado durante a tentativa de exibir uma página da Web. Se a página da Web não for exibida, o servidor exibirá a página de erro real enviada pelo site ou uma mensagem de erro amigável.

As vezes é útil criar uma pagina customizada para as paginas geradas automaticamente pelo servidor pois o mesmo pode mostrar nestas paginas informações que não queremos que o usuário remoto tenha conhecimento, além das boas praticas e uma mensagem esteticamente amigável, ainda temos entre os motivos, a segurança.

Para uma lista completa de todos os códigos de resposta enviados pelo servidor utilize o link abaixo:

Response Status Code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Customizando uma Página de Erro

11- Crie uma aplicação do tipo ASP.NET Web Application com o modelo C# Empty e chame seu projeto de DAWebStatusCode, crie uma nova pagina html chamada default. Copie o código para a pagina e rode o programa:

Default.html

Default.html

2 – Clique no link “ASP.NET” para que você obtenha a pagina de erro com a resposta gerada pelo servidor:

ASP.NET - Erro

ASP.NET – Erro

3 – Para substituir a pagina automática por uma pagina mais amigável precisamos capturar a resposta do servidor e exibir uma pagina com informações customizadas, entretanto não queremos que o usuário tenha acesso a esta pagina via o navegador, então precisamos criar uma pagina chamada de 404.html e alterar o web.config, redirecionando a resposta 404 para a pagina 404.html. Crie a pagina 404.html e altere o arquivo web.config utilizando os respectivos códigos abaixo, em seguida rode a aplicação:

Default.html

Default.html

4 – Clique novamente na opção “ASP.NET” e sua pagina customizada será exibida sem que nenhuma informação do servidor e de sua aplicação seja apresentada para o usuário remoto:

Erro - Customizado

Erro – Customizado

Entretanto ASP.NET possui algumas configurações diferenciadas, por exemplo no arquivo Web.Config, toda a configuração para paginas de erro customizadas em ASP.NET necessitam estar dentro da tag <system.web> na tag  <customErrors> enquanto as configurações para erros HTTP necessitam estar na tag <configuration> na tag <system.webserver>.

ASP.NET Custom Error: http://msdn.microsoft.com/pt-br/library/h0hfz6fc(v=vs.85).aspx

System.webServer: http://msdn.microsoft.com/pt-br/library/bb763179(v=vs.100).aspx

Exemplo:

Neste exemplo utilizamos a resposta do servidor para substituir a mensagem de erro 404 por uma mensagem exibida em uma pagina customizada. Como estamos utilizando uma aplicação que utiliza paginas html em um modelo vazio, a configuração de erro que possui efeito é a contida nos elementos system.webServer.

HTML

default.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Desenvolvimento Aberto - HTTP Respostas</title>
    <style>
        #header {
            background-color: Black;
            color: white;
            text-align: center;
            padding: 5px;
        }

        #nav {
            line-height: 30px;
            background-color: #eeeeee;
            height: 400px;
            width: 100px;
            float: left;
            padding: 5px;
        }

        #section {
            width: 450px;
            float: left;
            padding: 10px;
        }

        #footer {
            background-color: Black;
            color: white;
            clear: both;
            text-align: center;
            padding: 5px;
        }
    </style>

</head>
<body>
    <div id="header">
        <h1>Desenvolvimento Aberto</h1>
    </div>

    <div id="nav">

        <!-- HTTP Response:

         Este link referencia uma página que não existe,
         deste modo o servidor nos enviará um erro 404  -->
        <p>
            <a href='nao-existe.html'>ASP.NET</a>
        </p>
        <p>Web Forms</p>
        <p>MVC</p>
        <p>C#</p>

    </div>

    <div id="section">
        <h2>Desenvolvimento Aberto</h2>
        <p>
            Desenvolvimento Aberto é uma organização voltada para o
            aprendizado e discussão de técnicas de desenvolvimento focado em
            algumas linguagens de programação sendo parcialmente/totalmente
            abertas ou com licenças gratuitas para desenvolvedores de cada uma de
            suas respectivas marcas registradas.
        </p>
        <p>
            Desenvolvimento Aberto foi escrito e desenvolve utilizando
            ferramentas gratuitas disponibilizadas pelas melhores empresas de
            software da atualidade, incluindo a própria hospedagem e design deste
            site, sendo assim, também proporciona conteúdo gratuito, isso quer
            dizer que você não paga nada para aprender e utilizar as tecnologias
            de ponta que podem ser manuseadas através das linguagens de
            programação mais requisitadas pelas empresas no mercado atual.
        </p>
    </div>

    <div id="footer">
        Desenvolvimento Aberto ©
        desevolvimento.aberto@live.com
    </div>

</body>
</html>

404.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <h1>Desenvolvimento Aberto</h1>
    <h3>Desculpe! Não encontramos a página solicitada no servidor</h3>
    <p>Erro: HTTP 404. </p>
</body>
</html>

web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

    <customErrors defaultRedirect="GenericError.htm"
                 mode="On">
      <error statusCode="404"
             redirect="404.html"/>
    </customErrors>
  </system.web>

  <system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404"/>
      <error statusCode="404" path="404.html" responseMode="ExecuteURL"/>
    </httpErrors>
  </system.webServer>
  
</configuration>