Friday, August 8, 2014

HowTo:: Scala Spring 4 MVC without Web.XML configuration with static resources handling

This blog post is fully focused on Scala language and how to use it for Spring 4 based application development. I'll  modify application I've used over previous blog post series ("Spring4Netty without Web.XML configuration on Java 8.."). 

  Although Spring Framework is so popular in the Java land, there is no reason why not to use Scala language for the EE application development. 
In case when the Applicaiton front-end uses popular AngularJS Framework I personally find Scala usage much "easier" (ps: still lot of work :) and comfortable to understand back-end and front-end functionality as javascript uses callbacks. 

for building new Spring4 Scala application we use following tools: 
of course Jetty server can be change to the Tomcat one. 
  Whole sample application has been developed in IntelliJ IDEA 13.x IDE. 
After we have created the SBT project under IntelliJ we need to import some plugins.
Img.1.:: SBT Project Structure - plugins.sbt
  To import them we change sbt plugins setup by modifying appropriate file (Img.1.) in the following manner. 
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "1.0.0-M4")

addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
  We have now added two plugins  xsbt-web-plugin and sbt-idea.  The xsbt-web-plugin is used for building web enterprise application. Both of them are extensions to SBT building tool.

  Next step is to add necessary libraries dependences into the build.sbt file. As we want to link also static resources, for the front-end development, the number of needed libraries will be bigger. 
  The build.sbt file will look after our modification like following example.
name := "miko-spring-scala"

version := "1.0"

scalaVersion := "2.10.3"

libraryDependencies ++= Seq(
  "org.springframework" % "spring-webmvc" % "4.0.6.RELEASE",
  "org.springframework" % "spring-context" % "4.0.6.RELEASE",
  "org.springframework" % "spring-context-support" % "4.0.6.RELEASE",
  "javax.servlet" % "javax.servlet-api" % "3.0.1" % "provided",
  "javax.servlet" % "jstl" % "1.2" % "compile",
  "org.eclipse.jetty" % "jetty-webapp" % "9.1.0.v20131115" % "container, compile",
  "org.eclipse.jetty" % "jetty-jsp" % "9.1.0.v20131115" % "container"
)

jetty(port = 9090)
here is visible which kind of servlet engine provider will be used (in case of Tomcat change jetty() to tomcat()). 

  When the SBT application is ready we will use commands to start/stop it.
... SBT console ...
container:start

container:stop
...
  All libraries and plugins are ready and we can start building Spring4 Scala Application without using Web.XML and with linked static resources for the next front-end development. Web.xml file will look almost empty in contracts to XML configuration.
...
Miko Scala Spring 4 - Example without Web.xml 
...
  The application package structure is very similar to the previous ones. I want to keep consistency and get possibility to have the reference to the Java implementation (Img.2.) in case of possible comparison.
Img.2.:: Example Spring4 Scala application packages structure

Now I simply turn the Java into the Scala in several steps

1. Scala WebConfig will look like following

..
@Configuration
@ComponentScan(basePackages = Array("miko.scala.helloexample"))
@EnableWebMvc
class WebConfig extends WebMvcConfigurerAdapter{

  override def addResourceHandlers(registry: ResourceHandlerRegistry) = {
    registry.addResourceHandler("/app/**").addResourceLocations("/app/").setCachePeriod(31550522)
  }

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

  @Bean
  def viewResolver = {
    val viewResolver = new InternalResourceViewResolver
    viewResolver.setViewClass(classOf[JstlView])
    viewResolver.setPrefix("/WEB-INF/pages/")
    viewResolver.setSuffix(".jsp")
    viewResolver
  }
}
2. Scala WebInitializer which help us setup ServletContext at the starup 
class WebInitializer extends WebApplicationInitializer{

  override def onStartup(servletContext: ServletContext) = {
    val ctx = new AnnotationConfigWebApplicationContext
    ctx.register(classOf[WebConfig])

    ctx.setConfigLocation("META-INF/spring/app-spring-scala.xml")

    val servlet: Dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx))
    servlet.addMapping("/")
    servlet.setLoadOnStartup(1)
  }
}
3. Scala HelloExampleController class annotated by @Contoller annotation. The Annotation takes care about HttpServletRequest and Responses. This example controller also shows how Services are @Autowired when Scala language is used. 
@Controller
@RequestMapping(Array("/"))
class HelloExampleController @Autowired() (exampleService: ExampleService, exampleImportService: ExampleImportService){

  @RequestMapping(method =  Array(RequestMethod.GET))
  def hello( model: Model) = {
    model.addAttribute("message", "Here is Scala with ServiceName = " + exampleService.serviceName)
    model.addAttribute("importMessage", "Here is Scala with ServiceImportName = " + exampleImportService.name)
    "hello"
  }
}
4. Scala Example...Services used by HelloExampleController are done over quite powerful Traits implementation. Traits are very similar to Java Interfaces but they allows partial implementation which makes them much more powerful (out of blogpost scope ;).  
trait ExampleImportService {
  def name: String
}
-----
class ExampleImportServiceImpl extends ExampleImportService{
  override def name: String = "Imported service over XML"
}

after all those steps we've ready Scala Spring 4 application to test. We've also source code to compare with previous Java8 implementation. Scala does the great work because thinking in functions and callbacks intentions makes whole development more strait forward. 
Enjoy sample application ! (GitHub miko-spring-scala)

No comments: