Arquivo da categoria ‘Java’

JBoss Seam + DTO + EntityQuery

Outubro 16, 2009

Fazer um consulta na base de dados, retornar alguns registros e criar uma tela para pesquisa contendo ordenação e paginação é uma tarefa repetitiva no desenvolvimento de aplicações.

Pensando nisso, o framework JBoss Seam fornece uma classe chamada EntityQuery que, ao ser herdada, fornece todos os métodos necessários para execução e retorno da consulta, ordenação e paginação dos registros. Por exemplo, suponha uma classe persistente chamada EntidadeA, o código abaixo já é mais do que o suficiente para construção de uma tela de exibição e pesquisa:

@Name(“entidadeAList”)

public class EntidadeAList extends EntityQuery<EntidadeA> {

private static final String EJBQL = “select a from EntidadeA a”

private static final String[] RESTRICTIONS = { “lower(a.campoA) like lower(concat(#{entidadeAList.entidade.campoA},’%'))”,}

public EntidadeAList() {

setEjbql(EJBQL);

setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));

setMaxResults(10);

}

private EntidadeA entidade A;

//Get e Set para entidadeA

}

Prontinho!!! É só criar sua página de exibição e chamar os métodos disponíveis na classe.

Infelizmente (ou felizmente!?), nem todas as aplicações são tão simples asssim. Desenvolvimento uma dessas aplicações não tão simples, precisei de um DTO para encapsular joins espaciais e outras operações geométricas sobre as entidades persistentes. Segue abaixo o pseudo-código:

@Name(“entidadeDTOList”)

public class EntidadeDTOList extends EntityQuery<EntidadeDTO> {

private static final String EJBQL = “select new meupacote.EntidadeDTO(a.nome, intersection(a.theGeom, b.theGeom)) from EntidadeA a, EntidadeB b”

private static final String[] RESTRICTIONS = {“intersects(a.theGeom, b.theGeom) = #{true}”, “lower(a.campoA) like lower(concat(#{entidadeDTOList.entidade.campoA},’%'))”,}

public EntidadeAList() {

setEjbql(EJBQL);

setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));

setMaxResults(10);

}

private EntidadeA entidade A;

//Get e Set para entidadeA

}

Nesse caso, simplesmente herdar de EntityQuery não funcionou. O método de navegação “lastFirstResult” dispara a exceção “invalid select clause for query”.

Investigando mais de perto, abri o código-fonte da super classe Query e observei que o erro estava acontecendo dentro do método getCountEjbql(). O grande problema é que a seguinte expressão regular usada pelo Seam não abrange casos um pouco mais complexos:

SUBJECT_PATTERN = “Pattern.compile(“^select(\\w+((\\s+|\\.)\\w+)*\\s+from”, Pattern.CASE_INSENTIVE)

Como não queria criar um fork do Seam “corrigindo” o pattern, preferi sobrescrever o método na minha classe, que no final ficou parecida com o código abaixo:

@Name(“entidadeDTOList”)

public class EntidadeDTOList extends EntityQuery<EntidadeDTO> {

private static final String EJBQL = “select %s from EntidadeA a, EntidadeB b where intersects(a.theGeom, b.theGeom) = true”

private static final String EJBQL_PROJ = “new meupacote.EntidadeDTO(a.nome, intersection(a.theGeom, b.theGeom))”

private static final String[] RESTRICTIONS = { “lower(a.campoA) like lower(concat(#{entidadeDTOList.entidade.campoA},’%'))”,}

public EntidadeAList() {

setEjbql(String.format(EJBQL, EJBQL_PROJ);

setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));

setMaxResults(10);

}

@Override

protected String getCountEjbql() {

String query = getRenderedEjbql();

query = query.replace(EJBQL_PROJ, “count(c)”);

return query;

}

private EntidadeA entidade A;

//Get e Set para entidadeA

}

Agora sim! Funcionando de forma satisfatória, porém não ideal. Acho que o Seam já poderia ter feito uma expressão regular que contemplasse esses casos.

Até a próxima!

Mais uma da série: não perca tempo

Outubro 9, 2009

Opa pessoal,

Vou relatar mais uma experiência que pode poupar muito o tempo de vocês quando tiverem trabalhando com a combinação Seam + Eclipse (com JBoss Developer Tools) + JBoss 5.1.

Hoje precisei fazer uma pequena alteração no faces-config.xml de meu projeto e quando dei um seam explode, sem mais nem menos, o JBoss ficava em loop ao tentar fazer o deploy do projeto. Eu fazia um unexplode e quando, para testar, executava um seam deploy, ele conseguia fazer o deploy normalmente. Resolvi investigar e percebi, pela utilização de um controle de versões (Mercurial), que quando eu salvei o projeto utilizando o JBoss Tools XML Editor ele criou outros arquivos:

>hg status
M exploded-archives\sispetroleogas.war\WEB-INF\faces-config.xml
M resources\WEB-INF\faces-config.xml
M test-build\WEB-INF\faces-config.xml
? exploded-archives\sispetroleogas.war\WEB-INF\.faces-config.xml.jsfdia
? resources\WEB-INF\.faces-config.xml.jsfdia
? test-build\WEB-INF\.faces-config.xml.jsfdia

Bingo! Por alguma razão, o arquivo .faces-config.xml.jsfdia criado no WEB-INF do projeto e copiado pelo “seam explode” no processo de build, faz o JBoss se perder e ele fica em loop infinito. Para resolver o problema bastou apagar esses arquivos e para ele não se repetir utilizo agora o XML Editor padrão do Eclipse que não cria nenhum arquivo adicional.

Até a próxima,

Get Feature Info – Novo componente OL4JSF

Outubro 1, 2009

Uma típica chamada getfeatureinfo utilizando puramente o OpenLayers é assim:

map.events.register(‘click’, map, function (e) {
document.getElementById(‘nodelist’).innerHTML = “Carregando… aguarde…”;
var params = {
REQUEST: “GetFeatureInfo”,
EXCEPTIONS: “application/vnd.ogc.se_xml”,
BBOX: map.getExtent().toBBOX(),
X: e.xy.x,
Y: e.xy.y,
INFO_FORMAT: ‘text/html’,
QUERY_LAYERS: map.layers[1].params.LAYERS,
FEATURE_COUNT: 50,
Srs: ‘EPSG:4291′,
Layers: ‘topp:campos’,
Styles: ”,
WIDTH: map.size.w,
HEIGHT: map.size.h,
format: ‘image/png’};
OpenLayers.loadURL(“http://localhost:8080/geoserver/wms”, params, this, setHTML, setHTML);
OpenLayers.Event.stop(e);
});

Achou muito código? Que tal utlizar o OL4JSF e deixar o código assim:

<m:getFeatureInfo url=”#{request.contextPath}/JGSProxy/wms” layers=”topp:campos” onCompleteJsFunc=”setHTML” queryLayers=”map.layers[1].params.LAYERS” />

Um código muito mais legível e fácil de manter. ;)

Até a próxima!

Link do projeto:  https://ol4jsf.dev.java.net/

Projeto OL4JSF – Open Layers For JSF

Setembro 8, 2009

Olá pessoal,

Tenho o prazer de anunciar a versão inicial do projeto que tem por objetivo criar um conjunto de componentes JSF sobre a biblioteca OpenLayers. Dessa forma, o desenvolvimento da camada de visualização torna-se mais produtivo e menos propício a erros, tendo em vista que é necessário muito menos código javascript na construção das páginas. Além disso, tem um plugin inicial para o Netbeans e o plugin do Eclipse está a caminho.

Site do projeto: https://ol4jsf.dev.java.net/

Abraços,

Tutorial JBoss Seam – Abrir projeto no Eclipse

Janeiro 9, 2009

Como algumas pessoas têm entrado em contato comigo com dúvidas de como abrir um projeto seam no Eclipse, segue abaixo um pequeno passo a passo para ter o projeto dentro de usa IDE.

Primeiramente, acesse “File -> Import…”.

Obs: Para aparecer na lista de projetos, você deve selecionar o diretório escolhido para ser o “Java project workspace” (primeira pergunta ao executar o comando seam setup.

Pronto! Agora com o projeto dentro da IDE, torna-se possível utilizar todos os poderosos recursos do Eclipse!

Elipse – JBoss 5

Dezembro 11, 2008

Se você é como eu e já fez questão de fazer download do JBoss 5, encontrou alguns problemas no classpath em seu ambiente Eclipse (Ganymede).  Isso aconteceu porque o JBoss mudou a estrutura de diretório contendo diversas bibliotecas.

Como não queria esperar o tempo de fazer o download de uma versão do Eclipse só para corrigir isso, resolvi alterar um dos arquivos de configuração do WTP.

O arquivo é o seguinte:

<DIR INSTALAÇAO DO ECLIPSE>\plugins\org.eclipse.jst.server.generic.jboss_1.5.205.v200805140145\servers\jboss5.serverdef

Segue o  trecho do arquivo com a alteração. A única parte do xml que alterei foi a referente ao classpath (classpath id=”jbossproject”).

<classpath id=”jboss.project” >

<fileset dir=”${serverRootDirectory}”>
<include name=”client/*.jar” />
<include name=”server/default/lib/*.jar” />

<include name=”server/default/deploy/jbossweb.sar/jsf-libs/*.jar” />

<!– This will be ignored if EJB3 is not there 5.0 –>
<include name=”common/lib/*.jar” />
<include name=”lib/*.jar” />
<include name=”server/default/deployers/jbossweb.deployer/*.jar” />
<include name=”server/default/deployers/jboss-aop-jboss5.deployer/*.jar” />
<include name=”server/default/deployers/ejb3.deployer/*.jar” />

<!– for validation to work this library is defined as an archive –>

<exclude name=”common/lib/mail.jar” />

</fileset>

<!– leave one generic jar as an archive so that validation works –>

<archive path=”${serverRootDirectory}/common/lib/mail.jar” />

</classpath>

É issoa aí! Agora é só reiniciar o seu Elipse e adicionar o seu novo servidor em Window -> Preferences -> Server -> Runtime Environments.

Tutorial JBoss Seam

Outubro 21, 2008

Olá pessoal!

Resolvi escrever um breve tutorial sobre esse excelente framework Java para desenvolvimento de aplicações JEE. Breve tutorial? É possível fazer alguma coisa em JEE de forma breve?  Sim, com o Seam é possível. Obviamente, não explicarei sobre a arquitetura do framework e, muito menos, sobre a arquitetura JEE.  O nosso objetivo é desenvolver uma aplicação simples para cadastro de fornecedores e produtos. No nosso exemplo, um produto só pode pertencer a um único fornecedor.

DER do nosso pequeno sistema.

DER do nosso pequeno sistema.

Primeiro, você deve baixar o JBoss 4.2.3 GA e o JBoss-seam-2.0.2.SP1  (ver links) e descompactá-los em um diretório de sua escolha. Devo lembrá-lo que é necessário que o JDK 5, ou superior, esteja instalado e configurado no seu PATH.

Entre no diretório onde você descompactou o JBoss e inicie o servidor executando o script run.bat (Windows) ou run.sh (Linux) contido na pasta “Bin”.  Isso aí! Já temos um servidor JEE em execução!

Começaremos o desenvolvimento de nossa aplicação.

Para isso, abra o prompt de comando do seu SO e entre no diretório onde você descompactou o JBoss-seam.  Execute o seguinte comando (digite “seam help” para visualizar todas as opções disponíveis):

> seam setup

Algumas perguntas serão feitas e todas elas têm uma opção default. As respostas são bastante intuitivas. Mas vale ressaltar que o driver jdbc do seu SGBD deve estar no lib do JBoss-seam. Seguem abaixo as respostas que forneci:


Enter your Java project workspace (the directory that contains you Seam projects)
e:/EclipseProjects
Enter your JBoss home directory
c:/jboss-4.2.3.GA
Enter the project name
tutorial_seam
Do you want to use ICEFaces instead of RichFaces [n] (y, [n])
Select a RichFaces skin [blueSky] ([blueSky], classic, ruby, wine, deepMarine, emeraldTown, sakura, DEFAULT)
Is this project deployed as an EAR (with EJB components) or a WAR with no EJB support) [ear] ([ear], war)
Enter the Java package name for your session beans
com.mydomain.sessionbean
Enter the Java package name for your entity beans
com.mydomain.entitybean
Enter the Java package name for your test cases
com.mydomain.test
What kind of database are you using?
postgres
Enter the Hibernate dialect for your database [org.hibernate.dialect.PostgreSQLDialect]
Enter the filesystem path to the JDBC driver jar
../lib/postgresql-8.3-603.jdbc3.jar
Enter JDBC driver class for your database [org.postgresql.Driver]
Enter the JDBC URL for your database
jdbc:postgresql://localhost:5432/tutorial_seam
Enter database username
postgres
Enter database password
*******
Enter the database schema name (it is OK to leave this blank) []
Enter the database catalog name (it is OK to leave this blank) []
Are you working with tables that already exist in the database? [n] (y, [n])
Do you want to drop and recreate the database tables and data in import.sql each time you deploy? [n] (y, [n])

Com isso, temos a configuração necessária para criarmos efetivamente a estrutura de nosso projeto:

> seam create-project

Nesse ponto, já poderíamos abrir esse projeto no Eclipse ou no Netbeans. Mas não iremos abordar isso nesse tutorial.

Em seguida, gere o script da base de dados e importe em algum SGBD relacional de sua escolha. Para o exemplo, estou utilizando o Postgres.

Agora, vamos fazer a engenharia reversa da nossa base de dados e criar todas as páginas, classes, etc, necessárias para nossa aplicação funcionar:

> seam generate-entities

Pronto! Que tal fazermos um deploy de nossa aplicação no nosso servidor JEE? É muito simples:

> seam explode

Abra o seu browser e entre com a URL (O usuário para login é “admin” e a senha pode ser qualquer coisa):

http://localhost:8080/tutorial_seam

Screenshot da aplicação.

Screenshot da aplicação.

Conclusão

Dessa forma, concluímos o nosso projeto com todo o poder da plataforma JEE (transações distribuídas, pool de conexões, internacionalização, etc.) em poucos minutos (sem levar em consideração o tempo que levou para fazer os downloads :) ). Para aplicações do mundo real, esses utilitários são de grande ajuda, pois são o ponto de partida para pularmos tarefas tediosas como: montagem da estrutura inicial do projeto, criação de CRUDs,  mapeamentos ORM, etc. Sendo assim, direcionamos o nosso foco para a criação de regras de negócio e personalização dos artefatos gerados pela ferramenta.
Aconselho você a olhar o código gerado e observar como é relativamente simples, poderoso e robusto. Não se assuste com a quantidade de XMLs gerados, provavelmente, nunca você vai precisar mexer neles. ;)

Links

http://docs.jboss.com/seam/2.0.2.SP1/reference/en-US/html
http://www.seamframework.org/Download
http://www.jboss.org/jbossas/downloads/