Lançada a mais nova versão do framework que visa facilitar a persistência de objetos do apache Cassandra. Dentre as suas novidades está nas anotações, nessa versão estará usando as anotações do JPA. Outra novidade é o uso do recurso de JPQL, com isso se pode realizar querys com objetos e a ferramenta se encarregará de fazer a tradução para o Cassandra, para isso se utiliza a interface JCassandra que é estende de javax.persistence.Query. A expectativa é que aumentar ainda mais a produtividade para o desenvolvimento.

Listagem 1: exemplo usando o jpql no Easy-Cassandra


  JCassandra jCassandra=persistence.createJCassandra("select * from Person");
 List persons=jCassandra.getResultList();

Conforme dito acima as anotações foram adaptadas conforme mostra a tabela abaixo.

Easy-Cassandra 1.0.8 Easy-Cassandra 1.0.9 (Com JPA anotação)
org.easycassandra.annotations.ColumnFamilyValue javax.persistence.Entity
org.easycassandra.annotations.ColumnValue javax.persistence.Column
org.easycassandra.annotations.EmbeddedValue javax.persistence.Embedded
org.easycassandra.annotations.EnumeratedValue javax.persistence.Enumerated
org.easycassandra.annotations.KeyValue javax.persistence.Id
org.easycassandra.annotations.KeyValue equals true javax.persistence.GeneratedValue
org.easycassandra.annotations.IndexValue org.easycassandra.annotations.Index

tabela 1: relação entre as anotações da versão 1.0.8 e 1.0.9 com anotação jpa.

Também foi adicionado funcionalidade na anotação @Version do jpa, seu objetivo é verificar o tempo de inserção ou modificação do objeto.

Listagem 2: Usando a anotação version


@Entity(name = "autocount")
public class Count implements Serializable {
 
    private static final long serialVersionUID = 3L;
     
    @Id
    @GeneratedValue
    private BigInteger id;
     
   
    @Column(name = "name")
    private String name;
     
    @Version
    private Long timeStampLong;
 
    @Version
    private Date timeStampDate;
     
    @Version
    private Calendar timeStampCalendar;
 
//getter and setter
}

Para demonstrar novos recursos do framework será feito um exemplo de álbuns musicais que possa ser chamados em várias plataformas, para isso será usado web services. Para realizar esse exemplo será utilizado o java EE 6. Como o foco desse artigo não será o java EE 6, não entraremos em detalhes do mesmo. Após modelar e realizar as anotações com o jpa nossa classe ficará como mostra a listagem 3.

Listagem 3: classe com anotações jpa para o Easy-Cassandra


@XmlRootElement
@Entity
public class Album implements Serializable{
    
    @Id
    private Long id;
    
    @Column(name="nameOfAlbum")
    private String name;
    
    @Column  
    private String style;
    
    @Column
    private Calendar release;
    
    @Column
    private Double price;
    
    @Embedded
    private Artist artist;
//getter and setter
    }
@XmlRootElement
public class Artist implements  Serializable{
 
    /**
     * name of the artist
     */
    @Column(name="nameOfArtist")
    private String name;
    
    /**
     * was born
     */
    @Column
    private String country;
    
    @Enumerated
    private Sex sex;
//getter and setter
}

@XmlRootElement
public enum Sex {
    MALE,FAMALE
}

Uma vez pronta a classe de anotação o que será feito agora é recurso para o rest, uma coisa que vale salientar é que a inteface JCassandra estende da interface javax.persistence.Query, assim se pode estar a utilizando a interface Query (interessante para quem já está acostumado com o uso do jpa). Sendo que nem todas os métodos dessa interface estão implementados.

Assim realizando as chamadas com o novo recurso de jpql no Cassandra ficará de acordo mostra a tabela 5. Vale salientar como é feito para o Easy-Cassandra gerenciar a classe. Esse processo é realizado sem a necessidade do uso do xml, para isso é usado do método addFamilyObjec na Classe EasyCassandraManager. É necessário que a classe seja adicionada antes de se criar um jpql da respectiva classe. No nosso exemplo ele será feito na classe PersistenceManagement tão logo uma conexão para o cassandra for criada, como mostra a listagem 4.

Listagem 4: realizando um jpql no cassandra



@ApplicationScoped
public class PersistenceManagement {
    
   @Produces 
   private Persistence persistence;
      
  @Inject
    public void init(){
    persistence=EasyCassandraManager.getPersistence("javabahia", 
"localhost", 9160);
    
    EasyCassandraManager.addFamilyObject(Album.class);
    }     
}



@RequestScoped
public class PersistenceService {

@Inject    
 private Persistence persistence;
   
    public List findAllAlbum() {
        Query query=persistence.createJCassandra
           (" select * from Album");
        return query.getResultList();
    }

    public Album findById(Long id) {
        Query query=persistence.createJCassandra
           (" select * from Album where id =:id");
        query.setParameter("id", id);
        return (Album) query.getSingleResult();
        
    }

    public boolean save(Album album) {
      return  persistence.insert(album);
    }

    public void remove(Long id) {
        persistence.deleteByKeyValue(id, Album.class);
    }

    public String update(Long id, String name, 
    String style, Double price,String nameOfArtis,String country) {
       StringBuilder query=new StringBuilder();
     AuxQuery auxQuery=new AuxQuery();
       String conecion="";
       query.append("update Album set ");
       if(!isnull(name)){
           query.append(conecion);
           query.append(" name =:name ");
           auxQuery.updatable=true;
           conecion=" , ";
       }
       if(!isnull(style)){
       query.append(conecion);
           query.append(" style =:style ");
           auxQuery.updatable=true;
           conecion=" , ";
       }
       if(!isnull(price)){
           query.append(conecion);
           query.append(" price =:price ");
           auxQuery.updatable=true;
       }
       
         if(!isnull(country)){
       query.append(conecion);
           query.append(" artist.country =:country ");
           auxQuery.updatable=true;
           conecion=" , ";
       }
       if(!isnull(nameOfArtis)){
           query.append(conecion);
           query.append(" artist.name =:artist ");
           auxQuery.updatable=true;
       }
       
       query.append(" where id =:id ");
     
       if(!auxQuery.updatable){
            return "nothing is update";
       }
       
       Query jCassandra=persistence.createJCassandra(query.toString());
       
          if(!isnull(name)){
          jCassandra.setParameter("name", name);
       }
       if(!isnull(style)){
    
        jCassandra.setParameter("style", style);
       }
       if(!isnull(price)){
         jCassandra.setParameter("price", price);
       }
       if(!isnull(nameOfArtis)){
      
        jCassandra.setParameter("artist", nameOfArtis);
       }
       if(!isnull(country)){
         jCassandra.setParameter("country", country);
       }
      
       jCassandra.setParameter("id", id);
       return jCassandra.executeUpdate()==1?"executed with 
                                                sucess":" error in update ";
     
    }
   
    class AuxQuery{
      boolean updatable=false;
    
    }
    
    private boolean isnull(Object object){
    
        return object==null;
    }
    
}

Uma vez implementados as querys será feito agora as chamadas agora será criado o recurso conforme mostra a tabela 6.

Listagem 5: criando um servidor rest com o JAX-RS


@Path("/album")
@RequestScoped
public class AlbumResource {
   
     
@Inject    
 private PersistenceService persistenceService; 
 

@GET 
@Produces(MediaType.TEXT_XML)
 public List getProdutos() {
 return persistenceService.findAllAlbum();
 }
 
@Path("{id}")
@GET 
@javax.ws.rs.Produces(MediaType.TEXT_XML)
public Album getAlbum(@PathParam("id") long id) {
    return persistenceService.findById(id);
}

@Path("update/{id}")
@GET 
@javax.ws.rs.Produces(MediaType.TEXT_PLAIN)
public String updateAlbum(@PathParam("id") Long id ,@QueryParam("name") 
String name,@QueryParam("style") String style,@QueryParam("price") 
Double price,@QueryParam("artist") String nameOfArtis,@QueryParam("country") 
String country) {

    return persistenceService.update(id,name,style,price,nameOfArtis,country);
}
    
    
@POST 
@Consumes(MediaType.TEXT_XML)
@Produces(MediaType.TEXT_PLAIN)
public String addAlbum(Album album) {
    boolean sucess=persistenceService.save(album);
    if(sucess){
    return album.getName() + " added!";
    }
   return album.getName() + " not added!";
}



@Path("{id}") 
@DELETE
@Produces(MediaType.TEXT_PLAIN)
public String removeAlbum(@PathParam("id") Long id) {
    persistenceService.remove(id);
    return "Album removed."; 
}
    
 
}


Uma das maneiras de se realizar os testes é utilizando o poster, um plugin para o firefox, que estará disponível nos links. Com ele se poderá realizar todos os testes, inclusive aqueles que envolvam o post e remove. É possível realizar alguns testes já no navegador:

http://localhost:8080/AlbumServer/resources/album/ Lista de álbum
http://localhost:8080/AlbumServer/resources/album/1 Lista o álbum com o id 1
http://localhost:8080/AlbumServer/resources/album/n Lista o álbum com o id N
http://localhost:8080/AlbumServer/resources/album/update/12?name=%20Nome%20do%20Album&country=Brazil&style=Eletronic&price=23&artist=me Insere ou atualiza um álbum com id igual a 12 com o nome, país Brasil, estilo eletrônico, preço 23 e o artista eu

Tabela 2: Exemplos de serviços com o rest

Com isso foi demonstrado as novidades da nova versão do Easy-Cassandra, versão 1.0.9, que visa facilitar a vida do desenvolvedor. Foi demonstrado as mudanças para anotações típicas do jpa, novo recurso que recupera o timestamp da linha além do uso do JPQL por parte do framework. Muito ainda se tem de melhorar na ferramenta, mas com ajuda da comunidade isso será possível.

Link:

Exemplo servidor rest (AlbumServerRest.rar): https://github.com/otaviojava/Easy-Cassandra/downloads

Poster Plugin Firefox: https://addons.mozilla.org/en-US/firefox/addon/poster/

Easy-Cassandra: https://github.com/otaviojava/Easy-Cassandra/

Download o código e a documentação para a versão 1.0.9 ( documento 03): https://github.com/otaviojava/Easy-Cassandra/downloads