0

在将应用程序升级到 playframework 2.1.1 后,我在 jackson 中遇到了一些反序列化问题(jackson-mapper-asl-1.9.10.jar 和 jackson-core-asl-1.9.10.jar)

从播放控制台执行的、序列化到 json 和从 json 序列化的正常测试工作正常。当在应用程序内部使用相同的序列化时,它会像您在堆栈跟踪中看到的那样抱怨。

我的印象是,因为 akka 库,类路径受到了某种影响。

该代码使用两个函数

public static <T> String toJson(T data) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(Feature.INDENT_OUTPUT, true);
    try {
        return mapper.writeValueAsString(data);
    } catch (IOException e) {
        LOG.warn("can't format a json object from [" + data + "]", e);
        return null;
    }
    //
    // return Json.stringify(Json.toJson(data));
}

public static <T> T fromJson(String description, Class<T> theClass) {
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode parse = objectMapper.readValue(description, JsonNode.class);
        T fromJson = objectMapper.treeToValue(parse, theClass);
        return fromJson;
    } catch (JsonParseException e) {
        throw new RuntimeException("can't parse a json object of type " + theClass.getName() + " from ["
                + description + "]", e);
        // LOG.warn("can't parse a json object from [" + description + "]", e);
        // return null;
    } catch (JsonMappingException e) {
        throw new RuntimeException("can't parse a json object of type " + theClass.getName() + " from ["
                + description + "]", e);
        // LOG.warn("can't parse a json object from [" + description + "]", e);
        // return null;
    } catch (IOException e) {
        throw new RuntimeException("can't parse a json object of type " + theClass.getName() + " from ["
                + description + "]", e);
        // LOG.warn("can't parse a json object from [" + description + "]", e);
        // return null;
    }
}

在此之后,我在 playframework 中得到以下异常

4664956  INFO [play-akka.actor.default-dispatcher-186] - resync sending states BE-beA ...
java.lang.IllegalArgumentException: Invalid type id 'eu.ec.dgempl.eessi.flow.AddSedToFlowControlMessage' (for id type 'Id.class'): no such class found
        at org.codehaus.jackson.map.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:57)
        at org.codehaus.jackson.map.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:113)
        at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:82)
        at org.codehaus.jackson.map.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:52)
        at org.codehaus.jackson.map.deser.StdDeserializerProvider$WrappedDeserializer.deserialize(StdDeserializerProvider.java:461)
        at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704)
        at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1286)
        at org.codehaus.jackson.map.ObjectMapper.treeToValue(ObjectMapper.java:1733)
        at eu.ec.dgempl.eessi.flow.impl.FlowServiceImpl.fromJson(FlowServiceImpl.java:167)
        at eu.ec.dgempl.eessi.flow.impl.FlowServiceImpl.fromBody(FlowServiceImpl.java:144)
        at eu.ec.dgempl.eessi.flow.impl.FlowServiceImpl.resync(FlowServiceImpl.java:130)
        at controllers.Application.renderFlows(Application.java:796)
        at controllers.Application.flows(Application.java:785)
        at Routes$$anonfun$routes$1$$anonfun$applyOrElse$22$$anonfun$apply$22.apply(routes_routing.scala:314)
        at Routes$$anonfun$routes$1$$anonfun$applyOrElse$22$$anonfun$apply$22.apply(routes_routing.scala:314)
        at play.core.Router$HandlerInvoker$$anon$6$$anon$2.invocation(Router.scala:164)
        at play.core.Router$Routes$$anon$1.invocation(Router.scala:345)
        at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:31)
        at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:74)
        at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:73)
        at play.libs.F$Promise$PromiseActor.onReceive(F.java:420)
        at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.scala:159)
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
        at akka.actor.ActorCell.invoke(ActorCell.scala:386)
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
        at akka.dispatch.Mailbox.run(Mailbox.scala:212)
        at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:502)
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)
4666398  INFO [pool-204-thread-1] - JAX-WS RI 2.2.4-b01: Stub for http://192.168.1.6:18003/cn/reliableTransport> execute Execute with delay=10 S :java.util.co
4

1 回答 1

0

最后,问题是由于在开发模式下 play-2.1 中的类加载器管理错误导致的,它没有配置 ReloadableClassLoader (包含已编译的类)但 SBT/Play 共享的 ClassLoader (它不包含你的类,因为是类路径由游戏共享)。此处描述了这些问题http://ben-tech.blogspot.be/2013/05/play-run-in-dev-mode-and.html

解决方案是存储 ReloadableClassLoader 并在当前线程类加载器中配置它:

  1. 通过配置 Global 来拦截 ReloadableClassLoader(这里描述的http://www.playframework.com/documentation/2.1-RC2/ScalaGlobal 这个对象必须在默认(空)包中定义。

    //package nopackage;
    // - This object must be defined in the default (empty) package.
    import java.io.*;
    import org.h2.*;
    import com.typesafe.config.*;
    import akka.actor.*;
    import play.*;
    import play.mvc.Http.RequestHeader;
    import play.mvc.*;
    import eu.ec.dgempl.eessi.env.*;
    import eu.ec.dgempl.eessi.utils.*;
    
    public class Global extends GlobalSettings {
            @Override
            public Configuration onLoadConfig(
                    Configuration config, File path, ClassLoader classloader) {
                    PlayUtils.storeClassLoader(classloader);
                    return super.onLoadConfig(config, path, classloader);
            }
    }
    
  2. 定义 PlayUtils

    //http://stackoverflow.com/questions/16794298/upgrade-to-playframework-2-1-1-creates-json-deserialization-problems-with-jeckso/16794883#16794883
    public class PlayUtils {
            private static ClassLoader fullClassloader;
        public static void fixClassloader() {
            Thread.currentThread().setContextClassLoader(fullClassloader);
        }
    
        public static void storeClassLoader(ClassLoader classloader) {
            fullClassloader = classloader;
        }
    }
    
  3. 在需要使用jackson进行序列化/反序列化的类之前(或在需要postgresql或h2的sql驱动程序类之前),在akka线程中调用PlayUtils.fixClassloader()。这两个案例我都遇到了问题。

    //in the thread that needs the classloader fix
    PlayUtils.fixClassloader()
    

其他资源

列出的例外以帮助搜索

java.lang.IllegalArgumentException: Invalid type id 'eu.ec.dgempl.eessi.bm.CloseFlowChange' (for id type 'Id.class'): no such class found
        at org.codehaus.jackson.map.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:57) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:113) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:82) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:52) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider$WrappedDeserializer.deserialize(StdDeserializerProvider.java:461) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1286) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at org.codehaus.jackson.map.ObjectMapper.treeToValue(ObjectMapper.java:1733) ~[jackson-mapper-asl-1.9.10.jar:1.9.10]
        at eu.ec.dgempl.eessi.bm.impl.BusinessMessagingService.fromJson(BusinessMessagingService.java:533) [classes/:na]
        at eu.ec.dgempl.eessi.bm.impl.BusinessMessagingService.fromBody(BusinessMessagingService.java:504) [classes/:na]
        at eu.ec.dgempl.eessi.bm.impl.BusinessMessagingService.resync(BusinessMessagingService.java:459) [classes/:na]
        at eu.ec.dgempl.eessi.bm.client.LocalBusinessMessaging.resync(LocalBusinessMessaging.java:118) [classes/:na]
        at eu.ec.dgempl.eessi.bm.client.LocalInstitutionBusinessMessaging.resync(LocalInstitutionBusinessMessaging.java:100) [classes/:na]
        at controllers.Application.renderFlows(Application.java:639) [classes/:na]
        at controllers.Application.flows(Application.java:917) [classes/:na]
        at Routes$$anonfun$routes$1$$anonfun$applyOrElse$30$$anonfun$apply$30.apply(routes_routing.scala:470) [classes/:na]
        at Routes$$anonfun$routes$1$$anonfun$applyOrElse$30$$anonfun$apply$30.apply(routes_routing.scala:470) [classes/:na]
        at play.core.Router$HandlerInvoker$$anon$6$$anon$2.invocation(Router.scala:164) [play_2.10.jar:2.1.1]
        at play.core.Router$Routes$$anon$1.invocation(Router.scala:345) [play_2.10.jar:2.1.1]
        at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:31) [play_2.10.jar:2.1.1]
        at play.GlobalSettings$1.call(GlobalSettings.java:63) [play_2.10.jar:2.1.1]
        at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:74) [play_2.10.jar:2.1.1]
        at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:73) [play_2.10.jar:2.1.1]
        at play.libs.F$Promise$PromiseActor.onReceive(F.java:420) [play_2.10.jar:2.1.1]
        at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.scala:159) [akka-actor_2.10.jar:na]
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425) [akka-actor_2.10.jar:na]
        at akka.actor.ActorCell.invoke(ActorCell.scala:386) [akka-actor_2.10.jar:na]
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230) [akka-actor_2.10.jar:na]
        at akka.dispatch.Mailbox.run(Mailbox.scala:212) [akka-actor_2.10.jar:na]
        at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:502) [akka-actor_2.10.jar:na]
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262) [scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975) [scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478) [scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104) [scala-library.jar:na]
SBT/Play shared ClassLoader, with: WrappedArray(file:/c:/apps/play/framework/./sbt/boot/scala-2.10.0/lib/scala-library.jar, file:/c:/apps/play/repository/local/play/play_2.10/2.1.1/jars/play_2.10.jar, file:/c:/apps/play/repository/local/play/sbt-link/2.1
SBT/Play shared ClassLoader, with: WrappedArray(file:/c:/apps/play/framework/./sbt/boot/scala-2.10.0/lib/scala-library.jar, file:/c:/apps/play/repository/local/play/play_2.10/2.1.1/jars/play_2.10.jar, file:/c:/apps/play/repository/local/play/sbt-link/2.1
73424  WARN [play-akka.actor.default-dispatcher-3] - Can't deserialize properly [{
  "class" : "eu.ec.dgempl.eessi.bm.CloseFlowChange",
  "created" : "2013-09-25T00:59:03.890+02:00",
  "changeCreator" : {
    "institutionId" : "beA",
    "countryCode" : "BE"
  },
  "changeId" : {
    "value" : "RM.be.20130925T005903.C.22"

jdbc 驱动程序的类路径问题

7212 ERROR [New I/O worker #1] - The application couldn't be initialized.
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: No suitable driver found for j
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:575) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:639) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:676) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:720) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at eu.ec.dgempl.eessi.utils.db.PostgresDdlDialect.checkIfExists(PostgresDdlDialect.java:53) ~[classes/:na]
        ...
        at eu.ec.dgempl.eessi.apps.EessiApp.startAllServices(EessiApp.java:324) ~[classes/:na]
        at controllers.Application.createEessiDeployment(Application.java:120) [classes/:na]
        at controllers.Application.configure(Application.java:91) [classes/:na]
        at controllers.Global.onStart(Global.java:27) [classes/:na]
        at play.core.j.JavaGlobalSettingsAdapter.onStart(JavaGlobalSettingsAdapter.scala:17) [play_2.10.jar:2.1.1]
        at play.api.GlobalPlugin.onStart(GlobalSettings.scala:175) [play_2.10.jar:2.1.1]
        at play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:63) [play_2.10.jar:2.1.1]
        at play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:63) [play_2.10.jar:2.1.1]
        at scala.collection.immutable.List.foreach(List.scala:309) [scala-library.jar:na]
        at play.api.Play$$anonfun$start$1.apply$mcV$sp(Play.scala:63) [play_2.10.jar:2.1.1]
        at play.api.Play$$anonfun$start$1.apply(Play.scala:63) [play_2.10.jar:2.1.1]
        at play.api.Play$$anonfun$start$1.apply(Play.scala:63) [play_2.10.jar:2.1.1]
        at play.utils.Threads$.withContextClassLoader(Threads.scala:18) [play_2.10.jar:2.1.1]
        at play.api.Play$.start(Play.scala:62) [play_2.10.jar:2.1.1]
        at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:133) [play_2.10.jar:2.1.1]
        at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:106) [play_2.10.jar:2.1.1]
        at scala.Option.map(Option.scala:145) [scala-library.jar:na]
        at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:106) [play_2.10.jar:2.1.1]
        at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:104) [play_2.10.jar:2.1.1]
        at scala.util.Either$RightProjection.flatMap(Either.scala:523) [scala-library.jar:na]
        at play.core.ReloadableApplication.get(ApplicationProvider.scala:104) [play_2.10.jar:2.1.1]
        at play.core.server.Server$class.sendHandler$1(Server.scala:56) [play_2.10.jar:2.1.1]
        at play.core.server.Server$$anonfun$getHandlerFor$4.apply(Server.scala:88) [play_2.10.jar:2.1.1]
        at play.core.server.Server$$anonfun$getHandlerFor$4.apply(Server.scala:87) [play_2.10.jar:2.1.1]
        at scala.util.Either$RightProjection.flatMap(Either.scala:523) [scala-library.jar:na]
        at play.core.server.Server$class.getHandlerFor(Server.scala:87) [play_2.10.jar:2.1.1]
        at play.core.server.NettyServer.getHandlerFor(NettyServer.scala:34) [play_2.10.jar:2.1.1]
        at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$6.apply(PlayDefaultUpstreamHandler.scala:115) [play_2.10.jar:2.1.1]
        at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$6.apply(PlayDefaultUpstreamHandler.scala:115) [play_2.10.jar:2.1.1]
        at scala.util.Either.fold(Either.scala:98) [scala-library.jar:na]
        at play.core.server.netty.PlayDefaultUpstreamHandler.messageReceived(PlayDefaultUpstreamHandler.scala:109) [play_2.10.jar:2.1.1]
        at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70) [netty.jar:na]
        at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:560) [netty.jar:na]
        at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:787) [netty.jar:na]
        at org.jboss.netty.handler.codec.http.HttpContentDecoder.messageReceived(HttpContentDecoder.java:108) [netty.jar:na]
        at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70) [netty.jar:na]
        at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:560) [netty.jar:na]
        at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:787) [netty.jar:na]
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296) [netty.jar:na]
        at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:459) [netty.jar:na]
        at org.jboss.netty.handler.codec.replay.ReplayingDecoder.callDecode(ReplayingDecoder.java:536) [netty.jar:na]
        at org.jboss.netty.handler.codec.replay.ReplayingDecoder.messageReceived(ReplayingDecoder.java:435) [netty.jar:na]
        at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70) [netty.jar:na]
        at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:560) [netty.jar:na]
        at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:555) [netty.jar:na]
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268) [netty.jar:na]
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255) [netty.jar:na]
        at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88) [netty.jar:na]
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:107) [netty.jar:na]
        at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312) [netty.jar:na]
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:88) [netty.jar:na]
        at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178) [netty.jar:na]
        at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) [netty.jar:na]
        at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) [netty.jar:na]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.7.0_45]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.7.0_45]
        at java.lang.Thread.run(Unknown Source) [na:1.7.0_45]
Caused by: java.sql.SQLException: No suitable driver found for jdbc:postgresql://192.168.1.6:5432/postgres
        at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.7.0_45]
        at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.7.0_45]
        at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:173) ~[spring-jdbc-3.2.3.RELEASE
        at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:164) ~[spring-jdbc-3.2.3.RELEASE.jar:3.
        at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:153) ~[spring-jdbc-3.2.3.RE
        at org.springframework.jdbc.datasource.SingleConnectionDataSource.initConnection(SingleConnectionDataSource.java:244) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3
        at org.springframework.jdbc.datasource.SingleConnectionDataSource.getConnection(SingleConnectionDataSource.java:186) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) ~[spring-jdbc-3.2.3.RELEASE.jar:3.2.3.RELEASE]
        ... 91 common frames omitted
于 2013-11-03T01:08:02.797 回答