title: Finite State Machine for Java client - best practice needed
body: <p>I am creating a Java Client to print messages with a small state-machine at the heart of my main class. This client polls a JMS queue and decides if it needs to print a message from a queue or needs to send a message back with JMS.</p>
  
  <p>I was wondering if you Java gurus would share your state-machine advise for this example.</p>
  
  <ul>
  <li>I want to keep my state machine in the main class, but want to move all other methods to other classes.</li>
  <li>Should I keep track of my objects (config, message) as static fields?</li>
  <li>Is this a good idea?</li>
  </ul>
  
  <p>This is What I got.</p>
  
  <p>State Diagram:</p>
  
  <p><img src="https://i.stack.imgur.com/yBmU4.png" alt="Final State Machine"></p>
  
  <p>Main Class:</p>
  
  <pre><code>public class StateMachine {
  
  private static State state;
  private static Properties config;
  private static Message message;
  
  public static void main(String[] args) throws Exception {
  
      // Finite State Machine
      state = State.START;
      while (state != State.STOP) {
          switch (state) {
              case START:
                  start();
                  break;
              case INITIALIZE:
                  initialize();
                  break;
              case CONFIG:
                  config();
                  break;
              case POLLING:
                  polling();
                  break;
              case PUSH:
                  push();
                  break;
              case MESSAGE:
                  message();
                  break;
              case PRINT:
                  print();
                  break;
              case STOP:
                  polling();
                  break;
              default:
                  stop();
                  break;
          }
      }
      System.exit(0);
  }
  
  private static void start() {
      // The Client is started: move to initialization phase.
      state = State.INITIALIZE;
  }
  
  private static void initialize() {
      // Currently nothing - Go directory to configuration
      state = State.CONFIG;
  }
  
  private static void config() {
      // Get the configuration
      config = PropertyManager.readConfiguration();
  
      String task = config.getProperty("task");
      if (task.equals("polling")) {
          state = State.POLLING;
      } else {
          state = State.PUSH;
      }
  }
  
  private static void polling() {
      // Start polling until a message arrives
      try {
          ...
          //Implementation that polls a JMQ queue
          ...
          //Break when message arrives
          while (true) {
              message = consumer.receiveNoWait();
              break;
          }
          session.close();
          connection.close();
      } catch (Exception ex) {
          LOGGER.error(" - {}", ex.toString());
      }
      state = State.MESSAGE;
  }
  
  private static void push() {
      // Push a message to the queue
      ...
      // Start polling again
      state = State.POLLING;
  }
  
  private static void message() {
      // Decides what to do after a message is arrived
      ....
      // Currenty, print all messages
      state = State.PRINT;
  }
  
  private static void print() {
      // Print the message
      if (message instanceof TextMessage) {
          ... print ...
      }
      // Move back to polling after a print.
      state = State.POLLING;
  }
  
  private static void stop() {
      // Go to the STOP state.
      state = State.STOP;
  }
  }
  </code></pre>