Como acessar arquivo .properties a partir de uma classe na aplicação WEB?

13 respostas
L

Galera, pode ser uma coisa besta, mas tô com uma dúvida no seguinte:

Tenho uma classe Factory em minha aplicação responsável por obter conexões, e gostaria de usar um arquivo .properties para informar essa Factory a respeito da URL do banco, para não ser preciso recompilar a classe para mudar o endereço do banco.

eis o construtor:

private FactoryConexao() throws Exception{
		
	// encontra a string de conexão...
	// registra o driver jdbc...
	try{
			
	    Properties props = new Properties();
            FileInputStream in = new FileInputStream("database.properties");
            props.load(in);
            in.close();            
            URL = props.getProperty("jdbc.url");
            
	    Class.forName(DRIVER);
	}
	catch(Exception e){
	    throw e;
	}
}

obs: URL já está declarado globalmente

Acontece que estou recebendo uma Exception, indicando que o arquivo properties não foi encontrado.
Estou colocando o arquivo .properties junto da classe Factory, mas mesmo assim não está rolando.

Outra informação relevante: não estou usando Struts ou qualquer outro Framework… só JSP e Servlet mesmo; A classe acima citada não é um servlet.

Diante disso, qual o melhor lugar para se colocar o .properties e como referenciá-lo?

[]'s

13 Respostas

T

Primeira coisa: não use FileInputStream . Como seu arquivo .properties é apenas de leitura, use algo como

InputStream in = getClass().getResourceAsStream ("/resources/database.properties")

e ponha esse arquivo em algum lugar do seu PATH (talvez em WEB-INF/classes/resources/database.properties)

(aham, não sei se é getClass().getResourceAsStream() ou getClass().getClassLoader().getResourceAsStream(). Tente as duas alternativas :stuck_out_tongue:

P

não sei se isso que vc precisa lá vai :

A classe java.util.Properties guarda um conjunto de pares nome=valor, que
podem ser lidos ou gravados em um arquivo. Alem disso, a classe Properties
traz facilidades para voce acessar as propriedades e definir valores
padrao.

No exemplo abaixo, vamos carregar as propriedades padrao de um arquivo
(“padrao.properties”), depois ler as propriedades salvas pelo usuario
(“salvas.properties”), fazer algumas modificacoes, e depois salvar para uma
proxima execussao do programa:

import java.util.Properties;

. . .
// Cria e le os valores padrao
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("padrao.properties");
defaultProps.load(in);
in.close(); 

// Cria objeto de configuracao, com os valores padrao
Properties applicationProps = new Properties(defaultProps); 

// Carrega as propriedades configuradas na ultima execussao
in = new FileInputStream("salvas.properties");
applicationProps.load(in);
in.close();

. . .
// Utilizamos as propriedades quando precisarmos
String nome = applicationProps.getProperty("nome.usuario");
String servidor = applicationProps.getProperty("servidor.ip");

. . .
// Modificamos os valores das (ou criamos novas) propriedades
applicationProps.setProperty("nome.usuario", "Bruno JavaMan");
applicationProps.setProperty("nova.propriedade", "12345");

. . .
// Salvamos para uma proxima execussao
FileOutputStream out = new FileOutputStream("salvas.properties");
applicationProps.store(out, "---Aqui vai um comentario ---");
out.close();

. . .

O codigo acima utiliza duas propriedades cujos nomes sao “nome.usuario” e
“servidor.ip”. Eh comum utilizamros como nomes de propriedades
nomes.separados.por.pontos ou entao NomesComIniciaisMaiusculas, seguindo os
padroes de nomenclatura de Java.

Eh tambem comum que o arquivo de propriedades tenha a extensao
“.properties”, e no exemplo acima, o arquivo salvas.properties teria ao
final um conteudo similar a:

#---Aqui vai um comentario ---
#Wed Jun 26 18:10:46 BRT 2002
nome.usuario=Bruno JavaMan
servidor.ip=10.0.0.1
nova.propriedade=12345

Observe que o metodo Properties.getProperty() sempre devolve uma String, e
no caso da propriedade “nova.propriedade”, esse valor teria que ser
convertido para um tipo numerico no momento de leitura.

Atualmente o uso de XML como forma de armazenar arquivos de configuracao
vem ganahando popularidade, mas os arquivos de propriedades continuam ser
uma forma simples e eficaz de gerenciar configuracoes simples.

V

eu coloco no src e o referencio somente (file.properties), agora se vc colocar dentro dos pacotes se nao me engano tera que referenciar os pacotes ( meu.arquivo.file.properties ).

L

[EDITADO]

Funcionando!!!

[/EDITADO]

L

Como forma de agradecimento, aí vai a classe para quem precisar:

public class FactoryConexao {

	private static FactoryConexao factory;
	private static final String DRIVER = "com.mysql.jdbc.Driver";
	private static final String USUARIO = "root";
	private static final String SENHA = "@#@#%$";
	private static String URL;
	
	/** O contrutor já tenta registrar o driver jdbc 
	 * e encontrar a string de conexão
	 * 
	 * @throws Exception
	 */
	private FactoryConexao() throws Exception{
		
		// encontra a string de conexão...
		// registra o driver jdbc...
		try{
			Class.forName(DRIVER);			
			
			Properties props = new Properties();
			InputStream in = getClass().getClassLoader().getResourceAsStream("/resources/database.properties"); 
                       props.load(in);
                       in.close();            
                       URL = props.getProperty("jdbc.url");             
			
		}
		catch(Exception e){
			throw e;
		}
	}
	
	/** O método retorna uma instância de FactoryMethod, e caso
	 * não encontre uma válida tenta criá-la. 
	 * 
	 * @return uma instância de FactoryMethod.
	 */
	public static FactoryConexao getInstance() throws Exception{
		
		if(factory==null){
			factory = new FactoryConexao();
		}		
		return factory;
	}
	
	
	/** Retorna uma conexão com o banco de dados.
	 * 
	 * @return uma instância de Connection;
	 */
	public synchronized Connection getConnection() throws Exception{
		
		Connection conn = null;		
		
		try{
			conn = DriverManager.getConnection(URL, USUARIO, SENHA);
			return conn;
		}
		catch(Exception e){
			throw e;
		}
	}
	
}

Críticas e sugestões são bem vindas!

[]'s e mais uma vez obrigado a todos que ajudaram.

L

Maracuja:
Pq não usa Resource Bundle???

http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html

Acredito que usando o arquivo .properties, neste caso, é mais simples.
Mas de qualquer maneira, muito obrigado pela dica… li a referência e achei muito interessante.

[]'s

L

o que te faz tão crente disso?
você pode ter certeza de que se eu disse que li, é porque li… :smiley:

entendi sim maninho… mas o ResourceBundle me pareceu mais interessante no caso de uma necessidade de internacionalização da aplicação (uma das principais finalidades dele, não é)

só acho mais prático usar um properties para colocar uma única linha (jdbc.url=jdbc:mysql://host/banco) do que criar um ResourceBundle só para isso.

realmente pensei nisso… :smiley: vou avaliar essa alternativa também.

Essa dica do ResourceBundle acabou sendo valiosa, mas para um outro sistema que tenho aqui, que fiz em Swing.
Estou pensando em torná-lo Open-Source, e uma das coisas que quero fazer é prepará-lo para a internacionalização.
Esse sistema envolve relatórios, e os relatórios estariam sujeitos à internacionalização (claro) mas não só com relação ao idioma, mas à própria estrutura.
Ele começa a ficar interessante para mim aqui:

pois posso incluir os relatórios no ResorceBundle.

[]'s e obrigado pelas dicas!

G

Olá, estou com um problema parecido.

Estou fazendoa configuração da minha classe utilizando um arquivo xml. Como o xml não é um arquivo de propriedades (key=value), não dá para usar um ResourceBundle (ou dá???). Considerando também que esse arquivo deva ficar em algum diretório da aplicação web (WEB-INF, possivelmente), como eu poderia fazer para acessá-lo?

A

thingol:
Primeira coisa: não use FileInputStream . Como seu arquivo .properties é apenas de leitura, use algo como

InputStream in = getClass().getResourceAsStream ("/resources/database.properties")

e ponha esse arquivo em algum lugar do seu PATH (talvez em WEB-INF/classes/resources/database.properties)

(aham, não sei se é getClass().getResourceAsStream() ou getClass().getClassLoader().getResourceAsStream(). Tente as duas alternativas :P

Muito boa a dica…

Abraços,

A

Criei a pasta resources em WEB-INF depois via Eclise cliquei em Add To Build Path e coloquei o arquivo .properties mas não encontra o mesmo através da forma que estou
fazendo abaixo:

protected String getValor(String chave) { InputStream arquivoProperties = null; arquivoProperties = getClass().getResourceAsStream("/resources/versionamentoepub.properties"); try { props.load(arquivoProperties); } catch (IOException e) { e.printStackTrace(); } finally{ try { arquivoProperties.close(); } catch (IOException e) { System.err.println("Erro ao fechar conexao: " + e.getMessage()); } } return props.getProperty(chave); }

Sei fazer via a forma citada acima, num package/classpath do projeto mas gostaria de deixar dentro de WEB-INF mesmo…

R

Eu estou tentando usar esse arquivo . properties e mesmo testando com vários exemplos que encontrei na net ele não carrega as informações do arquivo.

Segue código:

#Esse seria meu arquivo banco.properties que está no mesmo pacote da classe onde irei usá-lo.

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/locadorabd
user = root
pass = ****** (teria uma senha)

//Classe que gerencia a conexão com o banco.

public class GerenciadorConexao implements IGerenciadorConexao{

public  String driver;

private String url;

private String user;

private String pass;

private static GerenciadorConexao instancia = null;

private Connection conexao = null;
private GerenciadorConexao() throws FileNotFoundException, IOException{  
    Properties props = new Properties();
    String arquivo = "banco.properties";
    
    try {
        props.load(new FileInputStream(arquivo));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    } catch (Exception ex) {
       System.out.println(ex.getMessage());
    }
}
public static GerenciadorConexao getInstancia() throws IOException {
    if(instancia==null)
        instancia = new GerenciadorConexao();
    return instancia;
}

@Override
public Connection connect() {
    if(conexao == null){
        try {
            Class.forName(driver);
            conexao = DriverManager.getConnection(url, user, pass);
        } catch (ClassNotFoundException ex) {
            //
        } catch (SQLException ex) {
            //
        }
    }
    return conexao;
}

@Override
public void disconnect() {
    try {
        conexao.close();
        conexao = null;
    } catch (SQLException ex) {
       //
    }
}

}

Não sei o que está errado, ele não encontra esse arquivo e não carrega as variáveis.

J

Pq não usa Resource Bundle???

http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html

J

Bom dia.

Pimeiro creio que vc ou não leu, ou não entendou o ResourceBundle; com um Bundle vc não deixaria de usar o .properties, e sim o utiliziraria de uma forma mais elegante (para não dizer correta) do que isso.

InputStream in = getClass().getClassLoader().getResourceAsStream("/resources/database.properties"); 
                        props.load(in);
                        in.close();

E mais uma como se tratam de dados para conexão com o Banco, pq utilizar um .properties??

É muito mais fácil, e novamente mais elegante, heheheheh, vc colocar isso como parametros de contexto a serem declarados no seu Web.xml!!!

Criado 12 de setembro de 2006
Ultima resposta 13 de set. de 2006
Respostas 13
Participantes 8