Você já parou para pensar o porque dessa obrigatoriedade para que sua aplicação funcione corretamente ? Na verdade, se você fizer um teste muito simples, verá que a própria IDE (no caso do ECLIPSE) não deixa que você execute a aplicação caso o seu método main esteja com a assinatura diferente do que foi predefinido.

Vejamos o exemplo:


public class Principal {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("iniciando aplicação...");
		
	}

}
Listagem 1. Método main da forma correta

public class Principal {

	/**
	 * @param args
	 */
	public static void main() {
		System.out.println("iniciando aplicação...");
		
	}

}
Listagem 2. Método main da forma errada

Perceba que ambos os códigos não apresentarão nenhum erro de sintaxe, de fato não deveriam, pois estão corretos. Crie uma classe igualmente a listagem 1, depois (usando o ECLIPSE IDE) clique com o botão direito do mouse sobre a classe, vá até Run As e você verá a opção: Java Application.

Isso significa, que ao clicar em Java Application nossa aplicação irá executar. Porém, se você criar uma classe igualmente a listagem 2 e tentar seguir os mesmos passos para executar a aplicação, verá que a opção Java Application não existe.

O args, definido no método main, é uma forma do “mundo externo” comunicar-se com sua aplicação através de argumentos. A sua utilidade está atrelada a diversas possibilidades de uso, que vão depender principalmente da regra de negócio de cada empresa, ou seja, a política que cada empresa adota.

Com o uso do args você pode inicializar sua aplicação parametrizando-a, ou seja, você pode definir inúmeros parâmetros de acordo com o ambiente que o usuário está rodando a aplicação. Nas seções anteriores vamos ver melhores exemplos e mais práticos a respeito do args.

Usando args

Se você trabalha com linux, deve estar acostumado a executar softwares via linha de comando (terminal) com parâmetros, a mesma lógica se aplica ao args do método main, poderemos construir uma aplicação que pode ser totalmente parametrizada em sua inicialização, assim construiremos uma aplicação robusta, portável e eficaz.

Uma aplicabilidade muito comum a este recuso é a execução de comandos específicos a uma aplicação sem interação gráfica. Imagine, por exemplo, que você está em um ambiente totalmente textual, sem nenhum GUI, e você precisa executar um comando na sua aplicação que realiza a checagem em alguns dados específicos. Se você criou um Jframe que tem um button que realiza essa função, então claramente você terá um problema. Agora como opção você poderia criar uma classe a parte (com o método main) que é parametrizada para checagem destes dados.

Este exemplo acima é um dos muitos que podem ser aplicados a este recurso, vamos abordar neste artigo um exemplo muito comum que ocorre em diversas empresas, assim poderemos assimilar melhor o uso de tal recurso.

Vamos supor o seguinte cenário para nosso exemplo: Temos uma aplicação de controle de frota de veículos, toda noite é necessário realizar uma checagem se todos os veículos estão com suas manutenções em dias, como por exemplo: troca de óleo, troca de filtro, limpeza de bico, troca de correia dentada e etc.

Fazendo uma rotina que verifique essas situações toda noite, no próximo dia, quando um funcionário acessar o sistema, ele terá alertas na sua tela, informando que determinadas veículos precisam passar por manutenção preventiva em determinados itens.

Se esse procedimento de checagem deve ser executado toda noite, quem irá executar isso ? Criaremos então uma classe chamada ChecarVeiculosAutomaticamente que terá um método main, assim poderemos executá-la independente se estivermos em um ambiente gráfico ou textual.

Não teremos aqui nenhuma interação humana, iremos configurar o crontab do linux (agendador de tarefas do linux, que não será abordado neste artigo, pois foge do escopo) para executar essa classe em determinada hora do dia, todo dia.

E onde entrará o args em todo esse cenário ? Essa mesma classe ChecarVeiculosAutomaticamente possibilitará o uso argumentos para tornar nossa aplicação bem flexível. Trabalharemos nas seguintes hipóteses:

  • Ao executar a checagem de veículos, pode ser passado um argumento para ignorarmos a checagem de veículos que possuem mais de 10 anos. Esse argumento será o: I10.
  • Ao executar a checagem de veículos, pode ser passado um argumento para ignorarmos a checagem de veículos que estão fora da empresa, em viagem externa. Esse argumento será o: ”IEXT
  • Ao executar a checagem de veículos, pode ser passado um argumento para enviarmos por e-mail um relatório sobre essa checagem. Esse argumento terá o seguinte formato: EMAIL:emaildestino@provedor.com.br.

Poderíamos ficar definindo inúmeros argumentos, mas não vamos nos prolongar mais, apenas 3 argumentos são suficientes para um bom entendimento da lógica. Dado os 3 argumentos acima poderemos mixar da forma que acharmos mais conveniente, veja os exemplos:

  • java ChecarVeiculosAutomaticamente I10 IEXT EMAIL:joao@oi.com.br
  • No exemplo acima, quando executarmos nossa classe ela saberá que deve ignorar todos os veículos com mais de 10 anos, ignorar os veículos que não estão na empresa, e enviar um relatório da checagem para o e-mail joao@oi.com.br.

  • java ChecarVeiculosAutomaticamente EMAIL:joao@oi.com.br IEXT I10
  • A ordem dos argumentos, para o nosso software, não vai importar, iremos construir uma classe capaz de entender qualquer ordem, assim excluímos a chance de erro de passagem de argumentos por ordenação errada, algo que é muito comum.

  • java ChecarVeiculosAutomaticamente EMAIL:joao@oi.com.br
  • Não exemplo 3, não vamos ignorar nada, apenas enviaremos a checagem para o e-mail descrito no argumento.

Vamos enfim criar nossa classe que fará tudo que descrevemos no cenário acima. Iremos abstrair as tecnologias que podem ser utilizadas aqui, tais como: Hibernate, Spring entre outras, pois foge do escopo deste artigo, atente apenas ao fato de como o args pode ser utilizado em uma aplicação real.


import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ChecarVeiculosAutomaticamente {

	private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.
	[_A-Za-z0-9-]+)*@"
			+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

	public static boolean isValidEmail(final String emailParaValidar) {
		Pattern pattern = Pattern.compile(EMAIL_PATTERN);
		Matcher matcher = pattern.matcher(emailParaValidar);
		return matcher.matches();
	}

	public static void main(String[] args) {
		boolean i10 = false, iext = false;
		String emailTarget = "";
		/*
		 * Lemos todos os args passados através de um foreach
		 */
		for (String arg : args) {

			/*
			 * Caso o usuário passo o argumento minusculo ou maiusculo,
			 * receberemos da mesma forma, assim evitamos o CASE SENSITIVE.
			 */
			arg = arg.toUpperCase().trim();

			/*
			 * Verifica se o argumento atual é o I10
			 */
			if (arg.equals("I10")) {
				System.out.println("Ignorando carros com mais de 10 anos");
				i10 = true;
			} else if (arg.equals("IEXT")) {
				System.out
						.println("Ignorando carros que estão fora da empresa");
				iext = true;
			} else if (arg.contains("EMAIL:")) {

				// Separamos o 'EMAIL:' do 'meuemail@provedor.com.br'
				String[] argEmail = arg.split(":");
				String email = argEmail[1];

				// Validaremos se o email é válido
				if (isValidEmail(email)) {
					emailTarget = email.toLowerCase().trim();
				} else {
					System.out.println("O Email " + email
							+ " é inválido. A execução será interrompida.");
					return;
				}

			} else {
				System.out
						.println("O argumento '"
								+ arg
								+ "' não existe, verifique se digitou 
								corretamente ou se este argumento existe");
				return;
			}
		}
		
		/*
		 * Após capturarmos os argumentos necessários,
		 * podemos começar a execução do código
		 * */
		List<Object> checados = new ArrayList<Object>();
		if (i10 && iext){
			checados = MetodosUtilitarios.checarVeiculos_
			IgnoreMaisDe10AnosEForaDaEmpresa();
		}else if (i10){
			checados = MetodosUtilitarios.checarVeiculos_
			IgnoreMaisDe10Anos();
		}else if (iext){
			checados = MetodosUtilitarios.checarVeiculos_
			IgnoreForaDaEmpresa();
		}else{
			checados = MetodosUtilitarios.checarVeiculos();
		}
		
		/*
		 * Em toda execução acima retornamos uma lista de veiculos que foram
		 * checados com algumas propriedades que não convém discutir aqui. 
		 * Agora verificamos se precisamos enviar tais dados por email
		 * */
		if (!emailTarget.isEmpty()){
			if (MetodosUtilitarios.sendEmailVeiculos(emailTarget, checados)){
				System.out.println("Email enviado com sucesso para "+emailTarget);
			}else{
				System.out.println("Não foi possível enviar o email para "+emailTarget);
			}
		}
		
		System.out.println("Veículos checados com sucesso !");

	}

}
Listagem 3. Classe ChecarVeiculosAutomaticamente

Agora é só testar a classe acima e realizar a passagem de argumentos da forma que você quiser. Veja um teste que fizemos:


Comando no terminal: 
java ChecarVeiculosAutomaticamente EMAIL:ronaldo.lanhellas@gmail.com I10 

Saída:
Checando veiculos... [Ignorando veiculos com mais de 10 anos]
Enviando email para ronaldo.lanhellas@gmail.com
Email enviado com sucesso para ronaldo.lanhellas@gmail.com
Veículos checados com sucesso !
Listagem 4. Testando classe

Conclusão

Este artigo teve como principal objetivo demonstrar o uso prático dos argumentos do método main, que são ignorados por muitos, mas tem inúmeras utilidades que podem resolver problemas antes considerados impossíveis de serem resolvidos.

Esperamos que com a aplicabilidade deste cenário explicado aqui, seja possível usufruir com mais frequência de tal recurso.