| Autor |
Mensagem |
|
|
|
Se você estiver executando isso no Event Dispatch Thread, não importará o quão lenta seja a operação dentro do seu "while". A execução de todos os métodos de pintura da JProgressBar ficará "na fila" no Event Dispatch Thread. Então, quando o seu while acabar, todas as operações de pintura serão executadas, uma imediatamente após a outra, preenchendo rapidamente o JProgressBar.
|
 |
|
|
O seu processamento está sendo executado no Event Dispatch Thread?
Caso afirmativo, você provavelmente não vai conseguir nem sequer incrementar sua barra de progresso.
Isso acontece porque os métodos de pintura são executados no mesmo Thread do seu processo. Ou seja, os métodos de pintura ficam na "fila" e somente depois que o seu processo acabar é que o thread vai estar livre para executa-los.
Se por outro lado, você executar sua operação lenta em um thread a parte, pode postar as operações de pintura no Event Dispatch Thread usando SwingUtilities.invokeLater(), e assim elas serão executadas quase que de imediato (dependendo do poder de processamento da máquina e de quão pesadas forem as operações dos outros threads concorrentes).
Creio que outra alternativa viável poderia ser o framework Foxtrot. Com ele você pode executar sua operação através de um método de uma classe estática chamada Worker que ele tem. Nesse caso, o framework se encarrega de despachar os eventos de pintura durante a sua operação (se não me engano).
|
 |
|
|
Saudações
Perdoem-me pela extensão do post, mas gostaria de expor algumas idéias à crítica pública:
Suponham o seguinte cenário:
- Uma grande aplicação industrial, com um domínio de objetos de aproximadamente 300 classes diferentes persistida em qualquer BD relacional.
- Previsão de carga de 10 a 500 usuários simultâneos.
- Muitos objetos de várias classes são associados entre si formando grandes grafos que uma vez completos contém importantes e detalhadas especificações industriais.
- É exigida uma interface gráfica Swing muito ágil para entrada de informações, que permita o "cadastramento" de dados para cerca de 80% dos objetos do domínio.
- Ainda na interface Swing tais objetos serão associados a outros e persistidos formando grafos de várias proporções (desde pequenos com cerca de 5 objetos associados, até grandes como árvores de 10 níveis de profundidade e um total de 100 objetos) .
- Não existem operações muito complexas envolvendo os objetos do domínio. A maioria delas são referentes a persistência ou atualizações de estados de objetos (exemplo: OrdemProducao: aberta, parada, encerrada, etc..), ou então duplicação dos grafos para que o usuário possa apenas alterar algumas informações, ao invés de entrar com todas elas novamente na interface (exemplo: duplicação de um objeto OrdemProducao, com todas as suas especificações industriais em que o usuário possa alterar apenas um detalhe como a Cor do produto, ou alterar totalmente todas as especificações).
- O único complicador, é que tais operações são sempre atômicas. Por exemplo: ao persistir um objeto OrdemProducao, todos os objetos associados devem ser persistidos em grandes cascatas em uma única transação de BD.
- A aplicação deve disponibilizar muitas consultas e relatórios que buscam e cruzam informações de objetos de todo o domínio.
Então ...
* Devido as necessidades de carga, optaria-se por J2EE e pelo app server JBoss que é freeware.
* EJBs de sessão ofereceriam os serviços para persistência, consultas e demais processos de negócios.
* Hibernate seria adotado como mecanismo de persistência, e seu HQL combinado com JXPath resolve as necessidades das consultas.
E finalmente os pontos mais importantes para discussão:
* Devido as necessidades de "edição" dos objetos na interface Swing seria necessário transporta-los até o lado cliente, tornando o domínio de objetos distribuído e criando vários complicadores.
* O primeiro problema seria que não poderíamos simplesmente serializar os objetos e despacha-los para o lado cliente, porque o tráfego na rede seria muito grande, já que a maioria dos objetos faz parte dos complexos grafos citados acima.
* Uma possível solução seria implementar um mecanismo no lado servidor para "recortar" dos grafos somente os objetos que realmente precisam ser transportados. Isso seria feito com a incorporação de "proxies" ao domínio de objetos, ou seja, para cada entidade do domínio teríamos uma interface que seria implementada por uma classe e também por um proxy. Por exemplo: para representação de um "produto" no sistema, teríamos uma interface chamada Produto + uma classe chamada ProdutoImpl e + um proxy chamado ProdutoProxy. Assim, se tivéssemos que enviar um objeto OrdemProducao para o lado cliente e esse objeto tivesse associado a si um objeto Produto, poderíamos trocar a instância de ProdutoImpl por uma instância de ProdutoProxy, desacoplando o objeto do restante do grafo (que segue adiante a partir do produto).
* Acredito que a primeira crítica a essa abordagem, seria a perda de tempo na implementação de tal mecanismo... Ainda porque, quando um objeto viajasse do lado cliente para o lado servidor, o processo inverso teria que ser feito para reintegrar o objeto ao domínio e persiti-lo quando for o caso.
* Outra alternativa seria criar um domínio de objetos paralelo, composto apenas por Value Objects criados a imagem e semelhança do modelo real que serviriam apenas para transportar valores de um lado para o outro. Porém essa, parece ainda mais ineficiente, já que haveria a necessidade de passar via código os valores do objeto do domínio real para o VO e vice versa.
* Seguindo a mesma linha, poderíamos pensar também em usar outros tipos de objetos para transportar os dados de maneira mais light. Como HashMaps e ArrayLists ou uma combinação deles, mas ainda haveria a necessidade de passar os valore dos objetos domínio "de" e "para" eles. Me parece inclusive, que uma técnica semelhante é usada em alguns frameworks para Web. Porém nesse caso, a auxência dos objetos inteiros pode complicar a implementação de um MVC...
Enfim, são muitos e sinuosos os caminhos possíveis...
Qual será o caminho das estrelas E qual será a estrada para a perdição
Anseio por críticas e sugestões...
|
 |
|
|
Aposto que foi a Olga. A secretária boazinha, discreta e sucetível.
"Águas paradas são as mais profundas."
|
 |
|
|
Sinto que esse tópico ainda vai mais longe.
Uma vez que tenhamos um domínio de objetos rico, com uma quantidade significativa de regras de negócio que não fossem implementados na forma de EJBs, mas ao contrário disso fizessem uso de EJBs de sessão e outros em um servidor de aplicação qualquer, como ficaria a ?plugabilidade? de diferentes interfaces com o usuário?
Se tais objetos de domínio estiverem dentro de uma aplicação cliente Swing por exemplo, não estaríamos unindo as regras de negócio à interface? Ou seria o caso de pensar em uma 4a. camada?
Por outro lado ... se não tivéssemos o domínio de objetos próximo da interface, seria difícil implementar um MVC com eles, seja para uma interface Swing, ou seja para Web ...
Entre tantas divagações, começo a pensar ser utópico um cenário onde a interface possa ser totalmente separada do domínio de objetos.
Alguém concorda?
|
 |
|
|
Bem, entendo ...
Na verdade o meu objeto de domínio para o estoque seria o próprio EJB. Mas eu também poderia criar um objeto de domínio no mesmo nível dos demais que internamente usaria o EJB para executar as suas operações.
[]'s
Gabriel C. Oliveira
|
 |
|
|
Lendo os comentários de cv e os demais posts deste thread refleti um pouco mais sobre o design de uma aplicação em que estou trabalhando e cheguei a algumas conclusões que gostaria de expor:
Até o momento, uma grande parte da lógica de negócios do já desenvolvi está codificada em Stateless Session Beans. Outra grande parte está implementada em modelos e controladores de MVC na interface gráfica Swing da aplicação. Ou seja, não há nada nos objetos reais do domínio.
As regras que estão nos modelos e controladores do MVC são basicamente para controlar a entrada de dados na aplicação e facilitar o preenchimento de formulários. Com base nas sugestões do cv estou pensando em maneiras de move-las para dentro objetos de domínio. Principalmente porque algumas dessas regras são validações complexas da associação entre certos objetos e implicam em acessos a um ou mais Session Beans para executar métodos de pesquisa.
Parece-me mais adequado deixar em Session Beans regras de negócio que tenham um impacto mais global sobre a aplicação, como por exemplo um controle de saldos de estoque:
Supondo que tivéssemos um objeto que representasse um lançamento de estoque (débito ou crédito) poderíamos ter um Session Bean com um método addLancamento que além de cuidar da persistência do objeto poderá fazer um cálculo de preço médio para um produto associado ao lançamento.
Isso porque um ?estoque? é algo de certa forma ?global? no sistema. Qualquer aplicação cliente poderá acessar o Session Bean do estoque para obter o saldo atual de um produto.
Podemos então, ver que existem outras regras que ficam ?isoladas? nas instâncias dos objetos a que dizem respeito. Por exemplo: Se para adicionarmos um objeto produto a um objeto venda precisamos verificar antes a sua disponibilidade de estoque, esse código poderá ser colocado no próprio objeto venda (que obviamente acessará o Session Bean do estoque para consultar). Essa verificação diz respeito somente a uma venda, e não interessa para a aplicação como um todo. Esse objeto venda só terá um impacto maior quando for persistido por um método de um outro Session Bean que também vai se encarregar de criar lançamentos de estoque correspondentes (de débito) e adiciona-los ao estoque usando o método addLancamento que comentei antes.
Bem ... apesar desse raciocínio todo ter uma certa lógica, não consigo imaginar que outros tipos de regras eu conseguiria encaixar nos objetos de domínio além das mais diversas validações que podem existir em um sistema.
São muitas as divagações possíveis à cerca desse assunto, e por isso termino esse post aqui.
Comentários serão muito bem vindos.
[]?s
Gabriel C. Oliveira
|
 |
|
|
Olá cv
Estive lendo o artigo que você mencionou e pude identificar a presença de um Anemic Model no projeto em que trabalho.
Temos muitos EJBs (Session Beans) que tratam várias regras de negócio da aplicação. Alguns deles são inclusive statefulls.
Os objetos de domínio como (exemplo: Cliente, Produto, Venda, Pedido ...) são planos e sem nenhuma codificação, exceto getters e setters.
A principal razão para isso é de que temos uma interface gráfica Swing que acessa esses Session Beans no servidor de aplicação (JBoss nesse caso). Isso implica na serialização de todos esses objetos de domínio, a fim de transportá-los pela rede até a máquina cliente, e portanto, quanto mais enxutos eles forem, mais rápido é o transporte.
Outro aspécto importante, é que várias regras de negócio da aplicação em questão (e algumas validações) precisam ser forçadas na própria interface, para torna-la altamente interativa. Para resolver isso, acabamos implementando várias classes que consideramos "modelos" no lado cliente. Esses modelos são geralmente implementados no estilo MVC, para exibir os dados em uma enorme variedade de formulários e controles visuais Swing extremamente complexos.
Para tornar meu relato ainda mais claro, darei alguns exemplos da interatividade que sempre buscamos:
Suponha que você tenha um formulário de entrada de dados para um objeto que representa uma "venda" no sistema. O usuário terá que associar à essa venda um objeto "cliente" já existente e também um objeto "pedido",
Agora imagine que o esse objeto "pedido" possui uma coleção de "itens", que representam todos os itens solicitados pelo "cliente".
Imagine também, que o objeto "venda" também possui uma coleção de "itens" que representa todos os itens que foram realmente vendidos ao cliente, e para os quais foi emitida uma nota fiscal por exemplo.
Para criar, tal formulário tivemos que desenvolver uma classe que chamamos de "Lookup". Essa classe se encarrega de criar uma janela modal na qual é exibida uma lista dos objetos que se deseja vincular. Por exemplo, uma lista de todos os clientes ou pedidos do sistema, que pode ser filtrada de acordo com alguns valores que podem ser informados pelo usuário nessa mesma janela. Para conseguir isso, a classe "Lookup" tem que recorrer ao servidor de aplicação para executar métodos de busca e obter as listas de objetos para exibição.
Suponha então, que ao associar um objeto "pedido" localizado através de um "Lookup" como mencionei antes, você tenha que criar automaticamente "itens" correspondentes na venda, pré supondo que todos os itens do pedido tenham sido efetivamente vendidos.
Levando em consideração que esses "itens" de venda devem ser exibidos em uma grade (JTable) tivemos que desenvolver um TableModel adequado para esse fim. Nesse caso, tal TableModel precisa acessar diretamente o objeto "venda" que estiver sendo editado para apresentar seus itens. Foi necessário ainda criar métodos auxiliares nesse TableModel para que se pudessem incluir, remover e alterar itens da lista dinamicamente, já que o usuário poderá querer incluir, remover ou alterar itens da venda antes de finalizá-la. Esses métodos, além de providenciarem a atualização do JTable também alteram a lista de itens do objeto "venda".
Outra sofisticação comum, seria por exemplo, mandar um aparâmetro para o "Lookup" dos pedidos de forma que ele só pudesse exibir "pedidos" do "cliente" previamente informado. Ou no "Lookup" de "clientes" só poderiam ser exibidos os clientes que tivessem algum pedido que ainda não tivesse sido associado a nenhuma venda!
Na inclusão de novos itens na venda por exemplo, poderia ser necessiário verificar a dispobilidade de estoque da quantidade vendida, antes de permitir a inclusão do item no formulário.
Por fim a venda poderia ser enviada para o método "insert" de um Session Bean no servidor de aplicação que faria sua persistência e atualizaria o estoque debitando as quantidades dos itens vendidos.
(Agora imagine, que esse exemplo é bem mais simples do que o que realmente temos que implementar no sistema real...)
Se anlisarmos esse requisitos em um estilo mais OO e mais abstrato, poderiamos chegar a algumas conclusões mais lógicas em relação ao domínio de objetos, que com certeza seria mais "rico".
- A lógica de validação do pedido e do cliente poderia estar dentro dos respectivos métodos set na classe da venda. Ou poderia haver um método set para associar os 2 ao mesmo tempo.
- A lógica de "copia" dos itens do pedido para a venda poderia também estar encapsulada dentro de um método set para o pedido dentro da classe venda. Ou poderia haver um método na classe venda específico para esse fim.
- A validação do item da venda em relação ao estoque poderia ser feita no método addItem (que inclui um item na venda) ou então no método que associasse o pedido.
- Para efetuar as baixas no estoque poderia também haver um método na própria classe da venda, ou poderia ser feito em Session Bean mesmo.
Entretanto, essa abordagem traria os seguintes problemas ...
- Teriamos objetos do domínio acessando Session Beans para buscar/validar informações e isso parece muito estranho.
- Teriamos bastante código nas classes do domínio, aumentando bastante o seu custo de transporte pela rede.
- A interatividade do formulário com o usuário seria perdida ou sua implementação se tornaria ainda mais complexa do que já é.
Para concluir ...
Gostaria de perguntar se você vê alguma maneira de tornar esse modelo, menos "anêmico", ou se você consegue identificar alguma falha de design em algum desses raciocínios...
E caso esse exemplo inspire mais alguém que também desenvolva uma interface Swing para uma aplicação J2EE, comentários serão bem vindos.
Saudações,
Gabriel C. Oliveira
|
 |
|
|
Olá Thiago
Veja abaixo o exemplo de uma cascata de quatro tabelas que desenvolvemos ao testar o Hibernate no inicio de um de nossos projetos:
(OBS: Todos os campos que começam com ID são chaves)
Veja abaixo os arquivos de mapeamento para essas tabelas:
Espero ter conseguido ajudar ...
Atenciosamente,
Gabriel.
|
 |
|
|
Você fez download dos capítulos anteriores?
Parece que eles não estão mais disponíveis. Somente o sexto...
Obrigado, Gabriel.
|
 |
|
|
Bem ...
O que me interessa realmente é o recurso de conexão ao BD, e execução de queries em HQL. Estou tentando há muitas e muitas horas fazer isso. Consegui configurar a conexão corretamente com Oracle e Firebird. Ao conectar todos os hbm.xml são carregados corretamente, sem erro nenhum, mas ao tentar executar qualquer instrução HQL aparece no o seguinte erro no log:
A versão que estou usando é a full. Digo isso porque tem uma outra versão que requer que você adicione vários JARs do Hibernate ao classpath. O problema ocorre com ambas.
Já me certifiquei também de que o erro não diz respeito a parâmetros de conexão com o BD. Porque quando se informa algo errado (como a senha por exemplo) a exceção é bem diferente.
Tenho certeza também, de que está tudo correto com as classes que devem ser materializadas (toString, hashCode, equals, etc.).
Qualquer sguestão será muito bem vinda.
Obrigado, Gabriel.
|
 |
|
|
Olá
Por acaso alguém já utilizou com sucesso o plugin Hibernator para o Eclipse?
Não sei se esse é o forum adequado para postar essa questão e por isso postarei também no Java Avançado.
Obrigado, Gabriel.
|
 |
|
|
Olá
Por acaso alguém já utilizou com sucesso o plugin Hibernator para o Eclipse?
Não sei se esse é o forum adequado para postar essa questão e por isso postarei também no de assuntos gerais.
Obrigado, Gabriel.
|
 |
|
|
O exemplo que seque foi copiado de do site da Sun.
Ele mostra como criar um InternalFrame que pode ser exibido de forma modal, retendo o fluxo do programa até que seja fechado e não permitindo que o usuário acesse qualquer coisa que esteja atrás dele.
Fica claro que para impedir o acesso aos demais formulários substitui-se o Glass do RootPane por um novo Glass que tem listeners que ignoram eventos do mouse.
O estranho, é que se fizermos esse InternalFrame resizable, ele é fechado ao redimensionarmos a janela com o mouse.
Além disso, parece ser impossível dimensioná-lo pelo método setSize(). O tamanho não se altera, seja qual for o tamanho passado nos parâmetros.
Alguém consegue entender porque isso acontece?
Vejam o código:
|
 |
|
|
Realmente ...
A sua idéia funciona. Agora consegui desenvolver um algoritmo para resolver o meu problema.
Muito obrigado.
Gabriel.
|
 |
|
|
|
|