Tuesday, August 19, 2014

Spring 4 Scala MVC without Web.XML - Tiles3 : WebConfig class configuration with Localisation


Img.1.:: Spring 4 Scala project structure with Tiles 3 and l18n(l10n) 
  Enabling Apache Tiles3 needs little more changes in the project (Img.1.) configuration. The WebConfig scala class needs to extended by WebMvcConfigurerAdapter (already touched in the previous post: Scala Spring 4 MVC without Web.XML configuration with static resources handling). 
  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  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. 

project: miko-spring-scala on github

No comments: