Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Scala 4 Spring MVC without Web.XML: WebConfig Class Configuration with Localization

DZone's Guide to

Scala 4 Spring MVC without Web.XML: WebConfig Class Configuration with Localization

· Integration Zone
Free Resource

Share, secure, distribute, control, and monetize your APIs with the platform built with performance, time-to-value, and growth in mind. Free 90 day trial 3Scale by Red Hat

In my previous article I was writing about Scala 4 Spring MVC without Web.XML and how to handle static resources accessed by AngularJS front-end client. In this article I will show how to connect the application with Apache Tiles 3.0. Apache Tiles enables possibility to define fragment os the pages and assemble them into to the complete one. In general Tiles 3.0 is nice and clean way of front-parts reusability. The one of those part are localised messages (see img.1.: The Project Structure).

 

Enabling Apache Tiles3 needs little more changes in the project (Img.1.) configuration. The WebConfig scala class needs to extended by WebMvcConfigurerAdapter (previous article )

We also define the set of annotations we do need to be scanned over the project package. The reason of such definition is to show possibilities of Scala configuration of the Spring Framework itself

@Configuration
@ComponentScan(basePackages = Array("miko.scala.helloexample"), useDefaultFilters = false, includeFilters = Array(
  new ComponentScan.Filter(`type` = FilterType.ANNOTATION,
    value = Array(classOf[Controller], classOf[Service]))))
@EnableWebMvc
class WebConfig extends WebMvcConfigurerAdapter{
...

In WebConfig we do replace @Bean setupViewResolver(), which implements the ViewResolver interface that allows directly resolved symbolic view names, by getTilesConfigurer @Bean, which provide TilesConfigurer

The TilesConfigurer class provide the tempting mechanism for web project (application) using JSP and other front-end engines. 

@Bean
def getTilesConfigurer: TilesConfigurer = {
  val configurer:TilesConfigurer = new TilesConfigurer()
  configurer.setCheckRefresh(true)
  configurer.setDefinitions({"/WEB-INF/pages/tiles.xml"})
  configurer
}

And additionally we have  to define ViewResolver for Tiles by getTilesViewResolver @Bean definition.

@Bean
def getTilesViewResolver: ViewResolver = {
  val resolver:TilesViewResolver = new TilesViewResolver()
  resolver.setContentType("text/html")
  resolver
}

The full configuration needs to define and override also couple of other Beans connected with our localisation (l10n/l18n) intent. The final WebConfig Scala class will look in following manner.

@Configuration
@ComponentScan(basePackages = Array("miko.scala.helloexample"), useDefaultFilters = false, includeFilters = Array(
  new ComponentScan.Filter(`type` = FilterType.ANNOTATION,
    value = Array(classOf[Controller], classOf[Service]))))
@EnableWebMvc
class WebConfig extends WebMvcConfigurerAdapter{

  private val logger = LoggerFactory.getLogger(getClass)

  override def configureDefaultServletHandling(configurer: DefaultServletHandlerConfigurer) = {
    configurer.enable()
  }

  override def addViewControllers(registry: ViewControllerRegistry): Unit ={
    registry.addViewController("/")
  }

  @Bean
  def getTilesViewResolver: ViewResolver = {
    val resolver:TilesViewResolver = new TilesViewResolver()
    resolver.setContentType("text/html")
    resolver
  }

  @Bean
  def getTilesConfigurer: TilesConfigurer = {
    val configurer:TilesConfigurer = new TilesConfigurer()
    configurer.setCheckRefresh(true)
    configurer.setDefinitions({"/WEB-INF/pages/tiles.xml"})
    configurer
  }

  override def addInterceptors(registry:InterceptorRegistry) = {
    val localeChangeInterceptor = new LocaleChangeInterceptor()
    localeChangeInterceptor.setParamName("lang")
    registry.addInterceptor(localeChangeInterceptor)
  }

  /**
   * equivalents for <mvc:resources> tags
   * @param registry
   */
  override def addResourceHandlers(registry: ResourceHandlerRegistry) = {
    logger.debug("Resources HANDLER")
    registry.addResourceHandler("/app/**").addResourceLocations("/app/").setCachePeriod(31550522)
    registry.addResourceHandler("/WEB-INF/layouts/**").addResourceLocations("/WEB-INF/layouts/").setCachePeriod(31550522);
    registry.addResourceHandler("/WEB-INF/pages/template/**").addResourceLocations("/WEB-INF/pages/template/").setCachePeriod(31550522);
  }

  @Bean(name = Array("localeResolver"))
  def getLocaleResolver: LocaleResolver = {
    val cookieLocaleResolver: CookieLocaleResolver = new CookieLocaleResolver()
    cookieLocaleResolver.setDefaultLocale(new Locale("en"))
    cookieLocaleResolver
  }

  override def configureContentNegotiation(configurer: ContentNegotiationConfigurer) = {
    configurer.favorPathExtension(true).ignoreAcceptHeader(true)
        .useJaf(false).defaultContentType(MediaType.TEXT_HTML)
        .mediaType("html", MediaType.TEXT_HTML)
        .mediaType("xml", MediaType.APPLICATION_XML)
        .mediaType("json", MediaType.APPLICATION_JSON)
  }

  @Bean(name = Array("messageSource"))
  def getMessageSource: MessageSource = {
    val msgSrc:ReloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource()
    msgSrc.setBasename("classpath:/messages/message")
    msgSrc
  }
}

After having enabled Tiles with l10n/l18n on the back-end side we can move to front-end and tell Tiles which kind of template it should use to display pages correctly to the user (Img.1. ~ project structure). Of course, with CSS or possible JavaScript libraries. 

But I'll do this in next blog post. 

Now Enjoy configuring your WebConfig scala class. (my blogs about scala)

Discover how you can achielve enterpriese agility with microservices and API management

Topics:

Published at DZone with permission of Miro Wengner. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}