Hi guys,

Vaughn Vernon asked me this morning if it would make sense to implement Qi4j in Scala. I said no, but maybe Qi4j can use Scala classes directly instead. So, having literally 0 experience with Scala I set out to try and see what could be done.

... a couple of hours later ...

Short story: works great!

Longer story:
Because of how Scala translates "traits" into bytecode, I hade to create a generic mixin that handles calls to Scala traits, and delegates them appropriately. The "trait" is converted to one interface, and one class with static methods. So, when the generic mixin is invoked on the interface methods of the trait, I simply look up the corresponding static method, and invoke it properly.

Example mixin declaration:
trait HelloWorldMixin2
{
  def doMoreStuff(@MaxLength(10) name: String): String = "Hello "+name
}

Example composite declaration:
@Concerns(Array(classOf[HelloThereConcern]))
trait HelloWorldComposite
  extends TransientComposite with HelloWorldMixin with HelloWorldMixin2

Example typed concern:
class HelloThereConcern
  extends ConcernOf[HelloWorldMixin2] with HelloWorldMixin2
{
  override def doMoreStuff(name: String) = next.doMoreStuff("there "+name);
}

And generic concern with filter:
@AppliesTo(Array(classOf[StringFilter]))
class ExclamationGenericConcern
  extends GenericConcern
{
def invoke(composite: AnyRef, method: Method, args: Array[AnyRef]) = next.invoke(composite, method, args)+"!"
}

class StringFilter
  extends AppliesToFilter
{
def appliesTo(method: Method, mixin: Class[_], compositeType: Class[_], fragmentClass: Class[_]) = method.getReturnType.equals(classOf[String])
}
---
So that pretty much covers the domain model part. Usage from Java is transparent, since it looks just like interfaces and classes. IntelliJ auto-completion for the "doMoreStuff" method even works properly when using the Scala plugin (I did the tests in Java+JUnit). Building in Gradle is trivial since there's a plugin for that.

In short, AFAICT we now have support for Scala in Qi4j. The only question is where to put the generic mixin that I wrote. Right now it's just in a sample app. It could theoretically be promoted to Core API and added to Composite, just like PropertyMixin, as I could get it to work without any references to the Scala library, so that it works out-of-the-box. Or, we could put it in a library. Either way is fine by me.

Thoughts on that?

/Rickard

_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to