1. Introdução

Mostrar uma barra de progresso em uma aplicação web não é tarefa fácil, não é a mesma coisa que em uma aplicação desktop, uma vez que a própria arquitetura web não facilita as coisas para o desenvolvedor, tanto do lado do cliente quanto do lado do servidor. Mas como em informática agente sempre dá um jeitinho, quero compartilhar com vocês o plugin JQuery MyProgressBar, que desenvolvi para contornar essa situação de maneira simples e prática.

O plugin funciona independente de linguagem, porém no nosso caso, vamos utilizar o Java, mas precisamente mostrando exemplos em Grails e JSF.

2. Como funciona

Como funciona

Figura 1. Como funciona

O processo inicia a partir de uma ação na camada de visualização (navegador), pode ser um botão, um link ou um código javascript. Essa ação chama um método no servidor (iniciarProcesso)que deverá criar uma thread com o processamento desejado que atualize uma variável de sessão com o percentual corrente do processo.

Listagem 1: A reposta dessa ação deverá renderizar uma página com o código javascript de execução do plugin:

< script type="text/javascript">
  jQuery.startProgress({url:'/método-de-atualizacao',success:function (){
	// coloque aqui o código de sucesso
  },
  erro: function (msg){
  	// coloque aqui o código de erro
  }});
</script>

Uma vez executado o método startProgress(), as ações ficam por conta do plugin que passa a fazer a mágica da visualização da barra de progresso na tela com o percentual processado.

Listagem 2: Para o plugin fazer essa atualização em tempo real, o mesmo precisa de um segundo método no servidor que retorne um código JSON no seguinte formato:

{
	status: < situacao-do-processamento>, 
	percent: < percentual-do-processamento>,
	erro: < erro-do processamento>
}

onde,

status 0: Fim do processamento com sucesso
1: Em processamento
2: Fim do processamento com erro.
percent Indica o percentual do processamento
erro Mensagem de erro para o status 2

3. Exemplo prático

Nosso exemplo será todo em Grails, mas em alguns pontos vou mostrar como ficaria utilizando JSF para deixar claro que independente de plataforma o plugin funciona normalmente.

Antes precisamos baixar os seguintes arquivos:

I. Criando o Serviço (apenas para Grails).

Listagem 3: Levando em consideração que você já tenha criado uma aplicação em Grails ou JSF com o nome de ProgressBarExemplo, vamos criar em grails um serviço com escopo de sessão para armazenar o percentual de progresso. Para isso execute o comando create-service ProgressBar e configure conforme o exemplo a seguir.

class ProgressBarService {

    static transactional = false
    static scope = "session"
    int percent

    def update(percent) {
	this.percent = percent
    }
	
    def getPercent() {
	return percent
    }
	
}

II. Criando o Controlador (Grails) ou FacesBean (JSF).

Listagem 4: Da mesma forma que criamos o serviço em grails, vamos agora, criar nosso controlador através do comando create-controller ProgressBar .Em seguida, configure conforme o exemplo a seguir.

class ProgressBarController {
	ProgressBarService progressBarService
	
       def index = { 
	}
	
	def start = {
		Thread.start {
			def percent = 0
			while (percent <= 100) {
				progressBarService.update(percent)
				percent++
				sleep(200)
			}
		}
		render (view:'index', model:['started':true])	
	}
	
	def updateProgress = {
		def percent = progressBarService.percent
		def status = percent < 100 ? 1 : 0 
		def erro = ''  render(text:"
        {status:${status},percent:${percent},erro:\"${erro}\"}",modal:[])
	}
	
}

Listagem 5: Para quem está usando o JSF, crie um FacesBean com escopo de sessão, conforme o exemplo a seguir.

public class ProgressBarFacesBean {

	public class ProgressBarFacesBean {

	private int percent;
	
    public String index() {
    	return "index";
	}
	
	public String start() {
		
		new Thread() {
			public void run() {
				percent = 0;
				while (percent <= 100) {
					percent++;
					sleep(200);
				}
			}
		};

		FacesContext.getCurrentInstance().getExternalContext().
       getRequestMap().put("started", true);

		return "index";	
	}
	
	public void updateProgress(ActionEvent event) {
		int status = percent < 100 ? 1 : 0; 
		String erro = "";
		response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write("
       {status:"+status+",percent:"+percent+",erro:\""+erro+"\"}");		
	}	
	
}
III. Criando a visualização (index.gsp ou index.jsp).

Listagem 6: Nossa página terá apenas um link para iniciar o processo e o trecho de código javascript para invocar o método startProgress() do plugin MyProgressBar.

<html>
    <head>
        <title>Progress Bar</title>
	    	< g:javascript library="jquery/jquery-1.3.2" />
	    	< script type="text/javascript">jQuery.noConflict();</script>
	    	< g:javascript library="jquery/jquery.myprogressbar-1.0.0" />
    </head>
    <body>
		
		<g:link action="start">Iniciar</g:link>    	
		
		<g:if test="${started}">
			<script type="text/javascript">
				jQuery.startProgress({url:
                      '/ProgressBarExemplo/progressBar/updateProgress', 
                      success:function (){
                     alert('sucesso');
				},
				erro: function (msg){
					alert('erro');
				}});
			</script>
		</g:if>
		
    </body>
</html>

Para fazer em JSF o código é basicamente o mesmo, já que se trata de HTML, apenas as tags específicas (g:link e g:if) deverão ser substituídas pelas correspondentes.

IV. Executando nosso exemplo.

Como podemos ver na imagem a seguir, o plugin MyProgressBar renderiza uma barra de progresso no centro da tela parecida com a do GMail, porém com o percentual atualizando em tempo real junto com a barra.

Ilustração da Barra

Figura 2. Ilustração da Barra

4. Conclusão.

Embora com as enormes dificuldades em fazer processamento assíncrono em aplicações web, podemos dar um jeitinho e fazer bastantes coisas como é o caso da barra de progresso que acabamos de construir. Recurso esse, que deixa nossas interfaces gráficas muito mais intuitivas e com a sensação da percepção do progresso daquilo que se está processando, além de deixar o usuário a vontade para fazer outras tarefas enquanto espera a conclusão do processo.

O plugin MyProgressBar ainda está na versão inicial mas já pode ser utilizado em aplicações web que tenham processos longos ou até mesmo para substituir aqueles gifs animados que não dizem absolutamente nada do que está acontecendo do lado do servidor.