O objetivo do Jnotify é notificar (como o próprio nome já sugere) sobre alguma alteração ocorrida em determinado diretório que está sendo monitorado. Isto é muito útil em situações em que precisamos saber quando alguém alterar determinado arquivo, deletar, criar ou modificar. Há inúmeras situações onde a biblioteca Jnotify pode ser aplicada, até mesmo em comunicação de sistemas totalmente distintos.

Imagine a seguinte situação: Você tem um sistema que funciona em COBOL e outro em Java, quando uma informações for inserida no sistema em COBOL você gostaria de replicar imediatamente essa informação em Java, como fazer isso ? (Esqueça Webservice). Uma solução é escrever os dados em um arquivo TXT, XML ou qualquer de sua preferência através do COBOL, e deixar o Java monitorando esse diretório através do Jnotify. Assim quando um dado for inserido no sistema em COBOL, ele escreverá um arquivo chamado “dado001.txt” e o Java capturará esse arquivo “dado001.txt” e irá fazer a inserção no banco, tudo automático sem interação homem-máquina, ou seja, essa é literalmente uma interação máquina-máquina.

Configurando Jnotify

Para este artigo utilizaremos a biblioteca Jnotify para o Linux 64bits (disponibilizada na seção de downloads deste artigo). Vamos ao passo a passo:

  • Baixe a biblioteca libjnotify.so disponível na seção de downloads deste artigo.
  • Coloque a libjnotify.so no diretório “/usr/lib/java/”.
  • Crie um novo projeto Java no eclipse e crie também uma classe chamada Myjnotifyapp.java.
  • Vá no menu Run -> Run Configurations...
  • Na tela que abriu clique no ícone para adicionar uma nova configuração, assim como mostrado na figura 1.
Criando Launch
Figura 1. Criando Launch

Em “Project” selecione o seu projeto criado, em “Main Class” deve estar selecionada a classe Myjnotifyapp (em nosso caso). Após isso, clique na aba “Arguments” e na área “VM Arguments” digite: -Djava.library.path=/usr/lib/java.

Isso irá garantir a inicialização da biblioteca libjnotify.so pela VM (Virtual Machine), veja como ficou na figura 2.

Configurando VM Arguments
Figura 2. Configurando VM Arguments

Por fim temos que apenas adicionar a biblioteca jnotify.jar ao nosso projeto, este encontra-se na seção de downloads deste artigo.

Usando o Jnotify

Após a configuração acima ser realizada, estamos prontos para começar a utilização da biblioteca em questão. Como já temos criado uma classe Myjnotifyapp vamos trabalhar nesse para exemplificar melhor o uso do Jnotify, utilizaremos também a biblioteca LOG4J para criar logs da nossa aplicação, ou seja, quando arquivos forem criados, deletados, alterados e etc.

Veja abaixo na listagem 1 a nossa classe Myjnotifyapp completa com todos os recursos necessários para monitorar determinado diretório.


import org.apache.log4j.Logger;

import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyAdapter;
import net.contentobjects.jnotify.JNotifyException;

public class Myjnotifyapp {
	
	private static Logger logger = Logger.getLogger(Myjnotifyapp.class);

	/* Diretório que que o JNotify ficará monitorando para
	   ver se alguma das alterações solicitadas na variável 
	   'mask' ocorreram.
	 */
	private static final String PATH_TO_LISTEN = "/home/admin/monitoring_dir";
	
	/*
	 * a variável 'mask' guardará a mascará necessária para o JNotify
	 * saber o que ele deve monitorar no diretório acima. Em nosso caso
	 * ele irá monitorar: Criações, Deleções, Modificações e Renomeações de arquivos.
	 * */
	private static int mask = JNotify.FILE_CREATED |
			JNotify.FILE_DELETED |
			JNotify.FILE_MODIFIED |
			JNotify.FILE_RENAMED;
	
	/*
	 * Serve para identificar se o JNotify irá ler um diretório que foi criado
	 * dentro do nosso diretório monitorado. 
	 * Ex: /tmp/dir1. O diretório dir1 será monitorado pois está dentro de /tmp. Mas
	 * se criarmos /tmp/dir1/subdir1/, a variável 'watchSubtree' deverá estar habilitada para que
	 * o JNotify monitore também o subdir1. 
	 * */
	private static boolean watchSubtree = true;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		/*
		 * Iniciamos a criação de Watch apartir da API JNotify, e gravamos o seu ID na 
		 * variável watchID, assim podemos remover posteriormente esse Watch pelo seu ID.
		 * */
		try {
			int watchID = JNotify.addWatch(PATH_TO_LISTEN, mask, watchSubtree, new JNotifyAdapter() {

				@Override
				public void fileCreated(int wd, String rootPath,
						String name) {
					logger.info("Arquivo criado: "+name);
				}

				@Override
				public void fileRenamed(int wd, String rootPath,
						String oldName, String newName) {
					logger.info("Arquivo renomeado de: "+oldName+" para: "+newName);
				}
				
				@Override 
				public void fileDeleted(int wd, String rootPath, String name){
					logger.info("Arquivo deletado: "+name);
				}
				
				@Override 
				public void fileModified(int wd, String rootPath, String name){
					logger.info("Arquivo modificado: "+name);
				}
			});
			
				Thread.sleep(1000000);
			
		} catch (JNotifyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e){
			e.printStackTrace();
		}

	}

}
Listagem 1. Implementação da classe Myjnotifyapp

A classe é autoexplicativa, foram adicionados vários comentários para cada passo afim de facilitar o entendimento desta. Vamos atentar apenas a alguns pontos importantes:

  • O Jnotify gera uma checked exception, por isso precisamos fazer um bloco try-catch
  • O Thread.sleep(tempo), serve para manter a nossa classe monitorando determinado diretório por um período de tempo, se tirássemos esse código, ela apenas iria inicializar e encerrar, quase que instantaneamente.

Faça você mesmo os testes, crie um diretório a seu gosto e crie arquivos, pastas, renomeie e veja o resultado.

Conclusão

Para quem já trabalha com Java 7 pode usufruir de bibliotecas nativas do Java que fazem a mesma tarefa do Jnotify, porém neste artigo consideramos a utilização de versões anteriores a 7, pois estas não possuem recurso nativo de monitoramento de diretórios, tal como o Jnotify o faz.