Docker, confd e DynamoDB

Dockerfile

FROM nginx:latest
MAINTAINER Genki Sugawara <sgwr_dts@yahoo.co.jp>

ENV DUMB_INIT_VERSION 1.1.3
ENV CONFD_VERSION 0.11.0

RUN apt-get update
RUN apt-get install -y –force-yes curl

RUN curl -sOL https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_amd64.deb
RUN dpkg -i dumb-init_*.deb
RUN rm dumb-init_*.deb

RUN curl -sOL https://github.com/kelseyhightower/confd/releases/download/v${CONFD_VERSION}/confd-${CONFD_VERSION}-linux-amd64
RUN chmod +x confd-*
RUN mv confd-* /bin/confd
RUN mkdir -p /etc/confd/{conf.d,templates}
ADD nginx_default.conf.toml /etc/confd/conf.d/
ADD nginx_default.conf.tmpl /etc/confd/templates/

ADD init.sh /
RUN chmod +x /init.sh

ENV CONFD_ARGS -backend dynamodb -table confd

ENV AWS_REGION ap-northeast-1
ENV AWS_DEFAULT_REGION ap-northeast-1
ENV AWS_ACCESS_KEY_ID …
ENV AWS_SECRET_ACCESS_KEY …

CMD /init.sh

init.sh

#!/usr/bin/dumb-init /bin/sh
confd $CONFD_ARGS &
nginx -g ‘daemon off;’

nginx_default.conf.toml

[template]
src = “nginx_default.conf.tmpl”
dest = “/etc/nginx/conf.d/default.conf”
keys = [
“/nginx/statuscode”
]
check_cmd = “service nginx configtest”
reload_cmd = “service nginx reload”

nginx_default.conf.tmpl

server {
listen       80 default_server;
server_name  _;

location / {
return {{getv “/nginx/statuscode”}};
}
}

DynamoDB

aws dynamodb create-table \
–table-name confd \
–attribute-definitions AttributeName=key,AttributeType=S \
–key-schema AttributeName=key,KeyType=HASH \
–provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1

$ ddbcli
ap-northeast-1> show create table confd;
CREATE TABLE `confd` (
`key` STRING HASH
) read=1 write=1

ap-northeast-1> select all * from confd;
[
{“key”:”/nginx/statuscode”,”value”:”404″}
]
// 1 row in set (0.05 sec)

$ docker build -t awesome-confd .

$ docker run –rm -p 10080:80 –name awesome-confd -it awesome-confd
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO Backend set to dynamodb
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO Starting confd
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO Backend nodes set to
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO DynamoDB table set to confd
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO /etc/nginx/conf.d/default.conf has md5sum 4dce452bf8dbb01f278ec0ea9ba6cf40 should be 1e1181119f8355e81d3b0a7de2859d5a
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO Target config /etc/nginx/conf.d/default.conf out of sync
2016-08-28T08:34:26Z 1f4823caba59 confd[8]: INFO Target config /etc/nginx/conf.d/default.conf has been updated

$ curl localhost:10080
<html>
<head><title>404 Not Found</title></head>
<body bgcolor=”white”>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.11.3</center>
</body>
</html>

#!/usr/bin/dumb-init /bin/sh
confd $CONFD_ARGS
nginx -g ‘daemon off;’

ap-northeast-1> update confd set value = ‘401’ where key = ‘/nginx/statuscode’;
// 1 row changed (0.08 sec)

$ docker exec -it awesome-confd confd -backend dynamodb -table confd -onetime
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO Backend set to dynamodb
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO Starting confd
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO Backend nodes set to
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO DynamoDB table set to confd
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO /etc/nginx/conf.d/default.conf has md5sum 1e1181119f8355e81d3b0a7de2859d5a should be 306f95f0ae59a29344ed21eb0c7886c9
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO Target config /etc/nginx/conf.d/default.conf out of sync
2016-08-28T08:40:44Z 4b3509b1fd93 confd[49]: INFO Target config /etc/nginx/conf.d/default.conf has been updated

$ curl localhost:10080
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor=”white”>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.11.3</center>
</body>
</html>

 

Annotations do Spring

@Configuration

É uma annotation que indica que determinada classe possui métodos que expõe beans.

@Controller

Identifica classes que possuem métodos que processam requests numa aplicação web.

@Repository

Identifica classes que isolam o acesso aos dados da sua aplicação. Comumente associada a DAO’s.

@Service

Identifica classes que representam a ideia do Service do Domain Driven Design. Para ficar menos teórico pense em classes que representam algum fluxo de negócio da sua aplicação. Por exemplo, um fluxo de finalização de compra envolve atualizar manipular o carrinho, enviar email, processar pagamento etc. Este é o típico código que temos dificuldade de saber onde vamos colocar, em geral ele pode ficar num Service.

@Component

A annotation básica que indica que uma classe vai ser gerenciada pelo container do Spring. Todas as annotations descritas acima são, na verdade, derivadas de @Component. A ideia é justamente passar mais semântica.

@ComponentScan

Em geral você a usa em classes de configuração(@Configuration) indicando quais pacotes ou classes devem ser scaneadas pelo Spring para que essa configuração funcione.

@Bean

Anotação utilizada em cima dos métodos de uma classe, geralmente marcada com @Configuration, indicando que o Spring deve invocar aquele método e gerenciar o objeto retornado por ele. Quando digo gerenciar é que agora este objeto pode ser injetado em qualquer ponto da sua aplicação.

@Autowired

Anotação utilizada para marcar o ponto de injeção na sua classe. Você pode colocar ela sobre atributos ou sobre o seu construtor com argumentos.

@Scope

Annotation utilizada para marcar o tempo de vida de um objeto gerenciado pelo container. Pode ser utilizada em classes anotadas com @Component, ou alguma de suas derivações. Além disso também pode usada em métodos anotados com @Bean. Quando você não utiliza nenhuma, o escopo default do objeto é o de aplicação, o que significa que vai existir apenas uma instância dele durante a execução do programa. Você alterar isso, anotando o local e usando alguma das constantes que existem na classe ConfigurableBeanFactory ou WebApplicationContext.

@RequestMapping

Geralmente utilizada em cima dos métodos de uma classe anotada com @Controller. Serve para você colocar os endereços da sua aplicação que, quando acessados por algum cliente, deverão ser direcionados para o determinado método.

@ResponseBody

Utilizada em métodos anotados com @RequestMapping para indicar que o retorno do método deve ser automaticamente escrito na resposta para o cliente. Muito comum quando queremos retornar JSON ou XML em função de algum objeto da aplicação.

@Primary

Caso você tenha dois métodos anotados com @Bean e com ambos retornando o mesmo tipo de objeto, como o Spring vai saber qual dos dois injetar por default em algum ponto da sua aplicação? É para isso que serve a annotation @Primary. Indica qual é a opção padrão de injeção. Caso você não queira usar a padrão, pode recorrer a annotation @Qualifier.

@Profile

Indica em qual profile tal bean deve ser carregado. Muito comum quando você tem classes que só devem ser carregadas em ambiente de dev ou de produção. Essa eu utilizo bastante e acho uma ideia simples, mas super relevante dentro do Spring.

@SpringBootApplication

Para quem usa Spring Boot, essa é uma das primeiras que você. Ela engloba a @Component, @ComponentScan e mais uma chamada @EnableAutoConfiguration, que é utilizada pelo Spring Boot para tentar advinhar as configurações necessárias para rodar o seu projeto.

Bom, acho que é isso aí. Adoro escrever posts que foram solicitados diretamente pela galera que acompanha o meu trabalho, é uma motivação bem grande.

@EnableAsync

Essa aqui não é tão comum, mas muitas vezes você precisa ações no sistema em background(outra thread). Essa annotation deve ser colocada em alguma classe marcada com @Configuration, para que o Spring habilite o suporte a execução assíncrona.

@Async

Uma vez que seu projeto habilitou o uso de execução de métodos assíncronos com a @EnableAsync, você pode marcar qualquer método de um bean gerenciado do projeto com essa annotation. Quando tal método for invocado, o Spring vai garantir que a execução dele será em outra thread.

Domain Driven Design

Domain Driven Design, ou seja, Desenvolvimento Orientado a Domínio.

O objetivo é focar no domínio da solução, através de um contexto apresentado, determinar a solução de maneira que atenda:

  1. Alinhar o código com as regras de negócio – para atender, pode-se utilizar XP, aproximando a equipe de negócio a equipe de desenvolvimento
  2. Minimizar acoplamento – fazer com que as partes do sistema interaja entre si, evitando dependência entre os módulos
  3. Favorecer o reuso – módulos do sistema, podem ser reutilizados em outras funções
  4. Independência de tecnologia – focar na regra de negócio e código

O modelo de software típico de DDD consiste:

  1. Interface com Usuário – responsável por interagir com o usuário, capturando intenções e informações
  2. Aplicação – camada intermediária entre a camada 1 e 3, atuando como comunicação de dados
  3. Domínio – camada com as regras de negócio. Toda a inteligência do sistema está aqui.
  4. Infra-estrutura – camada responsável pelos recursos técnicos, geralmente são classes que se comunicam com Banco de Dados e mensagens

mapping-ddd-to-java-ee

Exemplos:

https://github.com/paoesco/cargotracker-ddd

https://github.com/citerus/dddsample-core

https://github.com/olivergierke/spring-restbucks

http://www.the-coder-life.com/2016/02/domain-driven-design-hands-on-example.html

https://github.com/simbo1905/root-objects

Links:

http://www.agileandart.com/2010/07/16/ddd-introducao-a-domain-driven-design/

 

KumuluzEE – Framework para microserviços

A utilização da arquitetura de microserviços vem se tornando padrão entre as empresas.

Com a busca de informações dessa nova forma de desenvolver os aplicativos, encontrei uma solução de framework para utilização de microserviços, o KumuluzEE.

Por ser uma solução compatível com JEE, torna-se uma grande opção, tanto para novos projetos quanto para aplicações existentes e que deseja-se transformá-las em microserviços.

Fonte:

https://ee.kumuluz.com/

Conheça o KumuluzEE – seu novo framework para Microservices

 

Maven – Tutorial

Introdução

O Maven é uma excelente ferramenta para gerenciar e implantar projetos Java. O objetivo desse post é apresentar de forma clara e fácil como utilizar o Maven.

Instalação

  1. Baixe o Maven de https://www.apache.org/.
  2. Descompacte onde deseja que fique a instalação.
  3. Em Variáveis de Ambiente, crie a variável MAVEN_HOME ou MVN_HOME
  4. Na variável Path, inclua no início do trecho %MAVEN_HOME%\bin;
  5. Abra um Prompt de Comando e digite mvn -version (deverá aparecer a versão instalada)
  6. Pronto! É só utilizar

Criação de um projeto Web

Através do Prompt de Comando, vá no diretório onde deseja criar o projeto e digite

mvn archetype:generate -DgroupId=br.com.emp -DartifactId=WebAppDemo -DarchetypeArtifactId=maven-archetype-webapp

 

Microservices

Introdução

Arquitetura de microservices consiste em dividir a aplicação em conjunto de serviços. É recomendável utilizar em aplicações robustas e/ou que necessitam evoluir rapidamente.

 

Links:

https://www.infoq.com/br/articles/microservices-intro

https://dzone.com/articles/building-microservices-with-java

GitHub Desktop

Download

Procurando no Google, encontrei o GitHub Desktop em: https://desktop.github.com/

  1. Clique no link Download GitHub Desktop
  2. Instale o aplicativo
  3. Serão criados 2 atalhos no Desktop, GitHub e Git Shell

Git Shell

Baixando um projeto (Clone)

  1. Abra o programa Git Shell
  2. Vá no diretório onde deseja baixar o projeto, por exemplo c:\opt\wokspace\github
  3. Digite: git clone https://github.com/[[DIR_USER]]/[[REPOSITORY]]
    1. Pode ocorrer erro no Checkout, devido a incompatibilidade de arquivos (entre diferentes sistemas operacionais)

Criando novo arquivo

  1. Com o projeto baixado, crie o seu arquivo localmente
  2. Para verificar o status dos arquivos, utilize
    1. git status
    2. Apresentará o arquivo untracked em vermelho
    3. git log (apresenta o log de todas as alterações feitas pelo usuário)
  3. Para adicionar o arquivo novo
    1. git add [NOME_DO_ARQUIVO]
    2. Quando efetuar o “git status” deverá apresentar o nome do arquivo em verde
    3. Para cancelar o comando add
      1. git reset HEAD [NOME_DO_ARQUIVO]
    4. Para adicionar todos os arquivos
      1. git add .
  4. Comitando o arquivo adicionado
    1. git commit -m ‘Arquivo atualizado com nova regra’
    2. Se vários arquivos foram adicionados no “add”, o comentário será adicionado a todos. Para adicionar comentários diferentes, os comandos “add” devem ser isolados.
  5. Enviando para o servidor
    1. git push origin master
    2. Todos os arquivo comitados, serão efetivados no master do Github
  6. Resetando todo o projeto
    1. Para retornar a última versão remota, utilize o comando
      1. git reset –hard
  7. Pronto, arquivo atualizado no Github

Criando uma Branch

  1. Comando para criar branch
    1. git checkout -b [NOME_BRANCH]
    2. Os comandos para atualizar os arquivos são os mesmos (add e commit)
    3. O comando push agora deve ser feito apontando a nova branch
      1. git push origin [NOME_BRANCH]
    4. Trocando de branch
      1. git checkout [NOME_BRANCH]

Sincronizando Branch

  1. Estando na branch de destino (master)
  2. git merge [NOME_BRANCH]
  3. git push origin master

Comando Pull

  1. Quando existe um arquivo novo no Git não é possível consultar essa alteração com “git status”
  2. Para sincronizar com o master
    1. git fetch
    2. Agora podes-se usar o “git status”
  3. Para pegar todas as atualizações
    1. git pull
    2. O arquivo será atualizado na máquina do desenvolvedor

Iniciando um diretório no Git (por exemplo Github)

  1. Acesse o site www.github.com e crie o repositório (exemplo: java-redis)
  2. Acesse o diretório onde será enviado ao repositório (diretório: java-redis)
  3. Digite os comandos na sequência
    1. git init
    2. git add –all
    3. git commit -m “Initial version”
    4. git remote add origin https://github.com/lfchaim/java-redis.git
    5. git pull origin master
    6. git push -u origin master

Outros comandos

  1. git diff (mostra a diferença entre o arquivo local e a branch)
  2. git clean -d -f (remove modificações efetuadas localmente)

Problema com nome longo de arquivos (filename too long)

  1. git config –system core.longpaths true

 

MySQL – Configuração Windows

Instalando MySQL – Arquivo Zip

Quando utiliza-se o MySQL baixado como zip, é necessário:

  1. Baixar o MySQL, por exemplo mysql-5.7.16-winx64.zip
  2. Descompactar no local desejado, no meu caso foi o próprio drive C (C:\mysql-5.7.16-winx64)
  3. Abrir o prompt de comando como administrador
  4. Estando em C:\mysql-5.7.16-winx64\bin, digitar
    1. mysqld –initialize
    2. Após o comando, verifica-se a criação do diretório /data

 

My.ini

Na instalação do MySQL, é apresentado o arquivo my-default.ini. Devemos renomeá-lo para my.ini e editar a linhas:

  1. basedir = C:\\mysql-5.7.16-winx64
  2. datadir = C:\\mysql-5.7.16-winx64\data
  3. port = 3306
  4. server_id = 1

 

MySQL – Alterando a senha root

Caso esteja rodando o MySQL como serviço, parar o serviço.

  1. Criar um arquivo txt (exemplo: C:\mysql-5.7.16-winx64\MySQL.txt)
  2. Criar o seguinte conteúdo no arquivo criado (válido para 5.7.6 ou superior)
    1. ALTER USER ‘root’@’localhost’ IDENTIFIED BY ‘root’;
  3. Salvar o arquivo
  4. Abrir o prompt de comando
  5. Digitar em C:\mysql-5.7.16-winx64\bin
  6. mysqld –init-file=C:\mysql-5.7.16-winx64\MySQL.txt
  7. O MySQL subirá e alterará a senha. Basta então matar o processo mysqld que foi criado e nos serviços do Windows subir novamente.

 

Instalando MySQL como serviço do Windows

Para instalar o MySQL como serviço, devemos:

  1. Abrir um Prompt de Comando
    1. Windows 10
      1. Clique no botão Iniciar e digite “prompt”
    2. Aparecendo o item “Prompt de Comando”, clique com o botão direito do mouse e escolha “Executar como Administrador” (sem esta opção, não funciona)
  2. Com a tela de Prompt de Comando aberta, vá até o diretório do MySQL
    1. No meu caso, C:\Program Files\MySQL\MySQL Server 5.6\bin
    1. Digite: mysqld –install MySQL
  3. Abra a tela de serviços (services.msc) e verifique que foi criado um item “MySQL”