Acrescentei um novo recurso ao cartucho Spring: a geração automática de métodos de pesquisa quando o atributo da entidade é único. Para todos os atributos marcados como únicos ( <<Unique>> ) da sua entidade, será gerado um método de pesquisa no DAO que recebe um valor do mesmo tipo do atributo como parâmetro e retorna uma instância da entidade.
Por exemplo, se a sua entidade Aluno tem um atributo nome do tipo String, será gerado no DAO o seguinte método:
public Aluno searchUniqueNome(nome: String)
Caso esse método retorne mais de uma intância de Aluno, a exceção org.hibernate.NonUniqueResultException é disparada.
Blog do Walter
Comentários sobre desenvolvimento de software envolvendo MDA, Andromda, JavaEE e tecnologias relacionadas.
sábado, 25 de setembro de 2010
domingo, 19 de setembro de 2010
Simplificando Casos de Uso no cartucho andromda-jsf
Uma coisa que sempre me incomodou na modelagem de atividades do cartucho andromda-jsf foi a obrigação de se modelar métodos para responder aos eventos. Apesar de considerar que é uma modelagem válida do ponto de vista da aderência quando os métodos são reutilizados, eu considero que o simples fato de existir o evento de saída do <<FrontEndView>> deveria gerar um "gancho" para o programador escrever sua lógica.
Finalmente agreguei essa simplificação ao cartucho andromda-jsf, de modo que agora o desenvolvedor não precisa criar métodos no controller se não quiser. Pode de fato deixar o controller completamente em branco e simplesmente sobrepor os (novos) métodos que são gerados no controller ancestral para responder aos eventos do usuário. Por exemplo, no modelo abaixo:
o controller não tem método nenhum e ao programá-lo, basta ao programador sobrepor o método _dadosDoAluno_confirmar da classe ancestral para executar a inclusão do aluno, fazendo com que a implementação do controller fique assim:
São gerados também métodos para cada estado de ação que não seja <<FrontEndView>>, mas é um caso mais complicado, porque são gerados métodos que atendam a todas as combinações de transições de entrada, eventualmente dificultando a programação. O melhor é sobrepor os eventos mesmo...
Finalmente agreguei essa simplificação ao cartucho andromda-jsf, de modo que agora o desenvolvedor não precisa criar métodos no controller se não quiser. Pode de fato deixar o controller completamente em branco e simplesmente sobrepor os (novos) métodos que são gerados no controller ancestral para responder aos eventos do usuário. Por exemplo, no modelo abaixo:
o controller não tem método nenhum e ao programá-lo, basta ao programador sobrepor o método _dadosDoAluno_confirmar da classe ancestral para executar a inclusão do aluno, fazendo com que a implementação do controller fique assim:
São gerados também métodos para cada estado de ação que não seja <<FrontEndView>>, mas é um caso mais complicado, porque são gerados métodos que atendam a todas as combinações de transições de entrada, eventualmente dificultando a programação. O melhor é sobrepor os eventos mesmo...
quinta-feira, 5 de agosto de 2010
TextUML e Andromda
Ontem fiz uma pequena experiência com o TextUML e o Andromda. Foi uma experiência pequena porém bem sucedida, consistindo na criação de uma aplicação com 2 CRUDs associados.
Entendo que a possibilidade de se programar modelos sem desenhá-los abre um leque de caminhos para aqueles que, como eu, gostam do desenvolvimento organizado e com visão de alto nível, não abrindo mão da agilidade no processo.
O que mais senti falta foi dos casos de uso e das máquinas de estado. Espero que o TextUML evolua logo nesse sentido para que possamos fazer modelagens completas de aplicações sem, obrigatoriamente, termos que desenhar.
Entendo que a possibilidade de se programar modelos sem desenhá-los abre um leque de caminhos para aqueles que, como eu, gostam do desenvolvimento organizado e com visão de alto nível, não abrindo mão da agilidade no processo.
O que mais senti falta foi dos casos de uso e das máquinas de estado. Espero que o TextUML evolua logo nesse sentido para que possamos fazer modelagens completas de aplicações sem, obrigatoriamente, termos que desenhar.
domingo, 11 de julho de 2010
DNS Dinâmico no Amazon EC2
Recentemente passei a usar alguns servidores no Amazon EC2 para testar o ambiente e as possibilidades. Montei ambientes Ubuntu seguindo o AMI do Lucid disponibilizado pela Canonical.
Como eu queria ter acesso remoto ao ambiente desktop também, depois de criar os ambientes básicos eu instalei o Gnome e o NoMachine NX Server. Em poucas palavras, o NX Server (e o client) são uma forma MUITO eficiente de se acessar ambiente baseados em XWindows remotamente. É MUITO mais eficiente que o VNC, por exemplo.
Funcionou tudo muito bem, exceto por um detalhe: a cada vez que a máquina é ligada no EC2, ela ganha um IP novo... claro que a Amazon oferece um serviço de IP fixo, mas como esses ambientes são de teste, eu não queria inve$tir nada além do mínimo necessário.
Já uso o serviço de DNS do DNS Park e, depois de pesquisar muito consegui configurar o DDClient para atualizar o serviço de DNS dinâmico do DNS Park.
O arquivo de configuração do DDClient ( /etc/ddclient/ddclient.conf ) que usei foi:
Como eu queria ter acesso remoto ao ambiente desktop também, depois de criar os ambientes básicos eu instalei o Gnome e o NoMachine NX Server. Em poucas palavras, o NX Server (e o client) são uma forma MUITO eficiente de se acessar ambiente baseados em XWindows remotamente. É MUITO mais eficiente que o VNC, por exemplo.
Funcionou tudo muito bem, exceto por um detalhe: a cada vez que a máquina é ligada no EC2, ela ganha um IP novo... claro que a Amazon oferece um serviço de IP fixo, mas como esses ambientes são de teste, eu não queria inve$tir nada além do mínimo necessário.
Já uso o serviço de DNS do DNS Park e, depois de pesquisar muito consegui configurar o DDClient para atualizar o serviço de DNS dinâmico do DNS Park.
O arquivo de configuração do DDClient ( /etc/ddclient/ddclient.conf ) que usei foi:
daemon=300 # check every 300 seconds
syslog=yes # log update msgs to syslog
#mail=email@dnspark.com # mail all msgs to address
#mail-failure=email@dnspark.com # mail failed update msgs to address
pid=/var/run/ddclient.pid # record PID in file.
login=loginDoUsuarioDDNS # DNS Park DDNS username (NOT your DNS Park account login)
password=passwordDoUsuarioDDNS
use=cmd, cmd='curl http://169.254.169.254/2007-08-29//meta-data/public-ipv4'
protocol=dnspark subdominio.dominio.com.br #dominio que vc configurou no DNS Park para ser dinâmico
Um detalhe importante: em login/password não vai o seu login/password geral do DNS Park e sim um login específico para dns dinâmico que você cria livremente, no DNS Park.
Depois de testar na mão rodando do ddclient direto na linha de comando, montei o seguinte arquivo de configuração ( /etc/init/ddclient.conf ) para que o upstart do Ubuntu executasse o ddclient logo na inicialização:
Depois de testar na mão rodando do ddclient direto na linha de comando, montei o seguinte arquivo de configuração ( /etc/init/ddclient.conf ) para que o upstart do Ubuntu executasse o ddclient logo na inicialização:
# ddclient initialization
description "Starts ddclient"
start on (net-device-up
and local-filesystems)
exec /usr/sbin/ddclient
Funcionou que foi uma beleza. Todas as vezes que ligo a máquina o DDClient atualiza o IP no DNS Park e o meu sub domínio aponta para a máquina recém-ligada.
sábado, 20 de março de 2010
Paramêtros de Inicialização em Aplicações Web
As aplicações baseadas em servidor tem características próprias no que diz respeito aos parâmetros de inicialização. Em aplicações locais pode-se optar por passar os parâmetros "na linha de comando", criar um arquivo de configurações ou usar variáveis de ambiente. Apesar de ser possível o uso de qualquer um dos método acima ( mais parâmetros de contexto/filtros/servlets) meu método predileto em aplicações em baseadas em servidor é a criação de variáveis de ambiente JNDI.
Esse tipo de variável de ambiente pode ser usado em servidores JavaEE em geral, ou seja: em servidores de servlets/EJB ou outros que suportem JNDI.
De volta aos servidores web, a vantagem que vejo desse tipo de parâmetro em relação aos parâmetros de contexto (<context-param/>) ou de filtros e servlets (<init-param/>) é que nesses casos é necessário que o arquivo web.xml seja alterado... ou seja: se você enviar um .war/.ear para ser disponibilizado, quem for disponibilizá-lo terá que alterar o arquivo web.xml que fica dentro do .war/.ear antes de colocá-lo no ar. Por outro lado, as variável de ambiente JNDI podem ser configuradas em arquivos de contexto ou ambientes de configuração externos. Por exemplo, para configurar um arquivo de contexto do Tomcat, usamos a entrada <Environment/>, conforme segue:
De fato essa classe poderia ser usada de forma genérica e lendo parâmetros de várias fontes. Teríamos então uma classe genérica de configuração independente do ambiente de execução da aplicação.
Esse tipo de variável de ambiente pode ser usado em servidores JavaEE em geral, ou seja: em servidores de servlets/EJB ou outros que suportem JNDI.
De volta aos servidores web, a vantagem que vejo desse tipo de parâmetro em relação aos parâmetros de contexto (<context-param/>) ou de filtros e servlets (<init-param/>) é que nesses casos é necessário que o arquivo web.xml seja alterado... ou seja: se você enviar um .war/.ear para ser disponibilizado, quem for disponibilizá-lo terá que alterar o arquivo web.xml que fica dentro do .war/.ear antes de colocá-lo no ar. Por outro lado, as variável de ambiente JNDI podem ser configuradas em arquivos de contexto ou ambientes de configuração externos. Por exemplo, para configurar um arquivo de contexto do Tomcat, usamos a entrada <Environment/>, conforme segue:
...Nesse caso o valor da variável poderia ser lido pela aplicação, por exemplo, com a seguinte classe:
<Environment name="com.wim.jgnuteca.disableAllMonitors" type="java.lang.String" value="true"/>
...
...
/**
*
*/
package com.wim.jgnuteca;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* @author walter
*
*/
public class Config {
private static String getContextParamValue(String parameter) throws NamingException {
final Context ctx = new InitialContext();
return (String)ctx.lookup("java:comp/env/"+parameter);
}
private static String DISABLE_ALL_MONITORS="com.wim.jgnuteca.disableAllMonitors";
private static Boolean disableAllDTEMonitors=null;
public static boolean disableAllDTEMonitors(){
if(disableAllDTEMonitors == null){
try{
disableAllDTEMonitors=Boolean.valueOf(getContextParamValue(DISABLE_ALL_MONITORS));
} catch(Throwable t) {
disableAllDTEMonitors=false;
}
}
return disableAllDTEMonitors;
}
}
...
De fato essa classe poderia ser usada de forma genérica e lendo parâmetros de várias fontes. Teríamos então uma classe genérica de configuração independente do ambiente de execução da aplicação.
segunda-feira, 30 de junho de 2008
Inicialização do contexto Spring em testes unitários
Durante o desenvolvimento de uma classe de testes na semana passada, decidi que ela devia acessar o banco da forma mais realista possível. Como a aplicação usa Spring/Hibernate e jndi, procurei solução para a questão da inicialização do ambiente. Optei por criar uma classe "helper" para garantir a inicialização e as classes de teste executam um método de inicialização dessa classe:
/**
*
*/
package com.arcadian.logOne.interfacedte;
import javax.naming.NamingException;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
/**
* @author walter
*
*/
public class TestHelper {
private static String[] springFiles = { "beanRefFactory.xml" };
private static ClassPathXmlApplicationContext context=null;
public static void startSpringContext() throws NamingException{
if(context == null){//was not started
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUsername("morganalborg");
ds.setPassword("jpfr33");
ds.setUrl("jdbc:postgresql://localhost/interfacedte_teste");
SimpleNamingContextBuilder builder =
SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/interfacedte", ds);
context = new ClassPathXmlApplicationContext(springFiles);
}
}
}
domingo, 20 de abril de 2008
Criando Aplicações Javaserver Faces com o AndroMDA - Parte 2
Na segunda parte da apresentação acrescento uma classe e uma associação, com o objetivo de mostrar o comportamento do CRUD nessa situação. Mantêm-se 100% gerado pelo AndroMDA.
Assinar:
Postagens (Atom)