Is there way to reload autowired instance or replace autowired behavior in spring

dilip280 :

Currently I have a bean that is created in @Configuration which downloads json documents from web and creates a model object. Using this bean (autowired), lot of other beans are initialized on startup

I need a way to reload the bean whenever the json documents changes in the web.

What is the best way to do it?

Code:

@Configuration
@ComponentScan(basePackages = "com.wellmanage.prism")
public class PrismConfig {

...
@Bean
public Model model(@Qualifier("prismRestTemplate") RestTemplate restTemplate) {

    LOG.info("model()");
    MetadataReader metadataReader = new MetadataReader();
    String prismFormatJson = null;
    if (!isHasLatestTransformedJson()) {
        prismFormatJson = metadataReader.transformToPrismJson(restTemplate, environment);
        setLastGoodPrismConfiguration(prismFormatJson);
    } else {
        prismFormatJson = getLastGoodPrismConfiguration();
    }
    if (model != null) {
        return model;
    } else {
        return metadataReader.createModelForPrism(prismFormatJson);
    }
}

}

@Configuration
@ComponentScan(basePackages = "com.wellmanage.prism")
public class PrismDataSourceConfig implements DataSourceConfig {

private final Logger LOG = LoggerFactory.getLogger(PrismDataSourceConfig.class);

@Autowired
private Environment environment;

@Autowired
private Model model;

@Primary
@Bean(name = "itdb_dataSource")
public DataSource getDataSource() {

    LOG.info("getDataSource()");
    return getDataSource("itdb");
}

@Bean(name = "dataSourceMap")
public Map<String, DataSource> getDataSourceMap() {

    LOG.info("getDataSourceMap()");

    Map<String, DataSource> dataSourceMap = Maps.newHashMap();
    getDatabases().forEach((name, database) -> {
        Endpoint endpoint = getEndpoint(name);
        DataSource dataSource = createDataSource(endpoint);
        dataSourceMap.put(name, dataSource);
    });

    return dataSourceMap;
}

@Bean(name = "jdbcTemplateMap")
public Map<String, JdbcTemplate> getJdbcTemplateMap() {

    LOG.info("getDataSource()");

    Map<String, JdbcTemplate> jdbcTemplateMap = Maps.newHashMap();
    getDataSourceMap().forEach((name, datasource) -> {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
        jdbcTemplateMap.put(name, jdbcTemplate);
    });

    return jdbcTemplateMap;
}

@Override
public Environment getEnvironment() {

    return environment;
}

@Override
public Model getModel() {

    return model;
}

}

jbx :

Your approach is very wrong. Autowiring is for connecting dependencies at startup. (It is actually discouraged these days, in favour of constructor argument injection.)

What you probably need is to have a @Service which retrieves the data model from the remote service. You then inject this service in the classes that need it to get the model.

You can then also use caching like EhCache and add an annotation @Cacheable to your method so that you don't get the model from the remote source everytime it is needed by the other classes. (You can configure your ehcache.xml for how long you want the cache to live before refreshing the data).

@Service
public class ModelService {

  private final RestTemplate restTemplate;

  public ModelService(RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
  }

  @Cacheable(value = "model", key = "#root.methodName")
  public Model getModel() {

    MetadataReader metadataReader = new MetadataReader();
    String prismFormatJson = null;
    if (!isHasLatestTransformedJson()) {
        prismFormatJson = metadataReader.transformToPrismJson(restTemplate, environment);
        setLastGoodPrismConfiguration(prismFormatJson);
    } else {
        prismFormatJson = getLastGoodPrismConfiguration();
    }
    if (model != null) {
        return model;
    } else {
        return metadataReader.createModelForPrism(prismFormatJson);
    }
  }

  //... the rest of the code
}

Here we configure the cache to expire after 10 minutes:

<config
  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
  xmlns='http://www.ehcache.org/v3'
  xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
  xsi:schemaLocation="
  http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
  http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

  <service>
    <jsr107:defaults>
      <jsr107:cache name="model" template="model-cache"/>
    </jsr107:defaults>
  </service>

  <cache-template name="model-cache">
    <expiry>
      <ttl unit="minutes">10</ttl>
    </expiry>
  </cache-template>
</config>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=329522&siteId=1