Blog do Urubatan
msgbartop
Desenvolvedor, Arquiteto, Palestrante, Coordenador do RSJUG, Patinador e Blogger
msgbarbottom

21 Aug 07 MDA com Groovy! Crie seus modelos UML e deixe o Groovy gerar o seu código fonte.

Bom, esta é a mais nova ferramenta opensource MDA disponível por ai.

O nome da ferramenta é Groovy MDA, o desenvolvimento ainda esta bem no inicio, mas ja lançaram a versão 1.0, ou seja, ja da pra brincar um pouco.

Por enquanto o único template disponível é para gerar entidades JPA a partir de um modelo UML, a ferramenta ainda esta um pouco engessada, pois não tem como informar outros templates ainda, mas acho que o projeto tem futuro, pois eu achei muito fácil criar templates para ela (olhando o código do já existente), mesmo ainda não sendo possível utilizar os novos templates “out of the box”, mas com uma alteração rápida em um arquivo .groovy na raiz do jar, é fácil utilizar os novos templates também.

bom, um exemplo rápido:

Vamos partir do seguinte modelo (gerado pelo ArgoUML, ou qualquer outra ferramenta que gere um XMI válido).

addressbook.jpeg

Com o modelo pronto, basta executar o comando:

java -jar groovymda-1.0.jar 'jar:file:./addressbook.zargo!/addressbook.xmi'

E tudo pronto, as classes definidas no modelo vão gerar entidades JPA (mais sobre JPA aqui, aqui e aqui) válidas e com o código até que bem organizado, como no exemplo a baixo:

package com.acme.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* User Domain Object
*/
@Entity
@Table(name = "t_user")
@NamedQueries({
@NamedQuery(name = "User.findAll", query = "from User")
})
public class User implements Serializable {
@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "pk_id")
    private Long id;
@Column(name = "c_username")
    private java.lang.String username;
@Column(name = "c_password")
    private java.lang.String password;
@OneToMany(
        mappedBy = "user",
        cascade = {CascadeType.PERSIST, CascadeType.MERGE}
    )
    private java.util.Set<Address> addresss;
public java.lang.String getUsername() {
        return username;
    }
public void setUsername(java.lang.String username) {
        this.username = username;
    }
public java.lang.String getPassword() {
        return password;
    }
public void setPassword(java.lang.String password) {
        this.password = password;
    }
public java.util.Set<Address> getAddresss() {
        return addresss;
    }
public void setAddresss(java.util.Set<Address> addresss) {
        Address[] tempAddresss = (Address[]) getAddresss().toArray(new Address[getAddresss().size()]);
        for (Address address : tempAddresss) {
            removeFromAddresss(address);
        }
        if (addresss != null) {
            for (Address address : addresss) {
                addToAddresss(address);
            }
        }
    }
public void addToAddresss(Address address) {
        if (address != null) {
            address.setUser(this);
            getAddresss().add(address);
        }
    }
public void removeFromAddresss(Address address) {
        if (address != null) {
            address.setUser(null);
            getAddresss().remove(address);
        }
    }
public int hashCode() {
        int hashCode;
        if (id != null) {
            hashCode = 29 * id.hashCode();
        } else {
            hashCode = super.hashCode();
        }
        return hashCode;
    }
public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

       if (!(o instanceof User)) {
            return false;
        }
        final User otherUser = (User) o;
        if (hashCode() != otherUser.hashCode()) {
            return false;
        }
        return true;
    }
}

Eu só não gostei do nome das tabelas e campos gerados nas anotações, mas isto é fácil de costumizar, se abrirmos o jar, e editarmos o arquivo templates/JpaEntity.gtl (imagino que a extensão GTL signifique Groovy Template Language).

O template é básicamente código groovy misturado com strings, sempre que se quiser escrever código groovy, se marca o inicio e o fim com <% e %> respectivamente (como em uma JSP, mas sem as taglibs, e o código dentro dos marcadores é groovy e não Java), e quando se desejar apenas imprimir parte do texto, pode-se utilizar o mesmo marcador da EL do JSP (${ para inicio e } para fim), para se colocar código groovy que vai imprimir o texto desejado.


Acho que eles se inspiraram bastante no JET do Eclipse, que utiliza praticamente uma JSP para gerar código, com algumas tags definidas por eles mesmos.

O que eu acho que eles pretender fazer de errado:

  • Eles querem utilizar XML para configuração, sinceramente eu acho que ficaria muito melhor se utilizassem um Builder do Groovy
  • A estrutura de definir quais templates serão executados, e montagem do nome completo das classes/arquivos gerados esta muito engessada ainda, deveria ser mais flexível, por exemplo, com a estrutura atual, não é possível gerar uma JSP a partir de uma interface definida no diagrama.
  • Eles ainda não estão levando em conta os profiles da UML 2.0 para a geração de código, acho isto muito importante para qualquer ferramenta MDA.

Mas fora isto, acho que vale a pena dar uma olhada no progresso do projeto :D

Eles pretendem ainda criar um plugin para o maven para executar a geração de código, e uma task para ant, e para um futuro próximo, eles pretendem também criar um template completo para gerar uma aplicação grails (mais sobre grails aqui, aqui e aqui) a partir de um modelo UML.

E por falar em MDA, vocês estão utilizando MDA ou MDD por ai? usam os modelos UML apenas para definição e documentação?

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Tags: ,

Reader's Comments

  1. |

    Caro Urubatan, tentei seguir o exemplo passado e no console retorna um erro assim:
    C:\Users\neo\Desktop\Groovy>java -jar groovymda-1.0.jar ‘jar:file:./Teste.zargo!
    /Teste.xmi’
    java.net.MalformedURLException: no protocol: ‘jar:file:./Teste.zargo!/Teste.xmi’

    at java.net.URL.(Unknown Source)
    at java.net.URL.(Unknown Source)
    at java.net.URL.(Unknown Source)
    at net.sf.groovymda.GroovyMDA.loadModel(GroovyMDA.java:142)
    at net.sf.groovymda.GroovyMDA.processModel(GroovyMDA.java:75)
    at net.sf.groovymda.GroovyMDA.main(GroovyMDA.java:63)

    Venho procurando um plugin que anotasse minhas classes, mas esse promete fazer melhor, a partir de um modelo de classe o plugin gerar as classes anotadas, mas não consegui, me Ajuda.

    Reply to this comment
  2. |

    Tem que passar o caminho completo do arquivo para poder utilizar URLs que apontam para arquivos dentro de jars :D

    Reply to this comment
  3. |

    quer dizer, na verdade não precisa, eu testei aqui :(
    mas tente extrair o arquivo XMI a ver se funciona …

    Reply to this comment
  4. |

    Eu instalei o Argo e gerei o xmi, só nao passei o caminho completo, vou tentar

    Reply to this comment
  5. |

    passei assim C:\Users\neo\Desktop\Groovy>java -jar groovymda-1.0.jar ‘jar:file:C:\Users\neo\Desktop\Groovy\Teste.zargo!\Teste.xmi’ e nada, será que o groovymda tá danificado?

    Reply to this comment
  6. |

    Me fala como vc colocou ai..

    Reply to this comment
  7. |

    o comando que usei foi: java -jar groovymda-1.0.jar ‘jar:file:./teste.zargo!/teste.xmi’ teste
    sendo que o último “teste” é o nome do diretório onde criar as classes.

    Reply to this comment
  8. |

    Meu Caro, olha isso e fala o que tem de errado,
    C:\Groovy>java -jar groovymda-1.0.jar ‘jar:file:./Teste.zargo!/Teste.xmi’ Groovy

    java.net.MalformedURLException: no protocol: ‘jar:file:./Teste.zargo!/Teste.xmi’

    at java.net.URL.(Unknown Source)
    at java.net.URL.(Unknown Source)
    at java.net.URL.(Unknown Source)
    at net.sf.groovymda.GroovyMDA.loadModel(GroovyMDA.java:142)
    at net.sf.groovymda.GroovyMDA.processModel(GroovyMDA.java:75)
    at net.sf.groovymda.GroovyMDA.main(GroovyMDA.java:63)

    Reply to this comment
  9. |

    Desculpa tá sendo chato, tou até fazendo um plugin pra gerar os POJO’s managed beans e CRUDs em JSF, mas tb tou procurando alternativas..

    Reply to this comment
  10. |

    Urubatan, descobri, um detalhe sórdido, ao invés de rodar assim :
    C:\Groovy>java -jar groovymda-1.0.jar ‘jar:file:./Teste.zargo!/Teste.xmi’
    teria que rodar assim:
    C:\Groovy>java -jar groovymda-1.0.jar “jar:file:./Teste.zargo!/Teste.xmi”
    a diferença era apenas o plic, Obrigado pela ajuda.

    Reply to this comment
  11. |

    no linux funciona com aspas simples também :D

    Reply to this comment

Leave a Comment