diff --git a/.gitignore b/.gitignore
index fd8f3cbd39..9f15d8fc57 100755
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ deploy/*.jar
data
out
logs
+.#*
.codefellow
storage
.codefellow
diff --git a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQPMessage.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQPMessage.scala
index 34eb37aa14..2b53a73d08 100644
--- a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQPMessage.scala
+++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQPMessage.scala
@@ -5,6 +5,8 @@
package se.scalablesolutions.akka.amqp
import se.scalablesolutions.akka.actor.ActorRef
+import se.scalablesolutions.akka.AkkaException
+
import com.rabbitmq.client.AMQP.BasicProperties
import com.rabbitmq.client.ShutdownSignalException
diff --git a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ConsumerActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ConsumerActor.scala
index b01f79f949..d3f0acd1cf 100644
--- a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ConsumerActor.scala
+++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ConsumerActor.scala
@@ -4,13 +4,15 @@
package se.scalablesolutions.akka.amqp
-import com.rabbitmq.client.AMQP.Queue.DeclareOk
import collection.JavaConversions
+
import se.scalablesolutions.akka.amqp.AMQP.ConsumerParameters
import se.scalablesolutions.akka.util.Logging
-import com.rabbitmq.client.{Channel, Envelope, DefaultConsumer}
+import se.scalablesolutions.akka.AkkaException
+
+import com.rabbitmq.client.AMQP.Queue.DeclareOk
import com.rabbitmq.client.AMQP.BasicProperties
-import java.lang.Throwable
+import com.rabbitmq.client.{Channel, Envelope, DefaultConsumer}
private[amqp] class ConsumerActor(consumerParameters: ConsumerParameters)
extends FaultTolerantChannelActor(
diff --git a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ProducerActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ProducerActor.scala
index 1d125762ae..3551ffa276 100644
--- a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ProducerActor.scala
+++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ProducerActor.scala
@@ -5,7 +5,9 @@
package se.scalablesolutions.akka.amqp
import com.rabbitmq.client._
+
import se.scalablesolutions.akka.amqp.AMQP.ProducerParameters
+import se.scalablesolutions.akka.AkkaException
private[amqp] class ProducerActor(producerParameters: ProducerParameters)
extends FaultTolerantChannelActor(
diff --git a/akka-camel/src/main/scala/Consumer.scala b/akka-camel/src/main/scala/Consumer.scala
index 3f593e1e36..3b54c5df77 100644
--- a/akka-camel/src/main/scala/Consumer.scala
+++ b/akka-camel/src/main/scala/Consumer.scala
@@ -5,6 +5,7 @@
package se.scalablesolutions.akka.camel
import se.scalablesolutions.akka.actor._
+
import java.net.InetSocketAddress
/**
diff --git a/akka-camel/src/main/scala/component/ActorComponent.scala b/akka-camel/src/main/scala/component/ActorComponent.scala
index 7c9373be80..a5d56dd9dc 100644
--- a/akka-camel/src/main/scala/component/ActorComponent.scala
+++ b/akka-camel/src/main/scala/component/ActorComponent.scala
@@ -15,15 +15,14 @@ import org.apache.camel._
import org.apache.camel.impl.{DefaultProducer, DefaultEndpoint, DefaultComponent}
import se.scalablesolutions.akka.camel.{Failure, CamelMessageConversion, Message}
+import CamelMessageConversion.toExchangeAdapter
import se.scalablesolutions.akka.dispatch.{CompletableFuture, MessageInvocation, MessageDispatcher}
import se.scalablesolutions.akka.stm.TransactionConfig
+import se.scalablesolutions.akka.actor.{ScalaActorRef, ActorRegistry, Actor, ActorRef}
+import se.scalablesolutions.akka.AkkaException
import scala.reflect.BeanProperty
-import CamelMessageConversion.toExchangeAdapter
-import java.lang.Throwable
-import se.scalablesolutions.akka.actor.{ScalaActorRef, ActorRegistry, Actor, ActorRef}
-
/**
* Camel component for sending messages to and receiving replies from (untyped) actors.
*
diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala
index 1f669c9e32..a2bf63e4a3 100644
--- a/akka-core/src/main/scala/actor/Actor.scala
+++ b/akka-core/src/main/scala/actor/Actor.scala
@@ -10,6 +10,7 @@ import se.scalablesolutions.akka.config.ScalaConfig._
import se.scalablesolutions.akka.serialization.Serializer
import se.scalablesolutions.akka.util.Helpers.{narrow, narrowSilently}
import se.scalablesolutions.akka.util.{Logging, Duration}
+import se.scalablesolutions.akka.AkkaException
import com.google.protobuf.Message
@@ -67,11 +68,11 @@ case class MaximumNumberOfRestartsWithinTimeRangeReached(
@BeanProperty val lastExceptionCausingRestart: Throwable) extends LifeCycleMessage
// Exceptions for Actors
-class ActorStartException private[akka](message: String) extends RuntimeException(message)
-class IllegalActorStateException private[akka](message: String) extends RuntimeException(message)
-class ActorKilledException private[akka](message: String) extends RuntimeException(message)
-class ActorInitializationException private[akka](message: String) extends RuntimeException(message)
-class ActorTimeoutException private[akka](message: String) extends RuntimeException(message)
+class ActorStartException private[akka](message: String) extends AkkaException(message)
+class IllegalActorStateException private[akka](message: String) extends AkkaException(message)
+class ActorKilledException private[akka](message: String) extends AkkaException(message)
+class ActorInitializationException private[akka](message: String) extends AkkaException(message)
+class ActorTimeoutException private[akka](message: String) extends AkkaException(message)
/**
* Actor factory module with factory methods for creating various kinds of Actors.
diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala
index 6cf9cd5731..6f818b9c50 100644
--- a/akka-core/src/main/scala/actor/ActorRef.scala
+++ b/akka-core/src/main/scala/actor/ActorRef.scala
@@ -15,6 +15,7 @@ import se.scalablesolutions.akka.remote.protocol.RemoteProtocol._
import se.scalablesolutions.akka.remote.{RemoteNode, RemoteServer, RemoteClient, MessageSerializer, RemoteRequestProtocolIdFactory}
import se.scalablesolutions.akka.serialization.{Serializer, BinaryString}
import se.scalablesolutions.akka.util.{HashCode, Logging, UUID, ReentrantGuard}
+import se.scalablesolutions.akka.AkkaException
import RemoteActorSerialization._
import org.multiverse.api.ThreadLocalTransaction._
diff --git a/akka-core/src/main/scala/actor/Agent.scala b/akka-core/src/main/scala/actor/Agent.scala
index b800c94f23..df358cdfc4 100644
--- a/akka-core/src/main/scala/actor/Agent.scala
+++ b/akka-core/src/main/scala/actor/Agent.scala
@@ -5,11 +5,12 @@
package se.scalablesolutions.akka.actor
import se.scalablesolutions.akka.stm.Ref
+import se.scalablesolutions.akka.AkkaException
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.CountDownLatch
-class AgentException private[akka](message: String) extends RuntimeException(message)
+class AgentException private[akka](message: String) extends AkkaException(message)
/**
* The Agent class was strongly inspired by the agent principle in Clojure.
diff --git a/akka-core/src/main/scala/actor/Scheduler.scala b/akka-core/src/main/scala/actor/Scheduler.scala
index 07486521ec..a1b9fc6d4f 100644
--- a/akka-core/src/main/scala/actor/Scheduler.scala
+++ b/akka-core/src/main/scala/actor/Scheduler.scala
@@ -15,10 +15,11 @@
*/
package se.scalablesolutions.akka.actor
-import _root_.scala.collection.JavaConversions
+import scala.collection.JavaConversions
import java.util.concurrent._
import se.scalablesolutions.akka.util.Logging
+import se.scalablesolutions.akka.AkkaException
object Scheduler extends Logging {
import Actor._
diff --git a/akka-core/src/main/scala/actor/Supervisor.scala b/akka-core/src/main/scala/actor/Supervisor.scala
index 9b56bddf38..b146a74c12 100644
--- a/akka-core/src/main/scala/actor/Supervisor.scala
+++ b/akka-core/src/main/scala/actor/Supervisor.scala
@@ -8,12 +8,13 @@ import se.scalablesolutions.akka.config.ScalaConfig._
import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy}
import se.scalablesolutions.akka.util.Logging
import se.scalablesolutions.akka.remote.RemoteServer
+import se.scalablesolutions.akka.AkkaException
import Actor._
import java.util.concurrent.{CopyOnWriteArrayList, ConcurrentHashMap}
import java.net.InetSocketAddress
-class SupervisorException private[akka](message: String) extends RuntimeException(message)
+class SupervisorException private[akka](message: String) extends AkkaException(message)
/**
* Factory object for creating supervisors declarative. It creates instances of the 'Supervisor' class.
diff --git a/akka-core/src/main/scala/config/Config.scala b/akka-core/src/main/scala/config/Config.scala
index ec44453e59..aca46e6249 100644
--- a/akka-core/src/main/scala/config/Config.scala
+++ b/akka-core/src/main/scala/config/Config.scala
@@ -5,10 +5,11 @@
package se.scalablesolutions.akka.config
import se.scalablesolutions.akka.util.Logging
+import se.scalablesolutions.akka.AkkaException
import net.lag.configgy.{Config => CConfig, Configgy, ParseException}
-class ConfigurationException(message: String) extends RuntimeException(message)
+class ConfigurationException(message: String) extends AkkaException(message)
/**
* Loads up the configuration (from the akka.conf file).
diff --git a/akka-core/src/main/scala/dataflow/DataFlowVariable.scala b/akka-core/src/main/scala/dataflow/DataFlowVariable.scala
index baf3e33f6e..cd7ba704ad 100644
--- a/akka-core/src/main/scala/dataflow/DataFlowVariable.scala
+++ b/akka-core/src/main/scala/dataflow/DataFlowVariable.scala
@@ -10,6 +10,7 @@ import java.util.concurrent.{ConcurrentLinkedQueue, LinkedBlockingQueue}
import se.scalablesolutions.akka.actor.{Actor, ActorRef}
import se.scalablesolutions.akka.actor.Actor._
import se.scalablesolutions.akka.dispatch.CompletableFuture
+import se.scalablesolutions.akka.AkkaException
/**
* Implements Oz-style dataflow (single assignment) variables.
@@ -155,7 +156,7 @@ import se.scalablesolutions.akka.dispatch.CompletableFuture
/**
* @author Jonas Bonér
*/
- class DataFlowVariableException(msg: String) extends RuntimeException(msg)
+ class DataFlowVariableException(msg: String) extends AkkaException(msg)
}
diff --git a/akka-core/src/main/scala/dispatch/Future.scala b/akka-core/src/main/scala/dispatch/Future.scala
index c365df3c3c..17c63bcd57 100644
--- a/akka-core/src/main/scala/dispatch/Future.scala
+++ b/akka-core/src/main/scala/dispatch/Future.scala
@@ -4,11 +4,12 @@
package se.scalablesolutions.akka.dispatch
-import java.util.concurrent.locks.ReentrantLock
+import se.scalablesolutions.akka.AkkaException
+import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.TimeUnit
-class FutureTimeoutException(message: String) extends RuntimeException(message)
+class FutureTimeoutException(message: String) extends AkkaException(message)
object Futures {
diff --git a/akka-core/src/main/scala/remote/RemoteClient.scala b/akka-core/src/main/scala/remote/RemoteClient.scala
index 128205bf9a..2c810068a2 100644
--- a/akka-core/src/main/scala/remote/RemoteClient.scala
+++ b/akka-core/src/main/scala/remote/RemoteClient.scala
@@ -8,6 +8,7 @@ import se.scalablesolutions.akka.remote.protocol.RemoteProtocol._
import se.scalablesolutions.akka.actor.{Exit, Actor, ActorRef, RemoteActorRef, IllegalActorStateException}
import se.scalablesolutions.akka.dispatch.{DefaultCompletableFuture, CompletableFuture}
import se.scalablesolutions.akka.config.Config._
+import se.scalablesolutions.akka.AkkaException
import org.jboss.netty.channel._
import group.DefaultChannelGroup
@@ -55,7 +56,7 @@ case class RemoteClientConnected(
@BeanProperty val host: String,
@BeanProperty val port: Int) extends RemoteClientLifeCycleEvent
-class RemoteClientException private[akka](message: String) extends RuntimeException(message)
+class RemoteClientException private[akka](message: String) extends AkkaException(message)
/**
* The RemoteClient object manages RemoteClient instances and gives you an API to lookup remote actor handles.
diff --git a/akka-core/src/main/scala/stm/JTA.scala b/akka-core/src/main/scala/stm/JTA.scala
index 0fb10af4f0..80a0cda4ec 100644
--- a/akka-core/src/main/scala/stm/JTA.scala
+++ b/akka-core/src/main/scala/stm/JTA.scala
@@ -11,6 +11,7 @@ import javax.naming.{InitialContext, Context, NamingException}
import se.scalablesolutions.akka.config.Config._
import se.scalablesolutions.akka.util.Logging
+import se.scalablesolutions.akka.AkkaException
/**
* Detects if there is a UserTransaction or TransactionManager available in the JNDI.
diff --git a/akka-core/src/main/scala/stm/Transaction.scala b/akka-core/src/main/scala/stm/Transaction.scala
index a0e2077155..dc7baa3010 100644
--- a/akka-core/src/main/scala/stm/Transaction.scala
+++ b/akka-core/src/main/scala/stm/Transaction.scala
@@ -13,15 +13,16 @@ import scala.collection.mutable.HashMap
import se.scalablesolutions.akka.util.Logging
import se.scalablesolutions.akka.config.Config._
+import se.scalablesolutions.akka.AkkaException
import org.multiverse.api.{Transaction => MultiverseTransaction}
import org.multiverse.api.lifecycle.{TransactionLifecycleListener, TransactionLifecycleEvent}
import org.multiverse.api.ThreadLocalTransaction._
import org.multiverse.api.{TraceLevel => MultiverseTraceLevel}
-class NoTransactionInScopeException extends RuntimeException
-class TransactionRetryException(message: String) extends RuntimeException(message)
-class StmConfigurationException(message: String) extends RuntimeException(message)
+class NoTransactionInScopeException extends AkkaException("No transaction in scope")
+class TransactionRetryException(message: String) extends AkkaException(message)
+class StmConfigurationException(message: String) extends AkkaException(message)
object Transaction {
val idFactory = new AtomicLong(-1L)
diff --git a/akka-core/src/main/scala/stm/TransactionManagement.scala b/akka-core/src/main/scala/stm/TransactionManagement.scala
index 6aa80066e2..2da5ffad98 100644
--- a/akka-core/src/main/scala/stm/TransactionManagement.scala
+++ b/akka-core/src/main/scala/stm/TransactionManagement.scala
@@ -4,18 +4,15 @@
package se.scalablesolutions.akka.stm
+import se.scalablesolutions.akka.AkkaException
+
import org.multiverse.api.{StmUtils => MultiverseStmUtils}
import org.multiverse.api.ThreadLocalTransaction._
import org.multiverse.api.{Transaction => MultiverseTransaction}
import org.multiverse.commitbarriers.CountDownCommitBarrier
import org.multiverse.templates.OrElseTemplate
-class TransactionSetAbortedException(msg: String) extends RuntimeException(msg)
-
-// TODO Should we remove TransactionAwareWrapperException? Not used anywhere yet.
-class TransactionAwareWrapperException(val cause: Throwable, val tx: Option[Transaction]) extends RuntimeException(cause) {
- override def toString = "TransactionAwareWrapperException[" + cause + ", " + tx + "]"
-}
+class TransactionSetAbortedException(msg: String) extends AkkaException(msg)
/**
* Internal helper methods and properties for transaction management.
diff --git a/akka-core/src/main/scala/util/AkkaException.scala b/akka-core/src/main/scala/util/AkkaException.scala
new file mode 100644
index 0000000000..ca8284ced5
--- /dev/null
+++ b/akka-core/src/main/scala/util/AkkaException.scala
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2009-2010 Scalable Solutions AB
+ */
+
+package se.scalablesolutions.akka
+
+import se.scalablesolutions.akka.util.{UUID, Logging}
+
+import java.io.{StringWriter, PrintWriter}
+import java.net.{InetAddress, UnknownHostException}
+
+/**
+ * Akka base Exception. Each Exception gets:
+ *
+ * - a UUID for tracking purposes
+ * - a message including exception name, uuid, original message and the stacktrace
+ * - a method 'log' that will log the exception once and only once
+ *
+ *
+ * @author Jonas Bonér
+ */
+@serializable abstract class AkkaException(message: String) extends RuntimeException(message) {
+ @volatile private var isLogged = false
+ val exceptionName = getClass.getName
+
+ val uuid = String.format("%s_%s", AkkaException.hostname, UUID.newUuid.toString)
+
+ override val toString =
+ String.format("%s\n\t[%s]\n\t%s\n\t%s", exceptionName, uuid, message, stackTrace)
+
+ val stackTrace = {
+ val sw = new StringWriter
+ val pw = new PrintWriter(sw)
+ printStackTrace(pw)
+ sw.toString
+ }
+
+ def log = if (!isLogged) {
+ isLogged = true
+ AkkaException.log.error(toString)
+ }
+}
+
+object AkkaException extends Logging {
+ val hostname = try {
+ InetAddress.getLocalHost.getHostName
+ } catch {
+ case e: UnknownHostException => "unknown"
+ }
+}
diff --git a/akka-core/src/main/scala/util/Helpers.scala b/akka-core/src/main/scala/util/Helpers.scala
index ccbd896610..eab9e1981d 100644
--- a/akka-core/src/main/scala/util/Helpers.scala
+++ b/akka-core/src/main/scala/util/Helpers.scala
@@ -6,8 +6,6 @@ package se.scalablesolutions.akka.util
import java.security.MessageDigest
-class SystemFailure(cause: Throwable) extends RuntimeException(cause)
-
/**
* @author Jonas Bonér
*/
diff --git a/akka-core/src/main/scala/util/Logging.scala b/akka-core/src/main/scala/util/Logging.scala
index 711464ccaa..1fed0d017a 100644
--- a/akka-core/src/main/scala/util/Logging.scala
+++ b/akka-core/src/main/scala/util/Logging.scala
@@ -35,13 +35,13 @@ trait Logging {
* http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#format(java.lang.String,%20java.lang.Object...)
*/
class Logger(val logger: SLFLogger) {
- def name = logger.getName
+ def name = logger.getName
- def trace_? = logger.isTraceEnabled
- def debug_? = logger.isDebugEnabled
- def info_? = logger.isInfoEnabled
- def warning_? = logger.isWarnEnabled
- def error_? = logger.isErrorEnabled
+ def trace_? = logger.isTraceEnabled
+ def debug_? = logger.isDebugEnabled
+ def info_? = logger.isInfoEnabled
+ def warning_? = logger.isWarnEnabled
+ def error_? = logger.isErrorEnabled
//Trace
def trace(t: Throwable, fmt: => String, arg: Any, argN: Any*) {
@@ -59,6 +59,7 @@ class Logger(val logger: SLFLogger) {
def trace(msg: => String) {
if (trace_?) logger trace msg
}
+
//Debug
def debug(t: Throwable, fmt: => String, arg: Any, argN: Any*) {
debug(t,message(fmt,arg,argN:_*))
@@ -75,6 +76,7 @@ class Logger(val logger: SLFLogger) {
def debug(msg: => String) {
if (debug_?) logger debug msg
}
+
//Info
def info(t: Throwable, fmt: => String, arg: Any, argN: Any*) {
info(t,message(fmt,arg,argN:_*))
@@ -91,6 +93,7 @@ class Logger(val logger: SLFLogger) {
def info(msg: => String) {
if (info_?) logger info msg
}
+
//Warning
def warning(t: Throwable, fmt: => String, arg: Any, argN: Any*) {
warning(t,message(fmt,arg,argN:_*))
@@ -107,6 +110,7 @@ class Logger(val logger: SLFLogger) {
def warning(msg: => String) {
if (warning_?) logger warn msg
}
+
//Error
def error(t: Throwable, fmt: => String, arg: Any, argN: Any*) {
error(t,message(fmt,arg,argN:_*))
@@ -156,53 +160,3 @@ object Logger {
def apply(clazz: Class[_]) : Logger = apply(clazz.getName)
def root : Logger = apply(SLFLogger.ROOT_LOGGER_NAME)
}
-
-/**
- * LoggableException is a subclass of Exception and can be used as the base exception
- * for application specific exceptions.
- *
- * It keeps track of the exception is logged or not and also stores the unique id,
- * so that it can be carried all along to the client tier and displayed to the end user.
- * The end user can call up the customer support using this number.
- *
- * @author Jonas Bonér
- */
- // FIXME make use of LoggableException
-class LoggableException extends Exception with Logging {
- private val uniqueId = getExceptionID
- private var originalException: Option[Exception] = None
- private var isLogged = false
-
- def this(baseException: Exception) = {
- this()
- originalException = Some(baseException)
- }
-
- def logException = synchronized {
- if (!isLogged) {
- originalException match {
- case Some(e) => log.error("Logged Exception [%s] %s", uniqueId, getStackTraceAsString(e))
- case None => log.error("Logged Exception [%s] %s", uniqueId, getStackTraceAsString(this))
- }
- isLogged = true
- }
- }
-
- private def getExceptionID: String = {
- val hostname: String = try {
- InetAddress.getLocalHost.getHostName
- } catch {
- case e: UnknownHostException =>
- log.error("Could not get hostname to generate loggable exception")
- "N/A"
- }
- hostname + "_" + System.currentTimeMillis
- }
-
- private def getStackTraceAsString(exception: Throwable): String = {
- val sw = new StringWriter
- val pw = new PrintWriter(sw)
- exception.printStackTrace(pw)
- sw.toString
- }
-}
diff --git a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
index 4519fc7ede..ccaf7518f1 100644
--- a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
+++ b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
@@ -7,11 +7,9 @@ package se.scalablesolutions.akka.persistence.common
import se.scalablesolutions.akka.stm._
import se.scalablesolutions.akka.stm.TransactionManagement.transaction
import se.scalablesolutions.akka.util.Logging
+import se.scalablesolutions.akka.AkkaException
-// FIXME move to 'stm' package + add message with more info
-class NoTransactionInScopeException extends RuntimeException
-
-class StorageException(message: String) extends RuntimeException(message)
+class StorageException(message: String) extends AkkaException(message)
/**
* Example Scala usage.