Problemas com arquivos .properties

Boa tarde pessoALL.

Estou com um problema… Desenvolvi uma classe utilizando o pattern Singleton para obter a conexão ao banco de dados lendo um arquivo .properties. Testei num projeto que abri no eclipse e esta funcionando perfeitamente sem problemas. Gerei um .jar dessa classe e joguei na pasta \WEB-IF\lib de um projeto web (tomcat) que estou utilizando para testes. Joguei o arquivo .properties na mesma pasta onde esta o meu .jar. Ao executar o projeto ne retorna a seguinte mensagem :

java.lang.Exception: db.properties (The system cannot find the file specified)

Alguem tem alguma ideia do que pode estar acontecendo ?

Segue abaixo a minha classe de acesso ao banco:

[code]
/**

  • @Class DBconnection
  • @Version 1.0
  • @Author Alexandre Costa
  • Implementação do pattern Singleton para conexão a banco de dados

**/

package br.zj8t.bd;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public final class DBConnection{

//Referência para instância única
private static Connection instance;

// Atributos do banco de dados
private String driver;
private String url;
private String login;
private String password;


//Construtor privado
private DBConnection()throws Exception{
  try{
  		//Obtendo informações de configuração do banco de dados	
  	    this.getProperties();
  	 
 		Class.forName(this.driver);
  		instance = DriverManager.getConnection(this.url,this.login,this.password);
		
  }catch(ClassNotFoundException e){
 	    throw new Exception("Error : Driver não encontrado.");
  		     		
  }catch(SQLException e){
  		throw new Exception("Error : Não foi possível conectar ao banco de dados.");
	
  }catch(Exception e){
  	   	throw new Exception(e.getMessage());
  }
        
}

//Fornece acesso a instância única
public static Connection getConnection() throws Exception {
	
	if(instance == null){
		//Lazy instantation:só quando preciso
		new DBConnection();
	}

	//Retorna a instância única da conexão
	return instance;
	
}

//Encerra a conexão adequadamente
public static void shutdown() throws ClassNotFoundException, SQLException{

	if (instance != null){
		
		instance.close();
		instance = null;
		
	}
}

public void getProperties() throws Exception{
	
	//Abrindo o arquivo de configuração
	File file = new File("db.properties");
	Properties properties = new Properties();
	FileInputStream fis = null;
	try{
		
		fis = new FileInputStream(file);
		properties.load(fis);
		fis.close();
		
		// Recuperando valores
		this.driver = properties.getProperty("db.driver");
		this.url    = properties.getProperty("db.url");
		this.login  = properties.getProperty("db.login");
		this.password = properties.getProperty("db.password");
		
	}catch(IOException e){
		throw new Exception(e.getMessage());
	}
	
	
}

}[/code]

[quote=alexasrc][code]File file = new File(“db.properties”);
Properties properties = new Properties();
FileInputStream fis = null;

}[/code][/quote]

Não use File/FileInputStream. Há duas razões:
a) Você está tentando ler db.properties do diretório corrente, mas na verdade você não sabe, e nem deve saber, qual é o diretório corrente. (Só por curiosidade, tente logar o valor de file.getAbsolutePath(). Você vai ver que o valor retornado não tem nada nada nada a ver com o que você imagina. )

b) Em servidores de aplicações é desaconselhável tentar abrir arquivos diretamente, porque pode ser que o application server não permita que você abra arquivos diretamente.

No seu caso é melhor usar algo como getClass().getResourceAsStream(), que lhe retorna uma InputStream própria para ser usada com Properties.

Uma coisa não relacionada ao properties.

aqui:

[code]
public static Connection getConnection() throws Exception {

	if(instance == null){
		//Lazy instantation:só quando preciso
		new DBConnection();
	}

	//Retorna a instância única da conexão
	return instance;
	
}[/code]

deveria ser sincronizado para evitar que dois objetos tentem criar o objeto ao mesmo tempo:

public [color=red] synchronized [/color] static Connection getConnection() throws Exception

Tem a questão do “final” também que é discutível :slight_smile:

Olá

Se é para ficar dando palpite então meu pitaco vai para usar DataSource ao invés de DriverManager e estudar o uso de pool de conexões.

E por fim lembrar que Singletons não servem para aplicações que pretendem crescer e serem usadas em clusters.

[]s
Luca

Desse jeito resolveria o meu problema ?

              InputStream path = this.getClass().getResourceAsStream("db.properties");
              Properties properties = new Properties();
              properties.load(path);
              path.close();

[quote=Luca]Olá

Se é para ficar dando palpite então meu pitaco vai para usar DataSource ao invés de DriverManager e estudar o uso de pool de conexões.

E por fim lembrar que Singletons não servem para aplicações que pretendem crescer e serem usadas em clusters.

[]s
Luca[/quote]

Luca.

Eu não pretendo utilizar essa classe para uma aplicação de grande escabilidade. Somente para estudos mesmo. O meu proposito no inicio e estudar DAO + JSTL + JSP (MVC) para poder pegar alguns frameworks de mercado (Struts, Webwork, etc.).

[quote=Luca]
E por fim lembrar que Singletons não servem para aplicações que pretendem crescer e serem usadas em clusters.
[]s
Luca[/quote]

Desculpe a minha ignorância, mas porque não podem ser usados nesse ambiente?

[quote=skill_ufmt][quote=Luca]
E por fim lembrar que Singletons não servem para aplicações que pretendem crescer e serem usadas em clusters.
[]s
Luca[/quote]

Desculpe a minha ignorância, mas porque não podem ser usados nesse ambiente?[/quote]

Dá uma olhadinha aqui:
http://www.guj.com.br/posts/list/0/14615.java#78656

[]'s

[quote=caiofilipini]
Dá uma olhadinha aqui:
http://www.guj.com.br/posts/list/0/14615.java#78656
[]'s[/quote]

5 estrelinhas para você : )

Já tinha visto esse post mas nem lembrava dele, fico um pouco obscuro ainda, mas já deu pra pegar a idéia.
valeu.

[quote=skill_ufmt]fico um pouco obscuro ainda, mas já deu pra pegar a idéia.
valeu.[/quote]

Bom, basicamente, um Singleton só é mesmo um Singleton numa única VM. Se houver mais de uma VM envolvida, não dá pra garantir que apenas uma instância do objeto exista.

[]'s

Dica:

:arrow: When is a Singleton not a Singleton?
http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.html

[]'s

[quote=caiofilipini]
Bom, basicamente, um Singleton só é mesmo um Singleton numa única VM. Se houver mais de uma VM envolvida, não dá pra garantir que apenas uma instância do objeto exista.
[]'s[/quote]

Faz sentido…

isso não pode ser garantido nem com “final” na declaração?

Então se eu tiver duas VM, posso conseguir a façanha de duplicar todo os meus objetos? redundancia de objetos? :smiley:

A menos que seja não exatamente um singleton, mas uma constante:

public static final String isto_nao_eh_exatamente_um_singleton = “Ha ha 1.0.0.23”;

e mesmo assim, vai ser uma instância por JVM. E se cada JVM estiver rodando uma versão diferente das classes, imagine o que ocorre…

public static final String isto_nao_eh_exatamente_um_singleton = “Ha ha 1.0.0.25”;

Interessante, dessa eu não sabia, mas me bateu uma dúvida aogra, se eu não posso garantir que tenho o mesmo objeto em duas VM diferentes, nem variáveis, porque se ter 2 VMs? está me parecendo algo muito custoso para se gerenciar, até mesmo inviável.

Se tenho uma aplicação em cluster, as vm rodam locais em cada máquina, certo? como se faz esse gerenciamento de concorrência de objetos de várias VMs?

Aha, agora é que você entendeu o tamanho da encrenca.
Pra começar, não é tudo que é replicado no cluster, mas normalmente algum dado (como a sessão) que é serializável. Os objetos temporários de cada JVM não têm como ser replicados, e não faz sentido replicá-los.
Há várias formas de termos um mesmo dado “replicado” entre os diversos participantes do cluster.
Uma delas é ter um banco de dados de alta velocidade, específico para esse tipo de aplicação. Normalmente esse banco de dados é “transparente” para você (não é transparente para quem vai instalar ou gerenciar o cluster).
Mas isso implica também em guardar o mínimo de dados replicados entre os diversos participantes do cluster. Se você guardar 10MB em sessão do web server, por exemplo, você vai ter problemas graves - não adianta pôr placa de rede de 10 Gigabits.
Outra delas, que é muito nojenta (não funciona direito), é fazer com que todos os participantes do cluster fiquem jogando pacotes IP Multicast entre si, e de alguma forma eles concordem entre si sobre que versão do objeto usar.
Leia a documentação do seu servidor de aplicações, para ver como é que ele implementa o tal do cluster.

[quote=thingol]
Leia a documentação do seu servidor de aplicações, para ver como é que ele implementa o tal do cluster. [/quote]

Humm, ainda não trabalho com cluster :frowning:

Mas mesmo com tudo iso que você citou, isso ta me cheirando um problema do tipo que tive aqui com uma burrada do anasquita de sistemas que já postei em outro fórum e discuti bastante com o mister_M :slight_smile:

Ta me parecendo que vai precisar de sorte para que as coisas não sejam feitas ao mesmo tempo, ou vai ser problema grave hehe, e não me chamem para testar coisa assim ou concerteza vou ser um sortudo desse kkkk

Mas enfim, um tema legal, irei anotar aqui entre os vários que tenho para ler :wink: