This is an excerpt from the Scala Cookbook (partially modified for the internet). This is a short recipe, Recipe 15.6, “How to replace XML servlet mappings with Scalatra mounts.”
Problem
You want to add new servlets to your Scalatra application, and need to know how to add them, including defining their URI namespace.
Solution
Scalatra provides a nice way of getting you out of the business of declaring your servlets and servlet mappings in the web.xml file. Simply create a boilerplate web.xml file like this in the src/main/webapp/WEB-INF directory:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee "http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <listener> <listener-class>org.scalatra.servlet.ScalatraListener</listener-class> </listener> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/img/*</url-pattern> <url-pattern>/css/*</url-pattern> <url-pattern>/js/*</url-pattern> <url-pattern>/assets/*</url-pattern> </servlet-mapping> </web-app>
Next, assuming that you’re working with the application created in Recipe 15.5, edit the src/main/scala/ScalatraBootstrap.scala file so that it has these contents:
import org.scalatra._ import javax.servlet.ServletContext import com.alvinalexander.app._ class ScalatraBootstrap extends LifeCycle { override def init(context: ServletContext) { // created by default context.mount(new MyScalatraServlet, "/*") // new context.mount(new StockServlet, "/stocks/*") context.mount(new BondServlet, "/bonds/*") } }
The two new context.mount
lines shown tell Scalatra that a class named StockServlet
should handle all URI requests that begin with /stocks/, and another class named BondServlet
should handle all URI requests that begin with /bonds/.
Next, create a file named src/main/scala/com/alvinalexander/app/OtherServlets.scala to define the StockServlet
and BondServlet
classes:
package com.alvinalexander.app import org.scalatra._ import scalate.ScalateSupport class StockServlet extends MyScalatraWebAppStack { get("/") { <p>Hello from StockServlet</p> } } class BondServlet extends MyScalatraWebAppStack { get("/") { <p>Hello from BondServlet</p> } }
Assuming your project is still configured to recompile automatically, when you access the http://localhost:8080/stocks/ and http://localhost:8080/bonds/ URLs, you should see the content from your new servlets.
Discussion
Scalatra refers to this configuration process as “mounting” the servlets, and if you’ve used a filesystem technology like NFS, it does indeed feel similar to the process of mounting a remote filesystem.
As a result of the configuration, new methods in the StockServlet
and BondServlet
will be available under the /stocks/ and /bonds/ URIs. For example, if you define a new method like this in the StockServlet
:
get("/foo") { <p>Foo!</p> }
you’ll be able to access this method at the /stocks/foo URI, e.g., the http://localhost:8080/stocks/foo URL, if you’re running on port 8080 on your local computer.
In the end, this approach provides the same functionality as servlet mappings, but it’s more concise, with the added benefit that you’re working in Scala code instead of XML, and you can generally forget about the web.xml file after the initial configuration.
See Also
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |