0

I develop Spring-Mvc project and this project's application properties count too much. Also I can't change this properties during program is running. So, I want to get this properties from database and assign to member of classes.

Now, I take this properties from database by using a service but I don't think, this code is reusable. I wonder, is there any methodology to get this properties to members via custom annotation?

ApplicationPropertiesDao.java

@Repository
public class ApplicationPropertiesDao implements IApplicationPropertiesDao{
    @Value("#{appProperties.instanceName}")
    private String instanceName;

    @Override
    @Cacheable("applicationProperties")
    public HashMap<String, String> getApplicationPropertiesFromDB(){
        Map<String, Object> inputMap = new HashMap<String, Object>();
        inputMap.put("instanceName", instanceName);

        String sql = getSQL("getApplicationProperties");
        Map<String, String> list = new HashMap<String, String>();

        getNamedParameterJdbcTemplate().query(sql, inputMap, new ResultSetExtractor<Map<String, String>>() {
            @Override
            public Map<String, String> extractData(ResultSet resultSet) throws SQLException, DataAccessException {
                while (resultSet.next()) {
                    list.put( resultSet.getString("NAME"),resultSet.getString("VALUE"));
                }
                return list;
            }
        });
        return (HashMap<String, String>) list;
    }
}

ApplicationPropertiesService.java

@Service
public class ApplicationPropertiesService implements IApplicationPropertiesService{
    @Autowired
    private IApplicationPropertiesDao applicationPropertiesDao;

    public HashMap<String, String> getApplicationPropertiesFromDB(){
        return applicationPropertiesDao.getApplicationPropertiesFromDB();
    }

    public Object getApplicationPropertyByName(String name, ApplicationPropertyValueTypeEnum applicationPropertyValueTypeEnum){
        String value = getApplicationPropertiesFromDB().get(name);

        if (applicationPropertyValueTypeEnum.name().equals(ApplicationPropertyValueTypeEnum.INTEGER.toString())){
            return Integer.parseInt(value);
        }else if(applicationPropertyValueTypeEnum.name().equals(ApplicationPropertyValueTypeEnum.BOOLEAN.toString())){
            String upperCaseValue = value.toUpperCase(Locale.ENGLISH);
            return upperCaseValue.equals("TRUE") ? Boolean.TRUE : Boolean.FALSE;
        }
        return value;
    }
}

Can I create a custom annotation as shown below for this situation? If there is , I will be happy. How can i make this?

@Service
public class Demo{
    private String val;
    @Autowired
    public ApplicationPropertiesService applicationPropertiesService;

    @GetPropertyFromDB(key = "val", type = "String")
    public getVal(){
        //set(applicationPropertiesService.getApplicationPropertyByName("val", "String"));
        return this.val;
    }

    public void setVal(String val){
         this.val = val;
    }
}

Thank you for your help.

2 Answers 2

1

I think you need DB PropertyPlaceholderConfigurer. Something like this: Spring PropertyPlaceholderConfigurer load from DB

If you integrate your custom DB PropertyPlaceholderConfigurer. (see https://www.baeldung.com/properties-with-spring)

@Bean
public static PropertySourcesPlaceholderConfigurer properties(){
    return new MyDBPlaceholderConfigurer();
}

You will be able to use standard @Value and @ConfigurationProperties annotations.

Sign up to request clarification or add additional context in comments.

Comments

0

I used this class to configuration of properties at start but I could not load this properties from database at specific time periods. This class works only start. Can I call this loadProperties method for every minute without restarting the program?

DbPropertyPlaceholderConfigurer.java

@Service
public class DbPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private DataSource dataSource;
private String key = "NAME";
private String value = "VALUE";
private String table = "APPLICATION_PROPERTIES";
private String instanceName;


@Override
protected void loadProperties(final Properties props) throws IOException {
    if (null == props) {
        throw new IOException("No properties passed by Spring framework - cannot proceed.");
    }

    String sql = String.format("SELECT %s, %s FROM %s where INSTANCE_NAME = '%s'", key, value,
            table, instanceName);

    try {
        JdbcTemplate t = new JdbcTemplate(dataSource);
        t.query(sql, new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                String auxKey = rs.getString(key);
                String auxValue = rs.getString(value);

                if (null == auxKey || null == auxValue) {
                    throw new SQLException("Configuration database contains empty data. Name='" + (auxKey == null ? "" : auxKey)
                            + "', Value='" + (auxValue == null ? "" : auxValue) + "'.");
                }

                props.setProperty(auxKey, auxValue);
            }
        });
    } catch (Exception e) {
        logger.error("There is an error in the configuration database.");
        throw new IOException(e);
    }

    if (props.size() == 0) {
        logger.error("The configuration database could not be reached or does not contain any properties in '" + table
                + "'.");
    } else {
        logger.info("Application config info loaded from configuration database.");
    }
}

public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
}

public void setInstanceName(String instanceName) {
    this.instanceName = instanceName;
}

}

applicationContext.xml

<bean id="placeholderPropertiesDatabase" class="com.common.DbPropertyPlaceholderConfigurer" >
    <property name="dataSource" ref="dataSource" />
    <property name="instanceName" value="instance1" />

    <property name="placeholderPrefix" value="$db{" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="false" />
    <property name="order" value="1" />
</bean>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.