@Override
  public void describe(StreamApplicationDescriptor appDescriptor) {
    try {
      // TODO: Introduce an API to return a dsl string containing one or more sql statements.
      List<String> dslStmts = SamzaSqlDslConverter.fetchSqlFromConfig(appDescriptor.getConfig());

      Map<Integer, TranslatorContext> translatorContextMap = new HashMap<>();

      // 1. Get Calcite plan
      List<String> inputSystemStreams = new LinkedList<>();
      List<String> outputSystemStreams = new LinkedList<>();

      Collection<RelRoot> relRoots =
          SamzaSqlApplicationConfig.populateSystemStreamsAndGetRelRoots(dslStmts, appDescriptor.getConfig(),
              inputSystemStreams, outputSystemStreams);

      // 2. Populate configs
      SamzaSqlApplicationConfig sqlConfig =
          new SamzaSqlApplicationConfig(appDescriptor.getConfig(), inputSystemStreams, outputSystemStreams);

      // 3. Translate Calcite plan to Samza stream operators
      QueryTranslator queryTranslator = new QueryTranslator(appDescriptor, sqlConfig);
      SamzaSqlExecutionContext executionContext = new SamzaSqlExecutionContext(sqlConfig);
      // QueryId implies the index of the query in multiple query statements scenario. It should always start with 0.
      int queryId = 0;
      for (RelRoot relRoot : relRoots) {
        LOG.info("Translating relRoot {} to samza stream graph with queryId {}", relRoot, queryId);
        TranslatorContext translatorContext = new TranslatorContext(appDescriptor, relRoot, executionContext);
        translatorContextMap.put(queryId, translatorContext);
        queryTranslator.translate(relRoot, sqlConfig.getOutputSystemStreams().get(queryId), translatorContext, queryId);
        queryId++;
      }

      // 4. Set all translator contexts
      /*
       * TODO When serialization of ApplicationDescriptor is actually needed, then something will need to be updated here,
       * since translatorContext is not Serializable. Currently, a new ApplicationDescriptor instance is created in each
       * container, so it does not need to be serialized. Therefore, the translatorContext is recreated in each container
       * and does not need to be serialized.
       */
      appDescriptor.withApplicationTaskContextFactory(new ApplicationTaskContextFactory<SamzaSqlApplicationContext>() {
        @Override
        public SamzaSqlApplicationContext create(ExternalContext externalContext, JobContext jobContext,
            ContainerContext containerContext, TaskContext taskContext,
            ApplicationContainerContext applicationContainerContext) {
          return new SamzaSqlApplicationContext(translatorContextMap);
        }
      });
    } catch (RuntimeException e) {
      LOG.error("SamzaSqlApplication threw exception.", e);
      throw e;
    }
  }
Entry point for the SamzaSQl stream application that takes in SQL as input and performs stream processing.
samza-sql/src/main/java/org/apache/samza/sql/runner/SamzaSqlApplication.java