Merge branch 'master' of git@github.com:jboner/akka

This commit is contained in:
Jonas Bonér 2010-09-22 15:33:00 +02:00
commit 21b1eb43fc
21 changed files with 203 additions and 57 deletions

View file

@ -26,7 +26,7 @@ import org.apache.hadoop.hbase.util.Bytes
private[akka] object HbaseStorageBackend extends MapStorageBackend[Array[Byte], Array[Byte]] with VectorStorageBackend[Array[Byte]] with RefStorageBackend[Array[Byte]] with Logging {
val EMPTY_BYTE_ARRAY = new Array[Byte](0)
val HBASE_ZOOKEEPER_QUORUM = config.getString("akka.storage.hbase.zookeeper.quorum", "localhost")
val HBASE_ZOOKEEPER_QUORUM = config.getString("akka.storage.hbase.zookeeper-quorum", "localhost")
val CONFIGURATION = new HBaseConfiguration
val REF_TABLE_NAME = "__REF_TABLE"
val VECTOR_TABLE_NAME = "__VECTOR_TABLE"

View file

@ -48,7 +48,7 @@ class PersistenceSpec extends Spec with BeforeAndAfterAll with ShouldMatchers {
import org.apache.hadoop.hbase.client.HBaseAdmin
import org.apache.hadoop.hbase.client.HTable
val HBASE_ZOOKEEPER_QUORUM = config.getString("akka.storage.hbase.zookeeper.quorum", "0")
val HBASE_ZOOKEEPER_QUORUM = config.getString("akka.storage.hbase.zookeeper-quorum", "0")
HBASE_ZOOKEEPER_QUORUM should not equal ("0")
HBASE_ZOOKEEPER_QUORUM should equal("localhost")

View file

@ -106,7 +106,7 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:integer" use="required">
<xsd:attribute name="port" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Port of the remote host.
@ -152,10 +152,10 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:long" use="required">
<xsd:attribute name="timeout" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The default timeout for '!!' invocations.
The default timeout for '!!' invocations in milliseconds.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@ -198,10 +198,10 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:long">
<xsd:attribute name="timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The default timeout for '!!' invocations.
The default timeout for '!!' invocations in milliseconds.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@ -260,7 +260,7 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:integer" use="required">
<xsd:attribute name="port" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Port of the remote host.
@ -334,6 +334,14 @@
<xsd:attribute name="ref" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="config-type">
<xsd:attribute name="location" type="xsd:string"/>
</xsd:complexType>
<!-- akka conf -->
<xsd:element name="property-placeholder" type="config-type"/>
<!-- TypedActor -->
<xsd:element name="typed-actor" type="typed-actor-type"/>

View file

@ -70,3 +70,24 @@ class ActorForBeanDefinitionParser extends AbstractSingleBeanDefinitionParser wi
*/
override def getBeanClass(element: Element): Class[_] = classOf[ActorForFactoryBean]
}
/**
* Parser for custom namespace configuration.
* @author michaelkober
*/
class ConfigBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActorParser {
/*
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/
override def doParse(element: Element, parserContext: ParserContext, builder: BeanDefinitionBuilder) {
val location = element.getAttribute(LOCATION)
builder.addPropertyValue(LOCATION, location)
}
/*
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
*/
override def getBeanClass(element: Element): Class[_] = classOf[ConfiggyPropertyPlaceholderConfigurer]
override def shouldGenerateId() = true
}

View file

@ -6,10 +6,8 @@ package se.scalablesolutions.akka.spring
import org.springframework.beans.{BeanUtils,BeansException,BeanWrapper,BeanWrapperImpl}
import se.scalablesolutions.akka.remote.{RemoteClient, RemoteServer}
//import org.springframework.beans.factory.BeanFactory
import org.springframework.beans.factory.config.AbstractFactoryBean
import org.springframework.context.{ApplicationContext,ApplicationContextAware}
//import org.springframework.util.ReflectionUtils
import org.springframework.util.StringUtils
import se.scalablesolutions.akka.actor.{ActorRef, AspectInitRegistry, TypedActorConfiguration, TypedActor,Actor}
@ -42,10 +40,10 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App
@BeanProperty var typed: String = ""
@BeanProperty var interface: String = ""
@BeanProperty var implementation: String = ""
@BeanProperty var timeout: Long = _
@BeanProperty var timeoutStr: String = ""
@BeanProperty var transactional: Boolean = false
@BeanProperty var host: String = ""
@BeanProperty var port: Int = _
@BeanProperty var port: String = ""
@BeanProperty var serverManaged: Boolean = false
@BeanProperty var serviceName: String = ""
@BeanProperty var lifecycle: String = ""
@ -54,6 +52,20 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App
@BeanProperty var property: PropertyEntries = _
@BeanProperty var applicationContext: ApplicationContext = _
lazy val timeout = parseTimeout
private def parseTimeout() : Long = {
var result = -1L
try {
result = if (!timeoutStr.isEmpty) timeoutStr.toLong else -1L
} catch {
case nfe: NumberFormatException =>
log.error(nfe, "could not parse timeout %s", timeoutStr)
throw nfe
}
result
}
// Holds info about if deps have been set or not. Depends on
// if interface is specified or not. We must set deps on
// target instance if interface is specified
@ -95,7 +107,7 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App
val typedActor: AnyRef = TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig)
if (isRemote && serverManaged) {
val server = RemoteServer.getOrCreateServer(new InetSocketAddress(host, port))
val server = RemoteServer.getOrCreateServer(new InetSocketAddress(host, port.toInt))
if (serviceName.isEmpty) {
server.registerTypedActor(interface, typedActor)
} else {
@ -120,14 +132,14 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App
}
if (isRemote) {
if (serverManaged) {
val server = RemoteServer.getOrCreateServer(new InetSocketAddress(host, port))
val server = RemoteServer.getOrCreateServer(new InetSocketAddress(host, port.toInt))
if (serviceName.isEmpty) {
server.register(actorRef)
} else {
server.register(serviceName, actorRef)
}
} else {
actorRef.makeRemote(host, port)
actorRef.makeRemote(host, port.toInt)
}
}
if (hasDispatcher) {
@ -176,7 +188,7 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App
private[akka] def createConfig: TypedActorConfiguration = {
val config = new TypedActorConfiguration().timeout(Duration(timeout, "millis"))
if (transactional) config.makeTransactionRequired
if (isRemote && !serverManaged) config.makeRemote(host, port)
if (isRemote && !serverManaged) config.makeRemote(host, port.toInt)
if (hasDispatcher) {
if (dispatcher.dispatcherType != THREAD_BASED) {
config.dispatcher(dispatcherInstance())
@ -220,9 +232,8 @@ class ActorForFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with
@BeanProperty var interface: String = ""
@BeanProperty var host: String = ""
@BeanProperty var port: Int = _
@BeanProperty var port: String = ""
@BeanProperty var serviceName: String = ""
//@BeanProperty var scope: String = VAL_SCOPE_SINGLETON
@BeanProperty var applicationContext: ApplicationContext = _
override def isSingleton = false
@ -237,9 +248,9 @@ class ActorForFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with
*/
def createInstance: AnyRef = {
if (interface.isEmpty) {
RemoteClient.actorFor(serviceName, host, port)
RemoteClient.actorFor(serviceName, host, port.toInt)
} else {
RemoteClient.typedActorFor(interface.toClass, serviceName, host, port)
RemoteClient.typedActorFor(interface.toClass, serviceName, host, port.toInt)
}
}
}

View file

@ -8,8 +8,6 @@ import org.w3c.dom.Element
import scala.collection.JavaConversions._
import se.scalablesolutions.akka.util.Logging
import se.scalablesolutions.akka.actor.IllegalActorStateException
/**
* Parser trait for custom namespace configuration for typed-actor.
* @author michaelkober
@ -32,7 +30,7 @@ trait ActorParser extends BeanParser with DispatcherParser {
if (remoteElement != null) {
objectProperties.host = mandatory(remoteElement, HOST)
objectProperties.port = mandatory(remoteElement, PORT).toInt
objectProperties.port = mandatory(remoteElement, PORT)
objectProperties.serverManaged = (remoteElement.getAttribute(MANAGED_BY) != null) && (remoteElement.getAttribute(MANAGED_BY).equals(SERVER_MANAGED))
val serviceName = remoteElement.getAttribute(SERVICE_NAME)
if ((serviceName != null) && (!serviceName.isEmpty)) {
@ -54,15 +52,7 @@ trait ActorParser extends BeanParser with DispatcherParser {
objectProperties.propertyEntries.add(entry)
}
try {
val timeout = element.getAttribute(TIMEOUT)
objectProperties.timeout = if ((timeout != null) && (!timeout.isEmpty)) timeout.toLong else -1L
} catch {
case nfe: NumberFormatException =>
log.error(nfe, "could not parse timeout %s", element.getAttribute(TIMEOUT))
throw nfe
}
objectProperties.timeoutStr = element.getAttribute(TIMEOUT)
objectProperties.target = mandatory(element, IMPLEMENTATION)
objectProperties.transactional = if (element.getAttribute(TRANSACTIONAL).isEmpty) false else element.getAttribute(TRANSACTIONAL).toBoolean
@ -97,7 +87,7 @@ trait ActorForParser extends BeanParser {
val objectProperties = new ActorForProperties()
objectProperties.host = mandatory(element, HOST)
objectProperties.port = mandatory(element, PORT).toInt
objectProperties.port = mandatory(element, PORT)
objectProperties.serviceName = mandatory(element, SERVICE_NAME)
if (element.hasAttribute(INTERFACE)) {
objectProperties.interface = element.getAttribute(INTERFACE)

View file

@ -15,11 +15,11 @@ import AkkaSpringConfigurationTags._
class ActorProperties {
var typed: String = ""
var target: String = ""
var timeout: Long = _
var timeoutStr: String = ""
var interface: String = ""
var transactional: Boolean = false
var host: String = ""
var port: Int = _
var port: String = ""
var serverManaged: Boolean = false
var serviceName: String = ""
var lifecycle: String = ""
@ -38,7 +38,7 @@ class ActorProperties {
builder.addPropertyValue(PORT, port)
builder.addPropertyValue("serverManaged", serverManaged)
builder.addPropertyValue("serviceName", serviceName)
builder.addPropertyValue(TIMEOUT, timeout)
builder.addPropertyValue("timeoutStr", timeoutStr)
builder.addPropertyValue(IMPLEMENTATION, target)
builder.addPropertyValue(INTERFACE, interface)
builder.addPropertyValue(TRANSACTIONAL, transactional)
@ -46,7 +46,11 @@ class ActorProperties {
builder.addPropertyValue(SCOPE, scope)
builder.addPropertyValue(DISPATCHER_TAG, dispatcher)
builder.addPropertyValue(PROPERTYENTRY_TAG,propertyEntries)
}
}
def timeout() : Long = {
if (!timeoutStr.isEmpty) timeoutStr.toLong else -1L
}
}
@ -57,7 +61,7 @@ class ActorProperties {
class ActorForProperties {
var interface: String = ""
var host: String = ""
var port: Int = _
var port: String = ""
var serviceName: String = ""
/**

View file

@ -12,6 +12,7 @@ import AkkaSpringConfigurationTags._
*/
class AkkaNamespaceHandler extends NamespaceHandlerSupport {
def init = {
registerBeanDefinitionParser(CONFIG_TAG, new ConfigBeanDefinitionParser());
registerBeanDefinitionParser(TYPED_ACTOR_TAG, new TypedActorBeanDefinitionParser())
registerBeanDefinitionParser(UNTYPED_ACTOR_TAG, new UntypedActorBeanDefinitionParser())
registerBeanDefinitionParser(SUPERVISION_TAG, new SupervisionBeanDefinitionParser())

View file

@ -13,6 +13,7 @@ object AkkaSpringConfigurationTags {
// --- TAGS
//
// top level tags
val CONFIG_TAG = "property-placeholder"
val TYPED_ACTOR_TAG = "typed-actor"
val UNTYPED_ACTOR_TAG = "untyped-actor"
val SUPERVISION_TAG = "supervision"
@ -73,6 +74,9 @@ object AkkaSpringConfigurationTags {
val REJECTION_POLICY ="rejection-policy"
val MAILBOX_CAPACITY ="mailbox-capacity"
// config attribute
val LOCATION = "location"
// --- VALUES
//
// Lifecycle

View file

@ -0,0 +1,37 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
package se.scalablesolutions.akka.spring
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
import org.springframework.core.io.Resource
import net.lag.configgy.Configgy
import java.util.Properties
/**
* ConfiggyPropertyPlaceholderConfigurer. Property resource configurer for configgy files.
*/
class ConfiggyPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
/**
* Sets the akka properties as local properties, leaves the location empty.
* @param configgyResource akka.conf
*/
override def setLocation(configgyResource: Resource) {
if (configgyResource == null) throw new IllegalArgumentException("Property 'config' must be set")
val properties = loadAkkaConfig(configgyResource)
setProperties(properties)
}
/**
* Load the akka.conf and transform to properties.
*/
private def loadAkkaConfig(configgyResource: Resource) : Properties = {
Configgy.configure(configgyResource.getFile.getPath)
val config = Configgy.config
val properties = new Properties()
config.asMap.foreach {case (k, v) => properties.put(k, v); println("(k,v)=" + k + ", " + v)}
properties
}
}

View file

@ -60,7 +60,8 @@ class SupervisionFactoryBean extends AbstractFactoryBean[AnyRef] {
val isRemote = (props.host != null) && (!props.host.isEmpty)
val withInterface = (props.interface != null) && (!props.interface.isEmpty)
if (isRemote) {
val remote = new RemoteAddress(props.host, props.port)
//val remote = new RemoteAddress(props.host, props.port)
val remote = new RemoteAddress(props.host, props.port.toInt)
if (withInterface) {
new Component(props.interface.toClass, props.target.toClass, lifeCycle, props.timeout, props.transactional, remote)
} else {
@ -91,7 +92,7 @@ class SupervisionFactoryBean extends AbstractFactoryBean[AnyRef] {
}
val supervise = if (isRemote) {
val remote = new SRemoteAddress(props.host, props.port)
val remote = new SRemoteAddress(props.host, props.port.toInt)
Supervise(actorRef, lifeCycle.transform, remote)
} else {
Supervise(actorRef, lifeCycle.transform)

View file

@ -0,0 +1,13 @@
akka {
actor {
timeout = 2000
}
remote {
server {
service = on
hostname = "localhost" # The hostname or IP that clients should connect to
port = 9995 # The port clients should connect to
connection-timeout = 1
}
}
}

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:akka="http://www.akkasource.org/schema/akka"
xmlns:beans="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.akkasource.org/schema/akka
http://scalablesolutions.se/akka/akka-1.0-SNAPSHOT.xsd">
<akka:property-placeholder location="akka-test.conf"/>
<akka:untyped-actor id="actor-1"
implementation="se.scalablesolutions.akka.spring.foo.PingActor"
timeout="${akka.actor.timeout}">
<akka:remote host="${akka.remote.server.hostname}" port="${akka.remote.server.port}"/>
</akka:untyped-actor>
</beans>

View file

@ -25,8 +25,8 @@ class ActorFactoryBeanTest extends Spec with ShouldMatchers with BeforeAndAfterA
it("should have java getters and setters for all properties") {
bean.setImplementation("java.lang.String")
assert(bean.getImplementation == "java.lang.String")
bean.setTimeout(1000)
assert(bean.getTimeout == 1000)
bean.setTimeoutStr("1000")
assert(bean.getTimeoutStr === "1000")
}
it("should create a remote typed actor when a host is set") {
@ -50,7 +50,7 @@ class ActorFactoryBeanTest extends Spec with ShouldMatchers with BeforeAndAfterA
val bean = new ActorFactoryBean()
bean.setInterface("se.scalablesolutions.akka.spring.PojoInf")
bean.setImplementation("se.scalablesolutions.akka.spring.Pojo")
bean.timeout = 1000
bean.timeoutStr = "1000"
bean.typed = AkkaSpringConfigurationTags.TYPED_ACTOR_TAG
val entries = new PropertyEntries()
val entry = new PropertyEntry()

View file

@ -0,0 +1,42 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
package se.scalablesolutions.akka.spring
import foo.{IMyPojo, MyPojo, PingActor}
import se.scalablesolutions.akka.dispatch._
import org.scalatest.FeatureSpec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import org.springframework.beans.factory.support.DefaultListableBeanFactory
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader
import org.springframework.context.ApplicationContext
import org.springframework.context.support.ClassPathXmlApplicationContext
import org.springframework.core.io.{ClassPathResource, Resource}
import java.util.concurrent._
import se.scalablesolutions.akka.actor.{UntypedActor, Actor, ActorRef}
/**
* Tests for spring configuration of typed actors.
* @author michaelkober
*/
@RunWith(classOf[JUnitRunner])
class ConfiggyPropertyPlaceholderConfigurerSpec extends FeatureSpec with ShouldMatchers {
val EVENT_DRIVEN_PREFIX = "akka:event-driven:dispatcher:"
feature("The ConfiggyPropertyPlaceholderConfigurator") {
scenario("should provide the akkka config for spring") {
val context = new ClassPathXmlApplicationContext("/property-config.xml")
val actor1 = context.getBean("actor-1").asInstanceOf[ActorRef]
assert(actor1.remoteAddress.get.getHostName === "localhost")
assert(actor1.remoteAddress.get.getPort === 9995)
assert(actor1.timeout === 2000)
}
}
}

View file

@ -16,12 +16,12 @@ private[akka] class Foo
class SupervisionFactoryBeanTest extends Spec with ShouldMatchers {
val restartStrategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Throwable]))
val typedActors = List(createTypedActorProperties("se.scalablesolutions.akka.spring.Foo", 1000L))
val typedActors = List(createTypedActorProperties("se.scalablesolutions.akka.spring.Foo", "1000"))
def createTypedActorProperties(target: String, timeout: Long) : ActorProperties = {
private def createTypedActorProperties(target: String, timeout: String) : ActorProperties = {
val properties = new ActorProperties()
properties.target = target
properties.timeout = timeout
properties.timeoutStr = timeout
properties
}

View file

@ -65,7 +65,7 @@ class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers {
val props = parser.parseActor(dom(xml).getDocumentElement);
assert(props != null)
assert(props.host === "com.some.host")
assert(props.port === 9999)
assert(props.port === "9999")
assert(!props.serverManaged)
}
@ -77,7 +77,7 @@ class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers {
val props = parser.parseActor(dom(xml).getDocumentElement);
assert(props != null)
assert(props.host === "com.some.host")
assert(props.port === 9999)
assert(props.port === "9999")
assert(props.serviceName === "my-service")
assert(props.serverManaged)
}

View file

@ -1,8 +0,0 @@
<aspectwerkz>
<system id="akka">
<package name="se.scalablesolutions.akka.actor">
<aspect class="TypedActorAspect" />
<aspect class="ServerManagedTypedActorAspect" />
</package>
</system>
</aspectwerkz>

View file

@ -167,7 +167,7 @@ akka {
}
hbase {
zookeeper.quorum = "localhost"
zookeeper-quorum = "localhost"
}
}
}