Автономное развертывание сервлета Scalatra

Я реализовал сервлет Scalatra и теперь хочу создать исполняемый файл jar, как описано в этом руководстве: http://www.scalatra.org/2.2/guides/deployment/standalone.html

Я использую IntelliJ IDEA с плагином Scala для разработки и sbt для сборки и запуска моего сервлета (я использовал sbt-idea для генерации файлов проекта). Моя проблема в том, что пакеты Jetty, которые использует JettyLauncher из учебного пособия, не могут быть найдены, когда я пытаюсь скомпилировать свой проект.

ОБНОВЛЕНИЕ: Используя ответ Мэтта, я смог скомпилировать и запустить JettyLauncher. Тем не менее, у меня все еще есть проблемы с sbt-сборкой ( https://github.com/sbt/sbt-assembly). Я следовал инструкции в файле readme, но при попытке выполнить задачу сборки получаю следующую ошибку:

[error] Not a valid command: assembly
[error] No such setting/task
[error] assembly
[error]         ^  

ОБНОВЛЕНИЕ 2: Благодаря Мэтту, у меня теперь есть рабочий build.scala, и я могу сгенерировать исполняемый файл jar, используя задачу сборки. Тем не менее, sbt-assembly не добавляет содержимое / src / main / webapp в jar. Я использую эту папку для хранения файлов HTML, CSS и JavaScript. Если Scalatra не может сопоставить маршрут, он обслуживает эти файлы, что работает при запуске сервлета с использованием container:start. Кроме того, я храню некоторые файлы, которые нужны серверу, в /src/main/webapp/WEB-INF. Эти файлы также не добавляются в банку.

Мой build.scala выглядит так:

import sbt._
import Keys._
import org.scalatra.sbt._
import org.scalatra.sbt.PluginKeys._
import com.mojolly.scalate.ScalatePlugin._
import ScalateKeys._
import sbtassembly.Plugin._
import AssemblyKeys._

object SketchlinkBuild extends Build {
  val Organization = "de.foobar"
  val Name = "Foobar"
  val Version = "0.1"
  val ScalaVersion = "2.10.0"
  val ScalatraVersion = "2.2.0"

  lazy val project = Project (
    "foobar",
    file("."),
    settings = Defaults.defaultSettings ++ ScalatraPlugin.scalatraWithJRebel ++ scalateSettings ++ assemblySettings ++ Seq(
      organization := Organization,
      name := Name,
      version := Version,
      scalaVersion := ScalaVersion,
      resolvers += Classpaths.typesafeReleases,
      libraryDependencies ++= Seq(
            "org.scalatra" %% "scalatra" % ScalatraVersion,
            "org.scalatra" %% "scalatra-scalate" % ScalatraVersion,
            "org.scalatra" %% "scalatra-specs2" % ScalatraVersion % "test",
            "ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime",
            "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "compile;container",
            "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "compile;container;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar")),
            /* Apache commons libraries */
            "commons-codec" % "commons-codec" % "1.7", 
            "commons-io" % "commons-io" % "2.4",
            /* JSON support */
            "org.scalatra" %% "scalatra-json" % "2.2.1",
            "org.json4s"   %% "json4s-jackson" % "3.2.4",
            /* thumbnail library */
            "net.coobird" % "thumbnailator" % "0.4.3"
     ),
     // ignore about.html in jars (needed for sbt-assembly)
     mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => {
       case "about.html" => MergeStrategy.discard
       case x => old(x) }
     },
     scalateTemplateConfig in Compile <<= (sourceDirectory in Compile){ base =>
        Seq(
          TemplateConfig(
            base / "webapp" / "WEB-INF" / "templates",
            Seq.empty,  /* default imports should be added here */
            Seq(
              Binding("context", "_root_.org.scalatra.scalate.ScalatraRenderContext", importMembers = true, isImplicit = true)
            ),  /* add extra bindings here */
            Some("templates")
          )
        )
      }
    )
  )
}

Заранее спасибо!

3 ответа

В настоящее время существует два варианта автономного развертывания:

  1. Единственный.jar, использующий sbt-сборку, которая содержит ресурсы среды выполнения и веб-приложения. Загрузка ресурсов из файла.jar довольно медленная в моем опыте.
  2. Распространение.zip файла с использованием scalatra-sbt плагин, содержит скрипт запуска оболочки, ресурсы времени выполнения и ресурсы веб-приложения в папках.

1. Автономный JAR

Для отдельного файла.jar, использующего sbt-assembly вам нужно сначала добавить плагин project/build.sbt:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.0")

Затем вам нужно изменить сборку проекта, например project/build.scala, Импортируйте настройки и ключи плагина:

import sbtassembly.Plugin._
import sbtassembly.Plugin.AssemblyKeys._

С этим вы можете создать настройки для sbt-assembly плагин:

// settings for sbt-assembly plugin
val myAssemblySettings = assemblySettings ++ Seq(

  // handle conflicts during assembly task
  mergeStrategy in assembly <<= (mergeStrategy in assembly) {
    (old) => {
      case "about.html" => MergeStrategy.first
      case x => old(x)
    }
  },

  // copy web resources to /webapp folder
  resourceGenerators in Compile <+= (resourceManaged, baseDirectory) map {
    (managedBase, base) =>
      val webappBase = base / "src" / "main" / "webapp"
      for {
        (from, to) <- webappBase ** "*" x rebase(webappBase, managedBase / "main" / "webapp")
      } yield {
        Sync.copy(from, to)
        to
      }
  }
)

Первый определяет стратегию слияния, последний копирует статические веб-ресурсы из src/main/webapp в <resourceManaged>/main/webapp, Они будут включены в окончательный.jar в подпапке /webapp,

Включите настройки в свой проект:

lazy val project = Project("myProj", file(".")).settings(mySettings: _*).settings(myAssemblySettings:_*)

Теперь лаунчер нужно создать. Обратите внимание, как установлена ​​база ресурсов:

import org.eclipse.jetty.server.nio.SelectChannelConnector
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.webapp.WebAppContext
import org.scalatra.servlet.ScalatraListener

object JettyMain {

  def run = {
    val server = new Server
    val connector = new SelectChannelConnector
    connector.setPort(8080)
    server.addConnector(connector)

    val context = new WebAppContext
    context.setContextPath("/")

    val resourceBase = getClass.getClassLoader.getResource("webapp").toExternalForm
    context.setResourceBase(resourceBase)
    context.setEventListeners(Array(new ScalatraListener))
    server.setHandler(context)

    server.start
    server.join
  }
}

2. Распространение.zip с использованием scalatra-sbt Plugin

Вам нужно добавить этот импорт в ваш SBT build.scala:

import org.scalatra.sbt.DistPlugin._
import org.scalatra.sbt.DistPlugin.DistKeys._

Затем вам нужно добавить настройки плагина в ваш проект. Настройки находятся в DistPlugin.distSettings,

Вы также можете настроить свой дистрибутив и добавить пользовательские настройки памяти, экспорт и параметры командной строки. Обратите внимание, что это все необязательно:

val myDistSettings = DistPlugin.distSettings ++ Seq(
  mainClass in Dist := Some("ScalatraLauncher"),
  memSetting in Dist := "2g",
  permGenSetting in Dist := "256m",
  envExports in Dist := Seq("LC_CTYPE=en_US.UTF-8", "LC_ALL=en_US.utf-8"),
  javaOptions in Dist ++= Seq("-Xss4m", "-Dfile.encoding=UTF-8")
)

В командной строке SBT вы можете набрать dist, Файл.zip будет в target папка.

Я недавно столкнулся с проблемой, делая это.

Во-первых, вы должны убедиться, что пристань доступна во время компиляции. Эти две строки:

"org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container",
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" %     "container;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar")),

Нужно иметь в них компиляцию:

"org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "compile;container",
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "compile;container;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar"))

Во-вторых, из вашего описания звучит так, что sbt-сборка настроена неправильно. Вам необходимо удалить (закомментировать) эти строки:

lazy val buildSettings = Defaults.defaultSettings ++ Seq(
  version := "0.1",
  organization := "de.foobar",
  scalaVersion := "2.10.1"
)

lazy val app = Project("app", file("app"),
  settings = buildSettings ++ assemblySettings) settings(
    // your settings here
)

Вам нужно будет добавить ++ assemblySettings в ваш проект foobar сразу после scalateSettings, Ваш файл plugins.sbt также должен содержать следующую строку:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.0")

Для справки, я рекомендую не использовать sbt-assembly, потому что вы, скорее всего, столкнетесь с конфликтами зависимостей, которые необходимо будет решить с помощью стратегии слияния. Вместо этого я предлагаю вам использовать задачу, которая собирает ваши зависимости в каталог (примеры здесь и здесь). А затем добавить их в путь к классу Java с помощью java -cp /lib/* ...,

В-третьих, будьте осторожны с проектом Jetty в GitHub Scalatra. Я использовал:

import java.net.InetSocketAddress
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.DefaultServlet

import org.scalatra.servlet.ScalatraListener
import org.eclipse.jetty.webapp.WebAppContext

object Jetty {
  def main(args: Array[String]) = {
    val socketAddress = new InetSocketAddress(8080)
    val server = new Server(socketAddress)
    val context = new WebAppContext()
    context.setContextPath("/")
    context.setResourceBase("src/main/webapp")
    context.addEventListener(new ScalatraListener)
    context.addServlet(classOf[DefaultServlet], "/")
    server.setHandler(context)
    server.start()
    server.join()
  }
}

Наконец, возможно, стоит проверить, что ваш ScalatraBootstrap находится в обычном месте.

Надеюсь, это поможет. Если нет, я могу опубликовать всю мою сборку.scala для вас.

Для получения актуального ответа, пожалуйста, обратитесь к этим двум файлам (Кредиты идут в Scalatra в книге действий):

https://github.com/scalatra/scalatra-in-action/blob/master/chapter09-standalone/src/main/scala/ScalatraLauncher.scala

а также

https://github.com/scalatra/scalatra-in-action/blob/master/chapter09-standalone/project/Build.scala

Другие вопросы по тегам