// HACK: reflection
 private void updateScenarioParameters() {
   for (ConfigurableObject configObj : this.scenarioParameters.values()) {
     String beanName = configObj.getId();
     Object bean = this.context.getBean(beanName);
     Class<?> clazz = bean.getClass();
     HashMap<String, java.lang.reflect.Field> declaredFields =
         new HashMap<String, java.lang.reflect.Field>();
     do {
       for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
         declaredFields.put(field.getName(), field);
       }
       clazz = clazz.getSuperclass();
     } while (clazz != null);
     clazz = bean.getClass();
     for (ScenarioParameter parameter : configObj.getParameters()) {
       String field = this.capitalize(parameter.getField());
       Object value = parameter.getValue();
       Method[] methods = clazz.getMethods();
       for (Method method : methods) {
         if (method.getName().equals("set" + field)) {
           try {
             method.invoke(bean, value);
           } catch (Exception e) {
             throw new RuntimeException(e);
           }
           ((NodeBacked) bean).persist();
           break;
         }
       }
     }
   }
 }
 @RequestMapping(value = "/save", method = RequestMethod.POST)
 @ResponseBody
 public JsonResponse save(
     @RequestParam("ids") String[] ids,
     @RequestParam("counts") int[] counts,
     @RequestParam("fields") String[] fields,
     @RequestParam("values") String[] values) {
   Map<String, Map<String, ScenarioParameter>> params =
       new HashMap<String, Map<String, ScenarioParameter>>();
   Map<String, ConfigurableObject> oldParams = this.engineService.getScenarioParameters();
   int countsum = 0;
   String error = null;
   for (int i = 0; i < ids.length; i++) {
     Map<String, ScenarioParameter> p = new HashMap<String, ScenarioParameter>();
     for (int j = countsum; j < countsum + counts[i]; j++) {
       Object value;
       ConfigurableObject obj = oldParams.get(ids[i]);
       ScenarioParameter param = obj.getParameter(fields[j]);
       try {
         value = this.parseValue(param.getValue(), values[j]);
       } catch (IllegalArgumentException e) {
         error =
             "Incorrect value for '"
                 + ids[i]
                 + "' field '"
                 + fields[j]
                 + "' ("
                 + e.getMessage()
                 + ")";
         break;
       }
       p.put(fields[j], new ScenarioParameter(fields[j], value));
     }
     if (error != null) break;
     params.put(ids[i], p);
     countsum += counts[i];
   }
   if (error == null) {
     this.engineService.setScenarioParameters(params);
     return new JsonResponse(true);
   } else {
     JsonResponse response = new JsonResponse(false);
     response.setError(error);
     return response;
   }
 }
 @Override
 public synchronized void setScenarioParameters(
     Map<String, Map<String, ScenarioParameter>> parameters) {
   // perform sanity check first to avoid exploitation by hackers
   for (String obj : parameters.keySet()) {
     if (!this.scenarioParameters.containsKey(obj)) {
       throw new RuntimeException("Object with id '" + obj + "' can not be configured");
     }
     ConfigurableObject oldObj = this.scenarioParameters.get(obj);
     Map<String, ScenarioParameter> newParams = parameters.get(obj);
     for (String field : newParams.keySet()) {
       if (!oldObj.containsParam(field)) {
         throw new RuntimeException(
             "'" + obj + "'" + " has no configurable field '" + field + "'");
       }
       ScenarioParameter newParam = newParams.get(field);
       oldObj.setParamValue(field, newParam.getValue());
     }
   }
   this.updateScenarioParameters();
 }