为什么斯卡拉无法实例化一个伴侣对象?

我是新来Scala和阿卡所以请原谅我,如果这是对于新手的问题,但我找不到答案其他地方...

为了记录我使用Scala 2.9.0-1和阿卡1.1.3,并已列入我的SBT 0.10.1设置为好。

我写了下面这条消息在阿卡实验中的代码; 它是一个用户数据库和登记设施的一个玩具版本。 其基本思想是有UserServer的演员每个都有它采用STM互动与地图的用户键入关闭用户的电子邮件地址的MemoryUserDatabase实例的ActorPool - 很简单,不是吗?

该问题可通过在编译文件并运行在两个单独的控制台以下再现:

控制台1:

进口toy.service.user._; ServiceRunner.run

控制台2:

进口toy.service.user._; ClientRunner.run

这是从服务器控制台输出(#1)

Aug 31, 2011 5:21:29 PM org.multiverse.api.GlobalStmInstance <clinit> INFO: Initializing GlobalStmInstance using factoryMethod 'org.multiverse.stms.alpha.AlphaStm.createFast'. Aug 31, 2011 5:21:29 PM org.multiverse.stms.alpha.AlphaStm <init> INFO: Created a new AlphaStm instance Aug 31, 2011 5:21:29 PM org.multiverse.api.GlobalStmInstance <clinit> INFO: Successfully initialized GlobalStmInstance using factoryMethod 'org.multiverse.stms.alpha.AlphaStm.createFast'. [ERROR] [8/31/11 5:21 PM] [akka:event-driven:dispatcher:global-3] [LocalActorRef] Availability(foo) java.lang.NoClassDefFoundError: Could not initialize class toy.service.user.memory.MemoryUserDatabase$ at toy.service.user.memory.MemoryUserDatabase$$anonfun$getUser$1.apply(Registration.scala:96) at toy.service.user.memory.MemoryUserDatabase$$anonfun$getUser$1.apply(Registration.scala:96) at toy.service.user.memory.MemoryUserDatabase$$anonfun$getUser$2.apply(Registration.scala:96) at toy.service.user.memory.MemoryUserDatabase$$anonfun$getUser$2.apply(Registration.scala:96) at akka.stm.Stm$$anon$1.call(Stm.scala:51) at org.multiverse.templates.TransactionBoilerplate.executeWithTransaction(TransactionBoilerplate.java:279) at org.multiverse.templates.TransactionBoilerplate.executeChecked(TransactionBoilerplate.java:218) at org.multiverse.templates.TransactionBoilerplate.execute(TransactionBoilerplate.java:169) at akka.stm.Stm$class.atomic(Stm.scala:50) at akka.stm.package$.atomic(package.scala:10) at akka.stm.Stm$class.atomic(Stm.scala:47) at akka.stm.package$.atomic(package.scala:10) at toy.service.user.memory.MemoryUserDatabase.getUser(Registration.scala:95) at toy.service.user.UserDatabase$class.available(Registration.scala:88) at toy.service.user.memory.MemoryUserDatabase.available(Registration.scala:92) at toy.service.user.UserServer$$anonfun$receive$1.apply(Registration.scala:77) at toy.service.user.UserServer$$anonfun$receive$1.apply(Registration.scala:76) at akka.actor.Actor$class.apply(Actor.scala:478) at toy.service.user.UserServer.apply(Registration.scala:74) at akka.actor.LocalActorRef.invoke(ActorRef.scala:860) at akka.dispatch.MessageInvocation.invoke(MessageHandling.scala:26) at akka.dispatch.ExecutableMailbox$class.processMailbox(ExecutorBasedEventDrivenDispatcher.scala:214) at akka.dispatch.ExecutorBasedEventDrivenDispatcher$$anon$4.processMailbox(ExecutorBasedEventDrivenDispatcher.scala:120) at akka.dispatch.ExecutableMailbox$class.run(ExecutorBasedEventDrivenDispatcher.scala:186) at akka.dispatch.ExecutorBasedEventDrivenDispatcher$$anon$4.run(ExecutorBasedEventDrivenDispatcher.scala:120) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:680) at akka.dispatch.MonitorableThread.run(ThreadPoolBuilder.scala:181)

使用Scala 2.9.1.final误差稍微更有趣:

Aug 31, 2011 5:38:35 PM org.multiverse.api.GlobalStmInstance <clinit> INFO: Initializing GlobalStmInstance using factoryMethod 'org.multiverse.stms.alpha.AlphaStm.createFast'. Aug 31, 2011 5:38:35 PM org.multiverse.api.GlobalStmInstance getMethod INFO: Failed to initialize GlobalStmInstance through System property 'org.multiverse.api.GlobalStmInstance.factoryMethod' with value 'org.multiverse.stms.alpha.AlphaStm'.'org.multiverse.stms.alpha.AlphaStm.createFast' is not an existing class (it can't be found using the Thread.currentThread.getContextClassLoader). [ERROR] [8/31/11 5:38 PM] [akka:event-driven:dispatcher:global-3] [LocalActorRef] Availability(foo) java.lang.ExceptionInInitializerError at akka.stm.TransactionFactory.<init>(TransactionFactory.scala:172) at akka.stm.TransactionFactory$.apply(TransactionFactory.scala:122) at akka.stm.Stm$class.$init$(Stm.scala:44) at akka.stm.package$.<init>(package.scala:10) at akka.stm.package$.<clinit>(package.scala) at toy.service.user.memory.MemoryUserDatabase.getUser(Registration.scala:95) at toy.service.user.UserDatabase$class.available(Registration.scala:88) at toy.service.user.memory.MemoryUserDatabase.available(Registration.scala:92) at toy.service.user.UserServer$$anonfun$receive$1.apply(Registration.scala:77) at toy.service.user.UserServer$$anonfun$receive$1.apply(Registration.scala:76) at akka.actor.Actor$class.apply(Actor.scala:478) at toy.service.user.UserServer.apply(Registration.scala:74) at akka.actor.LocalActorRef.invoke(ActorRef.scala:860) at akka.dispatch.MessageInvocation.invoke(MessageHandling.scala:26) at akka.dispatch.ExecutableMailbox$class.processMailbox(ExecutorBasedEventDrivenDispatcher.scala:214) at akka.dispatch.ExecutorBasedEventDrivenDispatcher$$anon$4.processMailbox(ExecutorBasedEventDrivenDispatcher.scala:120) at akka.dispatch.ExecutableMailbox$class.run(ExecutorBasedEventDrivenDispatcher.scala:186) at akka.dispatch.ExecutorBasedEventDrivenDispatcher$$anon$4.run(ExecutorBasedEventDrivenDispatcher.scala:120) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:680) at akka.dispatch.MonitorableThread.run(ThreadPoolBuilder.scala:181) Caused by: java.lang.IllegalArgumentException: Failed to initialize GlobalStmInstance through System property 'org.multiverse.api.GlobalStmInstance.factoryMethod' with value 'org.multiverse.stms.alpha.AlphaStm'.'org.multiverse.stms.alpha.AlphaStm.createFast' is not an existing class (it can't be found using the Thread.currentThread.getContextClassLoader). at org.multiverse.api.GlobalStmInstance.getMethod(GlobalStmInstance.java:82) at org.multiverse.api.GlobalStmInstance.<clinit>(GlobalStmInstance.java:38) ... 22 more Caused by: java.lang.ClassNotFoundException: org.multiverse.stms.alpha.AlphaStm at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at org.multiverse.api.GlobalStmInstance.getMethod(GlobalStmInstance.java:76) ... 23 more

代码本执行部分是:

class MemoryUserDatabase extends UserDatabase { import MemoryUserDatabase._ def getUser(email: String) = atomic { users.get.get(email) } def register(user: User) = atomic { getUser(user.email) match { case None => users alter (_ + (user.email -> user)) true case Some(found) => false } } } object MemoryUserDatabase { import scala.collection.mutable.{ Map => MutMap } private val users = Ref(MutMap[String, User]()) }

我不明白为什么同伴对象不能被初始化。 最奇怪的是,你可以做同样的事情,但如果在服务器控制台(#1)首次访问伴侣对象:

MemoryUserDatabase

在运行ServerRunner之前初始化就好了,随后一切仅仅是花花公子。

谁能解释这是为什么?

谢谢! 伊詹

PS。 这是我第一次Scala代码所以尽量不要笑得太辛苦,任何其他建议(文体,philisophical,神学,...)的欢迎。

package toy.service.user import scala.collection.mutable.HashMap import akka.actor.{ Actor, ActorRef } import akka.config.Supervision.{ OneForOneStrategy, Permanent } import Actor._ import akka.routing._ import akka.stm._ import akka.actor.TypedActor import akka.event.EventHandler class User(var email: String, var password: String) extends Serializable /** Registration message types. */ sealed trait RegistrationMessage case class Availability(email: String) extends RegistrationMessage case class GetUser(email: String) extends RegistrationMessage case class Register(user: User) extends RegistrationMessage // Client --------------------------------------- class UserClient(defaultTimeout: Int = 1000) { val userService = Actor.remote.actorFor(UserService.USER_SERVICE_ID, "localhost", UserService.USER_SERVICE_PORT) EventHandler.info(this, "remote UserService: id(" + userService.id + "), uuid(" + userService.uuid + ")") def getUser(email: String, timeout: Int = defaultTimeout): Option[User] = (userService !! (GetUser(email), timeout)).as[User] def available(email: String, timeout: Int = defaultTimeout): Boolean = (userService !! (Availability(email), timeout)).as[Boolean].getOrElse(throw new RuntimeException("Oi!")) def register(user: User, timeout: Int = defaultTimeout): Boolean = (userService !! (Register(user), timeout)).as[Boolean].getOrElse(throw new RuntimeException("Got bogus (None) response from " + UserService.USER_SERVICE_ID)) } // Service Pool --------------------------------- object UserService { val USER_SERVICE_ID = "user:service" val USER_SERVICE_PORT = 2662 val host = "localhost" } class UserService extends Actor with DefaultActorPool with BoundedCapacityStrategy with MailboxPressureCapacitor with SmallestMailboxSelector with BasicFilter { import toy.service.user.memory._ def receive = _route // DefaultActorPool's receive def lowerBound = 1 def upperBound = 5 def pressureThreshold = 1 def partialFill = true // never send duplicate messages to same actor (only meaningful if selectionCount > 1) def selectionCount = 1 // How many in pool should receive each message def rampupRate = 0.1 // increase by 10% capacity (# num actors) def backoffRate = 0.50 // halve capacity once backoffThreshold is reached def backoffThreshold = 0.50 def instance = actorOf(new UserServer(new MemoryUserDatabase)) override def preStart() { import UserService.{ host, USER_SERVICE_ID, USER_SERVICE_PORT } remote.start(host, UserService.USER_SERVICE_PORT); remote.register(UserService.USER_SERVICE_ID, self) //Register the actorPool with the specified service id EventHandler.info(this, "Prestart: Started UserService(" + self.uuid + ") on %s:%s".format(host, UserService.USER_SERVICE_PORT.toString())) } } // Service -------------------------------------- class UserServer(db: UserDatabase) extends Actor { def receive = { case Availability(email) => self.reply(db.available(email)) case GetUser(email) => self.reply(db.getUser(email)) case Register(user) => self.reply(db.register(user)) } } // Database ------------------------------------- trait UserDatabase { def getUser(email: String): Option[User] def register(user: User): Boolean def available(email: String): Boolean = getUser(email) == None } package memory { class MemoryUserDatabase extends UserDatabase { import MemoryUserDatabase._ def getUser(email: String) = atomic { users.get.get(email) } def register(user: User) = atomic { getUser(user.email) match { case None => users alter (_ + (user.email -> user)) true case Some(found) => false } } } object MemoryUserDatabase { import scala.collection.mutable.{ Map => MutMap } private val users = Ref(MutMap[String, User]()) } } object ServerRunner { def run() { actorOf[UserService].start() } } object ClientRunner { def run { val client = new UserClient EventHandler.info(this, client.available("foo")) } }

--------------解决方案-------------

我有一个类似的问题,当我在我的应用程序的启动过程中创建的对象的构造函数初始化的TMap。 不知怎的,我的对象是正在STM静态初始化运行之前创建的。 我做了我对象的字段懒惰,它解决了这一问题。

...其实它只是延缓了问题的计划以后。 Grrrr。

我遇到了同样的问题。 添加依赖“org.multiverse.multiverse-α-腹中的”解决这个问题对我来说。

分类:斯卡拉 时间:2015-03-14 人气:3
本文关键词: 斯卡拉,STM,阿卡
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.505 (s). 10 q(s)