quarta-feira, 17 de janeiro de 2007

Exemplos de código

Para aqueles que estão aprendendo uma nova linguagem, ou como utilizar uma nova API, exemplos de código ajudam bastante. Uma excelente fonte de códigos são os softwares abertos, desenvolvidos nas mais diferentes linguagens.

Mas quando você está interessado em algo específico, como por exemplo, como utilizar a API do JMS, fica difícil procurar exemplos nos códigos abertos, a não ser que se utilize um mecanismo de busca, como o Koders, e o Google Code Search. Outra opção são os livros, e os tutoriais disponíveis na rede. Mas um serviço interessante oferece diversos códigos de exemplo, para linguagem Java, C#, ASP.Net, JavasScript, PHP, SQL, etc, etc, etc ... este serviço está disponível no endereço www.java2s.com.

Parece ser bem organizado, mas não consegui descobrir que mantém o site, tampouco quão atualizado ele é ... de qualquer forma, pode ser uma fonte interessante, especialmente para quem está iniciando o aprendizado.

powered by performancing firefox

quinta-feira, 11 de janeiro de 2007

Monitoramento de memória do JBoss

Recentemente ao testar uma funcionalidade que havia implementado no JBoss, tive um problema de falta de memória. Problema normal, fácil de resolver ... mas isto me chamou a atenção para que eu monitorasse o consumo de memória do JBoss.



Há algum tempo, ao começar a usar o ActiveMQ, tive a necessidade de monitorar os objetos dessa aplicação, e graças a isto conheci o JConsole. Minha primeira idéia foi usar o JConsole para monitorar o JBoss, e realmente funcionou. Para tanto segui os conselhos descritos por Steve Brownlee em seu blog (fusioncube). Segue o link para o post em questão:



Fusioncube » Blog Archive » JVM Memory Monitoring







powered by performancing firefox

quarta-feira, 2 de agosto de 2006

[JSF] - DataTables, CommandLink's e CommandButton's

Aqueles que já tiveram o prazer de tentar fazer uma componente commandLink ou commandButtons funcionar dentro de uma componente ''dataTable'' utilizando o escopo request para o managed bean que armazena os dados exibidos pelo dataTable, sabem que não dá. O jeito é mudar o escopo do managed bean para session.

O problema com esta "solução" é que os dados perduram. Exemplificando: imagine que você está implementando um caso de uso que mostra uma lista de entidades que obedecem às restrições impostas por filtros de busca cujos valores são determinados pelo usuário. O comportamento esperado é que, ao acessar a página, não se mostre nenhum valor, e após o usuário ordenar a busca, os elementos sejam obtidos e exibidos. Simples assim. Com a "solução" acima, isto ocorre na primeira vez que o usuário acessa esta página. Porém, dentro da mesma sessão, nas próximas vezes que o usuário acessar a página, ele irá automaticamente visualizar os dados da última busca que ele realizou.

Um pouco de pesquisa, na tentativa de manter o escopo como request, me levou à seguinte descrição de bug (que no final mostrou não ser um bug) - javaserverfaces:issue 69.

Conforme entendi, o problema é que no momento do processamento da fase Apply request values, o managed bean com os dados utilizados pela dataTable ainda não foi inicializado (ele somente será na fase Render response). Desta forma, a decodificação desta componente não funcionará como esperado, e tampouco a decodificação das componentes filhas (incluindo os commandLink's e commandButton's). Por isso, nenhum método de ação associado a estes elementos será executado.

Chegamos então à seguinte conclusão: nossa aplicação só funciona se usarmos escopo session. Mas isto é necessário somente para os dados a serem exibidos pelo dataTable. Com isto, sugiro a seguinte solução:

  1. Crie um managed bean (requestBean) em escopo request para gerenciar os dados não associados ao dataTable, e para gerenciar as ações da sua página
  2. Crie um managed bean (sessionBean) em escopo session somente para armazenar os dados exibidos pelo dataTable
  3. Você deve atribuir um valor vazio para os dados do sessionBean no construtor do requestBean, e com o resultado da busca, sempre que o método que realiza a busca em requestBean for executado

Surge aí outro problema. Como alterar os dados de sessionBean a partir do requestBean? Basta usar o seguinte código dentro do requestBean:


FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().
createValueBinding("#{SessionBean.data}").setValue( context, newData );


Você pode reparar que o EL #{SessionBean.data} é igual ao EL que você usa no seu JSP associado ao atributo value da sua componente dataTable (h:dataTable).

É uma solução trabalhosa. Muito melhor seria se o JSF funcionasse de forma um pouco mais intuitiva. Mas nada é perfeito ...

segunda-feira, 17 de julho de 2006

JBoss WrappedConnection

No JBoss, quando obtemos uma conexão de banco de dados de um Datasource, obtemos um objeto da classe org.jboss.resource.adapter.jdbc.WrappedConnection, que é uma classe que implementa a interface java.sql.Connection.

No entanto, ao utilizar algumas operações específicas da implementação do JDBC da Oracle, me deparei com a seguinte exceção:

java.lang.ClassCastException: org.jboss.resource.adapter.jdbc.WrappedConnection

Pelo que pude entender isto ocorre porque estas operações específicas esperam um objeto conexão do tipo oracle.jdbc.driver.OracleConnection. No entanto, a conexão devolvida pelo Datasource é deste tipo, uma vez que estou usando um banco de dados Oracle (pois é leitor, não iria tentar usar o JDBC da Oracle com outro banco). O que o JBoss faz é encapsular este objeto dentro do objeto WrappedConnection. Desta forma, é possível obter o objeto OracleConnection e utilizar as funcionalidades desejadas do JDBC da Oracle. Para tanto, escrevi o seguinte código:

public class ConnectionUtilities {
   
    /**
     *
     */
    private static final String WRAPPED_CONNECTION_NAME =
        "org.jboss.resource.adapter.jdbc.WrappedConnection";

    /**
     *
     */
    private static final String GET_UNDERLYING_CONNECTION_METHOD =
        "getUnderlyingConnection";

    /**
     * Se a aplicação estiver rodando dentro do JBoss retorna a conexão encapsulada dentro
     * da conexão obtida pelo JBoss. Caso contrário, retorna a própria conexão dada
     *
     * @param conn A conexão com o banco de dados
     * 
     * @return
     */
    public static Connection getUnderlyingConnection(Connection conn) {
        // Variaveis auxiliares
        Connection underlyingConn = conn;
        ClassLoader cl = null;
        Class wrappedConnectionClass = null;
        Method getUnderlyingConnectionMethod = null;
       
        try {
 
            cl = Thread.currentThread().getContextClassLoader();
            wrappedConnectionClass =  cl.loadClass( WRAPPED_CONNECTION_NAME );
            getUnderlyingConnectionMethod = wrappedConnectionClass.getMethod(
                    GET_UNDERLYING_CONNECTION_METHOD, (Class[]) null );
           
            if( wrappedConnectionClass.isAssignableFrom( conn.getClass() ) ) {
                underlyingConn =
                    (Connection) getUnderlyingConnectionMethod.invoke( conn,
                            (Object[]) null );
            }
        } catch (Exception e) {           
        }
       
        return underlyingConn;
    }

}

Note-se que se este código for utilizado fora do ambiente JBoss ele retorna a própria conexão dada como parâmetro. Desta forma consigo utilizar o mesmo código no ambiente de testes que configurei no Eclipse, e no ambiente de produção com o JBoss.

quinta-feira, 27 de abril de 2006

Código de alta qualidade

Na minha vida como desenvolvedor já tive a oportunidade de trabalhar com vários outros desenvolvedores, utilizando diferentes linguagens, diferentes ferramentas, diferentes arquiteturas ... no entanto, uma coisa que é comum em todas estas experiências, diz respeito com integração de códigos.

Modelar um software, e dividir a implementação entre vários desenvolvedores é bastante comum. Na teoria, agiliza o desenvolvimento. Cada um implementa sua parte, realiza seus testes, acha tudo perfeito, e quando vai integrar, tudo começa a dar errado. E daí quando você tem que mexer no código que outra pessoa fez, daí é que tudo vai pro espaço.

Para minimizar estes problemas, é bom adotar algumas práticas de programação e desenvolvimento. Definir bons testes de unidade antes de iniciar a implementação, utilizar códigos de programação, etc ... Tendo em vista este problema, um bom artigo é o post "Producing and maintaining high-quality code", do blog Ozone. O autor lista 10 dicas sobre como escrever bons códigos, e em decorrência, gerar bons softwares.

Uma das dicas interessantes é a de número 3 - Talk to your cardboard friend, que eu conhecia como "Técnica do ursinho". Esta técnica aprendi através de um professor, que relatou que um outro professor que lecionava na universidade em que ele fez doutorado tinha um ursinho de pelúcia que ele levava nas aulas de laboratório. Toda vez que um aluno tinha uma dúvida, ele tinha que explicar o problema pro ursinho. Com isso, boa parte dos alunos conseguiam enxergar o problema, só explicando o mesmo pro ursinho.

Voltando ao artigo, é bastante interessante, e pode ser bastante útil. O autor inclusive sugere ferramentas que podem facilitar a vida dos desenvolvedores. E você, tem mais alguma dica para compartilhar? Dê seus comentários.