I'm testing around with a Scala web framework (Udash) and trying to run a toy-example in Heroku. I have it running without issues in local following the instructions in the Heroku docs:
sbt compile stage
heroku local web
However, once deployed, any URL I type goes to 404, even the landing page of the app. These are the objects I am using:
object Launcher extends CrossLogging {
def main(args: Array[String]): Unit = {
val port = Properties.envOrElse("PORT", "5000").toInt
val server = new ApplicationServer(port, "frontend/target/UdashStatics/WebContent")
server.start()
logger.info(s"Application started...")
}
}
class ApplicationServer(val port: Int, resourceBase: String) {
private val server = new Server(port)
private val contextHandler = new ServletContextHandler
private val appHolder = createAppHolder()
contextHandler.setSessionHandler(new SessionHandler)
contextHandler.setGzipHandler(new GzipHandler)
contextHandler.getSessionHandler.addEventListener(new org.atmosphere.cpr.SessionSupport())
contextHandler.addServlet(appHolder, "/*")
server.setHandler(contextHandler)
def start(): Unit = server.start()
def stop(): Unit = server.stop()
private def createAppHolder() = {
val appHolder = new ServletHolder(new DefaultServlet)
appHolder.setAsyncSupported(true)
appHolder.setInitParameter("resourceBase", resourceBase)
appHolder
}
}
Is there any Heroku configuration/characteristic that I am missing?
EDIT
Tried to apply the changes suggested and ended up with the following ApplicationContext:
class ApplicationServer(val port: Int, val resourceBase: String) {
val server = new Server()
val connector = new ServerConnector(server)
connector.setPort(port)
server.addConnector(connector)
private val appHolder = createAppHolder()
val context = new ServletContextHandler(ServletContextHandler.SESSIONS)
context.setBaseResource(Resource.newResource(resourceBase))
context.setContextPath("/")
context.addServlet(appHolder, "/")
server.setHandler(context)
private def createAppHolder() = {
val appHolder = new ServletHolder("default", classOf[DefaultServlet])
appHolder.setInitParameter("dirAllowed", "true")
appHolder.setInitParameter("resourceBase", resourceBase)
appHolder
}
def start(): Unit = server.start()
def stop(): Unit = server.stop()
}
However, I still get Error 404 even on landing page after deploying to Heroku:
HTTP ERROR 404
Problem accessing /. Reason:
Not Found
When running the app on local I get to the landing page correctly.
Thank you! Thanks!
A few things to adjust that might help you.
resourceBase
as a init-parameter on DefaultServlet
is for alternate static file serving . ServletContextHandler.setBaseResource(Resource)
instead. Resource.newResource(String)
to create a new Resource reference. This should be an absolute path on the filesystem, or an absolute URI reference. no relative paths or URI fragments. DefaultServlet
must be on the url-pattern
of "/"
, not "/*"
(this is a servlet spec requirement) DefaultServlet
must be named, and must have the name "default"
(this is a servlet spec requirement, see link on point 1 for example) ServletContextHandler.setContextPath("/")
to be explicit about what base context-path you want to use. Some observations:
Your example code will only serve static content out of the resourceBase
.
Since you have no welcomeFiles
configured it would serve <resourceBase>/index.html
by default (if you don't specify a specific static resource you want to access)
You have a SessionListener
setup ( org.atmosphere.cpr.SessionSupport
), but since there's nothing that would access a Session
, that code is pretty much a no-op.
There's no dynamic results from a custom Servlet or Filter present in your example codebase.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.