Archive

Posts Tagged ‘Spring MVC’
  • Common code in Spring MVC, where to put it?

    Spring Boot logo

    During my journey coding an actuator for a non-Spring Boot application, I came upon an interesting problem regarding where to actually put a snippet of common code. This post tries to list all available options, and their respective pros and cons in a specific context.

    As a concrete example, let’s use the REST endpoint returning the map of all JVM properties accessible through the /jvmprops sub-context. Furthermore, I wanted to offer the option to search not only for a single property e.g. /jvmprops/java.vm.vendor but also to allow for filtering for a subset of properties e.g. /jvmprops/java.vm.*.

    == The current situation

    The code is designed around nothing but boring guidelines for a Spring application. The upper layer consists of controllers. They are annotated with @RestController and provide REST endpoints made available as @RequestMapping-annotated methods. In turn, those methods call the second layer implemented as services.

    As seen above, the filter pattern itself is the last path segment. It’s mapped to a method parameter via the @PathVariable annotation.

    [source,java]

    @RestController class JvmPropsController(private val service: JvmPropsService) { @RequestMapping(path = arrayOf(“/jvmprops/{filter}”), method = arrayOf(GET)) fun readJvmProps(@PathVariable filter: String): Map<String, *> = service.getJvmProps() } —-

    To effectively implement filtering, the path segment allows star characters. In Java however, string matching is achieved via regular expression. It’s then mandatory to “translate” the simple calling pattern to a full-fledge regexp. Regarding the above example, not only the dot character needs to be escaped - from . but to \\., but the star character needs to be translated accordingly - from * to .*:

    [source,java] val regex = filter.replace(“.”, “\.”).replace(“”, “.”)

    Then, the associated service returns the filtered map, which is in turn returned by the controller. Spring Boot and Jackson take care of JSON serialization.

    == Straightforward alternatives

    This is all fine and nice, until additional map-returning endpoints are required (for example, to get environment variables), and the above snippet ends up being copied-pasted in each of them.

    There surely must be a better solution, so where factor this code?

    === In a controller parent class

    The easiest hack is to create a parent class for all controllers, put the code there and call it explicitly.

    [source,java]

    abstract class ArtificialController() { fun toRegex(filter: String) = filter.replace(“.”, “\.”).replace(“”, “.”) }

    @RestController class JvmProps(private val service: JvmPropsService): ArtificialController() { @RequestMapping(path = arrayOf(“/jvmprops/{filter}”), method = arrayOf(GET)) fun readJvmProps(@PathVariable filter: String): Map<String, *> { val regex = toRegex(filter) return service.getJvmProps(regex) } } —-

    This approach has three main disadvantages:

    . It creates an artificial parent class just for the sake of sharing common code. . It’s necessary for other controllers to inherit from this parent class. . It requires an explicit call, putting the responsibility of the transformation in the client code. Chances are high that no developer but the one who created the method will ever use it.

    === In a service parent class

    Instead of setting the code in a shared method of the controller layer, it can be set in the service layer.

    The same disadvantages as above apply.

    === In a third-party dependency

    Instead of an artificial class hierarchy, let’s introduce an unrelated dependency class. This translates into the following code.

    [source,java]

    class Regexer { fun toRegex(filter: String) = filter.replace(“.”, “\.”).replace(“”, “.”) }

    @RestController class JvmProps(private val service: JvmPropsService, private val regexer: Regexer) { @RequestMapping(path = arrayOf(“/jvmprops/{filter}”), method = arrayOf(GET)) fun readJvmProps(@PathVariable filter: String): Map<String, *> { val regex = regexer.toRegex(filter) return service.getJvmProps(regex) } } —-

    While favoring composition over inheritance, this approach still leaves out a big loophole: the client code is required to call the shared one.

    === In a Kotlin extension function

    If one is allowed to use alternate languages on the JVM, it’s possible to benefit for Kotlin’s extension functions:

    [source,java]

    interface ArtificialController

    fun ArtificialController.toRegex(filter: String) = filter.replace(“.”, “\.”).replace(“”, “.”)

    @RestController class JvmProps(private val service: JvmPropsService): ArtificialController { @RequestMapping(path = arrayOf(“/jvmprops/{filter}”), method = arrayOf(GET)) fun readJvmProps(@PathVariable filter: String): Map<String, *> { val regex = toRegex(filter) return service.getJvmProps(regex) } } —-

    Compared to putting the code in a parent controller, at least the code is localized to the file. But the same disadvantages still apply, so the gain is only marginal.

    == More refined alternatives

    Refactorings described above work in every possible context. The following options apply specifically for (Spring Boot) web applications.

    They all follow the same approach: instead of explicitly calling the shared code, let’s somehow wrap controllers in a single component where it will be executed.

    === In a servlet filter

    In a web application, code that needs to be executed before/after different controllers are bound to take place in a servlet filter.

    With Spring MVC, this is achieved through a filter registration bean:

    [source,java]

    @Bean fun filterBean() = FilterRegistrationBean().apply { urlPatterns = arrayListOf(“/jvmProps/”) filter = object : Filter { override fun destroy() {} override fun init(config: FilterConfig) {} override fun doFilter(req: ServletRequest, resp: ServletResponse, chain: FilterChain) { chain.doFilter(httpServletReq, resp) val httpServletReq = req as HttpServletRequest val paths = request.pathInfo.split(“/”) if (paths.size > 2) { val subpaths = paths.subList(2, paths.size) val filter = subpaths.joinToString(“”) val regex = filter.replace(“.”, “\.”) .replace(“”, “.*”) // Change the JSON here… } } } } —-

    The good point about the above code is it doesn’t require controllers to call the shared code explicitly. There’s a not-so-slight problem however: at this point, the map has already been serialized into JSON, and been processed into the response. It’s mandatory to wrap the initial respons in a response wrapper before proceeding with the filter chain and process the JSON instead of an in-memory data structure.

    Not only is this way quite fragile, it has a huge impact on performance.

    === In a Spring MVC interceptor

    Moving the above code from a filter in a Spring MVC interceptor unfortunately doesn’t improve anything.

    === In an aspect

    The need of translating the string parameter and to filter the map are typical cross-cutting concerns. This is a typical use-case fore Aspect-Oriented Programming. Here’s what the code looks like:

    [source,java]

    @Aspect class FilterAspect { @Around(“execution(Map ch.frankel.actuator.controller..(..))”) fun filter(joinPoint: ProceedingJoinPoint): Map<String, > { val map = joinPoint.proceed() as Map<String, *> val filter = joinPoint.args[0] as String val regex = filter.replace(“.”, “\.”).replace(“”, “.*”) return map.filter { it.key.matches(regex.toRegex()) } } } —-

    Choosing this option works in the intended way. Plus, the aspect will be applied automatically to all methods of all classes in the configured package that return a map.

    === In a Spring MVC advice

    There’s a nice gem hidden in Spring MVC: a specialized advice being executed just after the controller returns but before the returned value is serialized in JSON format (thanks to @Dr4K4n for the hint).

    The class just needs to:

    . Implement the ResponseBodyAdvice interface . Be annotated with @ControllerAdvice to be scanned by Spring, and to control which package it will be applied to

    [source,java]

    @ControllerAdvice(“ch.frankel.actuator.controller”) class TransformBodyAdvice(): ResponseBodyAdvice<Map<String, Any?» {

    override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*») = returnType.method.returnType == Map::class.java

    override fun beforeBodyWrite(map: Map<String, Any?>, methodParameter: MethodParameter, mediaType: MediaType, clazz: Class<out HttpMessageConverter<*», serverHttpRequest: ServerHttpRequest, serverHttpResponse: ServerHttpResponse): Map<String, Any?> { val request = (serverHttpRequest as ServletServerHttpRequest).servletRequest val filterPredicate = getFilterPredicate(request) return map.filter(filterPredicate) }

    private fun getFilterPredicate(request: HttpServletRequest): (Map.Entry<String, Any?>) -> Boolean { val paths = request.pathInfo.split(“/”) if (paths.size > 2) { val subpaths = paths.subList(2, paths.size) val filter = subpaths.joinToString(“”) val regex = filter.replace(“.”, “\.”) .replace(“”, “.”) .toRegex() return { it.key.matches(regex) } } return { true } } } —-

    This code doesn’t require to be called explicitly, it will be applied to all controllers in the configured package. It also will only be applied if the return type of the method is of type Map (no generics check due to type erasure though).

    Even better, it paves the way for future development involving further processing (ordering, paging, etc.).

    == Conclusion

    There are several ways to share common code in a Spring MVC app, each having different pros and cons. In this post, for this specific use-case, the ResponseBodyAdvice has the most benefits.

    The main taking here is that the more tools one has around one’s toolbelt, the better the final choice. Go explore some tools you don’t know already about: what about reading some documentation today?

    Categories: JavaEE Tags: Spring MVCClean codeDesign
  • Fully configurable mappings for Spring MVC

    Spring Boot logo

    :page-liquid: :experimental: :imagesdir: /assets/resources/fully-configurable-mappings-spring-mvc/

    As I wrote some weeks link:{% post_url 2017-03-05-use-case-spring-component-scan %}[earlier^], I’m trying to implement features of the Spring Boot actuator in a non-Boot Spring MVC applications. Developing the endpoints themselves is quite straightforward. Much more challenging, however, is to be able to configure the mapping in a properties file, like in the actuator. This got me to check more closely at how it was done in the current code. This post sums up my “reverse-engineering” attempt around the subject.

    == Standard MVC

    === Usage

    In Spring MVC, in a class annotated with the @Controller annotation, methods can be in turn annotated with @RequestMapping. This annotation accepts a value attribute (or alternatively a path one) to define from which path it can be called.

    The path can be fixed e.g. /user but can also accepts variables e.g. /user/{id} filled at runtime. In that case, parameters should can be mapped to method parameters via @PathVariable:

    [source,java]

    @RequestMapping(path = “/user/{id}”, method = arrayOf(RequestMethod.GET)) fun getUser(@PathVariable(“id”) id:String) = repository.findUserById(id) —-

    While adapted to REST API, this has to important limitations regarding configuration:

    • The pattern is set during development time and does not change afterwards
    • The filling of parameters occurs at runtime

    === Implementation

    With the above, mappings in @Controller-annotated classes will get registered during context startup through the DefaultAnnotationHandlerMapping class. Note there’s a default bean of this type registered in the context. This is summed up in the following diagram:

    image::defaultannotationhandlermapping.png[DefaultAnnotationHandlerMapping sequence diagram,714,533,align=”center”]

    In essence, the magic applies only to @Controller-annotated classes. Or, to be more strict, quoting the DefaultAnnotationHandlerMapping’s Javadoc:

    [quote] __ Annotated controllers are usually marked with the Controller stereotype at the type level. This is not strictly necessary when RequestMapping is applied at the type level (since such a handler usually implements the org.springframework.web.servlet.mvc.Controller interface). However, Controller is required for detecting RequestMapping annotations at the method level if RequestMapping is not present at the type level. __

    == Actuator

    === Usage

    Spring Boot actuator allows for configuring the path associated with each endpoint in the application.properties file (or using alternative methods for Boot configuration).

    For example, the metrics endpoint is available by default via the metrics path. But’s it possible to configure a completely different path:

    [source] endpoints.metrics.id=mymetrics

    Also, actuator endpoints are by default accessible directly under the root, but it’s possible to group them under a dedicated sub-context:

    [source] management.context-path=/manage

    With the above configuration, the metrics endpoint is now available under the /manage/mymetrics.

    === Implementation

    Additional actuator endpoints should implements the MvcEndpoint interface. Methods annotated with @RequestMapping will work in the exact same way as for standard controllers above. This is achieved via a dedicated handler mapping, EndpointHandlerMapping in the Spring context.

    [quote] __ HandlerMapping to map Endpoints to URLs via Endpoint.getId(). The semantics of @RequestMapping should be identical to a normal @Controller, but the endpoints should not be annotated as @Controller (otherwise they will be mapped by the normal MVC mechanisms). __

    The class hierarchy is the following:

    image::mvcendpoint.png[MvcEndpoint class diagram,834,476,align=”center”]

    This diagram shows what’s part of Spring Boot and what’s not.

    == Conclusion

    Actuator endpoints reuse some from the existing Spring MVC code to handle @RequestMapping. It’s done in a dedicated mapping class so as to separate standard MVC controllers and Spring Boot’s actuator endpoint class hierarchy. In order to achieve fully configurable mappings in Spring MVC, this is the part of the code study, to duplicate and to adapt should one wants fully configurable mappings.

    Categories: JavaEE Tags: Spring MVCactuatorSpring Boot
  • Metrics, metrics everywhere

    :imagesdir: /assets/resources/metrics-metrics-everywhere/

    With DevOps, metrics are starting to be among the non-functional requirements any application has to bring into scope. Before going further, there are several comments I’d like to make:

    . Metrics are not only about non-functional stuff. Many metrics represent very important KPI for the business. For example, for an e-commerce shop, the business needs to know how many customers leave the checkout process, and in which screen. True, there are several solutions to achieve this, though they are all web-based (Google Analytics comes to mind) and metrics might also be required for different architectures. And having all metrics in the same backend mean they can be correlated easily. . Metrics, as any other +++NFR+++ (e.g. logging and exception handling) should be designed and managed upfront and not pushed in as an afterthought. How do I know that? Well, one of my last project focused on functional requirement only, and only in the end did project management realized +++NFR+++ were important. Trust me when I say it was gory - and it has cost much more than if designed in the early phases of the project. . Metrics have an overhead. However, without metrics, it’s not possible to increase performance. Just accept that and live with it.

    The inputs are the following: the application is http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html[Spring MVC^]-based and metrics have to be aggregated in http://graphite.wikidot.com/[Graphite^]. We will start by using the excellent https://dropwizard.github.io/metrics/[Metrics project^]: not only does it get the job done, its https://dropwizard.github.io/metrics/3.1.0/manual/[documentation^] is of very high quality and it’s available under the friendly OpenSource Apache v2.0 license.

    That said, let’s imagine a “standard” base architecture to manage those components.

    First, though Metrics offer a Graphite endpoint, this requires configuration in each environment and this makes it harder, especially on developers workstations. To manage this, we’ll send metrics to JMX and introduce http://www.jmxtrans.org/[jmxtrans^] as a middle component between JMX and graphite. As every JVM provides JMX services, this requires no configuration when there’s none needed - and has no impact on performance.

    Second, as developers, we usually enjoy develop everything from scratch in order to show off how good we are - or sometimes because they didn’t browse the documentation. My point of view as a software engineer is that I’d rather not reinvent the wheel and focus on the task at end. Actually, Spring Boot already http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html=production-ready-code-hale-metrics[integrates with Metrics^] through the Actuator component. However, it only provides GaugeService - to send unique values, and CounterService - to increment/decrement values. This might be good enough for +++FR+++ but not for +++NFR+++ so we might want to tweak things a little.

    The flow would be designed like this: Code > Spring Boot > Metrics > JMX > Graphite

    The starting point is to create an aspect, as performance metric is a cross-cutting concern:

    [source,java]

    @Aspect public class MetricAspect {

    private final MetricSender metricSender;
    
    @Autowired
    public MetricAspect(MetricSender metricSender) {
        this.metricSender = metricSender;
    }
    
    @Around("execution(* ch.frankel.blog.metrics.ping..*(..)) ||execution(* ch.frankel.blog.metrics.dice..*(..))")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
    
        StopWatch stopWatch = metricSender.getStartedStopWatch();
    
        try {
            return pjp.proceed();
        } finally {
            Class<?> clazz = pjp.getTarget().getClass();
            String methodName = pjp.getSignature().getName();
            metricSender.stopAndSend(stopWatch, clazz, methodName);
        }
    } } ----
    

    The only thing outside of the ordinary is the usage of autowiring as aspects don’t seem to be able to be the target of explicit wiring (yet?). Also notice the aspect itself doesn’t interact with the Metrics API, it only delegates to a dedicated component:

    [source,java]

    public class MetricSender {

    private final MetricRegistry registry;
    
    public MetricSender(MetricRegistry registry) {
        this.registry = registry;
    }
    
    private Histogram getOrAdd(String metricsName) {
        Map<String, Histogram> registeredHistograms = registry.getHistograms();
        Histogram registeredHistogram = registeredHistograms.get(metricsName);
        if (registeredHistogram == null) {
            Reservoir reservoir = new ExponentiallyDecayingReservoir();
            registeredHistogram = new Histogram(reservoir);
            registry.register(metricsName, registeredHistogram);
        }
        return registeredHistogram;
    }
    
    public StopWatch getStartedStopWatch() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        return stopWatch;
    }
    
    private String computeMetricName(Class<?> clazz, String methodName) {
        return clazz.getName() + '.' + methodName;
    }
    
    public void stopAndSend(StopWatch stopWatch, Class<?> clazz, String methodName) {
        stopWatch.stop();
        String metricName = computeMetricName(clazz, methodName);
        getOrAdd(metricName).update(stopWatch.getTotalTimeMillis());
    } } ----
    

    The sender does several interesting things (but with no state):

    • It returns a new StopWatch for the aspect to pass back after method execution
    • It computes the metric name depending on the class and the method
    • It stops the StopWatch and sends the time to the MetricRegistry
    • Note it also lazily creates and registers a new Histogram with an ExponentiallyDecayingReservoir instance. The default behavior is to provide an UniformReservoir, which keeps data forever and is not suitable for our need.

    The final step is to tell the Metrics API to send data to JMX. This can be done in one of the configuration classes, preferably the one dedicated to metrics, using the @PostConstruct annotation on the desired method.

    [source,java]

    @Configuration public class MetricsConfiguration {

    @Autowired
    private MetricRegistry metricRegistry;
    
    @Bean
    public MetricSender metricSender() {
        return new MetricSender(metricRegistry);
    }
    
    @PostConstruct
    public void connectRegistryToJmx() {
        JmxReporter reporter = JmxReporter.forRegistry(metricRegistry).build();
        reporter.start();
    } } ----
    

    The JConsole should look like the following. Icing on the cake, all default Spring Boot metrics are also available:

    image::jconsole.png[JConsole screenshot,662,452,align=”center”]

    Sources for this article are link:/assets/resources/metrics-metrics-everywhere/spring-metrics-1.0.0.zip[available] in Maven “format”.

  • Sanitizing webapp outputs as an an afterthought

    For sure, software security should be part of every developer’s requirements: they should be explained and detailed before development. Unfortunately, it happens in real life that this is not always the case. Alternatively, even when it is, developers make mistakes and/or have to make with tight (read impossible) plannings. In the absence of security checks automated tools, sooner or later, an issue will appear.

    I’ve been thinking about a way to sanitize the output of a large-scale legacy Spring MVC application in a reliable way (i.e. not go on each page to fix issues). Basically, there are 4 ways output is displayed in the HTML page.

    [options=”header,autowidth”] |===

    # Name Sample snippet Description
    1
    Form taglib
    Outputs a bean attribute
    2
    Spring taglib
    <spring:message code=”label.name.first”>
    Outputs a message from a properties file
    3
    Java Standard Taglib Library
    Outputs a value
    4
    Expression Language
    ${pageContext.request.requestURI}
    Outputs a value

    |===

    == Spring taglibs

    Spring taglibs are a breeze to work with. Basically, Spring offers multiple ways to sanitize the output, each scope parameter having a possibility to be overridden by a narrower one:

    . Application scoped, with the boolean defaultHtmlEscape context parameter + [source,xml] —-

    defaultHtmlEscape true

    + . Page scoped (i.e. all forms on page), with the <spring:defaultHtmlEscape> tag . Tag scoped, with the htmlEscape attribute of the tag

    There’s only one catch; the <spring:message> tag can take not only a code (the key in the property file) but also arguments - however, those are not escaped:

    [source] Hello, ${0} ${1}

    A possible sanitization technique consists of the following steps:

    . Create a new SanitizeMessageTag: +

    • Inherit from Spring’s MessageTag
    • Override the relevant revolveArguments(Object) method
    • Use the desired sanitization technique (Spring uses its own HtmlUtils.htmlEscape(String)) + . Copy the existing Spring TagLib Descriptor and create a new one out of it . Update it to bind the message tag to the newly created SanitizeMessageTag class . Last but not least, override the configuration of the taglib in the web deployment descriptor: + [source,xml] —-
    http://www.springframework.org/tags /WEB-INF/tld/sanitized-spring-form.tld

    + By default, the JavaEE specifications mandates for the container to look for TLDs insides JARs located under the WEB-INF/lib directory. It is also possible to configure them in the web deployment descriptor. However, the configuration takes precedence over automatic scanning.

    This way, existing JSP using the Spring taglib will automatically benefit from the new tag with no page-to-page update necessary.

    == JSTL

    The <c:out> tag works the same way as the <spring:message> one, the only difference being there’s no global configuration parameter, only a escapeXml tag attribute which defaults to false.

    The same technique as above can be used to default to true instead.

    == EL

    The EL syntax enables output outside any taglib so that the previous TLD override technique cannot be used to solve this.

    Not known to many developers, EL snippets are governed by so-called EL resolvers. Standard application servers (including servlet containers like Tomcat) provide standard EL resolvers, but it is also possible to add others at runtime.

    NOTE: Though only a single EL resolver can be set in the JSP context, the resolver hierarchy implements the Composite pattern, so it’s not an issue.

    Steps required to sanitize EL syntax by default are:

    . Subclasses relevant necessary EL resolvers - those are ScopedAttributeELResolver, ImplicitObjectELResolver and BeanELResolver, since they may return strings . For each, override the getValue() method: +

    • Call super.getValue()
    • Check the return value
    • If it is a string, sanitize the value before returning it, otherwise, leave it as it is + . Create a ServletContextListener to register these new EL resolvers + [source,java] —- public class SanitizeELResolverListener implements ServletContextListener {

      public void contextInitialized(ServletContextEvent event) { ServletContext context = event.getServletContext(); JspFactory jspFactory = JspFactory.getDefaultFactory(); JspApplicationContext jspApplicationContext = jspFactory.getJspApplicationContext(context); ELResolver sber = new SanitizeBeanELResolver(); jspApplicationContext.addELResolver(sber); // Register other EL resolvers } } —-

    == Summary

    Trying to sanitize the output of an application after it has been developed is not the good way to raise developers concerns about security. However, dire situations require dire solutions. When the application has already been developed, the above approaches - one for taglibs, one for EL, show how to achieve this in a way that does not impact existing code and get the job done.

    Categories: JavaEE Tags: JSTLsecuritySpring MVC
  • Chaining URL View resolvers in Spring MVC

    Spring IO logo

    Standard Java EE forward to internal resources go something like this:

    [source,java]

    public class MyServlet extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse resp) { req.getRequestDispatcher(“/WEB-INF/page/my.jsp”).forward(req, resp); } } —-

    Admittedly, there’s no decoupling between the servlet code and the view technology, even without the JSP location.

    Spring MVC introduces the notion of ViewResolver. The controller just handles logical names, mapping between the logical name and the actual resource is handled by the ViewResolver. Even better, controllers are completely independent from resolvers: just registering the latter in the Spring context is enough.

    Here’s a very basic controller, notice there’s no hint as to the final resource location.

    [source,java]

    @Controller public class MyController {

    @RequestMapping(“/logical”) public String displayLogicalResource() { return “my”; } } —-

    Even better, there’s nothing here as to the resource nature; it could be a JSP, an HTML, a Tiles, an Excel sheet, whatever. Each has a location strategy based on a http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-viewresolver-resolver[dedicated^] ViewResolver. The most used resolver is the http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/view/InternalResourceViewResolver.html[InternalResourceViewResolver]; it meant to forward to internal resources, most of the time, JSPs. It is initialized like this:

    [source,java]

    @Bean public ViewResolver pageViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix(“/WEB-INF/page/”); resolver.setSuffix(“.jsp”); return resolver; } —-

    Given this view resolver available in the Spring context, the logical name "my" will tried to be resolved with the "/WEB-INF/page/my.jsp" path. If the resource exists, fine, otherwise, Spring MVC will return a 404.

    Now, what if I’ve different folders with JSP? I expect to be able to configure two different view resolvers, one with a certain prefix, the other with a different one. I also expect them to be checked in a determined order, and to fallback from the first to the last. Spring MVC offers http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-viewresolver-chaining[multiple resolvers with deterministic order^], with a big caveat: it does not apply to InternalResourceViewResolver!

    Quoting Spring MVC Javadoc:

    [quote] When chaining ViewResolvers, an InternalResourceViewResolver always needs to be last, as it will attempt to resolve any view name, no matter whether the underlying resource actually exists.

    This means I cannot configure two InternalResourceViewResolver in my context, or more precisely I can but the first will terminate the lookup process. The reasoning behind (as well as the actual code), is that the resolver gets an handle on the RequestDispatcher configured with the resource path. Only much later is the dispatcher forwarded to, only to find that it does not exist.

    To me, this is not acceptable as my use-case is commonplace. Furthermore, configuring only "/WEB-INF" for prefix and returning the rest of the path ("/page/my")  is out of the question as it ultimately defeats the purpose of decoupling the logical name from the resource location. Worst of all, I’ve seen controller code such as the following to cope with this limitation:

    [source,java] return getViews().get(“my”); // The controller has a Map view property with “my” as key and the complete path as the “value”

    I think there must be some more Spring-ish way to achieve that and I’ve come to what I think is an elegant solution in the form of a ViewResolver that checks if the resource exists.

    [source,java]

    public class ChainableUrlBasedViewResolver extends UrlBasedViewResolver {

    public ChainableUrlBasedViewResolver() { setViewClass(InternalResourceView.class); }

    @Override protected AbstractUrlBasedView buildView(String viewName) throws Exception { String url = getPrefix() + viewName + getSuffix(); InputStream stream = getServletContext().getResourceAsStream(url); if (stream == null) { return new NonExistentView(); } return super.buildView(viewName); }

    private static class NonExistentView extends AbstractUrlBasedView { @Override protected boolean isUrlRequired() { return false; }

    @Override
    public boolean checkResource(Locale locale) throws Exception {
      return false;
    }
    
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model,
                                           HttpServletRequest request,
                                           HttpServletResponse response) throws Exception {
      // Purposely empty, it should never get called
    }   } } ----
    

    My first attempt was trying to return null within the buildView() method. Unfortunately, there was some NPE being thrown later in the code. Therefore, the method returns a view that a. tells caller that the underlying resource does not exist b. does not allow for its URL to be checked (it also fails at some point if this is not set).

    I’m pretty happy with this solution, as it enables me to configure my context like that:

    [source,java]

    @Configuration @EnableWebMvc @ComponentScan(basePackages = “ch.frankel.blog.spring.viewresolver.controller”) public class WebConfig {

    @Bean public ViewResolver pageViewResolver() { UrlBasedViewResolver resolver = new ChainableUrlBasedViewResolver(); resolver.setPrefix(“/WEB-INF/page/”); resolver.setSuffix(“.jsp”); resolver.setOrder(0); return resolver; }

    @Bean public ViewResolver jspViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix(“/WEB-INF/jsp/”); resolver.setSuffix(“.jsp”); resolver.setOrder(1); return resolver; } } —-

    Now, I’m pretty well inside Spring philosophy: I’m completely decoupled, and I’m using Spring nominal resolver ordering. The only con is that one resource can shadow another another by having the same logical name pointing to different resources given different view resolvers. As it is already the case with multiple view resolvers, I’m ready to accept the risk.

    A showcase project can be found link:/assets/resources/chaining-url-view-resolvers-in-spring-mvc/viewresolver.zip[here] in IntelliJ IDEA/Maven format.

    Categories: JavaEE Tags: Spring MVC
  • Spring 3.2 sweetness

    :page-liquid: :experimental:

    Even the most extreme Spring opponents have to admit it is all about making developers life easier. Version 3.2 of Spring MVC brings even more sweetness to the table.

    == Sweetness #1: No web.xml

    The ability to run a webapp without any web deployment descriptor comes from Servlet 3.0.

    One option would be to annotate your servlet with the @WebServlet annotation to set mapping and complementary data. When you get your servlet for free, like Spring’s DispatcherServlet, you’d need to subclass you servlet for no other purpose than adding annotation(s).

    Alternatively, Servlet 3.0 offers a way to both programmatically register servlets in the container and to offer hooks at startup through the ServletContainerInitializer interface. The container will call the onStartup() method of all concrete implementation at webapp startup. The Spring framework leverages this feature to do so for WebApplicationInitializer instances.

    Spring MVC 3.2 provides such an implementation - AbstractContextLoaderInitializer, to programmatically register the DispatcherServlet. This means that as soon as the spring-webmvc jar is in the WEB-INF/lib folder of the webapp, you’ve got the Dispatcher servlet up and ready.

    This replaces both the servlet and servlet mapping and the context listener declarations in the web.xml.

    == Sweetness #2: Easy Java configuration integration

    Java configuration is the way to configure Spring injection explicitly in a typesafe way. I won’t go into the full demonstration of it, as I link:{% post_url 2013-03-10-consider-replacing-spring-xml-configuration-with-javaconfig %}[already wrote about that^] some time ago.

    Earlier Spring versions provided a way to use Java configuration classes instead of XML files in the web deployment descriptor. Spring 3.2 offers AbstractAnnotationConfigDispatcherServletInitializer, a AbstractContextLoaderInitializer subclass with hooks for Java configuration classes.

    Your own concrete subclass has to implement methods to define servlet mappings, as well as root and web Java configuration classes:

    [source,java]

    public class SugarSpringWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { JavaConfig.class };
    }
    
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }
    
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    } } ----
    

    At this point, you just need to create those configuration classes.

    == Sweetness #3: integration testing at the mapping level

    Your code should be unit-tested, that is tested in isolation to ensure that each method is bug-free, and integration-tested to ensure that collaboration between classes yield expected results.

    Before v. 3.2, the Spring test framework let you assemble your configuration classes / files easily enough. The problem lay in the way you would call entry-points - the controllers. You could call methods of those controllers, but not the mappings, leaving those untested.

    With v. 3.2, Spring Test brings a whole MVC testing framework which entry-points are mappings. This way, instead of testing method x() of controller C, you would test a request to /z, letting Spring MVC handle it so we can check for expected results.

    The framework also provide expectations for view returning, forwarding, redirecting, and model attribute setting, all with the help of a specific DSL:

    [source,java]

    public class SayHelloControllerIT extends AbstractTestNGSpringContextTests {

    private MockMvc mockMvc;
    
    @BeforeMethod
    public void setUp() {
        mockMvc = webAppContextSetup((WebApplicationContext) applicationContext).build();
    }
    
    @Test(dataProvider = "pathParameterAndExpectedModelValue")
    public void accessingSayhelloWithSubpathShouldForwardToJspWithModelFilled(String path, String value) throws Exception {
        mockMvc.perform(get("/sayHello/Jo")).andExpect(view().name("sayHello")).andExpect(model().attribute("name", "Jo"));
    } } ----
    

    The project for this article can be link:/assets/resources/spring-3-2-sweetness/spring-sweet-1.0.0.zip[downloaded] in Eclipse/Maven format.

    Categories: JavaEE Tags: integration testingspringSpring MVC