code: public <T> T execute(long wait, int maxAttempts, Callable<T> callback)
  			throws Exception {
  		getLog().debug("Waiting for spring application to start...");
  		for (int i = 0; i < maxAttempts; i++) {
  			T result = callback.call();
  			if (result != null) {
  				return result;
  			}
  			String message = "Spring application is not ready yet, waiting " + wait
  					+ "ms (attempt " + (i + 1) + ")";
  			getLog().debug(message);
  			synchronized (this.lock) {
  				try {
  					this.lock.wait(wait);
  				}
  				catch (InterruptedException ex) {
  					Thread.currentThread().interrupt();
  					throw new IllegalStateException(
  							"Interrupted while waiting for Spring Boot app to start.");
  				}
  			}
  		}
  		throw new MojoExecutionException(
  				"Spring application did not start before the configured " + "timeout ("
  						+ (wait * maxAttempts) + "ms");
  	}
docs: Execute a task, retrying it on failure.
  @param <T> the result type
  @param wait the wait time
  @param maxAttempts the maximum number of attempts
  @param callback the task to execute (possibly multiple times). The callback should
  return {@code null} to indicate that another attempt should be made
  @return the result
  @throws Exception in case of execution errors