Project Polygene has retired. For details please refer to its Attic page.
Scala Support

Scala Support




The Scala Support Library allows Fragments and Composites to be written as Scala traits.

Table 24. Artifact

Group IDArtifact IDVersion




The Scala Support Library is a Generic mixin class that implements Composites by delegating to Scala traits.


Example mixin declaration:

trait HelloWorldMixin2
  def sayHello(@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 sayHello(name: String ) = next.sayHello("there " + name)

Example 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
    .equals(classOf[ String ])

And the assembly code. Note that the ScalaTraitMixin must be added.

module.transients( HelloWorldComposite.class, HelloWorldComposite2.class ).
    withMixins( ScalaTraitMixin.class ).
    withConcerns( ExclamationGenericConcern.class );

That pretty much covers the domain model part. Usage from Java is transparent, since it looks just like interfaces and classes.

Entity composites

The following example separate between command interface (suggestions to change), events (after the fact), and data, so they are in three separate traits below. Only commands are called by client code.

trait TestEntity
  extends EntityComposite with Commands with Events with Data

trait Commands
  self: Events =>
  def updateFoo(newValue: String )
    // Call "injected" service
    val repeated = testService.repeat(newValue)

    // Check here if input is ok

  // Service injection - this is really a method call to the ServiceFinder of the composite
  def testService: TestService

// Raw data of entity goes here
trait Data
  def foo: Property[ String ]

  // Define property
  def foo_=(v: String ) { foo.set(v)  } // Operator overloading for =

trait Events
  self: Data =>
  def updatedFoo(newValue: String )
    // Register change by modifying state
    foo = newValue

The self operator thing solves the @This injection requirements, although it doesn’t do private injections (i.e. the Entity has to extend Events and Data for it to work).

Everything is statically typed.

And the corresponding assembly code:

module.entities( TestEntity.class ).withMixins( ScalaTraitMixin.class );

Services composites

The following example is a pretty simple service written as a Scala trait:

trait TestService
  extends ServiceComposite
  def repeat(input: String ): String = input + input

And the corresponding assembly code: TestService.class ).withMixins( ScalaTraitMixin.class );