code: public void setListeners(StatsStorageRouter statsStorage, Collection<? extends TrainingListener> listeners) {
          //Check if we have any RoutingIterationListener instances that need a StatsStorage implementation...
          StatsStorageRouterProvider routerProvider = null;
          if (listeners != null) {
              for (TrainingListener l : listeners) {
                  if (l instanceof RoutingIterationListener) {
                      RoutingIterationListener rl = (RoutingIterationListener) l;
                      if (statsStorage == null && rl.getStorageRouter() == null) {
                          log.warn("RoutingIterationListener provided without providing any StatsStorage instance. Iterator may not function without one. Listener: {}",
                                          l);
                      } else if (rl.getStorageRouter() != null && !(rl.getStorageRouter() instanceof Serializable)) {
                          //Spark would throw a (probably cryptic) serialization exception later anyway...
                          throw new IllegalStateException(
                                          "RoutingIterationListener provided with non-serializable storage router "
                                                          + "\nRoutingIterationListener class: " + rl.getClass().getName()
                                                          + "\nStatsStorageRouter class: "
                                                          + rl.getStorageRouter().getClass().getName());
                      }
  
                      //Need to give workers a router provider...
                      if (routerProvider == null) {
                          routerProvider = new VanillaStatsStorageRouterProvider();
                      }
                  }
              }
          }
          this.listeners.clear();
          if (listeners != null) {
              this.listeners.addAll(listeners);
              if (trainingMaster != null)
                  trainingMaster.setListeners(statsStorage, this.listeners);
          }
      }
docs: Set the listeners, along with a StatsStorageRouter that the results will be shuffled to (in the
  case of any listeners that implement the {@link RoutingIterationListener} interface)
  
  @param statsStorage Stats storage router to place the results into
  @param listeners Listeners to set