Dicas e considerações iniciais ao usar o Cassandra
7 de Abril de 2014, 23:42 - sem comentários ainda
Easy-Cassandra, a versão 2.0.1
13 de Fevereiro de 2014, 22:35 - sem comentários aindaLançada a nova versão do Easy-Cassandra, a versão 2.0.1, dentre as novidades podemos citar;
- Refatoração nos contrutores das fábricas de sessão
- QueryBuilder (InsertBuilder, UpdateBuilder, DeleteBuilder, SelectBuilder e BatchBuilder)
- Maior velocidade na leitura e escrita
- Suporte nos processos assíncronos
- Maior suporte ao Cassandra com Spring-Data
ClusterInformation clusterInformation = ClusterInformation.create()Criando configuração para a fábrica de conexão
.addHost(HOST)
.withDefaultKeySpace(KEY_SPACE).withUser(USER).withPassword(PASS);
easyCassandraManager = new EasyCassandraManager(clusterInformation);
Dessa forma a configuração para usar o Spring no Cassandra também mudou para:
Nova configuração do Spring no Easy-Cassandra
localhost
org.easycassandra.persistence.cassandra.spring.entity.Contact
org.easycassandra.bean.model.Step
org.easycassandra.bean.model.Weight
Talvez a melhoria mais marcante nessa versão são os recursos dos QueryBuilders, os queryBuilders são maneiras muito mais fácil de fazer interações com o Cassandra com configurações adversas de uma maneira mais simples, com ele é possível definir o nível de consistência, definir o timeStamp, quais campos serão manipulados.
SimpleID id = new SimpleID();Simples exemplo inserindo valores a partir da chave
id.setIndex(ONE_HUNDRED_THIRTY);
id.setKey(ONE_HUNDRED_THIRTY);
UpdateBuilder update = template.updateBuilder(SimpleQueryBuilder.class, key);
update.put("map", "name", "otavioMap").value("value", TEN_DOUBLE).execute();
UpdateBuilder update = persistence.updateBuilder(SimpleQueryBuilder.class);criando toda a query de atualização
update.whereEq(Constant.KEY, Constant.ONE).whereEq(Constant.INDEX, Constant.ONE).addList("list", "otavioList").execute();
UpdateBuilder update = persistence.updateBuilder(SimpleQueryBuilder.class);executando uma atualização assincronamente
update.whereEq(Constant.KEY, Constant.ONE).whereEq(Constant.INDEX, Constant.ONE).value("value", 12D).executeAsync(new ResultAsyncCallBack() {
@Override
public void result(Boolean bean) {
// do some action
}
});
InsertBuilder insert= persistence.updateBuilder(SimpleQueryBuilder.class);Realizando inserção
Set set = new HashSet<>();
set.add("Linda");
Map map = new HashMap<>();
map.put("love", "Otavio and Poliana");
insert.value(Constant.KEY, Constant.ONE_HUNDRED).value(Constant.INDEX,
Constant.ONE_HUNDRED).value(Constant.LIST_COLUMN, Arrays.asList("Poliana", "Otavio", "Love")).value(Constant.SET_COLUMN, set).value("map", map).execute();
SimpleID id = new SimpleID();realizando inserção de modo assíncrono
id.setIndex(ONE_HUNDRED_TWO);
id.setKey(ONE_HUNDRED_TWO);
SimpleBean simpleBean = new SimpleBean();
simpleBean.setId(id);
simpleBean.setValue(VALUE);
InsertBuilder insert2 = persistence.updateBuilder(simpleBean);
insert2.executeAsync((new ResultAsyncCallBack() {
@Override
public void result(Boolean bean) {
// do some action
}
});
DeleteBuilder delete = persistence.deleteBuilder(SimpleQueryBuilder.class);primeira query remove todas as colunas a partir da chave, na segunda query remove apenas os campos map, list e set.
delete.whereEq(Constant.INDEX, ONE_HUNDRED_TWO).whereEq(Constant.KEY, ONE_HUNDRED_TWO).execute();
DeleteBuilder delete2 = persistence.deleteBuilder(SimpleQueryBuilder.class,"map", "list", "set"); //Delete specific columns
delete2 .whereEq(Constant.INDEX, ONE_HUNDRED_TWO).whereEq(Constant.KEY, ONE_HUNDRED_TWO).execute();
SimpleID id = new SimpleID();remoção assíncrona
id.setIndex(ONE_HUNDRED_TWO);
id.setKey(ONE_HUNDRED_TWO);
DeleteBuilder delete2 = persistence.deleteBuilder(SimpleQueryBuilder.class, id);
delete2.executeAsync((new ResultAsyncCallBack() {
@Override
public void result(Boolean bean) {
// do some action
}
});
SelectBuilder select = persistence.selectBuilder(SimpleQueryBuilder.class);Realizando o select em que o campo nome é igual a nome e o indice está em um, dois e três.
select.eq("name", "name");
select.in("index", ONE, TWO, THREE);
List result = select.execute();
SelectBuilder select = persistence.selectBuilder(SimpleQueryBuilder.class);Executando query assincronamente em que o indece seja mais que três e seja ordenado de forma descendente no índice.
select.eq(NAME, NAME).gt("index", THREE).asc(INDEX).executeAsync(new ResultAsyncCallBack>() {
@Override
public void result(List beans) {
// do some thing
}
});
O Batch é um recurso no cassandra que permite que se execute alterações no banco (inserção, atualização e remoção) de forma atômica, desse forma se pode enviar insert, updates e deletes como se fosse apenas uma requisição.
DeleteBuilder delete = dao.deleteBuilder();Executando processo de inserção, remoção e atualização de forma atômica com o BatchBuilder.
delete.whereEq(Constant.INDEX, Constant.ONE_HUNDRED_TWO)
.whereEq(Constant.KEY, Constant.ONE_HUNDRED_TWO);
InsertBuilder insert = dao.insertBuilder();
insert.value(Constant.KEY, Constant.ONE_HUNDRED).value(Constant.INDEX,
Constant.ONE_HUNDRED);
insert.value(Constant.LIST_COLUMN,
Arrays.asList("Poliana", "Otavio", "Love"));
UpdateBuilder update = dao.update();
update.whereEq(Constant.KEY, Constant.ONE).whereEq(Constant.INDEX, Constant.ONE);
update.addList("list", "otavioList");
BatchBuilder batchBuilder = dao.batchBuilder();
batchBuilder.addOperations(delete, insert, update);
batchBuilder.executeAsync(new ResultAsyncCallBack() {
@Override
public void result(Boolean bean) {
// do some action
}
});
Vale lembrar que recurso do Batch deve ser usados em casos específicos, já que distribuir as requisições entre os nós, no cassandra, sempre será sua melhor amiga.
Esse artigo tem como objetivo ilustrar as mudanças dentro do Easy-Cassandra, se demonstrou dos recursos e da sua melhoria na velocidade a expectativa é que muitos mais recursos estejam por vir.
- https://github.com/otaviojava/Easy-Cassandra/wiki/Builders
- https://github.com/otaviojava/Easy-Cassandra/wiki
- https://github.com/otaviojava/Easy-Cassandra/
- https://github.com/otaviojava/Easy-Cassandra-samples
Como compilar código Java dinâmicamente
29 de Janeiro de 2014, 22:56 - sem comentários aindaO Java é uma plataforma que se multiplicou exponencialmente, uma de sua grande vantagem é o fato de que você consegue com o mesmo código executar em diferentes plataformas, com isso se pode programar para servidor, dispositivos embarcados, desktop, etc. com a mesma linguagem. Além disso a JVM possui suporte para diversas linguagens, das quais possuem, diversas características e recursos interessantes. Um mito que existe é que o Java não compila em tempo de execução, o que faz muitas pessoas utilizem uma linguagem dinâmica, apenas por esse objetivo, mas será que isso é verdade?
Possuir uma linguagem dinâmica é muito interessante para alguns projetos específicos, por exemplo, quando se faz um projeto que realiza calculo tributário, como essa fórmula mudam muito ao ano e variam de município para município, nesse caso é melhor que o código fonte esteja em um banco de dados, por exemplo, para quando for necessário modificar o calculo não seja necessário compilar todo o código fonte e fazer o deploy, correndo o risco do sistema ficar fora do ar mesmo que por alguns instantes.
Sim é possível em Java compilar códigos dinamicamente. Na verdade isso é muito comum do que imaginamos! Por exemplo, o Hibernate para gerenciar das entidades, para facilitar ainda o seu uso a partir da versão 1.6 com a JSR 199 foi criada um API com essa finalidade.
Para demonstrar essa funcionalidade será usado a solução para o problema acima, fazer com que haja troca de fórmula, para facilitar a demonstração e focar na solução serão as 4 operações básicas, sendo que esse código fonte estará no banco de dados, no caso será simulado com arquivos dentro de um txt. Como não podemos referenciar uma classe não compilada, criaremos uma interface Operação, ela será implementada por nossas classes que estarão em nosso “banco de dados”.
public interface Calculo {
Double calcular(Number valorA, Number valorB);
}
Interface na qual será utilizada como referencias as classes compiladas dinamicamente.
Explicando o processo de compilação passo a passo: A classe JavaCompiler, que tem a responsabilidade de fazer a compilação do código-fonte. A chamada ToolProvider.getSystemJavaCompiler() retorna este objeto. Se um compilador Java não estiver disponível, o retorno será null. Ele conta com o método getTask(), que retorna um objeto CompilationTask. De posse desse objeto, a chamada call() efetua a compilação do código e retorna um booleano indicando se ela foi feita com sucesso (true) ou se houve falha (false).
public class JavaDinamicoCompilador {
private JavaCompiler compiler;
private JavaDinamicoManager javaDinamicoManager;
private JavaDinamicoClassLoader classLoader;
private DiagnosticCollector diagnostics;
public JavaDinamicoCompilador() throws JavaDinamicoException {
compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
throw new JavaDinamicoException("Compilador não encontrado");
}
classLoader = new JavaDinamicoClassLoader(getClass().getClassLoader());
diagnostics = new DiagnosticCollector();
StandardJavaFileManager standardFileManager = compiler
.getStandardFileManager(diagnostics, null, null);
javaDinamicoManager = new JavaDinamicoManager(standardFileManager, classLoader);
}
@SuppressWarnings("unchecked")
public synchronized Class compile(String packageName, String className,
String javaSource) throws JavaDinamicoException
{
try {
String qualifiedClassName = JavaDinamicoUtils.INSTANCE.getQualifiedClassName(
packageName, className);
JavaDinamicoBean sourceObj = new JavaDinamicoBean(className, javaSource);
JavaDinamicoBean compiledObj = new JavaDinamicoBean(qualifiedClassName);
javaDinamicoManager.setSources(sourceObj, compiledObj);
CompilationTask task = compiler.getTask(null, javaDinamicoManager, diagnostics,
null, null, Arrays.asList(sourceObj));
boolean result = task.call();
if (!result) {
throw new JavaDinamicoException("A compilação falhou", diagnostics);
}
Class newClass = (Class) classLoader.loadClass(qualifiedClassName);
return newClass;
}
catch (Exception exception) {
throw new JavaDinamicoException(exception, diagnostics);
}
}
}
Classe responsável pela compilação
O processo de compilação envolve dois tipos de arquivos: os códigos-fonte escritos em Java e os arquivos compilados (bytecodes). Na Compiler API estes arquivos são representados por objetos de uma única interface, chamada JavaFileObject. Felizmente a API disponibiliza uma classe que implementa esta interface, chamada SimpleJavaFileObject e, na escrita de código de compilação dinâmica, deve-se criar uma subclasse de SimpleJavaFileObject e sobrescrever os métodos necessários.
public class JavaDinamicoBean extends SimpleJavaFileObject {
private String source;
private ByteArrayOutputStream byteCode = new ByteArrayOutputStream();
public JavaDinamicoBean(String baseName, String source) {
super(JavaDinamicoUtils.INSTANCE.createURI(JavaDinamicoUtils.INSTANCE.getClassNameWithExt(baseName)),
Kind.SOURCE);
this.source = source;
}
public JavaDinamicoBean(String name) {
super(JavaDinamicoUtils.INSTANCE.createURI(name), Kind.CLASS);
}
@Override
public String getCharContent(boolean ignoreEncodingErrors) {
return source;
}
@Override
public OutputStream openOutputStream() {
return byteCode;
}
public byte[] getBytes() {
return byteCode.toByteArray();
}
}
Estrutura de dados que contem o codigo fonte e a classe compilada
Para representar os arquivos envolvidos será utilizado o ForwardingJavaFileManager que implementa a interface JavaFileManager.
public class JavaDinamicoManager extends ForwardingJavaFileManager {
private JavaDinamicoClassLoader classLoader;
private JavaDinamicoBean codigoFonte;
private JavaDinamicoBean arquivoCompilado;
public JavaDinamicoManager(JavaFileManager fileManager, JavaDinamicoClassLoader classLoader)
{
super(fileManager);
this.classLoader = classLoader;
}
public void setSources(JavaDinamicoBean sourceObject, JavaDinamicoBean compiledObject) {
this.codigoFonte = sourceObject;
this.arquivoCompilado = compiledObject;
this.classLoader.addClass(compiledObject);
}
@Override
public FileObject getFileForInput(Location location, String packageName,
String relativeName) throws IOException
{
return codigoFonte;
}
@Override
public JavaFileObject getJavaFileForOutput(Location location,
String qualifiedName, Kind kind, FileObject outputFile)
throws IOException
{
return arquivoCompilado;
}
@Override
public ClassLoader getClassLoader(Location location) {
return classLoader;
}
}
Classe responsável por gerenciar as classes compiladas e não compiladas
Para que ela possa ser utilizada, a JVM deve ser capaz de reconhecê-la como uma classe da aplicação, a fim de que possa carregá-la quando chegar o momento. O componente responsável pelo carregamento das classes das aplicações Java durante a execução é o Class Loader.
Portanto, para que a JVM saiba da existência das novas classes compiladas, é necessário implementar um class loader customizado, que fica atrelado ao gerenciador de arquivos.
Ele deve estender a classe ClassLoader (do pacote java.lang) e tem a responsabilidade de carregar as classes recém-criadas.
Com isso foi discutido um pouco sobre a compilação dinâmica do Java no Java, objetivo aqui foi apenas de demonstrar o seu funcionamento básico além de uma pequena explicação do uso da API. Pela sua complexidade o ideal é que ela esteja encapsulado a ponto de ser utilizadas várias vezes em diversos projetos. O objetivo aqui não foi desmerecer em nenhum momento as outras linguagens de programação rodando ou não em cima da JVM, afinal todas elas têm sua importância. O objetivo foi demonstrar que não existe a necessidade de mudar de linguagem caso seu problema seja ter um código que seja compilado dinamicamente.
Referências:
- https://www.jcp.org/en/jsr/detail?id=199
- Carlos Eduardo Gusso Tosin, Compilação Dinâmica no Java 6 - Revista Java Magazine 94
- Código: https://github.com/otaviojava/java_dinamico
Cassandra Trip Brasil [Agradecimentos]
3 de Outubro de 2013, 2:55 - sem comentários ainda
O evento Cassandra aconteceu entre os dias 2 e 6 de setembro com o objetivo de falar dos conceitos de nosql, bigdata, do cassandra e da sua arquitetura além das novidades com a nova versão, o Cassandra 2.0. O evento foi um sucesso, com isso, gostaríamos de agradecer todos que participaram e ajudaram o evento de alguma forma.
Para saber mais sobre o Cassandra, trocar experiência e tirar dúvidas técnicas ou conceituais foi criado o grupo Cassandra Trip Brasil, para mais informações aqui.
Slides utilizados no evento:
Existirá uma próxima atividade para o Cassandra que é o um mini-curso gratuito de Cassandra. No dia 10 de outubro, quinta-feira, na Global Code.
Título: Primeiros passos com o Cassandra
Descrição: O Cassandra é um banco de dados NOSQL orientado à família de coluna que nasceu para resolver problemas com aplicações que precisam operar com gigantescas cargas de dados além de poder escalar com grande facilidade. Ele nasceu no facebook e hoje vem sendo usado intensamente por empresas dos mais variados portes, tais como Netflix, Twitter, Instagram, HP, IBM, dentre muitas outras. Um fator importante que vale ser citado é a sua adoção crescente inclusive em mercados mais conversadores tais como, instituições financeiras e agências governamentais como a NASA.
Público alvo: Desenvolvedores, DBAs, entusiastas com curiosidade de conhecer mais sobre bancos de dados nosql e o banco Cassandra.
Ementa:
- Conceito Data Science
- Conceito BigData
- NOSQL
- Histórico
- Tipos de Bancos
- Comparação com o Modelo relacional
- Cassandra
- Arquitetura Cassandra
- Configurações Básica do Cassandra
- Configuração de multi-nodes no Cassandra
- Conhecendo o DevOpsCenter
- Instalando os Agentes
Para aqueles que não são de São Paulo:
Link : https://globalcode.webex.com/globalcode/onstage/g.php?t=a&d=662489296
Pass: cassandra
Mais informações: http://goo.gl/S3LQBm
JavaBahia e Linguágil no Cassandra Trip Brasil
31 de Agosto de 2013, 15:05 - sem comentários ainda
Com o intuito de divulgar essa idéia aqui no Brasil foi criado o Cassandra Trip Brasil, um evento com duração de uma semana, entre os dias 2 até 6 de setembro, sendo que cada dia será apresentado em uma cidade diferente. As cidades que sediarão esse evento serão:
- 2 de Setembro, segunda-feira, Campinas
- 3 de setembro, terça-feira, São Paulo
- 3 de setembro, terça-feira, Online para todo o Brasil
- 4 de setembro, quarta-feira, Florianópolis
- 5 de setembro, quinta-feira, Brasília
- 6 de setembro, sexta-feira, Salvador
O JavaBahia e o Linguágil farão parte desse evento aqui no Brasil, fazendo o encontro técnico dos grupos como parte do circuito. O encontro acontecerá na Estácio/FIB.
- Data: 6 de setembro, Serça-Feira
- Horário: 18:30
- Cidade: Salvador
- Local: Estácio/FIB Auditório do Andar G1
- Endereço: Rua Xingu, nº 179 - Jardim Atalaia/STIEP CEP: 41770-130
Apoio:
