<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8121425584076563711</id><updated>2011-12-31T13:22:05.723-08:00</updated><category term='Hibernate'/><category term='POA'/><category term='Frameworks'/><category term='Design'/><category term='Game Design'/><category term='Java'/><category term='jMonkeyEngine'/><title type='text'>Tecnologias Atuais</title><subtitle type='html'>Discutindo tecnologias atuais na área de desenvolvimento de software.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-2438837546756844061</id><published>2008-11-14T10:31:00.000-08:00</published><updated>2008-11-14T10:34:16.371-08:00</updated><title type='text'>Novo Blog</title><content type='html'>Devido a questões de usabilidade, estou migrando meu blog e todas as postagens para o wordpress. Não deixe de visitar o novo espaço: &lt;a href="http://germanofronza.wordpress.com/"&gt;http://germanofronza.wordpress.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Obrigado.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-2438837546756844061?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/2438837546756844061/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=2438837546756844061' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/2438837546756844061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/2438837546756844061'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/11/novo-blog.html' title='Novo Blog'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-133890195788092491</id><published>2008-11-13T16:41:00.000-08:00</published><updated>2008-11-14T07:31:47.394-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Design'/><title type='text'>Um domínio mais limpo...</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;A abordagem &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Domain&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Driven&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Design&lt;/span&gt; (ou apenas &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;DDD&lt;/span&gt;), dentre várias boas características, tem &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;contribuido&lt;/span&gt; para resgatar os originais valores das linguagens orientadas a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;objetos&lt;/span&gt;. Porém, isso só é possível graças aos "novos" &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;frameworks&lt;/span&gt;&lt;/span&gt; baseados em classes &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;POJOs&lt;/span&gt;, onde não somos obrigados a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;extender&lt;/span&gt; classes que não conhecemos. Agora as classes são baseadas em &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;metadados&lt;/span&gt; através de anotações no próprio código Java, provendo maior flexibilidade devido ao &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;desacoplamento&lt;/span&gt; com classes de &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;frameworks&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;Dentre todas as classes que compõem um domínio que faz uso de um mecanismo de persistência como a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;JPA&lt;/span&gt;, destacam-se as classes de entidades (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;Entity&lt;/span&gt;). Essas classes, que devem ser um espelho (orientado a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;objetos&lt;/span&gt;) da estrutura das entidades do banco de dados relacional, podem conter métodos de negócio que alteram ou &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;acessam&lt;/span&gt; informações da base de dados. Mas para que esse acesso à base de dados dentro das classes de entidades possa ser feito, é necessário que todos os seus atributos estejam mapeados, para que quando instâncias dessas classes forem obtidas através do contexto de persistência (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;EntityManager&lt;/span&gt; ou mesmo uma &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Session&lt;/span&gt; do &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;Hibernate&lt;/span&gt; Core), seus atributos também estejam no estado &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;gerenciado&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;managed&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;state&lt;/span&gt;). Se as classes de entidades forem implementadas dessa forma, não é necessário poluirmos elas com acesso à repositórios (implementados como &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;DAOs&lt;/span&gt;, por exemplo). A Listagem 1, exemplifica a implementação de uma classe de entidade com todos os atributos mapeados.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;@&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;Entity&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;public&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;class&lt;/span&gt; Curso {&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-family:courier new;"&gt;@&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;Id&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-family:courier new;"&gt;@&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;GeneratedValue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;private&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;Long&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;id&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;   &lt;span style="font-family:courier new;"&gt;@&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;ManyToMany&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;cascade&lt;/span&gt;=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;CascadeType&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;ALL&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span style="font-family:courier new;"&gt;@&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;JoinTable&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;name&lt;/span&gt;="Matricula",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;             joinColumns=@JoinColumn(name = "&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;idCurso&lt;/span&gt;"),  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;             inverseJoinColumns=@JoinColumn(name = "&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;idAluno&lt;/span&gt;"))  &lt;/span&gt;&lt;br /&gt;   &lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;private&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;List&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;pessoa&gt; alunos;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;public&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;Long&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;getId&lt;/span&gt;() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;return&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;this&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;id&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;      /** retorna uma lista &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;read&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;only&lt;/span&gt; */&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;public&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;List&lt;/span&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;pessoa&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;getAlunos&lt;/span&gt;() {&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;return&lt;/span&gt; Collections.unmodifiableList(this.alunos);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;public&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;boolean&lt;/span&gt; existeOuJaExistouAluno(Pessoa p) {&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;for(Pessoa aluno : &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;this&lt;/span&gt;.alunos&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;) {&lt;br /&gt; &lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;if&lt;/span&gt; (p.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;equals&lt;/span&gt;(p) { // por seguir o &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;pattern&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;Entity&lt;/span&gt;, compara pelo &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;ID&lt;/span&gt;.&lt;br /&gt;   &lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;return&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;return&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_66"&gt;public&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;void&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_68"&gt;matriculaPessoa&lt;/span&gt;(Pessoa p) {&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_69"&gt;this&lt;/span&gt;.alunos&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_70"&gt;add&lt;/span&gt;(p);&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_71"&gt;public&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_72"&gt;void&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_73"&gt;cancelaMatriculaAluno&lt;/span&gt;(Pessoa p) {&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_74"&gt;this&lt;/span&gt;.alunos&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.remove(p);&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;Nesta classe, é &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_75"&gt;possivel&lt;/span&gt; notar que não a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_76"&gt;poluimos&lt;/span&gt; com &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_77"&gt;getters&lt;/span&gt; e &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_78"&gt;setters&lt;/span&gt; desnecessários. Para alterar o estado desse &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_79"&gt;objeto&lt;/span&gt;, utilizamos os métodos de negócio nela contidos. A Listagem 2 mostra a implementação de um método que possui uma lista de pessoas e precisa verificar quais estão matriculadas em determinados cursos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_80"&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;Setor s = repositorioSetor.getById(2L);&lt;br /&gt;List&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;pessoa&gt; alunosDosCursosDoSetor = new ArrayList&lt;pessoa&gt;();&lt;br /&gt;for(Pessoa p : pessoas) {&lt;br /&gt;for (Curso c : s.getCursos()) {&lt;br /&gt;   if (c.&lt;/pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;existeOuJaExistouAluno&lt;/span&gt;(p) &lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;alunosDosCursosDoSetor.add(p);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;Esta implementação é muito mais OO do que a implementação mostrada na Listagem 3.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;Setor s = repositorioSetor.getById(2L);&lt;br /&gt;List&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;pessoa&gt; alunosDosCursosDoSetor = new ArrayList&lt;pessoa&gt;();&lt;br /&gt;for(Pessoa p : pessoas) {&lt;br /&gt;for (Curso c : s.getCursos()) {&lt;br /&gt;   if (&lt;/pessoa&gt;&lt;/pessoa&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;existeOuJaExistouAluno&lt;/span&gt;(c, p) &lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;             &lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;alunosDosCursosDoSetor.add(p);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;O método &lt;span style="font-family:courier new;"&gt;existeOuJaExistiuAluno &lt;/span&gt;(que tem mais aparência de função do que de método) teria que acessar o repositório de curso ou de pessoa e fazer um select para verificar se a pessoa está ou já foi matriculada no curso em questão. Isso é procedural demais!!&lt;br /&gt;&lt;br /&gt;A idéia de ter um modelo mais orientado a objetos é que podemos ter um código muito mais próximo do negócio a ser tratado, facilitando o entendimento do mesmo tanto pelos técnicos (desenvolvedores) quanto pelos especialistas do negócio.&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-133890195788092491?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/133890195788092491/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=133890195788092491' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/133890195788092491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/133890195788092491'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/11/um-domnio-mais-limpo.html' title='Um domínio mais limpo...'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-4906514257175410559</id><published>2008-07-31T10:44:00.000-07:00</published><updated>2008-07-31T11:05:36.305-07:00</updated><title type='text'>Arquiteturas...</title><content type='html'>Ao iniciar o desenvolvimento de qualquer software, uma das primeiras atividades desempenhadas pelos desenvolvedores (especialistas em computação) é a definição da arquitetura do mesmo. Essa tarefa custuma ocorrer logo após uma definição, ou melhor, do levantamento dos requisitos do negócio a ser tratado, sendo assim, o que for definido nesta etapa deverá ser considerado durante todo o tempo de vida do projeto. Acontece que essa não é uma atividade trivial. Com tantos padrões, técnicas, modas, conceitos mal entendidos, frameworks entre outros parâmetros, muitas vezes ficamos em dúvida do que de fato utilizar. Uma coisa é clara, desejamos que o código-fonte dos nossos softwares estejam cada vez mais próximo do domínio do problema, fazendo com que a comunicação entre desenvolvedores e especialistas do negócio utilize uma linguagem comum. Como uma tentativa de atingir esse nível de qualidade do código e ter uma maior aproximação dos envolvidos no projeto, o paradigma de Domain-Driven-Design (DDD) apresenta-se como uma abordagem extremamente útil e prática a ser considerada. Através do DDD, várias diretrizes podem ser seguidas para a elaboração de uma arquitetura transparente e mais próxima do domínio como desejamos. Essas diretrizes não são relacionadas apenas com o código-fonte em si, como é o caso do uso de determinados padrões de projeto, tal como o tão falado e confundido Repository. O DDD contempla também a elaboração de uma linguagem comum (chamada de Ubiquitous Language) a ser usada entre os envolvidos no projeto. Isso significa que os desenvolvedores devem nomear seus artefatos (classes, métodos, atributos, etc) de acordo com o negócio tratado. Isso também não quer dizer que os desenvolvedores não possam usar palavras do seu próprio jargão, por exemplo, o conceito de repositórios (pattern Repository) é comumente usado nessa comunicação, mas seu conceito deve estar bem claro para ambos os lados.&lt;br /&gt;Outra discussão que segue é em relação às camadas da arquitetura. A tradicional dúvida, "Onde devo colocar as regras de negócio?" A tradicional separação em classes do tipo Business Object, Value Object, Data Transfer Object, Classes de controle, entre outras, nos perguntamos onde se encaixa a orientação a objetos, essa forma tradicional é muito estruturada. Esses dias conversando com um amigo no Google Talk ele me perguntou: "me diz onde eu deveria criar meu objeto 'Notícias' que vai puxar os dados no BD, usar uma DAO? e as validações, regras de negócio?". Para responder a pergunta, abaixo consta um pequeno diagrama de classes envolvidas na solução.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_hHOO43VWwz4/SJH8yihug2I/AAAAAAAAAZ0/8pcIi2GP1Cc/s1600-h/news.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_hHOO43VWwz4/SJH8yihug2I/AAAAAAAAAZ0/8pcIi2GP1Cc/s320/news.png" alt="" id="BLOGGER_PHOTO_ID_5229238587545781090" border="0" /&gt;&lt;/a&gt;A classe News é a classe de domínio. Nessa solução, o padrão Repository está sendo implementado como uma DAO, porém perceba que a classe Client (classe que exemplifica o uso dessa estrutura criada, poderia ser uma action do Struts ou lógica do VRaptor por exemplo) tem associação apenas com a interface NewsRepository, isso é importante para não termos um forte acoplamento com a implementação. A classe concreta NewsDao então implementa a interface NewsRepository para conter de fato a implementação da interação dessa entidade com o banco de dados. Perceba também que a classe News não possui nenhum método de negócio digamos, mas caso existisse algum método que alterasse o estado dos atributos este deveria ser criado nessa classe, e não em uma NewsBO. Quando temos uma classe que contém os métodos de negócio e os atributos dizemos que ela possui um alto nível de coesão, que é um ponto forte dessa implementação. Quanto a questão de validação do estado dos atributos, fazendo uso de um framework como o HibernateValidator (que inclusive serviu de inspiração para a criação da JSR-303 - Bean Validator) a tarefa torna-se simples e declarativa.&lt;br /&gt;&lt;br /&gt;Para mais informações a respeito de DDD, peço que chequem os artigos contidos na InfoQ. Nesse espaço pode ser encontrado muito conteúdo bom sobre Java, arquitetutura, entre outros.&lt;br /&gt;&lt;br /&gt;[]s&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-4906514257175410559?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/4906514257175410559/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=4906514257175410559' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4906514257175410559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4906514257175410559'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/07/arquiteturas.html' title='Arquiteturas...'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_hHOO43VWwz4/SJH8yihug2I/AAAAAAAAAZ0/8pcIi2GP1Cc/s72-c/news.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-4455419628835630120</id><published>2008-07-12T07:07:00.000-07:00</published><updated>2008-07-12T07:35:24.953-07:00</updated><title type='text'>TankCoders 2, focando em agentes...</title><content type='html'>Olá pessoas,&lt;br /&gt;&lt;br /&gt;Como já apresentado em tópicos anteriores, o meu projeto de TCC foi desenvolver um simulador de batalhas de tanques de guerra em 3D onde pudessem ser desenvolvidos e testados agentes AgentSpeak(L) do interpretador Jason. Porém, além de prover um ambiente onde os agentes pudessem atuar, propus também que o simulador pudesse ser usado por usuários remotos. Essa feature, por mais interessante que possa ser, nada tem a contribuir para o estudo de Programação Orientada a Agentes (POA). Sendo assim, essa feature será retirada do projeto TankCoders 2.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TankCoders 2&lt;br /&gt;&lt;/span&gt;A primeira questão a ser tratada nesse novo projeto é o paradigma de programação a ser usado. Exceço de orientação a objetos em aplicações gráficas de tempo-real já pude perceber que&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;não é o melhor caminho. Sendo assim, de início estarei fazendo uma pesquisa de como desenvolver aplicações "orientadas a performance", focando em uma elevada taxa de FPS.&lt;br /&gt;&lt;br /&gt;Para essa segunda versão do TankCoders, outra mudança é em relação à versão da engine JME que estarei utilizando. Será usada a versão 1.0 juntamente com a versão 2.1 da JME Physics, que segundo os respectivos release-notes, muitas melhorias foram proporcionadas.&lt;br /&gt;&lt;br /&gt;Nesse versão também serão trocados os modelos de tanques utilizados. Pretendo tentar entrar em contato com pessoas especializadas em ferramentas de modelagens 3D, vendo a possibilidade de estar criando dois modelos com uma quantidade mínima de faces. Essa questão também irá melhorar a performance do cenário pelo menos 60% em relação a versão atual.&lt;br /&gt;&lt;br /&gt;Para um melhor aproveitamento dos estudantes de POA, nessa nova versão estarei provendo um cenário um pouco mais controlado, ou seja, sem tantas "realidades do mundo real". Na atual versão tudo é controlado pela física e percebi que se torna extremamente complexo para uma pessoa estar desenvolvendo agentes AgentSpeak(L) realmente eficientes. O simples fato de fazer o tanque virar 90º para a direita, por exemplo, já se torna complexo, pois pode que o tanque esteja subindo uma montanha e atrapalhe a realização da ação. Tudo isso ainda precisa ser especificado de forma mais detalhada.&lt;br /&gt;&lt;br /&gt;Conforme vou tendo mais novidades em relação ao desenvolvimento da versão 2 estarei publicando neste espaço.&lt;br /&gt;&lt;br /&gt;Obrigado pela atenção.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-4455419628835630120?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/4455419628835630120/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=4455419628835630120' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4455419628835630120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4455419628835630120'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/07/tankcoders-2-focando-em-agentes.html' title='TankCoders 2, focando em agentes...'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-4648051541489830487</id><published>2008-07-09T18:41:00.000-07:00</published><updated>2008-07-10T05:04:06.502-07:00</updated><title type='text'>"Fim" do trabalho, apresentação do TCC</title><content type='html'>Olá pessoal,&lt;br /&gt;&lt;br /&gt;Hoje não estarei comentando sobre alguma tecnologia estudada ou alguma reflexão sobre o mundo de desenvolvimento JavaEE como custumo fazer aqui no blog. Estarei comentando então como foi a conclusão do meu TCC representada pela apresentação do mesmo junto a &lt;span style="font-weight: bold;"&gt;banca&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Banca foi formada pelos professores:&lt;br /&gt;- Avaliador da proposta: Dr. &lt;a href="http://www.inf.furb.br/%7Emattos/"&gt;Mauro Marcelo Mattos&lt;/a&gt;&lt;br /&gt;- Segundo avaliador: Dr. &lt;a href="http://www.inf.furb.br/%7Erodacki/Site/Home.html"&gt;Paulo Cesar Rodacki Gomes&lt;/a&gt;&lt;br /&gt;- Orientador: M.Sc. &lt;a href="http://www.inf.furb.br/%7Edalton/"&gt;Dalton Solano dos Reis&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Apresentação teórica&lt;/span&gt;&lt;br /&gt;Conforme as regras para apresentação de TCCs no Departamento de Sistemas e Computação da Furb, o tempo máximo para essa apresentação é de 30 minutos. Em muitos trabalhos, essa questão de tempo não custuma ser um problema, porém não foi o que ocorreu comigo. Antes de apresentar o trabalho para a banca (dia 08/07/2008 às 21h), realizei duas prévias, sendo que a primeira delas foi supervisionada pelo meu orientador Dalton e por amigos de turma que também apresentam seus trabalhos nesse semestre. Na primeira prévia minha apresentação teórica demorou 48 minutos, nesse momento eu começei a ficar realmente preocupado. Precisava reduzir 18 minutos, sendo que não fazia ideia de como fazer isso. Seguindo a orientação do prof. Dalton e dos amigos, em especial o Israel D. Medeiros e o Eduardo Coelho, foi possível criar uma forma de apresentar o trabalho para a banca em um tempo de 31 minutos. Nessa apresentação, além de fazer uma introdução do tema escolhido e esplanar de forma clara os objetivos do trabalho, foi apresentada de forma bastante sucinta os assuntos estudados na fundamentação teórica, que foram a àrea de Ambientes Virtuais Distribuídos, Sistemas Multiagentes e por fim à parte gráfica com a engine JMonkey Engine. O grande desafio da apresentação era de fato na parte da &lt;span style="font-weight: bold;"&gt;especificação&lt;/span&gt; da ferramenta. O projeto desenvolvido apresentou um número de 135 arquivos .java sendo classes, interfaces e anotações. Nem todas as classes foram incluídas nos diagramas da UML utilizados (classes e estados), mas mesmo assim a maior parte delas foi ilustrada. Resolvi então apresentá-las de acordo com a separação dos módulos que desenvolvi no software. Dessa forma consegui explicar as classes em nível de pacotes e suas respectivas funcionalidades, reduzindo o tempo gasto na apresentação de forma geral. No final foquei nos resultados obtidos, onde fiz uma discução das abordagens seguidas no trabalho. Nesse momento falei sobre o uso de Orientação a Objetos e integração de diversas tecnologias diretentes em aplicações gráficas, mostrando como isso refletiu na performance do simulador. Por último apresentei as conclusões onde enfatizei que o foco não era desenvolver um jogo (um produto) mas sim prover um ambiente mais atrativo para o estudo do paradigma de Programação Orientada a Agentes (POA).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Apresentação Prática&lt;br /&gt;&lt;/span&gt;Começei a apresentação prática com a execução do simulador (aplicativos servidor e cliente). Utilizei dois computadores, um para cada cliente representando jogadores do tipo Avatar, que controlam os tanques de guerra atraves de teclado e mouse. Nesse momento consegui mostrar algumas caracteristicas do ambiente gráfico desenvolvido&lt;span style="font-weight: bold;"&gt;, &lt;/span&gt;porém obtive um crash na JVM ao carregar a batalha pela segunda vez. Esse erro ocorreu durante todo o desenvolvimento e eu já estava preparado para vê-lo também na apresentação, tanto que gravei um video para mostrar caso o erro insistisse em ocorrer. O crash ocorre devido ao uso dos modelos de tanques de guerra escolhidos. São modelos extremamente pesados, sendo que não foram criados para serem usados em ambientes gráficos de tempo-real. A solução pra esse problema é desenvolver modelos espefícos para o cenário em questão, porém isso requer muita habilidade em ferramentas de modelagem 3D, que não era o foco inicial do trabalho.&lt;br /&gt;Apresentei também a execução de uma batalha onde dois tanques eram controlados por agentes da ferramenta Jason, os tanques possuiam um código simples, porém foi possível mostrar o quão abstrato um código AgentSpeak(L) pode ser em relação às abordagens tradicionais.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Considerações da Banca&lt;/span&gt;&lt;br /&gt;Ao final da apresentação, os membros da banca inicialmente fizeram bastante elogios, tanto da parte escrita (monografia) quando no desenvolvimento e o tema escolhido. Também apresentaram várias contribuições e alguns ajustes a serem feitos, onde todos foram aceitos pelo meu orientador e por mim.&lt;br /&gt;&lt;br /&gt;Tenho a certeza de que esse trabalho contribuiu muito para o meu desenvolvimento (tanto técnico quanto pessoal). É claro que dá um alívio concluí-lo, mas com certeza vou sentir falta dessa rotina de prazos, desenvolvimento e etc. Também sei que esse trabalho não está de fato encerrado, tenho muita vontade de continuar desenvolvendo ele, em conjunto com o professor Dalton e outros que possam vir a se interessar. Sei isso, pois essa área pesquisada despertou em mim muito interesse já que tive que me esforçar muito para compreendê-la.&lt;br /&gt;&lt;br /&gt;Para mais informações do que foi desenvolvido, o site do projeto é: http://germanofronza.googlepages.com/tankcodersproject&lt;br /&gt;&lt;br /&gt;Slides da apresentação: http://www.inf.furb.br/~gfronza/tankcoders/Apresentacao.pdf&lt;br /&gt;&lt;br /&gt;Muito obrigado pela atenção.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-4648051541489830487?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/4648051541489830487/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=4648051541489830487' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4648051541489830487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4648051541489830487'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/07/fim-do-trabalho-apresentao-do-tcc.html' title='&quot;Fim&quot; do trabalho, apresentação do TCC'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-3778592466893752802</id><published>2008-07-03T06:07:00.000-07:00</published><updated>2008-07-03T06:37:01.952-07:00</updated><title type='text'>Next-Generation frameworks</title><content type='html'>Hoje em dia tanto se houve falar dos "Next-Generation frameworks" (também chamados de "lightweight frameworks") e como eles se diferenciam dos "antigos" (taxados de "heavyweight"). Esses frameworks antigos, caracterizados por utilizarem diversos arquivos XML de configuração, possuem uma estrutura extremamente robusta que causa um nível de baixa produtividade às equipes de desenvolvimento. Por esse motivo, os novos frameworks surgem com o intuito de extinguir os arquivos de configuração (properties ou XMLs) e trazer essas configurações, quando realmente necessárias, para dentro do código Java. Com o surgimento das Anotações no Java 5, conceitos como Inversão de Controle, Injeção de Dependências e Convensões sobre Configurações estão sendo amplamente usados, e isso de fato diminui o grau de dependências e aumenta o nível de entendimento do código. Porém, na minha visão, é nesse momento que alguns frameworks estão cometendo um novo erro: certas configurações devem mesmo estar no código Java? Qual o real motivo disso? Modismo? Empolgação? Ódio de XML ou Properties?&lt;br /&gt;Surgiu a motivação para escrever este post logo após fazer um estudo (ainda não muito aprofundado) do framework de Injeção de Dependências do Google chamado Guice (se lê: Juice). Trata-se de um framework muito interessante, simplifica diversas tarefas em relação ao seu "concorrente" Spring IoC. O problema dele é justamente na configuração que faz o &lt;span style="font-weight: bold;"&gt;bind &lt;/span&gt;das interfaces e implementações. O Guice tem o conceito de Modules, onde para se criar um módulo deve-se HERDAR uma classe chamada AbstractModule e sobrescrever o método configure. Esses módulos são classes Java que fazem a configuração de forma programática dos binds. Na minha visão, dois problemas surgem nesse conceito de módulo do Guice. O primeiro deles é o fato de ter que herdar de uma classe que não é sua, nem sabemos como ela é implementada. Herança é algo que deve ser evitada ao máximo! O segundo é em relação à configuração que é feita em código Java e de forma bem extensa. Se esses módulos fossem configurados em XML por exemplo, muita abstração seria proporcionada e o código Java seria limpo.&lt;br /&gt;&lt;br /&gt;Guice video introduction: http://crazybob.org/2007/06/introduction-to-guice-video-redux.html&lt;br /&gt;&lt;br /&gt;Só uma pequena discussão. ;D&lt;br /&gt;Até.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-3778592466893752802?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/3778592466893752802/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=3778592466893752802' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/3778592466893752802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/3778592466893752802'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/07/next-generation-frameworks.html' title='Next-Generation frameworks'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-118416105547367714</id><published>2008-06-18T11:07:00.000-07:00</published><updated>2008-06-18T12:00:58.136-07:00</updated><title type='text'>Java EE de hoje...</title><content type='html'>&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C02%5Cclip_filelist.xml"&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;As ferramentas tradicionais utilizadas em grande escala nas &lt;i style=""&gt;software houses&lt;/i&gt; são normalmente tecnologias mais antigas, pois o custo (tanto financeiro quanto recursos como tempo e equipe) para migrar sistemas legados para tecnologias atuais é muito alto. Tratando-se do mundo WEB, principalmente fazendo uso da tecnologia Java, a utilização de algum &lt;i style=""&gt;framework&lt;/i&gt; MVC apresenta-se como uma solução ideal para deixar as responsabilidades do software (camadas) mais isoladas, sem que uma invada o espaço da outra. Porém, como no caso de &lt;i style=""&gt;frameworks&lt;/i&gt; como Struts 1 e Spring, a quantidade de artefatos que precisam ser produzidos é tão alta que a produtividade começa a diminuir substancialmente. Lembrando que, no Struts 1, para cada nova &lt;i style=""&gt;action&lt;/i&gt; ser criada, quatro passos normalmente precisam ser executados, que são: criar a classe que representa a &lt;i style=""&gt;action&lt;/i&gt;, configurar o mapeamento no &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;struts.config.xml&lt;/span&gt;, criar a classe de formulário e por último criar a view (jsp) para exibir o ”resultado” ao usuário. Todo esse processo é feito somente para satisfazer o &lt;i style=""&gt;framework&lt;/i&gt;, nada de &lt;b style=""&gt;negócio&lt;/b&gt; foi realmente desenvolvido até o tal momento. Facilmente percebe-se que o tempo gasto com a infraestrutura é muito alto. Outra tecnologia que atualmente é vista como proporcionadora de baixa produtividade das equipes de desenvolvimento é o EJB 2. Nele, também muitas configurações (xml) necessitam ser criadas, sendo que praticamente nenhuma convenção é utilizada.&lt;p class="MsoNormal" style="text-align: justify; text-indent: 36pt;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C03%5Cclip_filelist.xml"&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;&lt;b style=""&gt;&lt;i style=""&gt;Frameworks&lt;/i&gt; recentes que visam resolver os problemas&lt;/b&gt;&lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C04%5Cclip_filelist.xml"&gt;&lt;o:smarttagtype namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="PersonName"&gt;&lt;/o:smarttagtype&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if !mso]&gt;&lt;object classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id="ieooui"&gt;&lt;/object&gt; &lt;style&gt; st1\:*{behavior:url(#ieooui) } &lt;/style&gt; &lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText 	{mso-style-noshow:yes; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} span.MsoFootnoteReference 	{mso-style-noshow:yes; 	vertical-align:super;}  /* Page Definitions */  @page 	{mso-footnote-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/04/clip_header.htm") fs; 	mso-footnote-continuation-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/04/clip_header.htm") fcs; 	mso-endnote-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/04/clip_header.htm") es; 	mso-endnote-continuation-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/04/clip_header.htm") ecs;} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;  &lt;/p&gt;&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C09%5Cclip_filelist.xml"&gt;&lt;o:smarttagtype namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="PersonName"&gt;&lt;/o:smarttagtype&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if !mso]&gt;&lt;object classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id="ieooui"&gt;&lt;/object&gt; &lt;style&gt; st1\:*{behavior:url(#ieooui) } &lt;/style&gt; &lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText 	{mso-style-noshow:yes; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} span.MsoFootnoteReference 	{mso-style-noshow:yes; 	vertical-align:super;}  /* Page Definitions */  @page 	{mso-footnote-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/09/clip_header.htm") fs; 	mso-footnote-continuation-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/09/clip_header.htm") fcs; 	mso-endnote-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/09/clip_header.htm") es; 	mso-endnote-continuation-separator:url("file:///D:/USERS/gfronza/CONFIG~1/Temp/msohtml1/09/clip_header.htm") ecs;} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;Como &lt;i style=""&gt;framework&lt;/i&gt; MVC, várias tecnologias recentes apresentam soluções interessantes. O próprio Struts 2 (ou Webwork), que foi lançado com características muito diferentes da sua versão anterior. Porém, pelo fato de ter seus desenvolvedores fora do Brasil, a questão do suporte e consultoria torna-se mais complicado e custoso.&lt;br /&gt;Sendo assim, após um estudo dos &lt;i style=""&gt;frameworks&lt;/i&gt; MVC desenvolvidos por brasileiros, destaca-se o VRaptor, que tem como desenvolvedores, o pessoal de uma empresa chamada Caelum&lt;a style="" href="http://www.blogger.com/post-edit.do#_ftn1" name="_ftnref1" title=""&gt;&lt;span class="MsoFootnoteReference"&gt;&lt;span style=""&gt;&lt;!--[if !supportFootnotes]--&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;, com sede em São Paulo.&lt;b style=""&gt; &lt;/b&gt;Trata-se de uma empresa que além de desenvolver sistemas e &lt;i style=""&gt;frameworks&lt;/i&gt;, provê uma gama de treinamentos &lt;st1:personname productid="em Java. O VRaptor" st="on"&gt;em Java. O VRaptor&lt;/st1:personname&gt;, que atualmente consta na versão 2.5, consiste em um &lt;i style=""&gt;framework&lt;/i&gt; onde primeiramente é levado em consideração “convenções” sobre “configurações”. Com ele, muitas das configurações que são feitas no Struts 1, por exemplo, são abolidas pelo uso de convensões. A criação de uma nova &lt;i style=""&gt;action&lt;/i&gt; com VRaptor,&lt;span style=""&gt;  &lt;/span&gt;consiste apenas na criação de um &lt;b style=""&gt;método&lt;/b&gt;. Dessa forma, uma classe Java pode conter determinadas &lt;i style=""&gt;actions&lt;/i&gt;, sendo que as classes podem então ser nomeadas como AlunoLogic, CentroLogic, etc. As classes passam a ser vistas como um agrupamento de actions, sendo que nenhuma configuração em XML precisa ser feita, tudo funciona à base de convenções. A passagem de parâmetros da camada view para a camada de lógica (&lt;i style=""&gt;action&lt;/i&gt;) ocorre de forma simples, sem que nenhuma classe seja criada, como no Struts 1 que precisa ser criada uma &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;ActionForm&lt;/span&gt;. A injeção dos parâmetros ocorre dentro da lista de parâmetros do próprio método.&lt;br /&gt;&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C10%5Cclip_filelist.xml"&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;O Quadro 1 apresenta um exemplo de código-fonte de uma classe de lógica no VRaptor.&lt;br /&gt;&lt;p class="MsoNormal" style="text-align: justify; text-indent: 27pt;"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C05%5Cclip_filelist.xml"&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} table.MsoTableGrid 	{mso-style-name:"Tabela com grade"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	border:solid windowtext 1.0pt; 	mso-border-alt:solid windowtext .5pt; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-border-insideh:.5pt solid windowtext; 	mso-border-insidev:.5pt solid windowtext; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;  &lt;table class="MsoTableGrid" style="border: medium none ; margin-left: 5.4pt; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0"&gt;  &lt;tbody&gt;&lt;tr style=""&gt;   &lt;td style="border: 1pt solid windowtext; padding: 0cm 5.4pt; width: 443.5pt;" valign="top" width="591"&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;@Component&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;public class AlunoLogic {&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;        &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;@Transaction(required=true)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;public   void cadastra(Aluno a) {&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;alunoRepository.save(a);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;}&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: justify;"&gt;        &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;@Transaction(required=true)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;public   void altera(Aluno a) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;            &lt;/span&gt;...&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;&lt;span style=""&gt;          &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p class="MsoNormal" style="text-align: justify;"&gt;&lt;span style=";font-family:&amp;quot;;font-size:85%;"   lang="EN-US"&gt;}&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;/p&gt;  &lt;div style=""&gt;&lt;!--[if !supportFootnotes]--&gt;&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C06%5Cclip_filelist.xml"&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;                                      Quadro 1 – Exemplo de classe de lógica VRaptor.&lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;meta name="ProgId" content="Word.Document"&gt;&lt;meta name="Generator" content="Microsoft Word 11"&gt;&lt;meta name="Originator" content="Microsoft Word 11"&gt;&lt;link rel="File-List" href="file:///D:%5CUSERS%5Cgfronza%5CCONFIG%7E1%5CTemp%5Cmsohtml1%5C11%5Cclip_filelist.xml"&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:hyphenationzone&gt;21&lt;/w:HyphenationZone&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;   &lt;/w:Compatibility&gt;   &lt;w:browserlevel&gt;MicrosoftInternetExplorer4&lt;/w:BrowserLevel&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="156"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-fareast-font-family:"Times New Roman";} @page Section1 	{size:612.0pt 792.0pt; 	margin:70.85pt 3.0cm 70.85pt 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Tabela normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.0pt; 	font-family:"Times New Roman"; 	mso-ansi-language:#0400; 	mso-fareast-language:#0400; 	mso-bidi-language:#0400;} &lt;/style&gt; &lt;![endif]--&gt;&lt;br /&gt;&lt;br /&gt;Para que a &lt;i style=""&gt;action&lt;/i&gt; &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;cadastra&lt;/span&gt;&lt;span style="font-size:85%;"&gt; &lt;/span&gt;seja invocada através de uma view (em um jsp), a seguinte URL deve ser submetida: “aluno.cadastra.logic”. Isso já faz com que o método &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;cadastra&lt;/span&gt;&lt;span style="font-size:85%;"&gt; &lt;/span&gt;da classe &lt;span style=";font-family:&amp;quot;;font-size:85%;"  &gt;AlunoLogic&lt;/span&gt;&lt;span style="font-size:85%;"&gt; &lt;/span&gt;seja chamado. A passagem de parametros também é interessante, pois basta informar a url: “aluno.cadastra.logic?aluno.nome=Teste1&amp;amp;aluno.dataNascimento=12/05/1990”. O VRaptor já sabe que precisa criar um objeto do tipo Aluno e povoar os atributos. Com VRaptor a integração com Ajax é muito simples, sendo que basta adicionar uma anotação acima do nome do método e o mesmo já pode ser acessado por uma requisição HTTP assincrona.&lt;br /&gt;A tecnologia EJB também evoluiu muito na sua versão atual que é a 3. Uma das principais vantagens sobre a versão anterior é o uso de anotações Java para realizar as configurações necessárias, que aumentam muito a produtividade. Essa versão também contempla uma maior integração com &lt;i style=""&gt;frameworks&lt;/i&gt; de mapeamento objeto relacional, tal como Hibernate e Prevayler. O EJB 3 traz consigo a especificação JSR-220, que inclui a Java Persistence API (JPA). Ela deixa livre a implemenação concreta do provedor de persistência de dados, onde na maioria das vezes é utilizado o Hibernate, porém a aplicação não precisa utilizar os recursos diretamente dele, tornando-a mais independente.&lt;br /&gt;Como ambiente de desenvolvimento &lt;i style=""&gt;freeware&lt;/i&gt; e &lt;i style=""&gt;opensource&lt;/i&gt;, o Eclipse Web Tools Plataform (WTP) apresenta-se como uma solução bastante prática para o desenvolvimento de aplicações web fazendo uso dos &lt;i style=""&gt;frameworks&lt;/i&gt; previamente citados. Tanto para se trabalhar com o VRaptor, como EJB 3, existem &lt;i style=""&gt;plug-ins &lt;/i&gt;gratuitos que auxiliam o desenvolvedor na criação de tarefas rotineiras.&lt;br /&gt;Por último, a empresa Caelum, cujo site já foi apresentado, possui diversos treinamentos. Todos os professores são certificados pela Sun e são altamente ativos na comunidade Java (nos fóruns principalmente). A maioria dos professores da Caelum sao os responsáveis pela elaboração da revista Mundo Java, que é bem conhecida no Brasil todo. Os treinamentos envolvem desde orientação a objetos e modelagem de arquiteturas, até a utilização de &lt;i style=""&gt;frameworks&lt;/i&gt; consagrados, incluindo o VRaptor.&lt;br /&gt;Além das tecnologias, para uma equipe de desenvolvedores Java ser mais ágil, é necessário que uma metologia de desenvolvimto ágil seja considerada. Conceitos como &lt;span style="font-weight: bold;"&gt;Domain Driven Design&lt;/span&gt; (DDD) são muito bem vindos, fazendo com que o código-fonte da aplicação por completo, fique muito mais próximo do domínio do negócio a ser desenvolvido, favorecendo o entendimento tanto por parte da equipe técnica (TI) quanto dos especialistas do negócio.&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;b style=""&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;p&gt;&lt;/p&gt;    &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-118416105547367714?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/118416105547367714/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=118416105547367714' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/118416105547367714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/118416105547367714'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/06/java-ee-de-hoje.html' title='Java EE de hoje...'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-5071799366731700570</id><published>2008-04-20T17:53:00.000-07:00</published><updated>2008-05-07T09:08:50.679-07:00</updated><title type='text'>Testes de Unidade para camada de negócios usando BDUnit</title><content type='html'>&lt;span style="font-weight: bold;font-size:100%;" &gt;Introdução&lt;/span&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Com a aproximação das áreas de negócio e conceitos atuais como SOA e BPM, o usuário está habilitando-se a visualizar de forma mais clara o funcionamento interno do software, e com isso garantindo que o mesmo faça o que realmente se propoe a fazer. Tendo em vista que os usuários endendem o "workflow" dos seus processos e como eles estão organizados (através de orquestração) dentro do software é imprescindível que todas as unidades que compõem os processos funcionem de acordo com o esperado.&lt;br /&gt;Paralelamente a isso, o crescimento e consequente popularização das metodologias de desenvolvimento ágil, tem levado os desenvolvedores a escrever Testes de Unidade em seus projetos. Tais testes, além de servirem para validar a corrente qualidade das unidades do software, servem também como uma ótima documentação (definida programaticamente) para quem vai utilizar as unidades em produção.&lt;br /&gt;Quando se pensa em Testes de Unidade é necessário ter em mente qual o nível ou camada do software eles devem atingir, isso implica diretamente na escolha das tecnologias (frameworks) e técnicas a serem utilizadas. Todas as camadas de um software podem ser testadas, tais como: camada de persistência, camada de negócios, camada de aplicação, ou até mesmo a camada de apresentação (de interface com o usuário). Dentre todas as camadas a serem testadas, destaca-se a camada de negócios. Esta, como o próprio nome sugere, diz respeito diretamente ao domínio do negócio do cliente. Os testes desta camada devem testar as ditas Regras do Negócio, elas compõem o ponto crítico do sistema, pois são estas regras que determinam o funcionamento dos processos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Porque começar a testar o negócio pela camada de negócios e não pela camada de aplicação?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Para explicar isso imagine o seguinte dialogo entre dois desenvolvedores Java:&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; Des1&lt;/span&gt;: - Meu teste deve começar da onde (qual camada)?&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; Des2&lt;/span&gt;: - Depende, qual o foco do seu teste?&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; Des1&lt;/span&gt;: - Ah, o meu foco agora é testar a segurança da aplicação, bem como outras questões relacionadas à infraestrutura.&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; Des2&lt;/span&gt;: - Okay, então o seu teste deve começar pela camada de aplicação (testar as Actions do Struts, Logicas do VRaptor, etc). Quando seu teste diz respeito à Infraestrutura da aplicação então ela deve iniciar no mínimo pela camada de aplicação.&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; Des1&lt;/span&gt;: - Entendi, mas como vou testar a minha camada de aplicação se nela eu utilizo recursos cedidos pelo servidor de aplicação/servlet container, tipo uma Session, etc.&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; Des2&lt;/span&gt;: - Simples, utilize Mock Objects, com eles pode-se criar "falsas implementações" das classes/interfaces que são utilizadas na camada de aplicação e que não são controladas por você.&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; Des1&lt;/span&gt;: Até aí tudo bem, mas agora imagine que meu foco é testar as regras de negócio do meu cliente, por que eu não deveria continuar iniciando meus testes pela camada de aplicação?&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; Des2&lt;/span&gt;: Você não quer testar as regras de negócio do seu cliente?&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; Des1&lt;/span&gt;: Sim, por que?&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; Des2&lt;/span&gt;: Então qual o motivo de você querer poluir o código de testes com questões da infraestrutura (cheio de mock objects no meio atrapalhando a visibilidade da real intenção do teste)&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; Des1&lt;/span&gt;: Faz sentido, assim quem for ler o código de testes vai entender como o negócio deve ser usado, independente de infraestrutura.&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;Des2&lt;/span&gt;: Exatamente! :D&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Testando aplicações baseadas em banco de dados (normalmente sistemas)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Agora que já sabe-se a necessidade dos testes e qual camada eles devem atingir, algumas regras precisam ser seguidas, são elas:&lt;br /&gt;- um método de teste não deve depender do estado da base de dados para funcionar;&lt;br /&gt;- um método de teste não deve depender de outro para funcionar;&lt;br /&gt;- quando um caso de teste tiver uma complexidade consideravelmente mais alta, este deve ser dividido em pequenos métodos de teste, por exemplo: testAdicionarClienteSemEndereco() ou testAdicionarClienteCpfInvalido(), etc;&lt;br /&gt;- um método de teste deve ser capaz de preparar a base de dados para que ele funcione independentemente.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cumprindo as regras anteriores usando os frameworks JUnit4 e DBUnit 2.2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JUnit é um dos mais conhecidos frameworks para execução de testes em Java, a versão 4 permite que o programador utilize anotações do Java 5 ao invés de utilizar métodos com nomes hardcode, tais como: setUp, tearDown, test. Já o framework DBUnit é uma extensão do JUnit, e como o nome sugere, serve para testes que envolvem base de dados.&lt;br /&gt;Esses tipos de testes são complicados, pois, como cumprir a regra de que um método de teste não pode depender do estado da base de dados? Imagine que deve-se testar uma rotina de faturamento, como o método de teste vai fazer para cadastrar um cliente, produto, tabela de preços, condições de pagamento, etc. Esse método de testes deveria ser capaz de fazer isso em uma única linha de código, tal como executar um script SQL para deixar a base pronta para a execução do teste. Mas será que um script SQL (gravado em um txt por exemplo) é uma idéia boa? e se a aplicação for independente de SGBD, pode ser que um script SQL comprometa demais a portabilidade. Com o DBUnit, ao invés de povoar as tabelas a partir de um script SQL, utiliza-se documentos XML para definição dos dados a serem povoados. Com esta funcionalidade, é possível cumprir todas as regras citadas anteriormente.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Criando uma classe base para os testes&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Para dar suporte às classes concretas de testes (Unit Test Cases), criaremos uma classe abstrata para abstrair algumas tarefas comuns a todos os métodos de teste. Segue o código desta classe:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/**&lt;br /&gt; * Classe base para os testes do sistema.&lt;br /&gt; * @author Germano&lt;br /&gt; * @version 1.0.0.0&lt;br /&gt; */&lt;br /&gt;public abstract class MyAppTestCase {&lt;br /&gt;&lt;br /&gt; protected TransactionManager transactionManager = new TransactionManager(HibernateUtilTDD.getSession());&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Conexão com o banco de dados.&lt;br /&gt;  */&lt;br /&gt; private static IDatabaseTester databaseTester;&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Cria um novo MyAppTestCase&lt;br/&gt;&lt;br /&gt;  * Configura o acesso a base de dados e as operações de SetUp e TearDown&lt;br /&gt;  */&lt;br /&gt; public MyAppTestCase() {&lt;br /&gt;  databaseTester = new JdbcDatabaseTester("com.mysql.jdbc.Driver",&lt;br /&gt;                     "jdbc:mysql://localhost/myApp_tdd", &lt;br /&gt;                      "myUser", &lt;br /&gt;                     "myPass");&lt;br /&gt;  &lt;br /&gt;  databaseTester.setTearDownOperation(DatabaseOperation.NONE);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Método a ser executado depois que todas as unidades de testes forem executadas.&lt;br/&gt;&lt;br /&gt;  * Responsável por realizar a desconexão com o banco de dados.&lt;br /&gt;  * @throws Exception&lt;br /&gt;  */&lt;br /&gt; @AfterClass&lt;br /&gt; public static void dropDBConnection() throws Exception {&lt;br /&gt;  databaseTester.closeConnection(databaseTester.getConnection());&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Before&lt;br /&gt; public void setUp() {&lt;br /&gt;  transactionManager.beginTransaction();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @After&lt;br /&gt; public void tearDown() {&lt;br /&gt;  transactionManager.commit();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Coloca um novo conjunto de dados na base de dados para ser utilizado na unidade de testes.&lt;br/&gt;&lt;br /&gt;  * Obs.: Não limpa a base de dados.&lt;br /&gt;  * @param xmlDataSet&lt;br /&gt;  * @throws Exception&lt;br /&gt;  */&lt;br /&gt; protected void appendDataSet(String xmlDataSet) throws Exception {  &lt;br /&gt;  IDataSet dataSet = new FlatXmlDataSet(new FileInputStream(getResourcesFolderFromTestUnit(xmlDataSet)));&lt;br /&gt;  databaseTester.setDataSet(dataSet);&lt;br /&gt;  &lt;br /&gt;  databaseTester.setSetUpOperation(DatabaseOperation.INSERT);&lt;br /&gt;  databaseTester.onSetup();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Atualiza os registros do conjunto de dados atual.&lt;br/&gt;&lt;br /&gt;  * Obs.: Não remove os registros já cadastrados no conjunto de dados atual.&lt;br /&gt;  * @param xmlDataSet&lt;br /&gt;  * @throws Exception&lt;br /&gt;  */&lt;br /&gt; protected void updateDataSet(String xmlDataSet) throws Exception {  &lt;br /&gt;  IDataSet dataSet = new FlatXmlDataSet(new FileInputStream(getResourcesFolderFromTestUnit(xmlDataSet)));&lt;br /&gt;  databaseTester.setDataSet(dataSet);&lt;br /&gt;  &lt;br /&gt;  databaseTester.setSetUpOperation(DatabaseOperation.UPDATE);&lt;br /&gt;  databaseTester.onSetup();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Remove registros do conjunto de dados atual.&lt;br/&gt;&lt;br /&gt;  * Obs.: Remove somente os registros contidos no conjunto de dados informado no &lt;i&gt;xmlDataSet&lt;/i&gt;.&lt;br /&gt;  * @param xmlDataSet&lt;br /&gt;  * @throws Exception&lt;br /&gt;  */&lt;br /&gt; protected void deleteDataSet(String xmlDataSet) throws Exception {  &lt;br /&gt;  IDataSet dataSet = new FlatXmlDataSet(new FileInputStream(getResourcesFolderFromTestUnit(xmlDataSet)));&lt;br /&gt;  databaseTester.setDataSet(dataSet);&lt;br /&gt;  &lt;br /&gt;  databaseTester.setSetUpOperation(DatabaseOperation.UPDATE);&lt;br /&gt;  databaseTester.onSetup();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Coloca um novo conjunto de dados a ser utilizado na unidade de testes.&lt;br/&gt;&lt;br /&gt;  * Obs.: Limpa a base de dados antes de inserir o novo conjunto de dados.&lt;br /&gt;  * @param xmlDataSet&lt;br /&gt;  * @throws Exception&lt;br /&gt;  */&lt;br /&gt; protected void setNewDataSet(String xmlDataSet) throws Exception {  &lt;br /&gt;  // dataset vazio para limpar a base de dados.&lt;br /&gt;  IDataSet dataSet = new FlatXmlDataSet(new FileInputStream(getResourcesFolderFromUtil("empty-database.xml")));&lt;br /&gt;  databaseTester.setDataSet(dataSet);&lt;br /&gt;  databaseTester.setSetUpOperation(DatabaseOperation.DELETE_ALL);&lt;br /&gt;  databaseTester.onSetup();&lt;br /&gt;  &lt;br /&gt;  // novo dataset definido via XML.&lt;br /&gt;  dataSet = new FlatXmlDataSet(new FileInputStream(getResourcesFolderFromTestUnit(xmlDataSet)));&lt;br /&gt;  databaseTester.setDataSet(dataSet);&lt;br /&gt;  databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);&lt;br /&gt;  databaseTester.onSetup();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Obtem o diretório de resources referente ao método de &lt;br /&gt;  * testes que invocou o método de definir DataSet.&lt;br /&gt;  * @return String&lt;br /&gt;  */&lt;br /&gt; private String getResourcesFolderFromTestUnit(String rsrc) {&lt;br /&gt;  StringBuffer packageName = new StringBuffer();&lt;br /&gt;  &lt;br /&gt;  // obtem a pilha de chamada de métodos (um pouco de Reflection)&lt;br /&gt;  Throwable t = new Throwable();&lt;br /&gt;  String fullClassName = t.getStackTrace()[2].getClassName();&lt;br /&gt;  &lt;br /&gt;  // através do nome completo da classe (pacote.class_name) extrai a string que&lt;br /&gt;  // representa o diretório onde se encontram os resources.&lt;br /&gt;  String[] folders = fullClassName.replace(".", "&gt;").split("&gt;");&lt;br /&gt;  for (int i = 0; i &lt; folders.length-1; i++) {&lt;br /&gt;   packageName.append(folders[i]);&lt;br /&gt;   packageName.append("/");&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;  URL rsrcUrl = MyAppTestCase.class.getClassLoader().getResource(packageName.toString() + rsrc);&lt;br /&gt;  return rsrcUrl.toString().substring(6);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Obtem o diretório de resources do pacote Utils dos testes.&lt;br /&gt;  * @return String&lt;br /&gt;  */&lt;br /&gt; private String getResourcesFolderFromUtil(String rsrc) {  &lt;br /&gt;  // obtem a pilha de chamada de métodos (um pouco de Reflection++)&lt;br /&gt;  Throwable t = new Throwable();&lt;br /&gt;  String fullClassName = "";&lt;br /&gt;  try {&lt;br /&gt;   String className = t.getStackTrace()[2].getClassName();&lt;br /&gt;         fullClassName = Class.forName(className).getSuperclass().getCanonicalName();&lt;br /&gt;        } catch (ClassNotFoundException e) {&lt;br /&gt;         e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;  // através do nome completo da classe (pacote.class_name) extrai a string que&lt;br /&gt;  // representa o diretório onde se encontram os resources.&lt;br /&gt;        StringBuffer packageName = new StringBuffer();&lt;br /&gt;  String[] folders = fullClassName.replace(".", "&gt;").split("&gt;");&lt;br /&gt;  for (int i = 0; i &lt; folders.length-1; i++) {&lt;br /&gt;   packageName.append(folders[i]);&lt;br /&gt;   packageName.append("/");&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;  URL rsrcUrl = MyAppTestCase.class.getClassLoader().getResource(packageName.toString() + rsrc);&lt;br /&gt;  return rsrcUrl.toString().substring(6);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;TransactionManager é uma simples classe que encapsula os tratamentos de transação, para isso ela deve receber no construtor uma instância da sessão do Hibernate.&lt;br /&gt;IDatabaseTester é a interface do DBUnit.&lt;br /&gt;&lt;br /&gt;Conteúdo do arquivo &lt;a href="http://www.inf.furb.br/%7Egfronza/artigos/testes/rsrc/empty-database.xml"&gt;empty-database.xml&lt;/a&gt;.&lt;br /&gt;Obs: Os arquivos XML usados nos testes devem ser colocados no mesmo diretório (pacote) da classe do teste em questão. Para quem utiliza o Eclipse, uma prática comum é criar dois &lt;span style="font-style:italic;"&gt;source folders&lt;/span&gt;, um para os códigos Java e outro para os &lt;span style="font-style:italic;"&gt;resources&lt;/span&gt;, sendo que ambos apontem para o mesmo diretório de &lt;span style="font-style:italic;"&gt;output&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Exemplo bem simples de um Unit Test Case utilizando esta classe base:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/**&lt;br /&gt; * Unidade de casos de testes de Modelo Corporativo.&lt;br /&gt; * @author Germano&lt;br /&gt; * @version 1.0.0.0&lt;br /&gt; */&lt;br /&gt;public class ModeloCorporativoTestCase extends MyAppTestCase {&lt;br /&gt;&lt;br /&gt; private NucleoBusinessFactory factory;&lt;br /&gt; &lt;br /&gt; public ModeloCorporativoTestCase() {&lt;br /&gt;  super();&lt;br /&gt;  factory = new NucleoBusinessFactory(DaoFactory.getInstance(transactionManager.getSession()));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Test&lt;br /&gt; public void testAdiciona() throws Exception {&lt;br /&gt;  // adiciona um usuário à base&lt;br /&gt;  setNewDataSet("modeloCorporativoAdiciona.xml");&lt;br /&gt;&lt;br /&gt;  // obtem o usuário de código 1&lt;br /&gt;  Usuario u = factory.getUsuarioBusiness().retorna(1L);&lt;br /&gt;  &lt;br /&gt;  ModeloCorporativo m = new ModeloCorporativo();&lt;br /&gt;  m.setCodigo("M01");&lt;br /&gt;  m.setDescricao("Empresas SUL");&lt;br /&gt;  m.setAbreviatura("M01 - EmpSul");&lt;br /&gt;  m.setUsuarioCadastro(u);&lt;br /&gt;  m.setMascara("11.22.333");&lt;br /&gt;  &lt;br /&gt;  ModeloCorporativoBusiness business = factory.getModeloCorporativoBusiness();&lt;br /&gt;  business.adiciona(m);&lt;br /&gt;  assertTrue("1 - Não adicionou o modelo corporativo", (m.getId() != 0));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Conteúdo do arquivo &lt;a href="http://www.inf.furb.br/%7Egfronza/artigos/testes/rsrc/modeloCorporativoAdiciona.xml"&gt;modeloCorporativoAdiciona.xml&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusão&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Dentre todas as práticas sugeridas pelas metodologias de desenvolvimento ágil, com certeza o uso de testes (principalmente usando o paradigma de Test Driven Development) é uma das mais praticadas em projetos de desenvolvimento de software. Podendo contar com poderosas ferramentas de testes, como as citadas neste artigo e outras, a produtividade da equipe de testes (ou dos próprios programadores de sistema) torna-se cada vez maior.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-5071799366731700570?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/5071799366731700570/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=5071799366731700570' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/5071799366731700570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/5071799366731700570'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/04/testes-de-unidade-para-camada-de.html' title='Testes de Unidade para camada de negócios usando BDUnit'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-2062238251108083994</id><published>2008-03-07T21:29:00.002-08:00</published><updated>2008-04-20T14:52:09.326-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jMonkeyEngine'/><category scheme='http://www.blogger.com/atom/ns#' term='POA'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Design'/><title type='text'>TCC + TCC</title><content type='html'>Olá,&lt;br /&gt;&lt;br /&gt;Estou a um tempo sem postar aqui no blog, a falta de tempo é o principal motivo.&lt;br /&gt;Desde a data do último post, além das pesquisas na área de desenvolvimento de sistemas corporativos, tenho estudado e desenvolvido um projeto na área de Jogos 3D usando Java e é justamente isso que estarei comentando hoje.&lt;br /&gt;Este projeto servirá como TCC da faculdade de Ciências da Computação da Universidade Regional de Blumenau, na qual estarei me graduando em julho deste ano de 2008.&lt;br /&gt;Tal projeto prevê o desenvolvimento de um Simulador de um Ambiente Virtual Distribuído  (AVD) multiusuário para batalhas de tanques em 3D. Na batalha, os tanques poderão ser controlados por usuários (humanos) ou também por agentes inteligentes programados na linguagem AgentSpeak(L) do interpretador &lt;a href="http://jason.sourceforge.net/JasonWebSite/Jason%20Home.php"&gt;Jason&lt;/a&gt;.&lt;br /&gt;Encontrei motivação para o desenvolvimento de tal projeto quando começei a utilizar o &lt;a href="http://robocode.sourceforge.net/"&gt;Robocode &lt;/a&gt;e programar alguns tanques diretamente na linguagem Java. Depois de várias tentativas de criar times com uma certa "inteligência", poucas tiveram sucesso. O principal motivo disso que notei foi que Java não parece ser a linguagem ideal para escrever entidades inteligentes, o código dos tanques ficava extremamento extenso e complicado quando queria implementar determinados "planos" que os tanques tinham que executar, principalmente quando precisava utilizar técnicas de cooperação e/ou coordenação. Simultâneamente ao estudo do Robocode, na faculdade eu estava estudando uma área da IA que se denomina Programação Orientada a Agentes (POA), cuja disciplina era ministrada pelo professor Jomi F. Hubner. Nessa disciplina, estudamos diversos modelos de Sistemas Multiagentes (SMA), porém o foco era contemplar a arquitetura BDI e o interpretador Jason, que é uma ferramenta para executar códigos de agentes escritos na linguagem AgentSpeak(L). Tal linguagem, por natureza, já provê diversas facilidades para a construção de entidades inteligentes. Nessa linguagem, um agente compreende: crenças, desejos e intenções, ou seja, os agentes percebem coisas que acontecem no ambiente, baseado nisso eles podem passar a acreditar em algo (passa para a base de crenças), podem também passar a desejar algo e então ter a intenção de realizar algo. A sintaxe abstrata da linguagem é baseada em linguagens de lógica, tal como o Prolog, dessa forma, se escreve pouco e se tem bastante resultado.&lt;br /&gt;Baseado no Robocode e no estudo de POA, idealizei um simulador de batalhas de tanques, porém com diversas melhorias. Nesta versão, o mundo virtual será em 3D, diferente do robocode que provê uma visualização em 2D. A programação dos tanques também será mais abstrata, pois será utilizada a linguagem AgentSpeak(L), e não mais o Java como o caso do Robocode.&lt;br /&gt;Espero que esse simulador se torne um ambiente mais atrativo para a programação de agentes inteligentes, e que tal paradigma de programação se torne um pouco mais popular.&lt;br /&gt;&lt;br /&gt;Conforme vou tendo mais resultados da implementação do simulador, vou postando aí as técnicas utilizadas e eventualmente versões preliminares do "executável".&lt;br /&gt;&lt;br /&gt;É isso! ;D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-2062238251108083994?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/2062238251108083994/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=2062238251108083994' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/2062238251108083994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/2062238251108083994'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2008/03/tcc-tcc.html' title='TCC + TCC'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-2937997662044686512</id><published>2007-10-14T13:06:00.000-07:00</published><updated>2008-04-20T14:54:37.112-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Construindo uma janela de consulta genérica - poder de Java Reflection + Annotations</title><content type='html'>Olá,&lt;br /&gt;&lt;br /&gt;Hoje estarei comentando sobre algo que fiz semana passada em um sistema web que estou desenvolvendo.  Por se tratar de um ERP cuja aplicação é Form-based, vi a necessidade de construir um sistema de consulta genérica, onde dada uma classe POJO qualquer, ele montasse uma janela de consulta baseada em todos os atributos da mesma. Para implementar tal funcionalidade, mais uma vez o grande poderio da tecnologia Java garantiu que isso fosse implementado de forma elegante e prática.&lt;br /&gt;Basicamente, o que desenvolvi foi um método que retorna uma lista de parâmetros de consulta para que a tela genérica possa ser &lt;span style="font-style: italic;"&gt;renderizada&lt;/span&gt;. Para descobrir os atributos da classe POJO passada por parâmetro ao método utilizei Java Reflection e Annotations.&lt;br /&gt;Consegui implementar isso, graças a utilização de uma DaoFactory genérica, que inclusive detalhei em um post anterior aqui do blog. Com ela, dada uma POJO qualquer, pode-se obter sua respectiva Dao, e com sua dao, executar o método retornarTodos().&lt;br /&gt;&lt;br /&gt;O código deste método postei em um pastebin externo para facilitar a leitura. Deixei o código bem comentado, por isso acho que está auto explicativo. O link é: http://fr.pastebin.ca/736916&lt;br /&gt;Só peço desculpas pela identação do código-fonte, no eclipse está perfeita, porém ao transferir para o textarea do pastebin ficou errado.&lt;br /&gt;&lt;br /&gt;Se achar interessante e tiver alguma dúvida, por favor não hesite em enviar um recado ou e-mail.&lt;br /&gt;&lt;br /&gt;[]'s&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-2937997662044686512?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/2937997662044686512/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=2937997662044686512' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/2937997662044686512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/2937997662044686512'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/10/construindo-uma-janela-de-consulta.html' title='Construindo uma janela de consulta genérica - poder de Java Reflection + Annotations'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-4172827820423005042</id><published>2007-09-11T07:05:00.000-07:00</published><updated>2008-04-20T14:55:00.989-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Herança "simples" com Hibernate</title><content type='html'>Olá pessoas,&lt;br /&gt;&lt;br /&gt;Hoje comentarei sobre mapeamento de herança com o Hibernate através de annotations.&lt;br /&gt;Conforme documentações e exemplos que encontramos por ai, sabemos que existem 3 tipos de mapeamento de herança:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Joined - Usado quando quer criar uma tabela para a classe genérica e demais tabelas que derivam dela, por exemplo: Pessoa, Pessoa Física, Pessoa Jurídica. Neste caso teriam 3 tabelas.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Single Table - Usado quando quer criar uma única tabela para armazenar os dados. No caso da Pessoa, Pessoa Física, Pessoa Jurídica, teria uma única tabela com todas os atributos.&lt;/li&gt;&lt;li&gt;Table Per Class - Usado quando quer criar uma tabela para cada subclasse. No caso da Pessoa, Pessoa Física, Pessoa Jurídica, teriam duas tabelas: Pessoa Fisica e Pessoa Juridica, os atributos da classe Pessoa seriam replicados nas duas tabelas.&lt;/li&gt;&lt;/ul&gt;A questão é que para utilizar estes tipos de mapeamento de herança é necessário anotar a classe mais genérica com @Entiety, ou seja deve ser uma entidade gerenciada pelo hibernate. Se uma classe é uma Entiety, obrigatoriamente ela deve conter um atributo anotado com @Id.&lt;br /&gt;Se for utilizar o mapeamento de herança do tipo Table Per Class, não é possível determinar o atributo anotado com @Id como @GeneratedValue do tipo AUTO ou IDENTITY. Em alguns casos isso é um problema, para explicar melhor vou citar um exemplo:&lt;br /&gt;&lt;br /&gt;Uma classe abstrata Modelo possui alguns atributos incluindo um ID.&lt;br /&gt;Uma classe concreta ModeloCorporativo deriva de Modelo e possui mais alguns atributos.&lt;br /&gt;A nível de base de dados, a tabela do modelo corporativo deve possuir todos os atributos da classe modelo e mais os seus atributos. Dentre estes atributos, está o ID, este deve ser gerado automaticamente pelo banco (via sequence, via auto_increment, etc)&lt;br /&gt;&lt;br /&gt;A primeira vista, parece que o melhor tipo de mapeamento para esta herança é usar TablePerClass, mas dessa forma o atributo ID da classe abstrata não poderia estar anotado com @GeneratedValue(stategy=GenerationType.AUTO), pois isso é uma regra do hibernate (inclusive citada na documentação do hibernate annotations).&lt;br /&gt;Então para resolver esta situação a forma mais indicada seria criar uma classe abstrata Modelo e anota-la com &lt;span style="font-weight: bold;"&gt;@MappedSuperclass&lt;/span&gt;, Este tipo de mapeamento de herança (que nunca aparece nos exemplos comuns de herança)  não exige que a classe seja anotada com @Entiety, ou seja, o hibernate vai saber que esta classe só vai servir para "embutir" os atributos na tabela representada pelas subclasses.&lt;br /&gt;&lt;br /&gt;O código ficaria assim:&lt;br /&gt;&lt;blockquote&gt;@MappedSuperclass&lt;br /&gt;public abstract class Modelo {&lt;br /&gt;  @Id&lt;br /&gt;  @GeneratedValue(strategy=GenerationType.AUTO)&lt;br /&gt;  private Integer id;&lt;br /&gt;&lt;br /&gt;  // outros atributos e getters e setters omitidos.&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Entity&lt;br /&gt;public class ModeloCorporativo extends Modelo {&lt;br /&gt;   private String mascara;&lt;br /&gt;&lt;br /&gt;  // getters e setters omitidos&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Desta forma a tabela ModeloCorporativo terá todos os atributos da classe Modelo e mais o seu atributo mascara. O importante é que o atributo ID herdado da classe Modelo pode ser anotado com @GeneratedValue(strategy=GenerationType.AUTO) e, de acordo com o banco de dados, terá seu id gerado automaticamente&lt;/blockquote&gt;Qualquer dúvida posta aí.&lt;br /&gt;[]'s&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-4172827820423005042?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/4172827820423005042/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=4172827820423005042' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4172827820423005042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4172827820423005042'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/09/herana-simples-com-hibernate.html' title='Herança &quot;simples&quot; com Hibernate'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-7387276367272745838</id><published>2007-08-30T07:40:00.000-07:00</published><updated>2008-04-20T14:55:20.883-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Fábrica de DAOs com Reflection</title><content type='html'>Olá a todos,&lt;br /&gt;Sabemos que uma boa prática na modelagem de arquiteturas de software é a serapação das responsabilidades em camadas bem definidas. Uma destas camadas, talvez a que esteja mais relacionada com os recursos da infra-estrutura, é a de Persistencia dos dados. Para esta camada, é comum utilizar-se &lt;span style="font-style: italic;"&gt;o pattern&lt;/span&gt; Data Access Object (DAO),  que tem o objetivo de encapsular estes acessos aos recursos de armazenamento de dados (normalmente bancos de dados relacionais).&lt;br /&gt;Além da separação de camadas, ouve-se muito falar que é importante manter um fraco acoplamento entre elas, tornando assim, mais independentes para futuras manutenções. Mas como garantir este fraco acoplamento? Segue um exemplo de utilização de uma DAO na camada de negócios:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;ClienteDao dao = new ClienteDao(HibernateUtil.getSession());&lt;br /&gt;dao.adiciona(cliente);&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Implementando desta forma, caso seja necessário refatorar a classe de acesso a dados de Clientes, ou mesmo criar uma nova versão desta classe que não utilizasse hibernate, mas sim acesso direto via JDBC, o que teria que ser feito? Teríamos que criar uma nova classe, por exemplo: ClienteDaoJDBC e implementar todos os metodos novamente. Até aí tudo bem, nada problemático. Mas o problema está na utilização da classe, imagine que quem for cliente da classe ClienteDao terá que mudar o tipo da variável/atriuto para ClienteDaoJDBC. Aí que está o Alto acoplamento.&lt;br /&gt;Para resolver isso é interessante criar interfaces para as DAOs, e então as classes ClienteDao e ClienteDaoJDBC implementariam estas interfaces. Quem fosse utilizar as DAOs usariam variável/atributo do tipo da interface: IFClienteDao por exemplo. Com isso já resolvemos o problema de ter que alterar o tipo da variável/atributo, mas ainda temos o alto acoplamento representado pela instrução &lt;span style="font-weight: bold;"&gt;new&lt;/span&gt;, conforme o código abaixo:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;IFClienteDao dao = &lt;span style="font-weight: bold;"&gt;new&lt;/span&gt; ClienteDaoJDBC();&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;Para resolvermos o problema do alto acoplamento, devemos então criar uma Fábrica de Daos. Uma classe que fosse responsável por instanciar nossas DAOs e tirar esta responsabilidade do cliente das classes DAOs, assim o dia que for necessário alterar a DAO a ser usada, seria só alterar nesta Fábrica. Este conceito de Fábrica segue o &lt;span style="font-style: italic;"&gt;pattern Factory&lt;/span&gt; definido pelo GoF.&lt;br /&gt;Uma fábrica de Daos poderia ser uma singleton, pois não parece ser necessário ter mais de uma instancia desta classe, então o código ficaria:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;public class DaoFactory {&lt;br /&gt;// controle da singleton&lt;br /&gt;private static DaoFactory factory = new DaoFactory();&lt;br /&gt;&lt;br /&gt;// construtor private para não permitir instanciar a factory diretamente com new.&lt;br /&gt;private DaoFactory() {}&lt;br /&gt;&lt;br /&gt;// através deste método é que se obtem a fábrica.&lt;br /&gt;// excepcionalmente este método recebe um atributo session pois este pode mudar&lt;br /&gt;// durante o tempo de vida da aplicação se assim o hibernate desejar :D&lt;br /&gt;public static DaoFactory getInstance(Session session) {&lt;br /&gt;   factory.setSession(session);&lt;br /&gt;   return factory;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public IFClienteDao getClienteDao() {&lt;br /&gt;     return new ClienteDaoJDBC();&lt;br /&gt;}&lt;br /&gt;}&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Com esta fábrica é possível obter DAOs sem saber o que é preciso disponibilizar à ela, mais uma vez o papel de encapsulamento ajudando.&lt;br /&gt;Mas ainda tem-se um pequeno problema, conforme o sistema for crescendo, muitas daos são criadas e muitos getXXXDao() vão sendo adicionados à fabrica. Quando ocorre estes métodos repetitivos, já é possível imaginar que poderia-se criar um getDao genérico que retornasse a Dao respectiva de uma classe persistente, por exemplo: "Quero que retorne a DAO referente a persistencia dos dados da classe Cliente", então a fábrica retornaria a ClienteDaoJDBC por exemplo. Para isso pode ser utilizado Java Reflection conforme o código a seguir:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;private static DaoFactory factory = new DaoFactory();&lt;br /&gt;private Session session;&lt;br /&gt;private Map&lt;class,&gt; daoMap = new HashMap&lt;class,&gt;();&lt;br /&gt;&lt;br /&gt;public Dao getDao(Class persistentClass) {&lt;br /&gt;   if (daoMap.containsKey(persistentClass)) {&lt;br /&gt;       return daoMap.get(persistentClass);&lt;br /&gt;   }&lt;br /&gt;   else {&lt;br /&gt;       if (persistentClass.isAnnotationPresent(DaoClass.class)) {&lt;br /&gt;           DaoClass daoClassInfo = (DaoClass)persistentClass.getAnnotation(DaoClass.class);&lt;br /&gt;           Dao dao = null;&lt;br /&gt;           try {&lt;br /&gt;               dao = daoClassInfo.value().getConstructor(Session.class, Class.class).newInstance(this.session, persistentClass);&lt;br /&gt;         &lt;br /&gt;               if (daoClassInfo.singleton()) {&lt;br /&gt;                   daoMap.put(persistentClass, dao);&lt;br /&gt;               }&lt;br /&gt;         &lt;br /&gt;               return dao;&lt;br /&gt;           }&lt;br /&gt;           catch (Exception e) {&lt;br /&gt;               throw new DaoFactoryException("A classe Dao não pode ser instanciada. Erro: " + e.getMessage());&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;       else {&lt;br /&gt;           throw new DaoFactoryException("Anotação @DaoClass ausente");&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/class,&gt;&lt;/class,&gt;&lt;/blockquote&gt;Não adicionei comentários neste código pois está bem legível. Espero que tenha sido útil.&lt;br /&gt;&lt;br /&gt;[]'s&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-7387276367272745838?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/7387276367272745838/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=7387276367272745838' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/7387276367272745838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/7387276367272745838'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/08/fbrica-de-daos-com-reflection.html' title='Fábrica de DAOs com Reflection'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-8126449877345998741</id><published>2007-08-21T12:28:00.000-07:00</published><updated>2008-04-20T14:55:41.517-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Frameworks'/><title type='text'>JBoss Rules (Drools)</title><content type='html'>Olá a todos,&lt;br /&gt;&lt;br /&gt;Hoje estarei publicando apenas links de documentos que possuo aqui em casa sobre um framework da JBoss estou estudando atualmente, chamado &lt;span style="font-weight: bold;"&gt;JBoss Rules&lt;/span&gt;. Não vou me estender muito com explicações, pois ainda não tenho muitas certezas em relação à utilização deste framework. Mesmo sem essas certezas, continuo apostando que este JBoss Rules irá trazer muitos benefícios aos meus projetos, que buscam uma arquitetura orientada a serviços (SOA) e regras de negócios que podem mudar frequentemente. Também estou achando interessante a integração deste framework com o JBPM, que é um framework para trabalhar com Business Process Management em Java (WorkFlows avançados).&lt;br /&gt;&lt;br /&gt;Em poucas palavras, o JBoss Rules é um framework Open Source para "externalizar" regras de negócio e/ou lógicas corporativas a fim de tornar o processo de manutenção e novas implementações mais rápido e seguro. Com essas &lt;span style="font-weight: bold;"&gt;regras&lt;/span&gt; externas, que podem ser escritas até em uma linguagem natural, qualquer stakeholder pode ler e interpretar, podendo assim garantir que elas realmente façam o que deveriam fazer.&lt;br /&gt;&lt;br /&gt;Seguem os links:&lt;br /&gt;- http://www.inf.furb.br/~gfronza/JBoss_Rules.pdf&lt;br /&gt;- http://www.inf.furb.br/~gfronza/Apresentacao_JBoss_Rules.pdf&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mais informações sobre o framework podem ser encontrados no &lt;a href="http://labs.jboss.com/drools/"&gt;site da JBoss&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Se tiverem interesse sobre o assunto podemos trocar ideias por e-mail ou IM.&lt;br /&gt;[]'s&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-8126449877345998741?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/8126449877345998741/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=8126449877345998741' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/8126449877345998741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/8126449877345998741'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/08/ol-todos-hoje-estarei-publicando-apenas.html' title='JBoss Rules (Drools)'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-9221502792838269252</id><published>2007-08-14T09:47:00.000-07:00</published><updated>2008-04-20T14:55:54.623-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>"AutoRelacionamento" com Hibernate</title><content type='html'>Hoje tive que implementar o menu de uma aplicação que estou fazendo e precisava de uma classe que representasse uma tabela mais ou menos assim:&lt;br /&gt;&lt;br /&gt;CREATE TABLE  sis_menu (&lt;br /&gt;  id bigint(20) NOT NULL,&lt;br /&gt;  acao varchar(255) default NULL,&lt;br /&gt;  chave varchar(255) NOT NULL,&lt;br /&gt;  idMenuPai bigint(20) default NULL,&lt;br /&gt;  PRIMARY KEY  (`id`),&lt;br /&gt;  KEY `fk_id_pai` (`idMenuPai`),&lt;br /&gt;  FOREIGN KEY (`idMenuPai`) REFERENCES `sis_menu` (`id`)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;Ou seja, tinha que fazer um relacionamento da tabela sis_menu com ela mesma para ter uma hierarquia dos itens do menu.&lt;br /&gt;&lt;br /&gt;Para isso escrevi a seguinte classe POJO com anotações do hibernate:&lt;br /&gt;&lt;br /&gt;@Entity&lt;br /&gt;@Table(name="sis_menu")&lt;br /&gt;public class Menu {&lt;br /&gt;   &lt;br /&gt;    @Id @GeneratedValue&lt;br /&gt;    private Long id;&lt;br /&gt;   &lt;br /&gt;    @NotEmpty(message="menu.chaveEmpty")&lt;br /&gt;    private String chave;&lt;br /&gt;   &lt;br /&gt;    private String acao;&lt;br /&gt;   &lt;br /&gt;    @OneToMany(mappedBy="menuPai", fetch=FetchType.LAZY)&lt;br /&gt;    @Cascade(CascadeType.ALL)&lt;br /&gt;    private List\&lt;menu\&gt; subMenus;&lt;br /&gt;&lt;br /&gt;    @ManyToOne(fetch = FetchType.EAGER)&lt;br /&gt;    @JoinColumn(name="idMenuPai", insertable=true, updatable=true)&lt;br /&gt;    @Fetch(FetchMode.JOIN)&lt;br /&gt;    @Cascade(CascadeType.SAVE_UPDATE)&lt;br /&gt;    private Menu menuPai;&lt;br /&gt;&lt;br /&gt;    // getters e setters&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Não cheguei nesta solução sozinho, o que fiz foi googlear até achar isso. Acabei encontrando um PDF em portugues muito bom que ensina como utilizar mapeamentos no hibernate. Segue o link:&lt;br /&gt;ftp://users.dca.ufrn.br/hibernate_anotacoes/T03_Relacionamentos_1.pdf&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-9221502792838269252?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/9221502792838269252/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=9221502792838269252' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/9221502792838269252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/9221502792838269252'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/08/autorelacionamento-com-hibernate.html' title='&quot;AutoRelacionamento&quot; com Hibernate'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-4592473487071457443</id><published>2007-08-13T18:28:00.000-07:00</published><updated>2008-04-20T14:56:12.707-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Alterando variável java.library.path em tempo de execução</title><content type='html'>Olá a todos,&lt;br /&gt;&lt;br /&gt;Estou postando aqui um trecho de código que eu e dois colegas (Israel e Gustavo) encontramos para solucionar um problema bem simples. Estavamos desenvolvendo uma ferramenta que utilizava o framework JOGL, e além do &lt;span style="font-style: italic;"&gt;jogl.jar&lt;/span&gt; tinhamos que carregar uma dll também do jogl. Para carregar esta dll tinhamos então que colocar elas, ou no path do sistema operacional (nem um pouco indicado pois no nosso caso nem teriamos como gravar arquivos nos diretórios do C:/... por motivos de falta de permissão) apontada pela variável &lt;span style="font-weight: bold;"&gt;java.library.path&lt;/span&gt;, ou colocar na raiz da aplicação. Mas queríamos que as dlls ficassem dentro da pasta &lt;span style="font-weight: bold;"&gt;lib&lt;/span&gt; do nosso projeto. Para resolver isso procuramos na web uma forma de alterar a variável &lt;span style="font-weight: bold;"&gt;java.library.path&lt;/span&gt; somente em tempo de execução e ao finalizar o aplicativo esta variável seria reinicializada com o valor anterior.&lt;br /&gt;&lt;br /&gt;A idéia é simples e o código também:&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;          Class clazz = ClassLoader.class;&lt;br /&gt;          Field field = clazz.getDeclaredField("sys_paths");&lt;br /&gt;       &lt;br /&gt;          boolean accessible = field.isAccessible();&lt;br /&gt;          if (!accessible)&lt;br /&gt;          field.setAccessible(true);&lt;br /&gt;          Object original = field.get(clazz);&lt;br /&gt;&lt;br /&gt;          field.set(clazz, null);&lt;br /&gt;          try {&lt;br /&gt;              System.setProperty("java.library.path", System.getProperty("java.library.path") + ";" + new File("").getAbsolutePath() + File.separator + "lib");&lt;br /&gt;              System.loadLibrary("jogl");&lt;br /&gt;          }&lt;br /&gt;          finally {&lt;br /&gt;              field.set(clazz, original);&lt;br /&gt;              field.setAccessible(accessible);&lt;br /&gt;          }&lt;br /&gt;      } catch (SecurityException e) {&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;      } catch (NoSuchFieldException e) {&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;      } catch (IllegalArgumentException e) {&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;      } catch (IllegalAccessException e) {&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;Prometo que os próximos códigos irei postar em um Pastbin, mas ainda não achei nenhum decente...&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-4592473487071457443?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/4592473487071457443/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=4592473487071457443' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4592473487071457443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4592473487071457443'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/08/alterando-varivel-javalibrarypath-em.html' title='Alterando variável java.library.path em tempo de execução'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8121425584076563711.post-4562969866940896468</id><published>2007-08-12T18:11:00.000-07:00</published><updated>2007-08-13T09:05:48.461-07:00</updated><title type='text'>Motivo da criação deste Blog...</title><content type='html'>Decidi criar este blog, inicialmente para ter um local na &lt;span style="font-weight: bold;"&gt;rede &lt;/span&gt;onde eu pudesse expor algumas idéias, problemas já passados para resolver determinados problemas, utilização com ou sem sucesso de algumas tecnologias,  enfim, tudo que possa ajudar outras pessoas a tomarem decisões sobre a escolha de tecnologias na área de TI.&lt;br /&gt;&lt;br /&gt;Tentarei escrever sobre algumas experiências que já tive na área de computação. Atualmente sou desenvolvedor Java EE e SE, mas utilizo também outras tecnologias como: Lua, OpenLaszlo, etc.&lt;br /&gt;&lt;br /&gt;Gosto muito de trocar idéias sobre como modelar arquiteturas de software, estudar metodologias de desenvolvimento ágil, como XP, Scrum, e o recente (pelo menos para mim) OpenUp da IBM juntamente com o Eclipse. Gosto também de conhecer novos frameworks que proporcionam produtividade e sobretudo qualidade.&lt;br /&gt;&lt;br /&gt;Sobre Java Web atualmente utilizo as tecnologias:&lt;br /&gt;- VRaptor - Controlador MVC&lt;br /&gt;- Hibernate - JPA&lt;br /&gt;- JSP + EL + Taglibs&lt;br /&gt;- JBoss + Tomcat - Servidor de Aplicações + Servelt Container&lt;br /&gt;&lt;br /&gt;Também estou estudando, e documentando bem, como criar plugins para o Eclipse. Sobre isso quero focar, principalmente, na parte da criação de editores (com syntax check e syntax highlight), pois o resto é trivial e já possuem diversas documentações que podem ser encontradas no google ;).&lt;br /&gt;&lt;br /&gt;É isso... abraços&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121425584076563711-4562969866940896468?l=gfronza.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfronza.blogspot.com/feeds/4562969866940896468/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8121425584076563711&amp;postID=4562969866940896468' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4562969866940896468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8121425584076563711/posts/default/4562969866940896468'/><link rel='alternate' type='text/html' href='http://gfronza.blogspot.com/2007/08/motivo-da-criao-deste-blog.html' title='Motivo da criação deste Blog...'/><author><name>Germano</name><uri>http://www.blogger.com/profile/11329495205680126856</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
