Pesquisar

Mostrando postagens com marcador tutorial. Mostrar todas as postagens
Mostrando postagens com marcador tutorial. Mostrar todas as postagens

terça-feira, 29 de junho de 2010

Habilitando Cache level 2 no JPA 1.0 (Hibernate)

Uma das características prometidas para o JPA 2.0 e já implementada no hibernate é Second Level cache! Pra habilita-lo é bem simples:

Basta informar ao Hibernate (seja pelo persistence.xml ou pelo applicationContext.xml) as seguintes propriedades.
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider {classe padrão pra prover serviços de cache}
hibernate.cache.use_query_cache=true {se deve ou não fazer caches de queries}


Lembrando que por padrão você deve configurar entidade a entidade as quais devem ou não serem cacheadas (com a anotação @Cache junto a @Entity, você também pode cachear coleções!) e qual a política (de concorrência) que deve ser usada no esquema de cache (NONSTRICT_READ_WRITE, NONE, READ_ONLY, WRITE_ONLY, TRANSACTIONAL). Depois é só observar pelo log de sql :D! Have fun!

sexta-feira, 7 de maio de 2010

Adicionando escopo de conversação ao JavaServer Faces 1.X (JSF 1.2)

Que o JSF não é perfeito todos sabemos mas se há algo que me incomoda muito são duas coisas chatas: URL amigáveis (que consegui resolver facilmente com PrettyFaces.) e tratar tudo como escopo de sessão (por falta de um escopo entre o requisição e o sessão).

Para o último problema começei a pesquisar algumas soluções possíveis e cheguei ao framework MyFaces Orchestra.

O MyFaces Orchestra é um framework que pode ser usado em aplicações web para prover as caracteristicas de escopo conversacional. Apesar de ter sido criado para ser um framework de escopo para web presentations ele tem, hoje, só implementações para JSF 1.1, 1.2 e 2.0.

Para utilizar o framework você precisa, obrigatoriamente, usar o Spring 2.0 (ou maior) como gerenciador de seus managed beans. E claro ter os modulos do Orchestra (core12 e o core15 são os usados no exemplo) no seu classpath.

Exemplo

Fiz um exemplo utilizando Eclipse juntamente com quarteto fantástico : richfaces 3.3.3 + Facelets + spring 3.0.1 + hibernate 3.0.2 (JPA)! e tive que mudar/configurar os seguintes arquivos:

web.xml

<listener>
<listener-class>org.apache.myfaces.orchestra.conversation.servlet.ConversationManagerSessionListener</listener-class>
</listener>

applicationContext.xml

<import resource="classpath*:/META-INF/spring-orchestra-init.xml" />

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="conversation.manual">
<bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope">
<property name="timeout" value="30" />
<property name="lifetime" value="manual"/>
</bean>
</entry>

<entry key="conversation.access">
<bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope">
<property name="timeout" value="30" />
<property name="lifetime" value="access"/>
</bean>
</entry>
</map>
</property>
</bean>


Simplesmente após ter feito tais mudanças e ter atendido aos requisitos básicos: declarei meu bean no applicationContext com scope="conversation.access". No exemplo naveguei de uma página listar.xhtml para outra editar.xhtml mantendo o estado! Fiz testes posteriores também com uso de Ajax (a4j) com multiplos requests para mesma página ou outra tudo passou perfeito!

Se quiser ver o projeto baixe aqui o projeto (.war com sources)!

Further Reading!

O framework também fornece uma solução (essa eu não testei) para os lazy initializations lançados (esse com integração forte ao hibernate). Há também um esquema de binding muito legal.

ps: todo o post está levando em consideração as características do Jsf 1.x o Jsf 2.0 resolve alguns desses empecilhos.
ps2: ainda há algo que me incomoda é a quantidade de linhas no faces-config para lhe dar com navegação entre as páginas.
ps3: fiz testes básicos nesse projeto aconselho fazer mais testes reais na sua aplicação antes de substituir session por conversation.

quarta-feira, 28 de abril de 2010

Integrando google app engine (GAE) + Spring 3.0.2 + Hibernate (JPA)

Google App Engine - GAESpring FrameworkHibernate - JPA

Introdução

Usar a infraestrutura do google para hospedar suas aplicações pode parecer algo fantástico. Imagine ter todo o poder e segurança fornecido pelo Google diretamente nas suas aplicações. É com essa promessa que o Google App Engine (GAE) foi lançado. Pode-se criar aplicações Web usando Python ou Java.
+Vantagens: boa documentação em pt_BR, aproveitar da escalabilidade do google, desenvolver em Java (no ponto de vista de número de pessoas aptas) e etc.
-Desvantagens: JRE com menos classes, frameworks não funcionando ou funcionando parcialmente, restrições ao uso do JPA e etc.

Configurando plugin no Eclipse

Para facilitar, muito, a criação, deploy e debug de seus aplicativos aconselho a utilizar o Eclipse juntamente com o plugin fornecido pelo google.

Integrações

Spring 3.0.2

Gosto de usar o controle transacional do Spring (@Transactional) , injeção de dependência e a implementação do open session in view (OpenEntityManagerInView) e para usar tais recursos tive que configurar o web.xml dessa forma.

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<filter>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Já o arquivo applicationContext.xml ficou assim.

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" lazy-init="true">
<property name="persistenceUnitName" value="t3st3" />
</bean>
<bean name="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

JavaServer Faces 2 (JSF 2.0)

Costumo repassar o trabalho de cuidar do ciclo de vida dos managedbean para o Spring. A utilização do jsf 2 (implementação myfaces) traz as novidades do jsf 2.0 (que é um grande passo) e saber que é compatível com gae é muito bom. Bem meu web.xml ficou assim.

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>


<!--
We need to set annotation lifecycyle provider manually as org.apache.myfaces.config.annotation.NoInjectionAnnotationLifecycleProvider.
Other providers use some classes that are restricted on Google App Engine.
-->
<context-param>
<param-name>org.apache.myfaces.config.annotation.LifecycleProvider</param-name>
<param-value>org.apache.myfaces.config.annotation.NoInjectionAnnotationLifecycleProvider</param-value>
</context-param>

<!--
Need to set a secret to avoid javax.crypto.BadPaddingException.
"param-value" must be Base64 encoded.
More details: http://wiki.apache.org/myfaces/Secure_Your_Application
-->
<context-param>
<param-name>org.apache.myfaces.SECRET</param-name>
<param-value>NzY1NDMyMTA=</param-value>
</context-param>

e o faces-config.xml assim:

<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>

Hibernate

Só usar! Ahh é mesmo tem que se criar um arquivo persistence.xml (META-INF) mínimo.

Observações gerais:
Tente usar sempre o objeto Key como id, pois objetos filhos devem usar Key ou String codificada, não sendo possível usar long ou int.
Você pode acompanhar o status do ambiente, quais serviços estão online qual a latência de uso e etc.

terça-feira, 23 de fevereiro de 2010

Como usar JavaScript na plataforma Java

Em minha mente o assunto scripting na plataforma Java já estava bem explorado e difundido. Mas hoje fui supreendido por um amigo com um mini-framework que servia de analisador e parser para simples fórmulas matemáticas como p.ex:
2+2-1*3/3
(2+2)*10

Usando Java 6 basta esse simples código.

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
try {
String script = " 10 + 2 * 2 "; //ou sua expressão
Object result = engine.eval(script);
System.out.println(result);
} catch (ScriptException ex) {
System.out.println("deu erro :P "+ex);
}

terça-feira, 1 de dezembro de 2009

Tutorial Apache Lucene 3.0.0 - motor de busca textual


Lucene um motor de busca textual

No dia 25 de novembro foi lançado a nova versão do motor de busca Lucene, a versão 3.0.0. Lucene é um framework de alta performance para busca textual feito em java. (há versões para php e .net também) Uma das características marcantes dele é a integração com Hadoop. (um framework para computação distribuida - que possui, dentre outros, um MapReduce e um sistema de arquivos distribuido HDFS)

Porque usar Lucene?

Imagine o seguinte cenário: Seu usuário deseja criar um modulo de gerenciamento de artigos e também expó-los na Internet. As informações do artigo são: título, autor e o contéudo. Normalmente cada artigo desse contém cerca de 1500 palavras e o usuário poderá buscar pelo conteudo desses artigos. Suponha que há 1 milhão e meio de artigos para serem cadastrados, o simples uso de um banco de dados e o operador LIKE '%palavra%' é inviável. E aí que entra um bom framework de busca textual, usá-lo passa ser a solução mais tranquila e viável. Além de trazer velocidade, também traz outras características nas buscas que dificilmente fariamos codificando tudo do zero.

Domain-Specific Language | Ubiquitous Language

Há vários termos usados na terminologia do framework, os principais são: Documento, Campo, Diretório, Indexador, Pesquisador, Analisador e Termo.

  • Documento - é o conjunto de dados que você deseja indexar, por ex. título, conteudo e autor formam o documento artigo, pode ser visto como um objeto no lucene é visto como Document.
  • Campo - é o dado, identificado, que pode ser analogo a um campo de uma tabela ou uma propriedade de um objeto no lucene é visto como Field.
  • Diretório - conceito abstrato que denota um local para guardar os índices no lucene é visto como uma interface Directory, que possui diversas implementações DbDirectory, FSDirectory, JEDirectory, RAMDirectory.
  • Indexador - é o responsável por indexar os documentos num diretorio no lucene é visto, geralmente, como IndexWriter.
  • Pesquisador - responsável por pesquisar uma Query no diretorio de índices, no lucene é visto como Searcher.
  • Analisador - atua como um filtro e faz uma pré-avaliação do que pode ser indexado ou não, no lucene há uma lista de vários analisadores.
  • Termo - pode ser visto como objeto que pode ser usado como parametro da pesquisa, composto pelo nome do campo e o valor a ser pesquisado, no lucene é visto como Term.

Como isso funciona?

A descrição a seguir é um resumo bem simplificado sobre o funcionamento de um motor de busca textual. A primeira fase, geralmente, é a indexação do documento, nessa fase o documento é analizado (por um Analizer que também já retira as stopwords) para posteriomente ser indexado.

Set stopWords = new HashSet();
stopWords.add("the");
stopWords.add("it");
stopWords.add("is");
IndexWriter writer = new IndexWriter(FSDirectory.open(INDEX_DIR),
new StandardAnalyzer(Version.LUCENE_CURRENT,
stopWords),
false,
IndexWriter.MaxFieldLength.LIMITED);


No Lucene você pode criar um índice usando o IndexWriter, a criação desse objeto envolve dizer onde será (ou está) o diretório dos índices, qual analizador você irá utilizar, se irá criar o indice e qual a quantidade máxima de campos.

O objetivo do indexador é indexar documentos, para tanto é necessário que haja documentos para serem indexados.
Document doc = new Document();
doc.add(new Field("nomedocampo", "valores a serem guardados", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("camp1","valores a serem analisados tokenizados",Field.Store.YES, Field.Index.toIndex(true, true)));
writer.addDocument(doc);
É o objetivo final de todo processo de busca textual é mesmo a busca em si.
String valueToBeSearched = "red";
String index = "indexDir"; //dirotorio base do indice
IndexReader reader = IndexReader.open(FSDirectory.open(new File(index)), true); //indexador
Searcher searcher = new IndexSearcher(reader); //pesquisador
QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, field, analyzer); //transoformador do texto em uma query
Query query = parser.parse(valueToBeSearched); //a consulta (query) em si
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, false); //os melhores resultados
searcher.search(query, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs; //o conjunto de melhores documentos para a consulta

int maximo = hits.length;
Document doc = searcher.doc(hits[index].doc);
String valor = doc.get("nomeDoCampo");

Recursos na busca de documentos

Quando se faz uma pesquisa por documentos no Lucene podemos utilizar de alguns operadores (+, -, AND, NOT, OR, * e etc.) juntamente com o termo pesquisado ou apenas pesquisar uma frase completa.

Exemplo : termo
Consequência: Irá pesquisar a palavra "termo" nos documentos indexados.

Exemplo : termo OR palavra ( == termo palavra)
Consequência: Irá pesquisar "termo" ou "palavra" nos documentos indexados.

Exemplo : +termo +palavra ( == termo AND palavra)
Consequência: Irá pesquisar "termo" e "palavra" nos documentos indexados.

Exemplo : campo:termo
Consequência: Irá pesquisar "termo" no campo "campo" nos documentos indexados.

Exemplo : +homer +simpsons -house
Consequência: Irá pesquisar documentos que contenham homer e simpsons e não tenha house.

Exemplo : "termo exato"
Consequência: Irá pesquisar documentos que contenham exatamente "termo exato".

Exemplo :
java*
Consequência: Irá pesquisar documentos que contenham palavras que começem com java (javadb, javanet...).

Exemplo : java~
Consequência: Irá pesquisar documentos que contenham palavras similares a java como por ex. lava, jaba...

Finalizando tive as seguintes impressões sobre essa nova versão do Lucene.

Prós:
  • Maior facilidade para uso do framework, ex: criações de Fields estão bem mais fluentes.
  • Sensível otimização nos tempos de busca e indexação.

Contras:
  • Otimas ferramentas como luke ainda não tem suporte para a versão 3.0.0. (mas já há uma solicitação aberta para tal mudança.)
  • Muitas mudanças no core do framework; o que fez livros mais antigos quase perderem seu valor.

Referências