title: Why optaplanner null pointer when calling move.doMove(guiScoreDirector);
body: <p>I have a problem on my optaplanner web application. This app is based on the vehiclerouting demo web example. I want to implement a manual doChangeMove function in the web example for course timetabling. My code (courseTimeTablingManager.java) is as follow:</p>
  
  <pre><code>public synchronized boolean solve(final String sessionId) {
  
      //final Solver&lt;CourseSchedule&gt; solver = solverFactory.buildSolver();
  
      Solver&lt;CourseSchedule&gt; solver;
      if(sessionSolverMap.containsKey(sessionId)){
          solver = sessionSolverMap.get(sessionId);
      }else{
          solver = solverFactory.buildSolver();
      }
      //solver = solverFactory.buildSolver();
      solver.addEventListener(new SolverEventListener&lt;CourseSchedule&gt;() {
          @Override
          public void bestSolutionChanged(BestSolutionChangedEvent&lt;CourseSchedule&gt; event) {
              CourseSchedule bestSolution = event.getNewBestSolution();
              synchronized (CourseTimeTablingManager.this) {
                  sessionSolutionMap.put(sessionId, bestSolution);
              }
          }
      });
      if (sessionSolverMap.containsKey(sessionId)) {
          return false;
      }
      sessionSolverMap.put(sessionId, solver);
      final CourseSchedule solution = retrieveOrCreateSolution(sessionId, xml);
      executor.submit(new Runnable() {
          @Override
          public void run() {
              Solver&lt;CourseSchedule&gt; solver = sessionSolverMap.get(sessionId);
              CourseSchedule bestSolution = solver.solve(solution);
              synchronized (CourseTimeTablingManager.this) {
                  sessionSolutionMap.put(sessionId, bestSolution);
                  //sessionSolverMap.remove(sessionId);
              }
          }
      });
      return true;
  }
  
  public synchronized boolean terminateEarly(String sessionId) {
      //Solver&lt;CourseSchedule&gt; solver = sessionSolverMap.remove(sessionId);
      Solver&lt;CourseSchedule&gt; solver = sessionSolverMap.get(sessionId);
      if (solver != null) {
          solver.terminateEarly();
          return true;
      } else {
          return false;
      }
  }
  
  public synchronized ChangeMove createChangeMove(Object entity, String variableName, Object toPlanningValue, String sessionId) {
      // TODO Solver should support building a ChangeMove
      Solver&lt;CourseSchedule&gt; solver = sessionSolverMap.get(sessionId);
      ScoreDirectorFactory scoreDirectorFactory = solver.getScoreDirectorFactory();
      guiScoreDirector = scoreDirectorFactory.buildScoreDirector();
      InnerScoreDirector guiInnerScoreDirector = (InnerScoreDirector) this.guiScoreDirector;
      SolutionDescriptor solutionDescriptor = guiInnerScoreDirector.getSolutionDescriptor();
      GenuineVariableDescriptor variableDescriptor = solutionDescriptor.findGenuineVariableDescriptorOrFail(
              entity, variableName);
      if (variableDescriptor.isChained()) {
          SupplyManager supplyManager = guiInnerScoreDirector.getSupplyManager();
          SingletonInverseVariableSupply inverseVariableSupply = supplyManager.demand(
                  new SingletonInverseVariableDemand(variableDescriptor));
          return new ChainedChangeMove(entity, variableDescriptor, inverseVariableSupply, toPlanningValue);
      } else {
          return new ChangeMove(entity, variableDescriptor, toPlanningValue);
      }
  }
  
  public synchronized void doChangeMove(Object entity, String variableName, Object toPlanningValue, String sessionId) {
      ChangeMove move = createChangeMove(entity, variableName, toPlanningValue, sessionId);
      doMove(move, sessionId);
  }
  
  public synchronized void doMove(Move move, String sessionId) {
      Solver&lt;CourseSchedule&gt; solver = sessionSolverMap.get(sessionId);
      if (solver.isSolving()) {
          //logger.error("Not doing user move ({}) because the solver is solving.", move);
          System.out.println("!!!!!!!!!!!!!!!!!! Not doing user move ({}) because the solver is solving.");
          return;
      }
      if (!move.isMoveDoable(guiScoreDirector)) {
          System.out.println("################## Not doing user move ({}) because it is not doable.");            
          return;
      }
      //System.out.println("------------------ doing user move ({}) .");           
      move.doMove(guiScoreDirector); // &lt;----- Here, crash with NULL pointer!!
      System.out.println("------------------ doing user move done ({}), try update score ... .");      
      guiScoreDirector.calculateScore();
  }
  </code></pre>
  
  <p>Each time i run the app, it will crash at function doMove's move.doMove(guiScoreDirector). The exception is : 
  <br></p>
  
  <pre><code>Caused by: java.lang.NullPointerException
  at org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.update(DroolsScoreDirector.java:157)
  at org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.afterVariableChanged(DroolsScoreDirector.java:152)
  at org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove.doMoveOnGenuineVariables(ChangeMove.java:69)
  at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:34)
  at org.optaplanner.webexamples.tt.rest.cdi.CourseTimeTablingManager.doMove(CourseTimeTablingManager.java:232)
  at org.optaplanner.webexamples.tt.rest.cdi.CourseTimeTablingManager.doChangeMove(CourseTimeTablingManager.java:217)
  at org.optaplanner.webexamples.tt.rest.cdi.CourseTimeTablingManager$Proxy$_$$_WeldClientProxy.doChangeMove(Unknown Source)
  at org.optaplanner.webexamples.tt.rest.service.DefaultCourseTimeTablingRestService.move(DefaultCourseTimeTablingRestService.java:179)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137)
  at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296)
  at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250)
  at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:237)
  at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356)
  ... 32 more
  </code></pre>
  
  <p>Can anyone help? Thanks in advance!</p>