Search code examples
javaspring-bootredisluaapplication.properties

How to edit application.properties during runtime (for next time use)


I want to be able to check if a script exists in a Redis cluster. If it doesn't, I will need to load a new script from my resources folder and save the corresponding SHA value of that new script. I would like to save that SHA value for next time the application starts up, inside of the application.properties. This would ideally be done by overwriting the previous entry for the sha value

I know that the properties file is read once during startup, but this does not matter as I only want to save that SHA value to the application.properties for use next time, ie preventing the overhead of checking for a script and loading each time.

This is my method for preparing the scripts

static String prepareScripts() throws ExecutionException, InterruptedException, IOException {
    List <Boolean> list = (List) asyncCommands.scriptExists(sha).get();
    shaDigest = sha;
    if (list.get(0) == false) {
        URL url = AbstractRedisDao.class.getClassLoader().getResource("script.txt");
        File file = new File(url.getPath());
        String str = FileUtils.readFileToString(file, "ISO_8859_1");
        shaDigest = (String) asyncCommands.scriptLoad(str).get();

        Properties  properties = new Properties();


        try {
            FileWriter writer = new FileWriter("application.properties");
            BufferedWriter bw = new BufferedWriter(writer);
            Iterator propertyIt =  properties.entrySet().iterator();

            while (propertyIt.hasNext() ) {
                Map.Entry nextHolder = (Map.Entry) propertyIt.next();
                while (nextHolder.getKey() != ("redis.scriptActiveDev")) {
                    bw.write(nextHolder.getKey() + "=" + nextHolder.getValue());
                }
            }

            bw.write("redis.scriptActiveDev=" + shaDigest);
        } catch (IOException e) {
            System.err.format("IOException: %s%n", e);
        }
        return shaDigest;
    } else {
        return shaDigest;
    }
}

these are the details for redis in application.properties:

redis.enabled=true
redis.hostname=xxxx
redis.port=xxxx
redis.password=xxxx
redis.sha=xxxx

Is this on the right track? also, how would i go about saving the application.properties back to the resources folder after rebuilding it with the new property? Is there a more efficient way to do this without recreating the whole application.properties just to add one line?


Solution

  • There is no need to store SHA digests for Lua scripts in application.properties.

    Use the API of your Redis client to get SHA digest on application startup.

    For instance, Lettuce provides the following API for scripting:
    String digest(V script)
    String scriptLoad(V script)
    List<Boolean> scriptExists(String... digests)

    You can execute the following code on each application startup to get the digest for your script:

    public String sha(String script) {
      String shaDigest = redisScriptingCommands.digest(script);
      boolean scriptExists = redisScriptingCommands.scriptExists(shaDigest).get(0);
      if (!scriptExists) {
        redisScriptingCommands.scriptLoad(script);
      }
      return shaDigest;
    }