Artigos de Desenvolvimento.



Deployment of a Spring Boot App with Jenkins in a Unix System using Gradle

One thing that I found very hard to do was to integrate a spring boot project into a CI environment using jenkins. As a default behavior, the Jenkins process tree killer always kills the process started by a job which stops the execution of a Spring Boot App after the jenkins job finishes. In addition of that, I wanted to see the server log on the jenkyns windows until it finishes loading. This article will try to help us solving this problems.

But first I would like to discuss what I consider a good practice to a Spring Boot App CI environment. I find very useful to first copy the artifacts to a specified area on the server to keep track of the artifacts deployed and deploy the artifact from that location. Also, I create a server log file there and start to listening on the jenkins window until the server started.

So the script below does that. With some minor improvements self explained on the comments, but in summary it does this:

  • stop whatever process running on the deployed port.
  • delete the files of the previous deploy
  • copy the files to deploy location
  • start application with nohup command, java – jar
  • start listening to the server log until it reaches an specific instruction.

Finally you have to do some adjustments to your job on Jenkins to avoid the default tree killing process. Just add this instruction before calling the sh: BUILD_ID=dontKillMe /path/to/my/script.sh (FIGURE 3)

You can see the jenkins job configuration window on FIGURES 1, 2, and 3 and the log result window on FIGURES 4 and 5.

Go to my github repo to check the project, but it recommend to extract the shell script to another repo to keep it lifecycle independent of your app.

https://github.com/rcoli/spring-boot-jenkins

Compila√ß√£o de m√ļltiplos projetos Maven

Em projetos de desenvolvimento de software mais complexos n√£o √© muito incomum a necessidade de quebrarmos uma aplica√ß√£o em peda√ßos menores que poder√£o ser reutilizados por outros projetos. E assim, acabamos criando a necessidade da compila√ß√£o de m√ļltiplos projetos de uma vez e em uma determinada ordem.

O Maven nos ajuda muito na tarefa de gest√£o de depend√™ncias e para o build de m√ļltiplos projetos ao mesmo tempo eles devem ter uma rela√ß√£o modular ou uma rela√ß√£o de pai para filho, saiba mais aqui e isto nem sempre √© desejado num ambiente de integra√ß√£o cont√≠nua.

O generic-maven-build nada mais √© do que um script preparado para compila√ß√£o de m√ļltiplos projetos de uma s√≥ vez, validando se compilaram corretamente e exibindo o tempo decorrido ao final.

A instrução executada partiu de uma necessidade de um projeto atual,  mvn clean install -U, no entanto nada impede que você faça a alteração no arquivo de acordo com a sua necessidade.

Explicando um pouco melhor as intru√ß√Ķes contidas no arquivo:

  • clean: ¬†attempts to clean a project’s working directory of the files that we’re generated at build-time. By default, it discovers and deletes the directories configured in project.build.directory, project.build.outputDirectory, project.build.testOutputDirectory, and project.reporting.outputDirectory.

  • install: install the package into the local repository, for use as a dependency in other projects locally

  • -U: Force Update, atualiza todas as depend√™ncias a partir dos reposit√≥rios configurados no pom.xml ou settings.xml

Instru√ß√Ķes de uso

Baixe o arquivo no meu repositório do bitbuket em uma pasta local do seu computador: https://rcoli@bitbucket.org/rcoli/generic-maven-build.git

Ali existem as vers√Ķes para Windows (pouco evolu√≠da, fique a vontade para melhor√°-la) e linux.

Para execut√°-lo, acesso o terminal ou prompt de comando e digite da seguinte forma:

Executando sem testes: generic-maven-build.sh /home/user/repository/project1/pom.xml /home/user/repository/project1/pom.xml semTestes

Executando com testes: generic-maven-build.sh /home/user/repository/project1/pom.xml /home/user/repository/project1/pom.xml

No Eclipse:

Clique no ícone External Tools na barra de tarefas do eclipse, escolha External Tools Configurations. Clique com o botão direito em Program e escolha new. Configure conforme as imagens abaixo:

Screenshot from 2015-07-08 10:26:07

Screenshot from 2015-07-08 10:26:28

Screenshot from 2015-07-08 10:28:35

Screenshot from 2015-07-08 10:28:48

Screenshot from 2015-07-08 10:37:19

Pré-requisitos:

Maven instalado e configurado, arquivo .sh ou .bat baixado em seu computador.

Referências:

https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

http://maven.apache.org/plugins/maven-clean-plugin/

http://books.sonatype.com/mvnex-book/reference/multimodule-web-spring-sect-intro.html

C√°lculo Simples de Data sem o uso de Date ou Calendar

Uma das grandes dificuldades do Java √© trabalhar com datas. Existem diversas APIs que resolvem esse problema de forma completa. No entanto atrav√©s de um simples c√°lculo utilizando os operadores “/” (divis√£o) e “%” (resto), somos capazes de obter o resultado sem a utiliza√ß√£o de nenhuma API espec√≠fica. Obviamente trabalhando com String.

Saída:
Hoje é: dia 3, mês 4, ano 14.

Hoje é: dia 23, mês 4, ano 2014.

[php]
public class Main {

public static void main(String[] args) {

String hojeComAnoEmDoisDigitos = "030414";
System.out.println(escreverDataPorExtensoComAnoEmDoisDigitos(hojeComAnoEmDoisDigitos));

String hojeComAnoEmQuatroDigitos = "23042014";
System.out.println(escreverDataPorExtensoComAnoEmQuatroDigitos(hojeComAnoEmQuatroDigitos));
}

public static String escreverDataPorExtensoComAnoEmDoisDigitos(String hojeComAnoEmDoisDigitos) {
try {

if(!isDataValida(hojeComAnoEmDoisDigitos, 6))
return ("Data Inválida, Verifique se o dia, o mês e ano possuem 2 dígitos.");

Integer divisorDiaDoisDigitos = 10_000;
Integer divisorAnoDoisDigitos = 100;

Integer hoje = Integer.parseInt(hojeComAnoEmDoisDigitos);

Integer dia;
Integer mes;
Integer ano;

dia = (hoje / divisorDiaDoisDigitos);
mes = (hoje / divisorAnoDoisDigitos) % 100;
ano = hoje % divisorAnoDoisDigitos;

return String.format("Hoje é: dia %d, mês %d, ano %d. \n", dia, mes, ano);

} catch (NumberFormatException e) {
return "Erro ao formatar valor para n√ļmero.";
}
}

public static String escreverDataPorExtensoComAnoEmQuatroDigitos(String hojeComAnoEmQuatroDigitos) {
try {

if(!isDataValida(hojeComAnoEmQuatroDigitos, 8))
return ("Data Inválida, Verifique se o dia, o mês possuem 2 dígitos e o ano quatro.");

Integer hoje = Integer.parseInt(hojeComAnoEmQuatroDigitos);

Integer divisorDiaQuatroDigitos = 1_000_000;
Integer divisorAnoQuatroDigitos = 10_000;

Integer dia;
Integer mes;
Integer ano;

dia = (hoje / divisorDiaQuatroDigitos);
mes = (hoje / divisorAnoQuatroDigitos) % 100;
ano = hoje % divisorAnoQuatroDigitos;

return String.format("Hoje é: dia %d, mês %d, ano %d. \n", dia, mes, ano);

} catch (NumberFormatException e) {
return "Erro ao formatar valor para n√ļmero.";
}
}

private static boolean isDataValida(String hoje, int i) {
return hoje.length() == i;
}

}[/php]

Back-up r√°pido de tabelas MySQL

Uma boa prática  antes de atualizar a sua base é sempre fazer um back-up das tabelas que pode ser feito de forma rápida com o seguinte comando:
[sourcecode language=”html”]
// criando a nova tabela
CREATE TABLE nova_tabela LIKE minha_base.tabela;
// copiando os dados

INSERT nova_tabela SELECT * FROM minha_base.tabela;
[/sourcecode]

CHAR ou VARCHAR? Que tipo de campo escolher no MySQL?

Ambos os tipos de campo “texto” podem ser definidos com um comprimento m√°ximo no MySQL. A principal diferen√ßa entre os dois tipos de campos √© que o CHAR sempre armazenar√° o texto com o tamanho fixo, mesmo que o “texto” seja menor do que o tamanho m√°ximo especificado na cria√ß√£o do campo. Neste caso, o pr√≥prio SGBD do MySQL ir√° usar espa√ßos a direita do “texto” preenchendo o campo at√© a quantidade m√°xima especificada em sua cria√ß√£o. Note, que esses espa√ßos ser√£o removidos quando voc√™ recuperar os dados a armazenados.

Por outro lado, “textos” armazenadas em uma coluna VARCHAR exigem apenas o tamanho do “texto” armazenado. Portanto, a palavra “ivo” em uma coluna VARCHAR(10) ir√° requerer quatro bytes de espa√ßo (o comprimento do “texto” mais 1), enquanto em uma coluna CHAR(10), a mesma palavra exigir√° 10 bytes de espa√ßo.

Assim, de modo geral, as colunas VARCHAR tendem a consumir menos espa√ßo em disco do que colunas CHAR. Contudo, as bases de dados s√£o normalmente mais r√°pidas quando se trabalha com colunas de tamanho fixo, o que √© um argumento a favor de CHAR. E essa mesma palavra de tr√™s letras, “ivo”, em um CHAR(3) utiliza apenas 3 bytes, enquanto em um VARCHAR(10) requer 4. Desta forma, como decidir qual usar?

Se o “texto” for sempre de um tamanho determinado¬†(por exemplo, uma abreviatura do estado), use CHAR, caso contr√°rio,¬†use VARCHAR. Voc√™ pode notar, por√©m, que, em alguns casos, o MySQL define uma coluna de um tipo (como CHAR) embora voc√™ a tenha criado como outro tipo (VARCHAR). Isto √© perfeitamente normal e √© a maneira que o MySQL possui para melhorar o desempenho.

OBS: Note que a palavra texto encontra-se marcada aqui no sentido de ressaltar que o campo “string” pode, al√©m de conter caracteres, conter tamb√©m n√ļmeros, datas ou listas armazenadas como texto (string). Neste caso, n√£o poder√£o ser usadas as fun√ß√Ķes SQL de c√°lculo espec√≠ficas de outros tipos. A n√£o ser que sejam convertidas antes.

Fonte: PHP 6 and MySQL 5 for Dynamic Web Sites. ULLMAN, Larry, 2007.

Tipos de Campos no MySQL, saiba como escolher o tipo correto

Este post tem o objetivo de ajudar o desenvolvedor na escolha adequada do tipo de campo que dever√° utilizar no banco MySQL para persistir seus dados.

O desenvolvedor inexperiente costuma confundir bastante os tipos de campo da linguagem utilizada (PHP por exemplo) com os tipos que o banco pode armazenar. Um exemplo clássico dessa confusão é o booleano que é automaticamente convertido de true para 1 e false para 0 (zero).  Além disso, há o clássico erro de armazenamento de CPF em campo numérico o que faz com que todos os zeros a esquerda se percam.

Portanto coloco abaixo a tabela com os campos do MySQL para que sirva de um guia de implementação do banco de dados de sua aplicação.

Lembro ainda que antes de mais nada voc√™ deve identificar qual o tipo de vari√°vel que ir√° armazenar: n√ļmero, texto, bin√°rio, data,¬† lista ou combina√ß√£o destes. Em seguida estimar o tamanho do campo e se ser√° vari√°vel ou fixo. O MySQL costuma preencher campos texto n√£o vari√°veis com espa√ßos em branco. Em seguida, verificar se permitir√° nulo ou n√£o, se √© uma chave candidata, prim√°ria, estrangeira, √≠ndice ou √ļnico.

N√£o h√° uma regra fixa para saber como os bancos dever√£o ser implementados, mas tenha sempre em mente que neste caso, mais √© melhor. Ou seja, √© melhor sobrar espa√ßo do que ter uma informa√ß√£o inserida com peda√ßos faltando. J√° viu algu√©m nascer no “Rio de Jane” pois o desenvolvedor n√£o colocou o campo com o tamanho correto?!

Observa√ß√Ķes:

  • O tamanho do campo para tipos num√©ricos n√£o afeta o intervalo de valores que¬†pode ser armazenado na coluna. Colunas definidas como TINYINT (1) ou TINYINT (20)¬†podem armazenar exatamente, os mesmos valores. Em vez disso, para inteiros, o tamanho determina a¬†largura do campo, para casas decimais, o tamanho √© o n√ļmero total de d√≠gitos que pode ser armazenado.
  • Muitos dos tipos de dados t√™m nomes sin√īnimos: INT e INTEGER, DEC e DECIMAL, etc
  • O tipo de campo TIMESTAMP √© automaticamente definido com a data e hora quando um INSERT ou UPDATE ocorre, mesmo se nenhum valor for especificado para esse campo . Se uma tabela possui m√ļltiplas colunas TIMESTAMP, somente a primeira ser√° atualizada quando um INSERT ou UPDATE √© realizado.
  • MySQL tamb√©m tem diversas variantes para os tipos de texto que permitem o armazenamento de dados bin√°rios. Estes tipos s√£o BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, e LONGBLOB. Esses tipos s√£o usados para armazenamento de arquivos ou dados criptografados.
Tipos Numéricos
Tipo Uso Tamanho
Atributo MIN MAX
TINYINT Um inteiro muito pequeno Signed: -128 127
Unsigned 0 255
SMALLINT Um inteiro pequeno Signed: ‚Äď32768 32767
Unsigned 0 65535
MEDIUMINT Um inteiro de tamanho mediano Signed: ‚Äď8388608 8388607
Unsigned 0 16777215
INT or INTEGER Um inteiro de tamanho normal Signed: ‚Äď2147483648 2147483647
Unsigned 0 4294967295
BIGINT Um inteiro de temanho grande Signed: ‚Äď9223372036854775808 9223372036854775807
Unsigned 0 18446744073709551615
FLOAT Um pequeno n√ļmero de ponto flutuante (precis√£o simples) Signed ‚Äď3.402823466E+38 ‚Äď1.175494351E-38, 0
1.175494351E-38 3.402823466E+38
N√£o pode ser unsigned
OBS Se o n√ļmero de decimais n√£o for especificado ou for <= 24 ser√° de precis√£o simples
DOUBLE,
DOUBLE PRECISION,
REAL
Um n√ļmero de ponto flutuante de tamanho normal (precis√£o dupla) Signed -1.7976931348623157E+308 -2.2250738585072014E-308, 0
2.2250738585072014E-308 1.7976931348623157E+308
N√£o pode ser unsigned
OBS Se o n√ļmero de decimais n√£o for especificado ou for 25 <= Decimals <= 53 ser√° de precis√£o dupla
DECIMAL,
NUMERIC
Um n√ļmero de ponto flutuante descompactado . Signed Se comporta como um campo CHAR: “descompactado” significa que o n√ļmero √© armazenado como uma string, usando um caractere para cada d√≠gito do valor. O ponto decimal e, para n√ļmeros negativos, o sinal ‘-‘ n√£o √© contado. Se o decimal for 0, os valores n√£o ter√£o ponto decimal ou parte fracion√°ria. O alcance m√°ximo de valores decimais √© o mesmo que para o DOUBLE, mas a faixa atual para um campo DECIMAL dado pode ser limitado pela escolha de comprimento e decimais.
N√£o pode ser unsigned
OBS Se Decimais é deixado de fora ele é definido como 0. Se o comprimento é deixado de fora ele é definido como 10. Note que no MySQL 3,22 o comprimento inclui o sinal eo ponto decimal
Campos de Datas
Formato MIN MAX
DATE Data ‚Äė1000-01-01‚Äô ‚Äė9999-12-31‚Äô
OBS Formato: ‚ÄėYYYY-MM-DD‚Äô
DATETIME Data e hor√°rio ‚Äė1000-01-01 00:00:00‚Äô ‚Äė9999-12-31 23:59:59‚Äô
OBS Formato: ‚ÄėYYYY-MM-DD HH:MM:SS‚Äô
TIMESTAMP Timestamp ‚Äė1970-01-01 00:00:00‚Äô aproximadamente 2037
OBS Formato: YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD ou YYMMDD, dependendo se M √© 14 (ausente), 12, 8 ou 6, podendo ser strings ou n√ļmeros.

Este tipo √© recomend√°vel para instru√ß√Ķes de INSERT ou UPDATE pois √© automaticamente marcado com os valores da opera√ß√£o mais recente quando n√£o informado.

TIME A time ‚Äė-838:59:59‚Äô ‚Äė838:59:59‚Äô
OBS formato: ‚ÄėHH:MM:SS‚Äô, podem ser strings ou n√ļmeros
YEAR Anos com 2 ou 4 digitos. O padrão é 4 digitos 4 digitos 1901 2155 e 0000
2 digitos 1970 2069
OBS Formato: YYYY
podem ser strings ou n√ļmeros.
Campos Texto
MIN MAX
CHAR String de tamanho fixo. Sempre é completada com espaços a direita até o tamanho definido 1 255 caracteres
OBS Espaços excessivos são removidos quando o valor é trazido.Os valores são ordenados e comparados ignorando caixas altas e baixas de acordo com a codificação padrão, a menos que seja fornecido uma chave binária.
VARCHAR String de tamanho vari√°vel 1 255 caracteres
OBS Os valores são ordenados e comparados ignorando caixas altas e baixas de acordo com a codificação padrão, a menos que seja fornecido uma chave binária.Nota: Espaços execessivos são removidos quando o valor é inserido.
TINYTEXT 0 255 (2^8 – 1) caracteres
TEXT 0 65535 (2^16 – 1) caracteres
MEDIUMTEXT 0 16777215 (2^24 – 1) caracteres
LONGTEXT 0 4294967295 (2^32 – 1) caracteres
Dados Bin√°rios
TINYBLOB 0 255 (2^8 – 1) caracteres
BLOB 0 65535 (2^16 – 1) caracteres
MEDIUMBLOB 0 16777215 (2^24 – 1) caracteres
LONGBLOB 0 4294967295 (2^32 – 1) caracteres
Listas
MIN MAX
ENUM Enumeração String que pode conter apenas um valor ou zero 65535 valores distintos.
SET Lista String que pode conter zero ou mais valores 64 itens
fonte: http://help.scibit.com/Mascon/masconMySQL_Field_Types.html e http://dev.mysql.com/doc/refman/5.0/en/data-type-overview.html(tradução livre)

Nota:

JQuery e AJAX – Combo de Estado e Cidade

Essa semana precisei implementar uma solu√ß√£o de combo din√Ęmico de Estado / Cidade que carregasse as op√ß√Ķes das cidades de acordo com a escolha do estado. Obviamente teria que usar Ajax (JQuery) e o Json (JavaScript Object Notation) que √© um formato leve de troca de dados (fonte: http://www.json.org/).

Fiz uma pesquisa r√°pida na NET e de cara encontrei um excelente artigo de Davi Ferreira: “Populando selects de cidades e estados com AJAX (PHP e jQuery)” (http://www.daviferreira.com/posts/populando-selects-de-cidades-e-estados-com-ajax-php-e-jquery). No entanto para o meu caso a solu√ß√£o do Davi teria que ser reinventada tendo em vista que no meu form haviam 3 conjuntos de Estado/Cidade. Um para os dados de endere√ßo do usu√°rio e outros dois para os dados profissionais. Uma op√ß√£o seria repetir o c√≥digo 3 vezes, uma para cada conjunto, o que n√£o √© nada elegante.

A op√ß√£o foi portanto, criar uma fun√ß√£o dentro do Javascript que fizesse o trabalho sujo de forma din√Ęmica. Ao inv√©s de criar uma fun√ß√£o JS que aproveitasse o JQuery, segui a sugest√£o do Basil Godman, “Definindo suas pr√≥prias fun√ß√Ķes com o JQuery” (http://blogs.microsoft.co.il/blogs/basil/archive/2008/09/22/defining-your-own-functions-in-jquery.aspx) e criei uma fun√ß√£o do pr√≥prio JQuery.

Outra coisa que fiz tamb√©m foi retirar o campo de “span” est√°tico com a mensagem “Carregando …” como sugere o Davi. Ela agora aparece de forma din√Ęmica dentro da pr√≥pria fun√ß√£o. Facilitando a manuten√ß√£o, inclus√£o de em gif animado, uma classe espec√≠fica e despoluindo o HTML, imagina isso para 4 ou 5 campos Estado/Cidade!

Abaixo você poderá baixar o código completo inclusive com o DDL e o DML do MySQL, além de verificar os 4 arquivos necessários para que tudo funcione comentados.

Arquivos completos para download

Arquivo de conex√£o com o Banco
[php]$con = mysql_connect( ‘localhost’, ‘root’, ” ) ;
mysql_select_db( ‘cadastro’, $con );[/php]

O PHP e o HTML dos Selects
[sourcecode language=”html”]<?php
require("conn.open.php");

function listaEstadosOrderIdAsc(){
return mysql_query("SELECT cod_estados, sigla FROM estados ORDER BY sigla ASC");
}
?>
<p>
<label for="cod_estados">Estado:</label>
<select name="cod_estados" id="cod_estados">
<option value="">(selecione aqui)</option>
<?php $estados = listaEstadosOrderIdAsc(); while ($row = mysql_fetch_object($estados)) { ?>
<option value="<?php echo $row->cod_estados; ?>"><?php echo $row->sigla; ?></option>
<?php } ?>
</select>
<label for="cod_cidades">Cidade:</label>
<select name="cod_cidades" id="cod_cidades">
<option value="">– Escolha um estado –</option>
</select>
</p>
[/sourcecode]

Aqui a função JQuery propriamente dita, comentada para facilitar o entendimento.

[sourcecode language=”javascript”]
$(document).ready(function(){

// Por Rogerio Coli, www.rcoli.com.br – favor n√£o remover
jQuery.fn.carregaCidades = function() {

// Objeto que guarda os argumentos
var args = arguments[0] || {};

//id do Select de Cidades
var idSelectCidade = args.idSelectCidade;

// P√°gina que ir√° criar o JSon
var paginaPhpCidades = ‘cidades.ajax.php’;

// Conte√ļdo do elemento span que vai aparecer enquanto carregam as cidades,
// pode ser substituído por uma imagem. Coloque a tag completa
var carregandoMsg = ‘Aguarde, carregando…’

// Classe do elemento span que vai aparecer enquanto carregam as cidades
var carregandoClass = ‘class’;
// após as cidades carregarem aparece esta mensagem
var jsonPrimeiroElemento = ‘(selecione a cidade)’;
// Aqui eu pego a frase do primeiro option de Cidade
var primeiroElemento = $(idSelectCidade).find(‘option:first’).html();

if( $(this).val() ) {
// escondendo as cidades até carregarem
$(idSelectCidade).hide();
// mensagem de espera: carregando
$(idSelectCidade).after(‘<span class=’+ carregandoClass +’>’+carregandoMsg+'</span>’);

$.getJSON(paginaPhpCidades+’?search=’,{cod_estados: $(this).val(), ajax: ‘true’}, function(j){
// √Č importante que o value seja vazio pra que o formul√°rio n√£o seja enviado vazio
// caso use o form validate
var options = ‘<option value="">’+jsonPrimeiroElemento+'</option>’;
for (var i = 0; i < j.length; i++) {
// √Č importante que o value seja vazio pra que o formul√°rio n√£o seja enviado vazio
// caso use o form validate
options += ‘<option value="’ + j[i].cod_cidades + ‘">’ + j[i].nome + ‘</option>’;
}
// mostrando as cidades após carregarem e removendo a mensagem de espera
$(idSelectCidade).html(options).show();
$(idSelectCidade).next().remove();
});
} else {
$(idSelectCidade).html(‘<option value="">’+primeiroElemento+'</option>’);
}

};
//Inciando o SELECT, importante ao recarregar a p√°gina
$("#cod_estados option:first").attr(‘selected’,’selected’);
// Aqui eu chamo a função e o método que irá carregá-la
$(‘#cod_estados’).change(function(){ $(this).carregaCidades({idSelectCidade: ‘#cod_cidades’}); })
});
[/sourcecode]

O Arquivo AJAX que monta o JSon

[sourcecode language=”php”]
header( ‘Cache-Control: no-cache’ );
header( ‘Content-type: application/xml; charset="utf-8"’, true );

require("conn.open.php");

$cod_estados = mysql_real_escape_string( $_REQUEST[‘cod_estados’] );

$cidades = array();

$sql = "SELECT cod_cidades, nome
FROM cidades
WHERE estados_cod_estados=$cod_estados
ORDER BY nome";
$res = mysql_query( $sql );
while ( $row = mysql_fetch_assoc( $res ) ) {
$cidades[] = array(
‘cod_cidades’ => $row[‘cod_cidades’],
‘nome’ => htmlentities($row[‘nome’]),
);
}

echo( json_encode( $cidades ) );

[/sourcecode]

JQuery Form Validation РValidação de Datas no Google Chrome

Recentemente me deparei com um BUG ser√≠ssimo do plugin do JQuery, form validation. O campo “data:true” do jQuery Validation Plugin 1.9.0 aceita o formato de data em portugu√™s (ex: 31/12/2011) em todos os navegadores exceto o Google Chrome (15.0.874.121 m, no momento desse artigo) e possivelmente no Safari, de acordo com algumas reclama√ß√Ķes de outros programadores com o mesmo problema.

Ao tentar buscar alternativas de contornar o problema eu percebi que havia uma funcionalidade j√° desenvolvida para a valida√ß√£o de data no formato DE (alem√£o,”29.04.1994″ ou “1.1.2006”), bastante semelhante ao padr√£o brasileiro. S√≥ que essa fun√ß√£o n√£o aparece no arquivo dispon√≠vel para o download, ou foi retirada posteriormente como pode ser visto no reposit√≥rio do GitHub do plugin. Sendo que na linha 275 (messages) alguns arquivos do site do plugin ainda fazem refer√™ncia a tal fun√ß√£o: “dateDE”.

Para normalizar a situa√ß√£o eu sugiro incluir algumas linhas de c√≥digo no seu “jquery.validate.js”, vamos a elas:

Procure nas linhas 268/275 dentro de messages aonde aparece a mensagem de data e coloque abaixo de date a linha destacada:
[sourcecode language=”javascript” highlight=”8″]
messages: {
required: "Campo obrigat&oacute;rio.",
remote: "Por favor revise este campo.",
email: "Por favor digite um e-mail v&aacute;lido.",
url: "Por favor digite uma URL v&aacute;lida.",
date: "Por favor digite uma data v&aacute;lida.",
dateISO: "Por favor digite uma data v&aacute;lida (ISO).",
dateDE: "Por favor digite uma data v&aacute;lida (DE, BR).",
number: "Por favor digite um n√ļmero v&aacute;lido.",
digits: "Por favor digite somente n√ļmeros.",
creditcard: "Por favor digite um cartão de crédito v&aacute;lido.",
equalTo: "Por favor digite o mesmo valor.",
accept: "Por favor digite um valor com uma extens√£o v&aacute;lida.",
maxlength: $.validator.format("Por favor digite mais de {0} caracteres."),
minlength: $.validator.format("Por favor digite pelo menos {0} caracteres."),
rangelength:$.validator.format("Por favor digite um valor entre {0} e {1} caracteres."),
range: $.validator.format("Por favor digite um valor entre {0} e {1}."),
max: $.validator.format("Por favor digite um valor menor ou igual a {0}."),
min: $.validator.format("Por favor digite um valor maior ou igual a {0}.")
},
[/sourcecode]

Em seguida ache a função dateISO lá pela linha 1050 e insira a a função abaixo. Atente que há a função original e a alterada
[sourcecode language=”javascript”]
// //http://docs.jquery.com/Plugins/Validation/Methods/dateDE
dateDE:function(value,element){
// Original DE
//return this.optional(element)||/^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
// Oposite ISO
return this.optional(element)||/^\d{1,2}[\/-]\d{1,2}[\/-]\d{4}$/.test(value);
},
[/sourcecode]
Agora é só fazer a chamada normalmente em sua validação:
[sourcecode language=”javascript”]
$("#form").validate({
rules:
{
data_nascimento: { required:true, minlength: 10, dateDE:true },
}
});
[/sourcecode]

Atente que esta validação não verifica se é uma data válida, somente se atende a um formato específico. Para a validação de uma data válida (meses com 30 ou 31 dias, anos bissextos e etc) é necessário
extender as funcionalidades do plugin. Em breve farei isso, até lá.

O que é Spring Web Flow?

Neste tutorial apresento uma s√©rie de perguntas e respostas para quem estiver interessado em saber um pouco mais sobre o Spring Web Flow e suas aplica√ß√Ķes.

O que é Spring Web Flow?
Spring Web Flow é uma extensão do Spring MVC que permite a implementação do fluxo de navegação de uma aplicação web.

O que é fluxo de navegação?
Um fluxo encapsula uma seq√ľ√™ncia de etapas que guiam o usu√°rio atrav√©s da execu√ß√£o de algumas tarefas de neg√≥cios. Ele abrange v√°rias solicita√ß√Ķes HTTP, estados, dados transacionais, √© reutiliz√°vel e pode ser din√Ęmico e de longa dura√ß√£o.

Quando devo usar o Spring Web Flow?
Quando sua aplicação necessitar de uma navegação controlada. Por exemplo, o check-in para um voo, a solicitação de um empréstimo, carrinho de compras, ou mesmo adicionando um passo de confirmação para um formulário. O que esses cenários têm em comum é uma ou mais das seguintes características:

  1. Há um início claro e um ponto final.
  2. O usuário deve passar por um conjunto de telas em uma ordem específica.
  3. As altera√ß√Ķes n√£o s√£o finalizados at√© a √ļltima etapa.
  4. Uma vez completo, não deve ser possível repetir uma transação acidentalmente.

Em que mais o Spring Web Flow pode ajudar?
Pode ajudar em aplica√ß√Ķes onde:

  1. Visualizar o fluxo é muito difícil.
  2. A aplicação tem um monte de código de acesso a sessão HTTP.
  3. Forçar a navegação controlada é importante, mas não possível.
  4. O suporte adequado ao botão Voltar do navegador parece inatingível.
  5. O navegador e o servidor ficam fora de sincronia com o uso do bot√£o “Voltar”.
  6. Várias abas do navegador causam problemas de concorrência com os dados da sessão HTTP.

Posso Integrar o Spring Web Flow com outras Tecnologias?
Certamente, Spring Web Flow fornece uma linguagem declarativa de defini√ß√£o de fluxo para os fluxos de cria√ß√£o em um n√≠vel maior de abstra√ß√£o. Ele permite que ele seja integrado em uma grande variedade de aplica√ß√Ķes sem quaisquer altera√ß√Ķes (para o modelo de programa√ß√£o de fluxo), incluindo Spring MVC, JSF, e at√© mesmo aplica√ß√Ķes Portlet web.

fonte: http://www.springsource.org/spring-web-flow#documentation. Acessado em 14/11/2011.

Tutorial Spring MVC and WebFlow

Para quem entende inglês e está interessado em aprender um pouco mais sobre o Spring eu sugiro que acompanhe a série de vídeos do pessoal do Virtual Pair Programmers no canal de VPPChesterwood (http://www.youtube.com/user/VPPChesterwood) do youtube.

Trata-se de uma série de vídeos do curso deles de Spring e Webflow, obviamente os vídeos não são completos pois o negócio dos caras é vendê-los o que vale a pena fazer já que concedem desconto de 20% para estudantes, bastando entrar em contato por e-mail e solicitar o código promocional.

Para quem não sabe o que é Webflow segue uma breve explicação: é um plugin do mesmo fabricante do Spring, o Spring Source Community, capaz de controlar fluxo de navegação do usuário com mais propriedade. Indicado quando é necessário o controle mais preciso da navegação. Para saber mais leia este post.

Abaixo você encontra os vídeos na forma cronológica do curso e com a descrição do capítulo. Aproveitem!

 

1 – Introduction
A quick overview of the course.

 

2 – Getting Started
We configure your development environment and Tomcat. In case you need a review of plain MVC, we give a quick overview. You may not need this chapter if you have already done web development and are familiar with MVC.

 

3 – Spring MVC Controllers
We now write our first Spring-MVC controller. We’ll see how to configure the “DispatcherServlet” and what the @RequestMapping annotation is.

 

4 – Automatic Controller Scanning
Although the controller we previous wrote works, many projects use an alternative approach which reduces the amount of XML you need. In this short chapter we show how this works.

 

5 – Parameters and Sessions
We now see how to pass parameters from a web page to a controller, and then how to handle sessions.

 

6 – Form Handling
We’ll now add a more complex form and we’ll see how to “bind” an object to the form.

 

7 – Validation
The most important aspect of Forms is how to check they are valid before you process them. Here, we add “manual validation” to your form.

 

8 – Declarative Validation (JSR-303)
An alternative to manual validation is “declarative validation”, covered by a Java standard called JSR-303.

 

9 – Alternative Views
As well as JSP, Spring-MVC supports a range of different views. Here we look at PDF and Excel spreadsheets.

 

10 – View Resolvers
Many projects use View Resolvers with Spring-MVC – these remove hardcoding from your controllers. We’ll add two view resolvers to our code and see the benefit.

 

11 – Ajax and JSON
We give a full overview of Ajax in case you’re new to it. Then we see how a simple annotation is used to make a Spring controller work with an Ajax client.

 

12 – WebFlow – Getting Started
WebFlow is an add-on to Spring-MVC. We’ll see when it should be used, and then go through the configuration steps.

 

13 – WebFlow – Complex Flows
Now we’re set up, we’ll see how to write a professional standard flow using a very expression XML description.

 

14 – WebFlow – Going Further
We need another chapter to complete our WebFlow knowledge! We’ll see how the back button and refresh buttons work, and what Flash Scope is.

 

15 – Where to go Next
We’ve aimed to get you to a professional standard in Spring-MVC and WebFlow. We can’t quite cover everything, so we now describe your next steps. We also briefly cover the legacy Spring-MVC controllers.

 

16 – Practicals and Code
All the code you need for the course.

Assine o RSS de meus Artigos e Comentários.