2011-08-31 10 views
10

मैं स्कैला और अक्का के लिए नया हूं इसलिए मुझे माफ़ कर दो अगर यह एक नया सवाल है, लेकिन मुझे कहीं और जवाब नहीं मिल रहा है ...स्कैला एक कंपैनियन ऑब्जेक्ट को तुरंत चालू करने में विफल क्यों होता है?

रिकॉर्ड के लिए मैं स्कैला 2.9.0-1 और अक्का का उपयोग कर रहा हूं 1.1.3 और मैंने अपना एसबीटी 0.10.1 सेटअप भी शामिल किया है।

मैंने इस संदेश को अक्का में एक प्रयोग के रूप में लिखा है; यह उपयोगकर्ता डेटाबेस और पंजीकरण सुविधाओं का एक खिलौना संस्करण है। मूल विचार यह है कि उपयोगकर्तासेवर कलाकारों का एक अभिनेतापूल है जिसमें से प्रत्येक में मेमोरी यूज़रडेटाबेस का उदाहरण होता है जो उपयोगकर्ताओं के ईमेल पतों को बंद करने वाले उपयोगकर्ताओं के मानचित्र के साथ बातचीत करने के लिए एसटीएम का उपयोग करता है - बहुत सरल, है ना?

समस्या फ़ाइल संकलन और दो अलग अलग शान्ति में निम्नलिखित चलाकर reproduced किया जा सकता है:

कंसोल # 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) 

त्रुटि से थोड़ा अधिक दिलचस्प उपयोग कर रहा है स्काला 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

यह सिर्फ initializes इससे पहले कि आप ServerRunner चलाने ठीक है और बाद में बाकी सब कुछ सिर्फ बेवकूफ है।

क्या कोई यह समझा सकता है कि यह क्यों है?

धन्यवाद! इडान

पीएस। यह मेरा पहला स्कैला कोड है इसलिए बहुत मुश्किल से हंसने की कोशिश न करें ... और कोई अन्य सुझाव (स्टाइलिस्ट, फिलिसॉफिकल, थ्योलॉजिकल, ...) का स्वागत है।

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")) 
    } 
} 
+0

स्कैला 2.9.1 हाल ही में जारी किया गया था। शायद इसे एक शॉट दे दो? –

+0

मुझे लगता है कि आपको किसी भी उपयोग के लिए अधिक स्टैक ट्रेस जोड़ने की आवश्यकता है। –

+2

इसके अलावा, आप साझा, unthreadsafe राज्य का उपयोग कर रहे हैं, जो एक बड़ा नंबर नहीं है –

उत्तर

1

मैं जब मैं अपने अनुप्रयोग के बूटिंग के दौरान बनाए गए एक वस्तु का एक निर्माता में एक TMap आरंभ किया गया था एक ऐसी ही समस्या थी। किसी भी तरह से मेरा ऑब्जेक्ट एसटीएम स्थैतिक प्रारंभकर्ता भागने से पहले बनाया जा रहा था। मैंने अपनी वस्तु के क्षेत्र को आलसी बना दिया और यह समस्या ठीक कर दी।

... असल में इसने प्रोग्राम में बाद में समस्या को देरी कर दी। Grrrr।

+0

आपकी विधि ठीक काम करती है। आलसी संशोधक जोड़े जाने के बाद, समस्या हल हो जाती है। –

0

मैं एक ही समस्या में भाग गया। निर्भरता 'org.multiverse.multiverse-alpha-unborn' जोड़ना मेरे लिए मुद्दा हल किया।

संबंधित मुद्दे

 संबंधित मुद्दे