sábado, 29 de março de 2008

[ADO.NET] Estendendo ADO.NET: Parte 1- Projeto dos provedores de persistência.

Alguns dos aspectos criticados por alguns colegas na API ADO.NET seriam: (a) a dependência sintática do SQL e (b) a arquitetura orientada a dados no modelo de referência sugerido pela Microsoft para a camada de persistência. Uma vez que a dependência sintática do SQL é plenamente suprimida pela API LINQ do framework 3.5, pensei em escrever alguns artigos neste escopo de adaptação dos componentes da ADO.NET. O modelo de referência citado obtem grande produtividade pela modelagem visual do componente DataSet “tipado”. No entanto, os objetos definidos no componente DataSet para representação dos objetos de transferência (DataTable) e serviços (TableDataAdapter) são selados (i.e. selead), não permitindo sua herança, ou mesmo composição de tipos por referência.

Desta forma, apresentações alternativas e relatórios podem eventualmente exigir a definição de Value Objects (VO) auxiliares para transporte vertical de dados à camada de apresentação. Tal estrutura condiciona fortemente as camadas superiores ao modelo de entidades, definindo um grande esforço de refatoração no caso da mudança das definições da base de dados, ou na extensão de relatórios.

Neste escopo, um primeiro ponto de interessante seria a possibilidade da referência por reflection/remoting aos service factories de persistência, de forma tal que extensões em assemblies distintos possam ser adaptados em tempo de execução. Tal feature teria alto valor agregado em sistemas de alta disponibilidade com baixa resistência a mudança.


A arquitetura proposta é apresentada na figura ao lado, onde o seu principal componente consiste da classe DaoProvider, projetada conforme o design pattern provider. Tal classe possui a responsabilidade de gerenciar os service factories concretos para os objetos de persistência.

Para tanto, tal classe possui uma composição de objetos DaoProviderSettings (estrutura que representa a configuração para um service factory concreto dos objetos de persistência), onde estes objetos podem ser acessados de forma aleatória, adicionados na lista de provedores ou interpretados a partir de uma string de conexão fornecida.


A tabela ao lado apresenta descrição da interface da classe DaoProviderSettings proposta, que consiste de uma extensão da classe System.Configurations.ConfigurationSection. A classe pai define a associação entre um identificador textual único (“Name”), a string de conexão (“ConnectionString”) e a classe do provedor de acesso ao banco de dados (“ProviderName”), responsável por implementar a interface de tratamento das queries SQL sobre a string de conexão. Na classe estendida, proposta neste estudo, são adicionadas a existência de uma classe proxy para o provider (“ProxyName”), que implementa de forma concreta um mapeamento objeto relacional. Tal proxy pode ainda ser definido no contexto da aplicação ou em um assembly externo (DLL), neste caso, sendo referenciado pelo atributo “ProxyAssemblyName”. Desta forma, a extensão provê uma interface consistente para atendimento do requisito de referência por reflection aoa service factories de persistência.

Os parâmetros dos provedores de persistência da plataforma proposta são definidos no contexto da aplicação pelos arquivos padrões de configuração das APIs da plataforma.NET. (arquivo web.config em contexto ASP.NET e app.config em contexto Windows Forms). A listagem abaixo ilustra a marcação do arquivo web.config de uma aplicação web implementando o modelo proposto. Observa-se a sintaxe padrão para a definição de strings de conexão sobre o nó . A string de conexão de nome “Prevalente (default)” não apresenta um atributo “providerName” conforme definido no padrão ADO.NET. Neste caso não é necessário, pois será empregado um proxy (provedor concreto de serviços de persistência) da plataforma proposta. As marcações relativas aos atributos “ProxyName” e “ProxyAssemblyName” são definidos sobre o atributo “ConnectionString”. A marcação “Default” indica qual o provedor corrente.

<connectionstrings>
<add connectionstring="ProxyName=net.jorgealbuquerque.pedweb.Dao.ConcreateFactories.XMLDaoFactoryProxy; Data Source=data.xml; ProxyAssemblyName=prevalentDao.dll; Default; " name="Prevalente (default)" providername="">

<add connectionstring="Integrated Security=SSPI; Persist Security Info=False;Initial Catalog=pedweb; User ID=sa; password=; Data Source=.\SQLSERVER;" name="Microsoft SQL Server 2000" providername="System.Data.SqlClient">

</connectionstrings>


Desta forma, a classe DaoProvider, realiza a leitura dos arquivos de configuração das APIs da plataforma .NET, interpreta seus parâmetros e mantêm referências aos seus provedores, que podem ser livremente criados, alterados ou removidos em tempo de execução e instanciados de forma estática.


A Tabela ao lado apresenta uma descrição resumida da interface da classe DaoProvider. A interpretação dos arquivos de configuração o ocorre durante a chamada do método GetInstance(). O carregamento somente é definido se a própria classe não contiver uma instância desta (design pattern singleton). Neste contexto, caso não exista uma instância, o método GetInstance() chama o método privado FillFromConfigManager() que, por sua vez, delega a leitura dos arquivos de configuração a classe nativa da plataforma .NET System.Configuration.ConfigurationManager (propriedade ConnectionStrings). Uma vez obtidas as strings de conexão (definidas nos arquivos web.config ou app.config), a responsabilidade da interpretação das mesmas é delegada a classe DaoProviderSettingsParse (método Parse), retornando os objetos DaoProviderSettings, que são adicionados a lista de provedores existentes (método Add). A seqüência de mensagens descritas é representada em notação UML na figura abaixo.

Nos próximos posts pretendo implementar estas primeiras classes de serviço e a seguir projetar o serviço de prevalência propriamente dito...

domingo, 23 de março de 2008

[Pessoal] Comer Sozinho

Minha mulher encontrou essa pérola no google e me mostrou! Eu não me lembrava! Foi escrito as 3:46 am num site obscuro. Claro que foi antes de efetivamente ficarmos juntos... Testemunho de uma época em que eu não estava satisfeito com a minha vida, e antes de mais nada por não estar com ela! Te amo, minha loira!

Adoro comer só
Máxima liberdade do egoísmo
Comer o que quiser... Quanto quiser... Como quiser...
O cardápio é seu, assim como o tempo
Um mini-mundo ao seu controle
E, se você voltar mais de uma vez
Juro que param de olhar...

"Aceita o último pedaço?"
O outro sempre aceita
Mesmo quando você queria
A voz de sua mãe espreita

Colegas de trabalho são os piores
Vinte pessoas num mesa (Sempre uma churascaria)
Jung diz que aproxima o grupo
Max diz que mistura a conta

Ao invés, almoço sushi
Self-service no supermecado
Badejinha de isopor, tudo em 20 segundos
Emagrece e não enche o saco

Odeio lavar pratos
Sempre janto na tupperware
Abro a tampa,
ligo o microondas
e pego um garfo.
Sempre na frente da TV
com 2 litros coca-cola (recentemente coca-zero)
E sem copos

A pizza, então, é perfeita
Sempre sobram ao menos 4 pedaços
Que ficam muito melhores frios
Perfeitos para o café
Perfeitos na noite seguinte

Mas o destino é irreverente
Estou em vias de casar
E adoro cozinhar para ela
Assisto ao Oliver (o ingles) e ao Olivier (o frances)

Me divirto muito preparando,
comendo a dois
e até lavando...

sexta-feira, 7 de março de 2008

[Livro] Muito longe de casa


Na contra-capa deste livro tem uma crítica da Newsweek: "É necessário ler apenas 20 páginas de 'Muito Longe de Casa' para afirmar que, se fosse ficção, o jovem autor deveria ganhar um prêmio Nobel". Parece uma chamada exagerada. Mas não é!

Essa é a auto-biografia de Ishmael Beah, contanto sua infância e adolescência em Serra Leoa em meio a uma guerra civil. O menino perde a família, passa a fugir para sobreviver ao conflito até ser recrutado como soldado pelo exercíto. A linguagem é simples, direta e tocantemente honesta. O livro foge a todos os lugares comuns. Ishmael não descreve em detalhes as atrocidades que comete como soldado, apenas em flashes (evidentemente pela vergonha e por querer esquecer), preferindo se ater a fuga e ao seu processo de recuperação. Mesmo assim, os flashs e os relatos de sobrevivência dramática deixam claro o tipo de violência praticada no interior de Serra Leoa de 1991 a 2002. A tática geral consiste em recrutar crianças, e tomar suprimentos de pequenas aldeiras para sustentar continuo conflito entre exército oficial e rebeldes (RUF). O detalhe é que em vez de saquear o necessário, a orientação é sempre torturar e exterminar com crueldade a todos os habitantes da aldeia (aparentemente na lógica corrente, massacrar com crueldade por nada demonstra força, sendo uma postura desejável). Não é preciso imaginar o custo humano dessa política em um povo já miserável e sem recursos.

Um detalhe que me chamou atenção é a discrepância entre a longevidade das pessoas e das armas. Os meninos soldados são extremamente descartáveis, mas as armas são sempre capturadas e postas novamente em circulação, nunca sendo destruídas.

Coincidência ao não, assim que acabei o livro liguei a TV e estava começando naquele instante o Senhor da Guerra no telecine!!! Embora o filme nem de longe sonhe em arranhar a profundidade do livro, completa o cenário discutindo o lado de quem ganha com tudo isso (apresenta a vida de um traficante de armas para Serra Leoa nesta mesma guerra civil). Ver o filme logo após ler o livro foi muito forte, porque remetia constantemente aos episódios do último, tornando-os ainda mais sinistros. O conflito de Serra Leoa ainda inspirou o filme Diamante de Sangue, que também é um conto da carochinha perto do livro. Acho que o filme que melhor captura a atmosfera desse livro (e do problema) é o Hotel Ruanda, embora não trate da questão das crianças propriamente dita (e também seja mais ameno). Em comum, o filme e o livro ilustram bem a perversidade humana, e que na falta de interesse, ninguem interfere na matança (em verdade, o presidente eleito somente tomou posse em Serra Leoa com a ajuda do exércido do Congo, aprovado pela ONU, mas essa ajuda demorou 10 anos).

Muito provavelmente, as únicas publicações comparáveis que tenha entrado em contado foram as graphic novels Gen (talvez a melhor de todos os tempos) e Maus, respectivamente, auto-biografias de um sobrevivente de Hiroshima e do Holocausto. Todos são impedíveis e as pessoas deveriam ler esses livros em alguma ocasição.

Para se pensar! E como disse Ghandi: "a civilização é uma boa idéia".

Apenas no enigma do macaco eu não vi graça: percebi a solução imediatamente!! :)

quinta-feira, 6 de março de 2008

[Java] Desenvolvimento declarativo orientado a anotações sobre JSF/Spring/JPA

A arquitetura definida sobre a pilha JSF/Spring/JPA apresenta um altenativa interessante para gestão da configuração de aplicações web, permitindo produtividade pelo uso extensivo de programação declarativa, desacoplamento entre camadas e independencia da persistencia/visualização. Neste contexto, é proposto um projeto "mock", demonstrando a integração JSF/Spring/JPA fortemente orientada a "annotations". A proposta consiste em somente definir por xml os elementos basicos da infra-estrutura descrita tais como datasource, entityManagerFactory e transactionManager (utiliza-se MyFaces 1.2.2 com Facelets, Spring 2.5 e JPA sobre Hibernate).

A aplicação consiste de um "Xavecometro", destinado a cadasto de "xavecos" (contatos do sexo oposto). Neste contexto, existem duas categorias de "xavecos": "tchutchucas" e "bagangas". (As colegas nao se ofendam! É uma grande piada!)

Classe Xaveco

package net.jorgealbuquerque.tutorial.xavecometro.entidades;

//imports not displayed

@Entity
public class Xaveco implements Serializable{

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Basic
private String nome;

@Basic
private Integer telefone;

@Enumerated
private Categoria categoria;

public Xaveco() {}

public Xaveco(String nome, Integer telefone) {
this.nome = nome;
this.telefone = telefone;
}

public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}

public Integer getTelefone() {
return telefone;
}
public void setTelefone(Integer telefone) {
this.telefone = telefone;
}

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

public Categoria getCategoria() {
return categoria;
}
public void setCategoria(Categoria categoria) {
this.categoria = categoria;
}
}


Para a DAO, é definida uma interface generica para os operadores CRUD (IDAO)

Interface IDAO

package net.jorgealbuquerque.tutorial.xavecometro.dao;

//imports not displayed

public interface IDAO {

T getById(ID id);
void persist(T entity);
void update(T entity);
void delete(T entity);
List getAll();
}


Seguindo o contrato IDAO, apresenta-se a implementação com JPA. Note que como a entityManager é instanciada. Ao inves de exterder a JPATemplate com a anotação @PersistenceContext, a entityManager é resolvida pelo Spring.

Classe AbstractJPADAO

package net.jorgealbuquerque.tutorial.xavecometro.dao;

//imports are not displayed

public abstract class AbstractJPADAO implements IDAO {

private Class persistentClass;

protected EntityManager entityManager;

@SuppressWarnings("unchecked")
public AbstractJPADAO() {
this.persistentClass = (Class) ((ParameterizedType) getClass().
getGenericSuperclass()).getActualTypeArguments()[0];
}

@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}

public Class getPersistentClass() {
return persistentClass;
}

public T getById(ID id) {
return entityManager.find(persistentClass, id);
}

public void persist(T entity) {
entityManager.persist(entity);
}

public void update(T entity) {
entityManager.merge(entity);
}

public void delete(T entity) {
entityManager.remove(entity);
}

@SuppressWarnings("unchecked")
public List loadAll() {
return entityManager.createQuery("Select t from " +
persistentClass.getSimpleName() + " t").getResultList();
}
}


A interface IXavecoDAO apresenta as especializacoes (operações especificas no database) sobre a IDAO

Interface IXavecoDAO

package net.jorgealbuquerque.tutorial.xavecometro.dao;

//imports not displayed

public interface IXavecoDAO extends IDAO{

public List getByNome(String nome);
}



Finalmente, a classe XavecoDAO recebe a anotação @Repository, desta forma o Spring pode gerenciar seu comportamento, também permitidindo ExceptionTranslation (PersistenceAnnotationBeanPostProcessor deve ser configurado no applicationContext.xml).

classe XavecoDAO

package net.jorgealbuquerque.tutorial.xavecometro.dao;

//imports not displayed

@Repository
public class XavecoDAO extends AbstractJPADAO implements IXavecoDAO{

@SuppressWarnings("unchecked")
public List getByNome(String nome) {
Query query = entityManager.createQuery("Select m from Xaveco m where m.nome = ?1");
query.setParameter(1, nome);
return query.getResultList();
}

}


A camada de negócios apresente a ServiceBean (XavecoService) e sua interface (IXavecoService). Note a anotação @Transactional, desta forma as transações tambem são configuradas por anotações (É necessária a marcação em applicationContext.xml)

Interface IXavecoService

package net.jorgealbuquerque.tutorial.xavecometro.service;

//imports not displayed

public interface IXavecoService {

@Transactional
public void createNew(Xaveco xaveco);
public List getAll();
public List getByNome(String nome);
}


Na classe Classe XavecoService, a anotação @Service transforma a classe em uma spring bean, e a classe XavecoDAO é injetada por referência utilizando @AutoWired

Classe XavecoService

package net.jorgealbuquerque.tutorial.xavecometro.service;

//imports not displayed

@Service
public class XavecoService implements IXavecoService{

private XavecoDAO xavecoDAO;

@Autowired
public XavecoService(XavecoDAO xavecoDAO) {
this.xavecoDAO = xavecoDAO;
}

public void createNew(Xaveco xaveco) {
xavecoDAO.persist(xaveco);
}

public List getAll() {
return xavecoDAO.getAll();
}

public List getByNome(String nome) {
return xavecoDAO.getByNome(nome);
}
}


Finalmente, Beans JSF e Facelets são utilizados para criacao de novos xavecos no sistema.

createXaveco.xhtml




A classe CreateXaveco tem a responsabildiade de manipular a página acima, sendo gerenciado pelo Spring. A anotação @Component refencia a spring bean com o nome "createXaveco". Nas views JSF, este nome é resolvido com expressões do tipo:
#{createXaveco.Xaveco.nome}. A anotação @Scope é utilizada para definir o request, separando escopos customizados.

Classe CreateXaveco

package net.jorgealbuquerque.tutorial.xavecometro.view;

//imports not displayed

@Component("createXaveco")
@Scope("request")
public class CreateXaveco implements Serializable{

private XavecoService xavecoService;
private Xaveco xaveco = new Xaveco();

@Autowired
public CreateXaveco(XavecoService xavecoService) {
this.xavecoService = xavecoService;
}

public Xaveco getXaveco() {
return xaveco;
}
public void setXaveco(Xaveco xaveco) {
this.xaveco = xaveco;
}

public String save() {
xavecoService.createNew(xaveco);
FacesMessage facesMessage = new FacesMessage(
FacesMessage.SEVERITY_INFO, "O Xaveco foi salvo com sucesso!",
"OK");
FacesContext.getCurrentInstance().addMessage(null, facesMessage);
xaveco = new Xaveco();
return null;
}
}


Arquivos XML:

Arquivo applicationContext.xml




Notas sobre o spring config;

  • habilita a busca anotações nos subpacotes de xavecometro.

  • habilita a gestao de transacoes orientada a annotations



Arquivo persistence.xml

net.jorgealbuquerque.tutorial.xavecometro.entidades



Arquivo faces-config.xml

com.sun.facelets.FaceletViewHandler
org.springframework.web.jsf.DelegatingVariableResolver


Arquivo web.xml

javax.faces.STATE_SAVING_METHOD
client

javax.faces.DEFAULT_SUFFIX
.xhtml

contextConfigLocation
classpath:applicationContext.xml

org.springframework.web.context.ContextLoaderListener
org.springframework.web.context.request.RequestContextListener

JPA Filter
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter

JPA Filter
*.jsf

Faces Servlet
javax.faces.webapp.FacesServlet
1

Faces Servlet
*.jsf


Adicionalmente, foi incluida uma classe de teste de integraçào para a XavecoDAO (TDD).

Classe XavecoDAOTest

package net.jorgealbuquerque.tutorial.xavecometro.dao;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import net.jorgealbuquerque.tutorial.xavecometro.entidades;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@TransactionConfiguration(transactionManager="txManager")
@ContextConfiguration(locations={"/applicationContext.xml"})
public class XavecoDAOTest{

private XavecoDAO xavecoDAO;

@Autowired
public void setRepository(XavecoDAO xavecoDAO) {
this.xavecoDAO = xavecoDAO;
}

@Test
public void shouldPersistNewXaveco() {
Xaveco xaveco = new Xaveco();
xaveco.setNome("Robertinha Fireball");
xaveco.setTelefone(new Integer(2342343));
xavecoDAO.persist(xaveco);
assertNotNull(xaveco.getId());
}

@Test
public void shouldFindBynome() {
Xaveco xaveco = new Xaveco();
xaveco.setNome("Renatinha Raio Laser");
xaveco.setTelefone(new Integer(7452354));
xavecoDAO.persist(xaveco);
assertNotNull(xaveco.getId());
List results = xavecoDAO.findBynome("Renatinha Raio Laser");
assertEquals(1, results.size());
assertEquals("Renatinha Raio Laser", results.get(0).getNome());
}

@Test
public void shouldReadAllXavecos() {
Xaveco xaveco1 = new Xaveco();
xaveco1.setNome("Pathy Tissunami");
xaveco1.setTelefone(new Integer(86452343));
Xaveco xaveco2 = new Xaveco();
xaveco2.setNome("Rafinha Quebra-Barraco");
xaveco2.setTelefone(new Integer(6734565));
xavecoDAO.persist(xaveco1);
assertNotNull(xaveco1.getId());

xavecoDAO.persist(xaveco2);
assertNotNull(xaveco2.getId());
List results = xavecoDAO.loadAll();
assertEquals(2, results.size());
}
}


Desta forma, pelo estudo proposto, concluí-se que a orientação a anotações para a pilha JSF/Spring/JPA permitinde, delegando a responsabilidade de ligação das camadas ao Spring.

terça-feira, 4 de março de 2008

[.NET] Videos ASP.NET 3.5

Como parte integrante do lançamento da IDE VS 2008, a API ASP.NET 3.5 integra nativamente Ajax e novos componentes de GUI e processamento de dados. Vale a pena conferir os video-tutoriais em http://asp.net/learn/3.5-videos/