diff options
| author | Thomas <> | 2022-01-09 15:01:28 +0100 | 
|---|---|---|
| committer | Thomas <> | 2022-01-09 15:01:28 +0100 | 
| commit | e3639ef805f1e525415c43cbda80ed71cc43a70c (patch) | |
| tree | 2b215fd820f510d71652c0ac4a7c3015bd579ce7 /eaaf_core/src/main/java/at/gv | |
| parent | 6fcfe3946fb8c252f9b7a4961720dd851f720f9a (diff) | |
| download | EAAF-Components-e3639ef805f1e525415c43cbda80ed71cc43a70c.tar.gz EAAF-Components-e3639ef805f1e525415c43cbda80ed71cc43a70c.tar.bz2 EAAF-Components-e3639ef805f1e525415c43cbda80ed71cc43a70c.zip | |
feature(core): add synch. and asynch. GUI builder implementation that use Spring MVC architecture
Diffstat (limited to 'eaaf_core/src/main/java/at/gv')
4 files changed, 391 insertions, 0 deletions
| diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/builder/AsynchGuiFormBuilderImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/builder/AsynchGuiFormBuilderImpl.java new file mode 100644 index 00000000..6ed50955 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/builder/AsynchGuiFormBuilderImpl.java @@ -0,0 +1,72 @@ +package at.gv.egiz.eaaf.core.impl.gui.builder; + + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ViewResolver; + +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.gui.utils.MvcGuiRenderUtils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AsynchGuiFormBuilderImpl implements ISpringMvcGuiFormBuilder { + +  private @Autowired(required = false) ViewResolver[] viewResolvers; +  private @Autowired(required = false) LocaleResolver localeResolver; +   +  @Override +  public void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, +      final IGuiBuilderConfiguration config, final String loggerName) throws GuiBuildException { +    build(httpReq, httpResp, config, null, loggerName); + +  } + +  @Override +  public void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, +      final IGuiBuilderConfiguration config, final String contentType, final String loggerName) +      throws GuiBuildException { +    if (config.isWriteAsynch()) {     +      log.debug("{} injects GUI model: {} for asynch. rendering", loggerName, config.getViewName()); +      MvcGuiRenderUtils.setMvcForAsynchRendering(httpReq, config); +       +    } else { +      renderGuiDirectly(httpReq, httpResp, config, loggerName); +       +    } + +  } + +  @Override +  public String evaluateResponseContentType(HttpServletRequest httpReq, IGuiBuilderConfiguration config,  +      String loggerName) throws GuiBuildException { +    try { +      return MvcGuiRenderUtils.evaluateResponseContentType(httpReq, config, viewResolvers, localeResolver); +       +    } catch (final Exception e) { +      log.info("Can NOT evaluate contentType for response GUI: {}", loggerName, e); +      throw new GuiBuildException(e.getMessage(), e); + +    }           +  } +   +  private void renderGuiDirectly(final HttpServletRequest httpReq, final HttpServletResponse httpResp, +      final IGuiBuilderConfiguration config, final String loggerName) throws GuiBuildException { +    try { +      MvcGuiRenderUtils.render(MvcGuiRenderUtils.prepareSpringGuiModel(config),  +          httpReq, httpResp, viewResolvers, localeResolver); + +    } catch (final Exception e) { +      log.info("Can NOT generate GUI for: {}", loggerName, e); +      throw new GuiBuildException(e.getMessage(), e); + +    } +     +  } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/builder/SpringMvcGuiFormBuilderImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/builder/SpringMvcGuiFormBuilderImpl.java new file mode 100644 index 00000000..9fae07e2 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/builder/SpringMvcGuiFormBuilderImpl.java @@ -0,0 +1,57 @@ +package at.gv.egiz.eaaf.core.impl.gui.builder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ViewResolver; + +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.gui.utils.MvcGuiRenderUtils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SpringMvcGuiFormBuilderImpl implements ISpringMvcGuiFormBuilder { + +  private @Autowired(required = false) ViewResolver[] viewResolvers; +  private @Autowired(required = false) LocaleResolver localeResolver; + +  @Override +  public void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, +      final IGuiBuilderConfiguration config, final String loggerName) throws GuiBuildException { +    build(httpReq, httpResp, config, null, loggerName); + +  } + +  @Override +  public void build(final HttpServletRequest httpReq, final HttpServletResponse httpResp, +      final IGuiBuilderConfiguration config, final String contentType, final String loggerName) +      throws GuiBuildException { +    try { +      MvcGuiRenderUtils.render(MvcGuiRenderUtils.prepareSpringGuiModel(config),  +          httpReq, httpResp, viewResolvers, localeResolver); + +    } catch (final Exception e) { +      log.info("Can NOT generate GUI for: {}", loggerName, e); +      throw new GuiBuildException(e.getMessage(), e); + +    } +  } +   +  @Override +  public String evaluateResponseContentType(HttpServletRequest httpReq, IGuiBuilderConfiguration config,  +      String loggerName) throws GuiBuildException { +    try { +      return MvcGuiRenderUtils.evaluateResponseContentType(httpReq, config, viewResolvers, localeResolver); +       +    } catch (final Exception e) { +      log.info("Can NOT evaluate contentType for response GUI: {}", loggerName, e); +      throw new GuiBuildException(e.getMessage(), e); + +    }           +  } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/interceptor/AsynchSpringMvcGuiBuilderIntercepter.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/interceptor/AsynchSpringMvcGuiBuilderIntercepter.java new file mode 100644 index 00000000..708e3b84 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/interceptor/AsynchSpringMvcGuiBuilderIntercepter.java @@ -0,0 +1,63 @@ +package at.gv.egiz.eaaf.core.impl.gui.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.ViewResolver; + +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.gui.utils.MvcGuiRenderUtils; +import lombok.extern.slf4j.Slf4j; + +/** + * Intercepter to render GUI in response processing. + * + * @author tlenz + * + */ +@Slf4j +public class AsynchSpringMvcGuiBuilderIntercepter implements HandlerInterceptor { + +  private @Autowired(required = false) ViewResolver[] viewResolvers; +  private @Autowired(required = false) LocaleResolver localeResolver; + +  /* +   * (non-Javadoc) +   * +   * @see +   * org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet. +   * http. HttpServletRequest, javax.servlet.http.HttpServletResponse, +   * java.lang.Object, org.springframework.web.servlet.ModelAndView) +   */ +  @Override +  public void postHandle(final HttpServletRequest httpReq, final HttpServletResponse httpResp, +      final Object handler, final ModelAndView modelAndView) throws Exception { + +    final ModelAndView model = MvcGuiRenderUtils.getMvcForAsynchRendering(httpReq); +    if (model != null) { +      log.debug("Find GUI model: {} Starting model rendering ... ", model.getViewName()); +      renderGui(model, httpReq, httpResp); + +    } else { +      log.trace("No GUI model skipping asynch model rendering"); + +    } + +  } + +  private void renderGui(final ModelAndView mav, +      final HttpServletRequest httpReq, final HttpServletResponse httpResp) throws GuiBuildException { +    try { +      MvcGuiRenderUtils.render(mav, httpReq, httpResp, viewResolvers, localeResolver); + +    } catch (final Exception e) { +      log.info("Can NOT generate GUI for illustration", e); +      throw new GuiBuildException(e.getMessage(), e); + +    } +  } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/utils/MvcGuiRenderUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/utils/MvcGuiRenderUtils.java new file mode 100644 index 00000000..5a3f14cb --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/gui/utils/MvcGuiRenderUtils.java @@ -0,0 +1,199 @@ +package at.gv.egiz.eaaf.core.impl.gui.utils; + +import java.util.Locale; + +import javax.annotation.Nullable; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.HttpStatus; +import org.springframework.util.Assert; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.ViewResolver; + +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +/** + * Utils GUI generation by using Spring MVC. + + * @author tlenz + * + */ +@Slf4j +public class MvcGuiRenderUtils { + +  private static final String REQ_ATTR_MODEL_HOLDER = "GUI_MODEL_ASYNCH_RENDERING"; +   +  /** +   * Build Spring MVC model from GUI configuration. +   *  +   * @param config GUI configuration +   * @return MVC model +   */ +  @NonNull +  public static ModelAndView prepareSpringGuiModel(@NonNull final IGuiBuilderConfiguration config) { +    final ModelAndView mav = new ModelAndView(config.getViewName()); +    if (config.getViewParameters() != null) { +      mav.addAllObjects(config.getViewParameters()); +       +    }     +    return mav; +     +  } +   +   +  /** +   * Inject GUI-builder configuration into http request to render it asynchronous in Spring intercepter.  +   *  +   * @param request Current HttpServletRequest +   * @param config Configuration for GUI rendering +   */ +  public static void setMvcForAsynchRendering(@NonNull final HttpServletRequest request,  +      @NonNull final IGuiBuilderConfiguration config) { +    request.setAttribute(REQ_ATTR_MODEL_HOLDER, prepareSpringGuiModel(config)); +         +  } +   +  /** +   * Get GUI model for asynchronous rendering. +   *  +   * @param request Current HttpServletRequest +   * @return GUI model, or <code>null</code> of model was set +   */ +  @Nullable +  public static ModelAndView getMvcForAsynchRendering(@NonNull final HttpServletRequest request) { +    return (ModelAndView) request.getAttribute(REQ_ATTR_MODEL_HOLDER); +     +  } +   +  /** +   * Analyze GUI template and HTTP request to evaluate ContentType of HTTP response generated by this builder. +   *  +   * @param httpReq Current HttpServletRequest +   * @param config GUI configuration +   * @param viewResolvers Spring based view-resolvers +   * @param localeResolver Spring based locale-resolvers +   * @return Response content-type, or <code>null</code> if evaluation has no result +   * @throws Exception In case of a GUI rendering error +   */ +  @Nullable +  public static String evaluateResponseContentType(HttpServletRequest httpReq, +      IGuiBuilderConfiguration config, @Nullable final ViewResolver[] viewResolvers,  +      @Nullable final LocaleResolver localeResolver) throws Exception {     +    return buildViewFromModel(viewResolvers,  +        getLocaleByRequest(localeResolver, httpReq), +        prepareSpringGuiModel(config)).getContentType(); +     +  } +   +  /** +   * Render a GUI by using Spring based ModelAndView (MVC) components. +   *  +   * @param mv GUI model +   * @param request Current HttpServletRequest +   * @param response Current HttpServletResponse +   * @param viewResolvers Spring based view-resolvers +   * @param localeResolver Spring based locale-resolvers +   * @throws Exception In case of a GUI rendering error +   */ +  public static void render(@NonNull final ModelAndView mv, @NonNull final HttpServletRequest request, +      @NonNull final HttpServletResponse response, @Nullable final ViewResolver[] viewResolvers,  +      @Nullable final LocaleResolver localeResolver) throws Exception { +    Assert.notNull(request, "http request object"); +    Assert.notNull(response, "http response object"); +    Assert.notNull(mv, "Model and view"); + +    // Determine locale for request and apply it to the response. +    final Locale locale = getLocaleByRequest(localeResolver, request); +    response.setLocale(locale); + +    // Determine view for response +    View view = buildViewFromModel(viewResolvers, locale, mv); + +    final HttpStatus modelStatus = mv.getStatus(); +    if (modelStatus != null) { +      response.setStatus(modelStatus.value()); + +    } else { +      log.trace("HttpStatus is 'null' Set {} as default", HttpServletResponse.SC_OK); +      response.setStatus(HttpServletResponse.SC_OK); + +    } + +    // Delegate to the View object for rendering. +    if (log.isTraceEnabled()) { +      log.trace("Rendering view [{}] ", view); +    } + +    try { +      view.render(mv.getModelMap(), request, response); +       +    } catch (final Exception ex) { +      if (log.isDebugEnabled()) { +        log.debug("Error rendering view [{}]", view, null, ex); +      } + +      throw ex; + +    } + +  } + +  private static Locale getLocaleByRequest(LocaleResolver localeResolver, @NonNull HttpServletRequest request) { +    return localeResolver != null ? localeResolver.resolveLocale(request) : request.getLocale(); +     +  } +   +  private static View buildViewFromModel(ViewResolver[] viewResolvers, Locale locale,  +      @NonNull ModelAndView mv) throws Exception { + +    final String viewName = mv.getViewName(); +    View view; +    if (viewName != null) { +      // We need to resolve the view name. +      view = resolveViewName(viewResolvers, viewName, locale); +       +      if (view == null) { +        throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' "); +      } + +    } else { +      // No need to lookup: the ModelAndView object contains the actual View object. +      view = mv.getView(); +      if (view == null) { +        throw new ServletException( +            "ModelAndView [" + mv + "] neither contains a view name nor a " + "View object "); +         +      } +    }   +     +    return view; +     +  } + + +  private static View resolveViewName(@Nullable final ViewResolver[] viewResolvers,  +      final String viewName, final Locale locale) throws Exception { +    if (viewResolvers != null) {       +      for (final ViewResolver viewResolver : viewResolvers) { +        final View view = viewResolver.resolveViewName(viewName, locale); +        if (view != null) { +          return view; +        } + +      } +    } + +    return null; +  } +   +  private MvcGuiRenderUtils() { +    // private constructor for class with only static methods +  } +   +} | 
