[JNoSQL] Começando com Diana API de Colunas

Umas das API que existem no Diana, camada de comunicação do JNoSQL, é a camada de família de colunas. O objetivo desse artigo é falar rapidamente sobre essa API para esse tipo de banco de dados.

No nosso caso será utilizado o Cassandra, assim:

<dependency>
  <groupId>org.jnosql.diana</groupId>
  <artifactId>cassandra-driver</artifactId>
  <version>0.0.1</version>
</dependency>

p.s: Atualmente é necessário adicionar o repositório do JNoSQL para ter acesso as suas dependências:

<repositories>
  <repository>
    <id>jnsoql-repo</id>
    <name>JNoSQL Maven Repository</name>
    <url>https://dl.bintray.com/jnosql/maven/</url>
    <layout>default</layout>
  </repository>
</repositories>


As classes da API de documento seguem a seguinte estrutura:

  • ColumnConfiguration: Classe responsável pela configuração e conexão com o banco de dados, uma vez esse setup varia fortemente em cada banco de dados. Ela costuma ter formato variável
  • ColumnManagerFactory: classe responsável pela criação de uma interface Manager
  • ColumnManager: assim como no JPA, essa classe é a responsável pelo gerenciamento da entidade.
  • ColumnEntity: uma entidade de uma família de colunas
  • Column: Um ColumnEntity é composto por diversas colunas, ele é composto por uma tupla em que a chave é o nome e o valor é a informação propriamente dita. Essa informação poderá ser qualquer valor, variando de cada driver, inclusive uma coluna ou subcoluna.

 

Com o driver do Cassandra é possível realizar o CRUD de maneira simples:

public class App {

    public static final String KEY_SPACE = "newKeySpace";
    public static final String COLUMN_FAMILY = "newColumnFamily";

    public static void main(String[] args) {

        ColumnConfiguration condition = new CassandraConfiguration();

        try(ColumnFamilyManagerFactory managerFactory = condition.get()) {
            ColumnFamilyManager columnEntityManager = managerFactory.get(KEY_SPACE);
            ColumnEntity entity = ColumnEntity.of(COLUMN_FAMILY);
            Column id = Column.of("id", 10L);
            entity.add(id);
            entity.add(Column.of("version", 0.001));
            entity.add(Column.of("name", "Diana"));
            entity.add(Column.of("options", Arrays.asList(1, 2, 3)));

            columnEntityManager.save(entity);

            ColumnQuery query = ColumnQuery.of(COLUMN_FAMILY);
            query.and(ColumnCondition.eq(id));
            Optional<ColumnEntity> result = columnEntityManager.singleResult(query);
            System.out.println(result);

        }


    }
}

Vale salientar que é necessário existir um banco Cassandra instalado e rodando. Com o Cassandra é necessário também informar o IP para que o Diana consiga se conectar. Para isso, é necessário o arquivo diana-cassandra.properties no classpath, além do IP é possível configurar a estrutura inicial utilizando o CQL, Cassandra query language. Assim, ele terá as informações dos bancos que serão conectados. No nosso, exemplo:

cassandra-hoster-1=172.17.0.2
cassandra-threads-number=4
cassandra-initial-query-1=CREATE KEYSPACE IF NOT EXISTS newKeySpace WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};
cassandra-initial-query-2=DROP TABLE IF EXISTS newKeySpace.newColumnFamily;
cassandra-initial-query-3=CREATE COLUMNFAMILY IF NOT

Tip: uma maneira simples de instalar o Cassandra é utilizando o docker:
https://hub.docker.com/_/cassandra/

Especializações

O Cassandra possui recurso que irão além da simples API, recursos como nível de consistência e também o CQL.

public class CassandraApp {


    public static final String KEY_SPACE = "newKeySpace";
    public static final String COLUMN_FAMILY = "newColumnFamily";

    public static void main(String[] args) {

        CassandraConfiguration condition = new CassandraConfiguration();

        try(CassandraDocumentEntityManagerFactory managerFactory = condition.get()) {
            CassandraColumnFamilyManager columnEntityManager = managerFactory.get(KEY_SPACE);
            ColumnEntity entity = ColumnEntity.of(COLUMN_FAMILY);
            Column id = Column.of("id", 10L);
            entity.add(id);
            entity.add(Column.of("version", 0.001));
            entity.add(Column.of("name", "Diana"));
            entity.add(Column.of("options", Arrays.asList(1, 2, 3)));

            columnEntityManager.save(entity);

            //common implementation
            ColumnQuery query = ColumnQuery.of(COLUMN_FAMILY);
            query.and(ColumnCondition.eq(id));
            List&ltColumnEntity&gt columnEntities = columnEntityManager.find(query, ConsistencyLevel.LOCAL_QUORUM);

            //cassandra implementation
            columnEntityManager.save(entity, ConsistencyLevel.THREE);
            List&ltColumnEntity&gt entities = columnEntityManager.cql("select * from newKeySpace.newColumnFamily");
            CassandraPrepareStatment cassandraPrepareStatment = columnEntityManager.nativeQueryPrepare("select * from newKeySpace.newColumnFamily where id ?");
            List&ltColumnEntity&gt entityList = cassandraPrepareStatment.bind(10L).executeQuery();
            System.out.println(entities);

        }


    }

}

Com isso concluímos o artigo falando da camada de comunicação do projeto JNoSQL para colunas.

Referências:

MicroProfile 1.0

micro-profile-logo

O termo microsserviço, no mundo do desenvolvimento de software, se tornou um termo muito popular. Assim, diversos artigos e diversas ferramentas vem surgindo relacionado a esse tópico. No mundo Java, o Spring vem discutindo sobre esse tópico principalmente após a versão 4.0 e o Spring Boot. Porém, essa é a única solução existente? A resposta é não, recentemente foi lançado uma nova ferramenta no mundo Java, o MicroProfile, e esse foi um dos tópicos mais comentados no JavaOne 2016.

Existem diversos termos e pontos de vista em relação ao o que significa microsserviço. Segundo o Henrique Lobo o microsserviço é: mais uma solução para o problema do alto acoplamento em aplicações corporativas. A diferença é que desta vez estamos atacando aplicações monolíticas.

Ou seja, de uma maneira geral o microsserviço é o oposto de uma arquitetura monolítica, que visualiza a aplicação como um único componente. Uma vez que o componente é a menor unidade dentro do software que pode ser substituída de forma independente. A arquitetura monolítica trabalha numa aplicação com um único componente, ou seja, em termo de escalabilidade caso seja necessário crescer a aplicação, é necessário criar uma instância de todo o componente. Porém, sua arquitetura é mais simples, um grande desafio do microsserviço é separar a aplicação em uma menor unidade, uma separação errônea significa um grande desastre na vida de uma aplicação.

Uma vez conseguindo separar um software em menor componentes ou serviços (o serviço seria um tipo de componente especial que realiza a comunicação utilizando mecanismo remoto como webservice). O microsserviço tem algumas vantagens:

  • Consegue entregar novos recursos mais rapidamente, uma vez que apenas o componente que foi alterado precisará ser atualizado.
  • Com componentes menores, os times também podem ser, seguindo o estilo e a metodologia ágil.
  • A escalabilidade se torna mais simples, no caso, caso o serviço A precise escalar, é necessário apensar que tenha mais uma instância desse recurso A.

Uma vez definido, rapidamente, os conceitos ao redor de aplicações de microsserviços, aplicações monolíticas, componentes, etc. O próximo passo desse post é falar um pouco sobre a iniciativa do MicroProfile.


Q&A MicroProfile

O que é Microprofile?

O Microprofile é uma iniciativa formada por alguns fornecedores Java EE (Red Hat, Payara, Tomitribe, IBM) e Java User Groups (SouJava e London Java Community) cujo o principal objetivo é trazer inovações do microsserviços ao redor ou próximo do mundo Java EE. Atualmente, os servidores, com o comportamento lazy, e as tecnologias elas estão prontas para aplicações de microsserviços, porém, a ideia é tornar a experiência ainda melhor.

microprofile-logos

O seu propósito é bastante simples:

  • Ser um ambiente simples para iterar, testar, inovar e principalmente falhar rapidamente.
  • Após testes, experiência chegar em um comum acordo entre todos.
  • Uma vez, nesse comum acordo e um código estável o próximo passo, e o último, é o processo de padronização.

micro-profile-process

E o Java EE?

O Java EE continua sendo uma série de especificações ou guarda-chuva de especificações bem definidas cujo o foco principal são aplicações focadas ao mundo Web. O Java EE em sua sexta versão trouxe um grande número de novidades, principalmente com o CDI, e sua versão atual, a sétima versão, trouxe ainda mais novidades e melhorias nos recursos existentes.

A próxima versão está sendo trabalhada sob a JSR 366 no qual o líder da especificação é a Oracle.

microprofile-java-ee-road-map

MicroProfile é Java EE?

Não, apesar do envolvimento de diversos fornecedores do mundo Java EE o MicroProfile não é e não tem nada relacionado com o mundo Java EE. Como foi dito previamente, a Oracle é a líder da especificação do Java EE e detentora da sua propriedade intelectual, assim apenas ela pode definir o que é Java EE ou não. Da mesma forma que o CDI a Red Hat é líder da especificação. O fato do MicroProfile utilizar algumas especificações do mundo Java EE não o remete a um proflie do Java EE, do contrário, uma vez que o Spring suporte algumas especificações ele também o seria.

JCP e MicroProfile?

Apesar da exaustiva tentativa de comprar o JCP com todos e qualquer movimento Java, são movimentos totalmente diferentes. O JCP é focado em padrão e o MicroProfile a ideia é que seja um local para inovação. Inovação é o primeiro passo para um padrão, é necessário testar, experimentar e caso seja um sucesso padronizar. Afinal, como padronizar algo que não existe ainda? Faria sentido padronizar a internet na idade média?

Essa resposta também é válida para os framworks do Spring, o JCP não tem nenhuma posição contra o Spring, afinal, eles são muito importantes dando esse primeiro passo, a inovação. Inclusive vários membros do mundo Spring participaram e participam das JSRs, especificação Java, é o caso da JSR 330 que teve a participação do Rod Johnson, conhecido mundialmente como o pai do Spring.

Uma informação importante é que boa parte das instituições que começaram o MicroProfile faz parte do Comitê executivo do JCP.

A ideia do MicroProfile é ser um subset do Java EE?

Não. Como foi dito previamente, o Java EE é uma umbrela de especificação, ou seja, algo estável e fora do mundo de inovação. Além do problema de apenas a Oracle como Spec Leader definir o que é Java EE ou não. Por exemplo, umas das ideias é que nas próximas versões do MicroProfile o Jcache, JSR 107, fazer parte do MicroProfile e essa especificação não está presente no full profile do Java EE 7 e nem se tem previsão de se adicionar essa especificação na próxima versão do Java EE.

JCP + Microprofile

Uma vez bem detalhado os papéis de cada organização/iniciativa, uma para padrão e outro para inovação. Ambos tem algo em comum: O feedback contínuo da comunidade.

O último passo do processo do Microprofile é definir padrões e nesse passo será um trabalho em conjunto com o JCP. Vale lembrar que o padrão traz algumas vantagens:

  • A escolha do fornecedor e/ou escolha da implementação
  • Portabilidade da aplicação
  • Retrocompatibilidade
  • Uma vez estável, reduz o risco do projeto

MicroProfile 1.0

Lançado na proximidade do JavaOne 2016 a versão 1.0 do microprofile vem com três recursos:

  • JAX-RS: Java API for RESTful Web Services (JAX-RS) uma API especificada que traz suporte para a criação de serviços REST.
  • CDI: Contexts and Dependency Injection ferramente especificada para injeção de dependência com contexto.
  • JSON-P: Uma API especificada para realizar parse, gerar, transformar e buscar JSON.

Próximos passos

roadmap-microprofile

Uma vez lançada a sua primeira versão os próximos passos estão em mover para uma fundação e o trabalho para a versão 1.1 do MicroProfile. A ideia original é que seja lançado uma versão a cada seis meses. O backlog para as próximas versões está vasto.

  • Container API
  • Microservic-y annotations (Ex: @CircuitBreaker)
  • Testing
  • Distributed Logging
  • Distributed Tracing
  • OAuth2/OpenID Connect
  • Microservice Security
  • Service Discovery
  • Health Check
  • Configuration
  • Metrics/Monitoring
  • WebSockets
  • JSON-B
  • Bean Validation
  • JPA
  • JTA
  • Concurrency Utilities for Java EE
  • Messaging / Eventing
  • Asynchronous/Reactive Support / Patterns
  • Integration with Reactive / Eventing systems
  • Big Data/NoSQL strong & weak consistency support
  • NetFlix OSS Integration
  • JCache
  • JDK 8 Lambda+Streams
  • EJB Lite
  • Servlets
  • HTTP/2
  • Startup Time
  • Disk Space
  • Memory
  • Uber-jar
  • Java 9 Modularity

JCP é lento em relação ao MicroProfile

Tal comparação não faz sentido algum! Como foi explicado, previamente, são organizações de propósito totalmente diferente. Comparar o JCP só faz sentido se for para outro órgão de padronização como o W3C com o HTML 5, começou o seu trabalho em 2004 e até o presente momento nenhum navegador dá suporte total ao Html 5.

Show me the Code

Dentro do organization do github do microprofile existe alguns exemplos de código o mais recente foi o exemplo utilizado no JavaOne, o microprofile-conference. Porém, também será criado uma simples aplicação demo utilizando microprofile, cujo a implementação será o tomee e maven.

Essa aplicação será realmente simples:

Será um serviço de votos, basicamente, dado uma pergunta a API permitirá uma resposta com sim ou não, sim será algo bem simples já que o principal objetivo é criar um simples serviço.

O primeiro passo é a criação do contador de voto, basicamente ele terá um contador para sim e outro para não, esse recurso terá único para toda aplicação, ou seja, um escopo de aplicação.

@ApplicationScoped
public class VoteCounter {

private final AtomicInteger yes = new AtomicInteger();

private final AtomicInteger no = new AtomicInteger();

public void voteYes() {
yes.incrementAndGet();
}

public void voteNo() {
no.incrementAndGet();
}

public Map<String, Integer> getResult() {
Map<String, Integer> votes = new HashMap<>();
votes.put("yes", yes.get());
votes.put("no", no.get());
return votes;
}
}

Após criar o contador o próximo passo é criar a API para exibir esse recurso.

@ApplicationScoped
@Path("votes")
@Produces(MediaType.APPLICATION_JSON)
public class VoteResource {

@Inject
private VoteCounter voteCounter;

@GET
@Path("question")
public String getQuestion() {
return "Did you like the post?";
}

@POST
@Path("/yes")
public void voteYes() {
voteCounter.voteYes();
}

@POST
@Path("/no")
public void voteNo() {
voteCounter.voteNo();
}

@GET
public Map<String, Integer> getResult() {
return voteCounter.getResult();
}
}

Após feito o código, o próximo passo são os códigos de configuração. Com o JAXRS, definir o caminho que serve como base de todos os URI.

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/resource")
public class ApplicationConfiguration extends Application {
}

Também tem as configurações do web descriptor e do beans.xml para o CDI. Até o momento nada diferente tanto em código quanto em configuração que o desenvolvedor Java EE conhece.

Olhando para o arquivo de configuração do maven, o pom.xml, além de definir a API do Java EE 7 como provida é adicionado um plugin para o tomee:

  • O parâmetro tomeeClassifier define o profile do tomee que será selecionado. Os tipos disponíveis são: webprofile, plus, plusme
  • O parâmetro context define o nome do contexto.

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.soujava</groupId>
    <artifactId>microprofile-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>microprofile-demo</name>

    <url>https://soujava.org.br/</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.ee.version>7.0</java.ee.version>
        <java.se.version>1.8</java.se.version>
        <version.tomee>7.0.1</version.tomee>
        <version.jackson>2.8.2</version.jackson>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>${java.ee.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${version.jackson}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-json-provider</artifactId>
            <version>${version.jackson}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.se.version}</source>
                    <target>${java.se.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.0.0</version>
            </plugin>
            <plugin>
                <groupId>org.apache.tomee.maven</groupId>
                <artifactId>tomee-maven-plugin</artifactId>
                <version>${version.tomee}</version>
                <configuration>
                    <tomeeClassifier>webprofile</tomeeClassifier>
                    <context>${project.artifactId}</context>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

Feito isso basta empacotar e em seguida executar o exemplo com os seguintes comandos:

  • mvn clean package tomee:exec -DskipTests
  • java -jar target/microprofile-demo-1.0-SNAPSHOT-exec.jar

Com isso temos os seguintes recursos:

 

Assim, concluímos o material sobre essa novidade para o mundo dos frameworks para microsserviços.

Referências:

O que é arquitetura baseada em micro serviços?

http://www.itexto.net/devkico/?p=1755

Microservices for Java Developers: A Hands-On Introduction to Frameworks and Containers.: http://developers.redhat.com/promotions/microservices-for-java-developers/
Arquitetura de microserviços ou monolítica?

http://blog.caelum.com.br/arquitetura-de-microservicos-ou-monolitica/

Microservices

http://martinfowler.com/articles/microservices.html

Java EE 7 spec:

https://java.net/downloads/javaee-spec/WebProfile.pdf

MicroProfile Site:

http://microprofile.io/

Código exemplo:

https://github.com/soujava/microprofile-demo