docs: public void service(CmsFlexRequest req, CmsFlexResponse res)
      throws CmsFlexCacheException, ServletException, IOException {
  
          if (!m_completed) {
              return;
          }
  
          if (m_redirectTarget != null) {
              res.setOnlyBuffering(false);
              res.setCmsCachingRequired(false);
              // redirect the response, no further output required
              res.sendRedirect(m_redirectTarget, m_redirectPermanent);
          } else {
              // process cached headers first
              CmsFlexResponse.processHeaders(m_headers, res);
              // check if this cache entry is a "leaf" (i.e. no further includes)
              boolean hasNoSubElements = (m_elements.size() == 1);
              // write output to stream and process all included elements
              for (int i = 0; i < m_elements.size(); i++) {
                  Object o = m_elements.get(i);
                  if (o instanceof String) {
                      // handle cached parameters
                      i++;
                      Map<String, String[]> paramMap = CmsCollectionsGenericWrapper.map(m_elements.get(i));
                      Map<String, String[]> oldParamMap = null;
                      if (paramMap.size() > 0) {
                          oldParamMap = req.getParameterMap();
                          req.addParameterMap(paramMap);
                      }
                      // handle cached attributes
                      i++;
                      Map<String, Object> attrMap = CmsCollectionsGenericWrapper.map(m_elements.get(i));
                      Map<String, Object> oldAttrMap = null;
                      if (attrMap.size() > 0) {
                          oldAttrMap = req.getAttributeMap();
                          // to avoid issues with multi threading, try to clone the attribute instances
                          req.addAttributeMap(cloneAttributes(attrMap));
                          //req.addAttributeMap(attrMap);
                      }
                      // do the include call
                      req.getRequestDispatcher((String)o).include(req, res);
                      // reset parameters if necessary
                      if (oldParamMap != null) {
                          req.setParameterMap(oldParamMap);
                      }
                      // reset attributes if necessary
                      if (oldAttrMap != null) {
                          req.setAttributeMap(oldAttrMap);
                      }
                  } else {
                      try {
                          res.writeToOutputStream((byte[])o, hasNoSubElements);
                      } catch (IOException e) {
                          CmsMessageContainer message = Messages.get().container(
                              Messages.LOG_FLEXCACHEKEY_NOT_FOUND_1,
                              getClass().getName());
                          if (LOG.isDebugEnabled()) {
                              LOG.debug(message.key());
                          }
  
                          throw new CmsFlexCacheException(message, e);
                      }
                  }
              }
          }
      }