Infinitest

 

Mais uma ferramenta para otimizar o desenvolvimento e evitar a identificação tardia de bugs.

O Infinitest faz isso da seguinte forma: ao salvar uma alteração em um código na IDE ele dispara os testes, avalia e marca os que não passaram. Assim garante a verificação de erros on time.

No meu caso instalei-o no Eclipse (Mars.2 Release (4.5.2)), bem rápido e tranquilo pelo Marketplace.

Ainda pode ser configurado para excluir pacotes, classes ou padrões específicos criando um arquivo na raiz do projeto chamado infinitest.filters.

A documentação do projeto está aqui em https://infinitest.github.io/.

E a fonte deste post está no blog da Caelumn, aqui.

Até!

Apache Cassandra on Ubuntu

Cassandra logo

 

So I decided to test the NoSql Cassandra database. But to install was a non-trivial proccess on Ubuntu 16 release.

After some googling I found this link inside the Download area of the oficial Cassandra site. And then it works!

It was necessary to change the first key number for the one that is showing on the error after the apt-get update. I skipped the add of the other two keys and it works.

Now I can test the Cassandra with Spring Boot, via this link on Dzone.

Hope this can help…

Microservices boundaries

Fronteira entre serviços

Sob a nova perspectiva de softwares como microservices surge um desafio em identificar as fronteiras entre estes que compõem a aplicação.

Duas abordagens podem ser consideradas, ambas baseadas no princípio da Single Responsible Principle (Princípio da Responsabilidade Única):

A primeira estabelece que os microservices devem ser identificados por meio do verbo de execução de sua responsabilidade. Por exemplo, em uma aplicação de Gerência de Estoques, como a twarehouse em tetraTI, ao analisarmos as ações de entrada de produtos, o cadastro e análise daqueles com baixa em estoque, teríamos assim 3 candidatos a microservices: Entrada de Produtos Service, Cadastro de Produtos Service e Analisador de Baixa Service.

A outra abordagem é a de definir fronteiras por meio da identificação das entidades ou recursos oferecidos pelo sistema. Dessa forma e utilizando o exemplo acima teríamos serviços como Movimentação Service, responsável por todas as operações de movimentação. Ou Analisador de Estoque Service, que forneceria informações em tempo real sobre o estoque.

É muito sutil a escolha ou identificação de serviços por meio de suas fronteiras, que juntos definem a aplicação em si. Para enfrentar este desafio deste novo conceito de SaaS e usufruir de suas vantagens será necessário bom senso e experiência por parte do arquiteto.

Fonte: Devmedia e Building Microservices Book.

Sai JSF, entra AngularJS

AngularJS-large

Atualmente utilizo JSF para o front-end mas percebo que nem de perto é tão produtiva quanto Angular. A ideia deste post é mostrar como substituir tags jsf de uma página xhtml que consome dados de um backend em java pelo AngularJS.

Isso implicará na troca da arquitetura monolítica onde a back e front são tratados na própria aplicação para uma onde estarão separados.

Segue um video para introdução ao Angular como sugestão de tutorial para início com o framework javascript MVC AngularJS.

Mais sobre o processo de substituição dos JSF pelo Angular nos próximos posts. Até.

Conteúdo estático no Wildfly em produção

upload-cloud

Neste Post demonstrarei como utilizar de forma eficiente imagens como conteúdo estático em uma aplicação Java Web com JSF que rode em um ambiente Linux e num servidor WildFly 8.x.

A ideia é utilizar imagens no cadastro de produtos, fazendo seu upload e exibindo-as em diversas partes.

upload_1

As ferramentas necessárias são o PuTTy para criação do diretório no servidor e um editor xml para configuração do Handler no arquivo de configuração do WildFly. No meu caso utilizei o próprio Eclise IDE. Claro que assumindo que já exista uma aplicação com as devidas configurações e rodando. Disponibilizarei a classe que utilizo para tratar o upload da imagem também.

Criando a estrutura de diretório: a aplicação está hospedada num servidor integrator.com.br, portanto definia a seguinte estrutura:

upload_2

Para criação dos diretório é necessário pelo PuTTy criar os diretórios a partir da pasta home, assim: /home/<<usuário>>/var/static/images/pecas.

Configurando o handler no WildFly: agora que as pastas estão criadas é necessário mapear esta estrutura no servidor de aplicação para que possamos acessá-lo. Para isso configuramos o arquivo de configuração, standalone.xml, da seguinte forma:

upload_3

O handler mapeará o caminho definido em /imagens/meu-espaco. Para acessar o conteúdo do diretório basta acessar a url http://<<endereço_do_servidor>>/imagens/meu-espaco.  A opção directory-listing permite que seu conteúdo seja listado:

upload_4

A classe para upload da imagem: o mecanismo de upload é simples graças ao componente Upload da biblioteca PrimeFaces. Sua utilização é simples:
upload_5

A classe FotoProdutoBean encaminhará a ação à Camada de Serviço de produto, que utilizará a classe FotoHelper para escrever o conteúdo do download para o diretório definido.

upload_6

A constante CAMINHO_DAS_FOTOS contém o caminho para o nosso diretório de conteúdo estático, isto é, nossas fotos de produtos (peças): /home/meuvisua/var/static/images/pecas/.

Exibindo as imagens: Enfim, para exibir a imagem basta uma tab <img> html com o mapeamento. Desta forma:

upload_7

Só isso! Ao utilizarmos o handler para mapear um diretório fora do servidor de aplicação tornamos nosso conteúdo estático independente. Num cenário de atualização ou substituição do servidor nada será afetado. Ainda, assim evitamos também salvarmos essas imagens direto no banco, impactando a performance.

Se alguém tiver uma solução melhor ou alternativa, comentem.

Até o próximo.

 

LocalDate e LocalDateTime em JSF 2.2 e 2.3

tempo_122-692x360

Com a API Date-Time do Java 8 novos objetos de representação e tratamento de data e tempo foram introduzidos no cotidiano de desenvolvedores que recorriam à implementações diversas, como o Joda Time.

Como caraterística desta API pode ser destacados a facilidade na utilização o que não era presente nas versões anteriores com os objetos java.util.Date e java.sql.Date.

Entretanto a versão JSF 2.2 ainda não proporciona a conversão nativa desses objetos. O que já incorporado na próxima versão, 2.3, programada para ser lançada em 2017 junto a Java EE 8.

Assim, para utilizar os objetos LocalDate e LocalDateTime é necessário criar conversores JSF e atribuí-los ao conversor da tag <h:outputText>. Abaixo o exemplo de utilização.

Os converters devem implementar a interface javax.faces.convert.Converter e ser anotados com javax.faces.convert.FacesConverter, onde é definido o nome (id).

@FacesConverter("localDateTimeFacesConverter")
public class LocalDateTimeFacesConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String stringValue) {

if (null == stringValue || stringValue.isEmpty()) {
return null;
}

LocalDateTime localDateTime = null;

try {

localDateTime = LocalDateTime.parse(
stringValue.trim(),
DateTimeFormatter.ofPattern(“dd/MM/yyyy hh:mm:ss”).withZone(ZoneId.systemDefault()));

} catch (DateTimeParseException e) {

throw new ConverterException(“O formato da data e hora deve ser 13/11/2015 12:00:00.”);
}

return localDateTime;

}

@Override
public String getAsString(FacesContext context, UIComponent component, Object localDateTimeValue) {

if (null == localDateTimeValue) {

return “”;
}

return ((LocalDateTime) localDateTimeValue)
.format(DateTimeFormatter.ofPattern(“dd/MM/yyyy hh:mm:ss”)
.withZone(ZoneId.systemDefault()));
}
}

@FacesConverter("localDateFacesConverter")
public class LocalDateFacesConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String stringValue) {

if (null == stringValue || stringValue.isEmpty()) {
return null;
}

LocalDate localDate;

try {
localDate = LocalDate.parse(
stringValue,
DateTimeFormatter.ofPattern(“dd/MM/yyyy”));

} catch (DateTimeParseException e) {

throw new ConverterException(“O ano deve conter 4 dígitos. Exemplo: 13/11/2015.”);
}

return localDate;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object localDateValue) {

if (null == localDateValue) {

return “”;
}

return ((LocalDate) localDateValue).format(DateTimeFormatter.ofPattern(“dd/MM/yyyy”));
}
}

Os Converters apenas fazem a conversão do objeto para String e vice-versa, não há maiores problemas na implementação. Caso o parse para o padrão definido gere uma exceção esta é lançada como ConverterException e exibida ao usuário. No entanto nos testes e em implementações dessa lógica esta mensagem não chega ao na view e deve ser definido o atributo converterMessage da tag <h:inputText>.

<code><label for=”inputAdmissao”>Data de admissão <span class=”required”>*</span></label>
<h:inputText
class=”form-control input-sm m-bot15″
id=”inputAdmissao”
pt:placeholder=”Admissao ”
value=”#{cadastroFuncionarioBean.funcionario.dataDeAdmissao}”
required=”true”
requiredMessage=”É necessário informar a data de admissão.”
converterMessage=”A data deve estar no formato dd/MM/aaaa”>

<f:converter
converterId=”localDateFacesConverter”
for=”inputAdmissao”/>

<f:ajax
event=”blur”
render=”m_inputAdmissao” />

</h:inputText> </code>

data

A novidade que a versão do JSF 2.3 traz é a adição de type attributes para as classes java.time.LocalDate e java.time.LocalDateTime, respectivamente localDate e localTime. :-p

<code>

<h:inputText value="#{myBean.startTime}">
    <f:convertDateTime type="localDateTime" />
</h:inputText>
<h:outputText value="#{myBean.endDate}">
    <f:convertDateTime type="localDate" pattern="dd.MM.uu" />
</h:outputText>

</code>

É isso. E para saber mais das novidades da nova versão do JSF segue esse link What’s new in JSF 2.3?.

JSF and Bootstrap form modal

Na atualização de versão do software twarehouse além da migração do Tomcat para o Wildfly, a correção de alguns bugs, o refatoramento das classes e outras melhorias resolvi alterar o framework front-end do primefaces para o bootstrap (Twitter).

Tenho enfrentado muitos desafios neste processo já que é grande o trabalho para configurar templates htmls criados com bootstrap.

Somado a isso ainda há algumas incompatibilidades de design e comportamento entre o framework e o JSF, que consomem bastante tempo e neurônios.

Uma dessas dificuldades que enfrentei foi quando surgiu a necessidade de um mensagem de confirmação na exclusão de registros:

Controle na pesquisa dos registro.s

Controle na pesquisa dos registro.

Os “botões” do controle na verdade correspondem ao atributo <a> do html com o atributo jsfc que permite a utilização dos atributos do componente aninhado à tag html, no caso o <a>. Segue abaixo:

[code language=”html”]

<a class="btn btn-danger"
jsfc="h:commandLink"
type="button"
action="#{pesquisaSubgrupoBean.setSubgrupoSelecionado(subgrupo)}"
immediate="true">
<f:setPropertyActionListener
value="#{subgrupo}"
target="#{pesquisaSubgrupoBean.subgrupoSelecionado}"/>

<f:passThroughAttribute name="data-toggle" value="modal" />
<f:passThroughAttribute name="data-target" value="#myModal" />
<f:ajax/>

<i class="icon_close_alt2"></i>
</a>
[/code]

Até ai tudo bem. O problema mesmo era fazer com que o form modal fosse chamado ao clicar no botão. Segue o código do form:

[code language=”html”]

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModal" aria-hidden="true" data-keyboard="false" data-backdrop="static">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<h:form id="myForm">
<div class="modal-header">
<button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button>
<h4 class="modal-title">Confirmação de exclusão</h4>
</div>
<div class="modal-body">
<h:panelGroup
layout="block"
id="panelDescricao">

Deseja realmente excluir o registro selecionado?

<a type="submit"
class="btn btn-warning btn-sm"
jsfc="h:commandLink"
action="#{pesquisaSubgrupoBean.excluir()}">
Sim
<f:passThroughAttribute name="data-dismiss" value="modal" />
<f:ajax
execute="@this"
render="@form"/>
</a>

<button
id="close"
type="submit"
class="btn btn-info btn-sm">Não</button>
</h:panelGroup>
</div>

</h:form>
</div>
</div>
</div>

[/code]

Após muitas falhas, como Edson, só precisei acertar uma vez. Com a adição dos atributos no código do botão o form passou a ser chamado, mas instantaneamente era fechado:

[code language=”html”]

<f:passThroughAttribute name="data-toggle" value="modal" />
<f:passThroughAttribute name="data-target" value="#myModal" />

[/code]

Form modal chamado pelo botão excluir.

Form modal chamado pelo botão excluir.

Espero que tenha contribuído e ajudado alguém, já que vi algumas tantas dúvidas ainda não respondidas ou que a solução fosse diferente e ineficaz.

Em tempo: ainda tem um pequeno problema. Não consegui a descrição das instância selecionada na mensagem de exclusão. O componente seta a propriedade mas o valor não é exibido. Vou debugar utilizando alguns phaseListeners para identificar o momento de cada ação.

Até!

Site institucional tetra TI no ar.

tetrati-desenvolvimento

Voltando aos posts depois de algum muito tempo, aproveito para lançar o site institucional da empresa tetra TI.

A criação deste site representa dois marcos: a criação do nome, já que o domínio era sidroniolima.com.br, que passará a corresponder a este blog. E a tendência e consolidação do desenvolvimento Web, estático ou dinâmico.

Com isso surge então o tetrati.com.br com a apresentação de 3 principais projetos:

  • O software PCP que está em desenvolvimento;
  • O software Twarehouse (foto), já comercializado, para controle de almoxarifado e estoque;
  • Dashboard do Twarehouse.

    Dashboard do Twarehouse.

  • E o software ERP para micro e pequena empresas que será lançado em breve.
  • Para conhecer o Twarehouse basta acessar aqui.

    Em breve novas atualizações!

    Os números de 2012

    Os duendes de estatísticas do WordPress.com prepararam um relatório para o ano de 2012 deste blog.

    Aqui está um resumo:

    600 pessoas chegaram ao topo do Monte Everest em 2012. Este blog tem cerca de 2.100 visualizações em 2012. Se cada pessoa que chegou ao topo do Monte Everest visitasse este blog, levaria 4 anos para ter este tanto de visitação.

    Clique aqui para ver o relatório completo

    Backup Schedule no MySql – Resolvendo

    Saudações!

    Em uma aplicação que estou desenvolvendo me deparei com erro ao criar um backup agendado (Schedule backup) no MySql Administrator.

    Pesquisando eu observei a quantidade de desenvolvedores com o mesmo problema. Algumas soluções propostas não funcionaram e como eu consegui, resolvi postar a solução, que é simples.

    Ao criar um projeto de backup e defini-lo como agendado, o MySql cria um task no windows, mas o problema é que ele não executa e gera o seguinte erro no log de tarefas do windows, o arquivo SchedLgU.Txt:

    (MySQLAdministrator.exe) 12/1/2013 10:10:00 ** ERRO **
    A tentativa de recuperar informações da conta para a tarefa especificada falhou. A tarefa não foi executada. Ocorreu um erro ou não existiam informações de conta para a tarefa.
    O erro específico é:

    0x8004130f: Não foi possível encontrar informações de conta no banco de dados de segurança do agendador de tarefas para a tarefa indicada.

    Cheguei a solução que é necessário marcar a opção Executar somente se conectado nas opções da tarefa (task) criada pelo MySql. Só isso e funcionou.

    Espero ajudar aos muitos que passaram por esse problema.

    Até!