【问题标题】:Scala enumeration serialization in jersey/jackson is not working for mejersey/jackson 中的 Scala 枚举序列化对我不起作用
【发布时间】:2014-10-15 18:52:42
【问题描述】:

我已经阅读了关于枚举处理的 jackson-module-scala 页面 (https://github.com/FasterXML/jackson-module-scala/wiki/Enumerations)。我仍然没有让它工作。基本代码如下:

@Path("/v1/admin")
@Produces(Array(MediaType.APPLICATION_JSON + ";charset=utf-8"))
@Consumes(Array(MediaType.APPLICATION_JSON + ";charset=utf-8"))
class RestService {

  @POST
  @Path("{type}/abort")
  def abortUpload(@PathParam("type") typeName: ResourceTypeHolder) {
    ...
  }
}

object ResourceType extends Enumeration {
    type ResourceType = Value
    val ssr, roadsegments, tmc, gab, tne = Value
}

class ResourceTypeType extends TypeReference[ResourceType.type]
case class ResourceTypeHolder(
  @JsonScalaEnumeration(classOf[ResourceTypeType])
  resourceType:ResourceType.ResourceType
)

这就是它应该的工作方式,对吧?我仍然收到这些错误:

Following issues have been detected:
WARNING: No injection source found for a parameter of type public void no.tull.RestService.abortUpload(no.tull.ResourceTypeHolder) at index 0.

unavailable
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public void no.tull.RestService.abortUpload(no.tull.ResourceTypeHolder) at index 0.; source='ResourceMethod{httpMethod=POST, consumedTypes=[application/json; charset=utf-8], producedTypes=[application/json; charset=utf-8], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class no.tull.RestService, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@7ffe609f]}, definitionMethod=public void no.tull.RestService.abortUpload(no.tull.ResourceTypeHolder), parameters=[Parameter [type=class no.tull.ResourceTypeHolder, source=type, defaultValue=null]], responseType=void}, nameBindings=[]}']
    at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:467)
    at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:163)
    at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:323)
    at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
    at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)

我还组装了一个小型可运行项目(同时试图消除任何其他复杂性)来证明问题:project.tgz

更新:创建了一个 sbt 文件来查看 gradle 是否正在构建一个奇怪的构建。得到了相同的结果,但这是 build.sbt

name := "project"

version := "1.0"

scalaVersion := "2.10.4"

val jacksonVersion = "2.4.1"
val jerseyVersion = "2.13"

libraryDependencies ++= Seq(
  "com.fasterxml.jackson.core" % "jackson-annotations" % jacksonVersion,
  "com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion,
  "com.fasterxml.jackson.jaxrs" % "jackson-jaxrs-json-provider" % jacksonVersion,
  "com.fasterxml.jackson.jaxrs" % "jackson-jaxrs-base" % jacksonVersion,
  "com.fasterxml.jackson.module" % "jackson-module-scala_2.10" % jacksonVersion,
  "org.glassfish.jersey.containers" % "jersey-container-servlet-core" % jerseyVersion
)

seq(webSettings :_*)

libraryDependencies ++= Seq(
  "org.eclipse.jetty" % "jetty-webapp" % "9.1.0.v20131115" % "container",
  "org.eclipse.jetty" % "jetty-plus"   % "9.1.0.v20131115" % "container"
)

...这是project/plugins.sbt

addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.9.0")

【问题讨论】:

标签: scala jersey jackson enumeration


【解决方案1】:

您的 tarball 似乎有一些问题。

您需要向 Jackson 添加一些 Scala 模块才能使用任何 Scala 功能。可以这样做:

val jsonObjectMapper = new ObjectMapper()
jsonObjectMapper.registerModule(DefaultScalaModule)
val jsonProvider: JacksonJsonProvider = new JacksonJsonProvider(jsonObjectMapper)

据此working jersey-jackson example。您还需要将org.glassfish.jersey.jackson.JacksonFeature 注入位于jersey-media-json-jackson 的泽西岛。我的RestApplication.scala是这样出来的

import javax.ws.rs.core.Application
import javax.ws.rs.ext.{ContextResolver, Provider}

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.google.common.collect.ImmutableSet
import org.glassfish.jersey.jackson.JacksonFeature

@Provider
class ObjectMapperProvider extends ContextResolver[ObjectMapper] {
  val defaultObjectMapper = {
    val jsonObjectMapper = new ObjectMapper()
    jsonObjectMapper.registerModule(DefaultScalaModule)
    jsonObjectMapper
  }

  override def getContext(typ: Class[_]): ObjectMapper = {
    defaultObjectMapper
  }
}

class RestApplication extends Application {
  override def getSingletons: java.util.Set[AnyRef] = {
    ImmutableSet.of(
      new RestService,
      new ObjectMapperProvider,
      new JacksonFeature
    )
  }
}

不过,真正的问题是@PathParam 注释。此代码路径根本不调用 Jackson。然而,有趣的是,Jersey 似乎一般支持解析为具有单个字符串构造函数的任何类型。所以如果你修改你的ResourceTypeHolder,你毕竟可以获得你想要的功能。

case class ResourceTypeHolder(@JsonScalaEnumeration(classOf[ResourceTypeType]) resourceType:ResourceType.ResourceType) {
  def this(name: String) = this(ResourceType.withName(name))
}

您也许可以将枚举持有者的通用支持添加到 Jersey 作为可注入提供程序。然而,在 dropwizard-scala 中并没有出现这种情况,该项目也将遭受与使用 Jersey 相同的命运。因此,我认为这要么是不可能的,要么只是不够普遍,任何人都无法完成这项工作。说到枚举,我倾向于使用 Java。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    相关资源
    最近更新 更多