Como mudar a configuração do spring dinamicamente?

Olá pessoal, estou desenvolvendo uma aplicação com spring+hibernate+jsf no qual para fazer transação com o banco de dados, injeto um bean que contém toda a configuração de um datasource, o problema é que eu quero mudar essa configuração de banco de dados(username,password,driver,url) em tempo de execução para se conectar com um outro banco, mais o spring não aceita.

Estou tentado mudar a configuração do banco de acordo com o nome de login que pertence ao contexto atual.

O sistema pega esse login e verifica em um banco temporário se esse login contém algum servidor sendo gerenciado, se tem ele pega os dados para se conectar com outro banco.

O problema é que antes de autenticar, por que também estou utilizando o spring-security, ainda não existe nenhum login no contexto atual, e o sistema nem inicia por que ele precisa dessas informações.

Dá um erro de nulo.

agradeço por qualquer respota.

Se ouver alguma duvida postarei o código.

veja JMX… acredito que isso seja uma das possiveis soluções…

Obrigado por responder !

vou dar uma pesquisada.

Mais pra melhorar a ajuda vou postar o codigo.

Tenho o seguinte arquivo do spring:

<?xml version=“1.0” encoding=“UTF-8”?>
<beans xmlns=“http://www.springframework.org/schema/beans
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance
xmlns:context=“http://www.springframework.org/schema/context
xmlns:aop=“http://www.springframework.org/schema/aop
xmlns:sec=“http://www.springframework.org/schema/security
xmlns:tx=“http://www.springframework.org/schema/tx
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd”>

    &lt;!-- Parâmetros de conexão com o banco de dados --&gt;
&lt;bean id="dataSourcePostgre" class="br.com.vicente.config.conexao.Conexao"/&gt;

     &lt;!--configuração postgre--&gt;
     &lt;bean id="daoGenericoCliente" class="br.com.vicente.util.DaoGenericoCliente"&gt;
     &lt;property name="sessionFactory" ref="sessionFactory2" /&gt;    
     &lt;/bean&gt;
     
    &lt;bean id="sessionFactory2"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt;
        &lt;property name="dataSource" ref="dataSourcePostgre" /&gt;
        &lt;property name="annotatedClasses"&gt;
            &lt;list&gt;
                    &lt;value&gt;br.com.vicente.model.Dialplan&lt;/value&gt;
                    &lt;value&gt;br.com.vicente.model.Chamada&lt;/value&gt;
            &lt;/list&gt;
        &lt;/property&gt;
            &lt;!--propriedade do hibernate--&gt;
        &lt;property name="hibernateProperties"&gt;
            &lt;props&gt;
                &lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.PostgreSQLDialect&lt;/prop&gt;
                &lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;
                &lt;prop key="hibernate.hbm2ddl.auto"&gt;update&lt;/prop&gt;
            &lt;/props&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
        
        &lt;!-- View scope, recupera o scopo --&gt;
    &lt;bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"&gt;
        &lt;property name="scopes"&gt;
            &lt;map&gt;
                &lt;entry key="view"&gt;
                    &lt;bean class="br.com.vicente.util.ViewScope"/&gt;
                &lt;/entry&gt;
            &lt;/map&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
&lt;/beans&gt;

Tenho a seguinte classe de conexão:

package br.com.vicente.config.conexao;

import br.com.vicente.managerBean.config_serializableBean;
import java.util.Properties;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class Conexao extends DriverManagerDataSource{
//informações de conexao com o banco valores default

Properties properties;
config_serializableBean obj_leitura;

public Conexao() {
le_conf();    
}

  //ler as configurações de um arquivo de propriedades
  private void le_conf() {
  obj_leitura = new config_serializableBean();      
  properties = new Properties();
  properties = obj_leitura.loadProperties();
  
  Object driver_temp = properties.getProperty("jdbc.driverClassName");
  Object username_temp = properties.getProperty("jdbc.username");
  Object password_temp = properties.getProperty("jdbc.password");
  Object banco_temp = properties.getProperty("banco");
  Object ip_temp = properties.getProperty("ip");
  Object porta_temp = properties.getProperty("porta");
  Object bancoDados_temp = properties.getProperty("bancoDados");

  String url_temp = "jdbc:"+banco_temp.toString()+"://"+ip_temp.toString()+":"+porta_temp.toString()+"/"+bancoDados_temp.toString();
      
  this.setDriverClassName(driver_temp.toString());
  this.setUrl(url_temp);
  this.setUsername(username_temp.toString());
  this.setPassword(password_temp.toString());      
}

}

Classe para pegar as configurações de um arquivo de propriedade:

package br.com.vicente.managerBean;

import br.com.vicente.model.config_serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Properties;
import java.util.Set;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

/**
*

  • @author Vicente
    */
    @ManagedBean
    @SessionScoped
    public class config_serializableBean implements Serializable{

    private String login_temp;
    private Properties table;
    private config_serializable obj_leitura = new config_serializable();
    private config_serializable obj_conf = new config_serializable();

    public config_serializableBean() {
    }

    public config_serializableBean(Properties table){
    this.table=table;
    }

    // salva as propriedades em um arquivo
    public void saveProperties()
    {
    FacesContext fc = FacesContext.getCurrentInstance();
    //pega o nome do usuario atual
    login_temp = fc.getExternalContext().getUserPrincipal().getName();
    try
    {
    FileOutputStream output = new FileOutputStream(“C:/configuracoes/conf”+login_temp+".properties");
    table.store( output, “Sample Properties” );// salva as propriedades
    output.close(); // fecha o arquivo
    }
    catch ( IOException ioException )
    {
    ioException.printStackTrace();
    }
    }

    //faz a leitura do arquivo properties
    public Properties loadProperties()
    {
    // carrega o conte?do de tabela
    Set<Object> keys=null;
    FacesContext fc = FacesContext.getCurrentInstance();
    //pega o nome do usuario atual
    login_temp = fc.getExternalContext().getUserPrincipal().getName();
    try
    {
    FileInputStream input = new FileInputStream( “C:/configuracoes/conf”+login_temp+".properties" );
    table.load(input);// carrega propriedades
    input.close(); // fecha o arquivo
    //listProperties(); // exibe os valores da propriedade
    }catch ( IOException ioException )
    {
    ioException.printStackTrace();
    }
    return table;
    }

    //gera sa?da de valores de propriedade
    public Set<Object> listProperties()
    {
    Set<Object> keys = table.keySet(); // obtem nomes de propriedade
    return keys;
    }

    public void limpar_properties() {
    FacesContext fc = FacesContext.getCurrentInstance();
    login_temp = fc.getExternalContext().getUserPrincipal().getName();
    try {
    table=new Properties();
    FileOutputStream output = new FileOutputStream(“C:/configuracoes/conf”+login_temp+".properties");
    table.store( output, “Sample Properties” );// salva as propriedades
    output.close();
    } catch (Exception erro_grava) {
    }
    }
    }

O seguinte Bean gerenciavel:

package br.com.vicente.managerBean;

import br.com.vicente.model.Dialplan;
import java.io.Serializable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

/**
*

  • @author Vicente
    */
    @Controller(“dialplanBean”)
    @Scope(“view”)
    public class dialplanBean implements Serializable{
    public Dialplan dialplan = new Dialplan();

    @Autowired
    public dialplanBean(DaoGenericoCliente daoGenericoCliente) {
    this.daoGenericoCliente = daoGenericoCliente;
    }

    //apartir daqui utilizo o objeto daoGenericoCliente para salvar, deletar, atualizar e pesquisar

}

Quando o sistema inicializa o arquivo spring-config é carregado e procura pela classe de conexão para pegar os dados
de conexão. Através do login que é o nome que está no contexto atual, ele procura por um arquivo chamado nomedologin.properties.
Mas quando a aplicação ainda está iniciando ele tenta carregar essas informações mas esse nome de login ainda é nulo, então dá um erro e o sistema não chega nem a iniciar.

Eu preciso modificar a configuração enquanto o sistema estiver rodando pra me conectar com outros servidores.

Da forma que está, só posso me conectar com um banco só e esse é o problema.

Toda vez que precisar gerenciar outro banco é necessario parar o servidor e modificar as configurações na mão pra funcionar, tornando a aplicação totalmente inviavel.

Já tentei fazer o seguinte ao invés de carregar o spring-config na inicialização,
coloco esse arquivo em um pacote junto com as classes java, fora da inicialização que estáva no arquivo web.xml.

E pego o bean através da seguinte classe:

package br.com.vicente.config.conexao;

import org.springframework.context.support.ClassPathXmlApplicationContext;

   /*
    * Lê o arquivo de configuração do spring (spring.xml) e fornece métodos para recuperar os beans declarados no arquivo de configuração do spring
    */
 public class BeanFactory {
 
 public ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("br/com/vicente/config/conexao/spring-config.xml");         

 public Object getBean(String beanName) {
     return ctx.getBean(beanName);
 }
 
 public Object getBean(String beanName, Class classe) {
     return ctx.getBean(beanName, classe);
 }
 
}

e na classe que vou fazer as operações com o banco de dados faço o seguinte:

daoGenericoCliente = (DaoGenericoCliente) new BeanFactory().getBean("daoGenericoCliente");    

public void insere() {
daoGenericoCliente.insere(obj);      
}


public void excluir() {
daoGenericoCliente.exluir(obj);      
}


public void atualiza(){
daoGenericoCliente.atualiza(obj);    
}

Dessa forma funciona porque o arquivo é carregado depois de iniciado, pois já tenho um login no contexto atual e ele não é mais nulo.

Mas toda vez que precisar fazer uma transação com o banco esse arquivo terá que ser carregado, deixando a aplicação muito lenta.

Mais muito lenta mesmo… não vale a pena.

O que preciso é conseguir alguma outra solução na forma anterior.

Bom pessoal, se alguém poder me ajudar serei muito agradecido.

Já faz muito tempo que ando pesquisando na internet, livros, apostilas, e não encontrei nada.

Será que alguém nunca precisou modificar as configurações de conexão do spring com o sistema rodando.