How to override macwire injectables in subclasses

204 views Asked by At

The Play web framework allows injecting a list of "filters" to do common processing on requests (gzip, cors, logging, etc.)

package play.api

trait BuiltInComponents {
  ...
  lazy val httpFilters: Seq[EssentialFilter] = Nil
  <stuff that uses httpFilters>
  ...
}

I would like to have a common set of these filters (and other things).

package example

import play.api.BuildInComponents

trait MyCommonComponents extends BuiltInComponents {
    ...
    override lazy val filters = Seq(
      wire[Filter1],
      wire[Filter2],
      wire[Filter3]
    )
    ...
}

Which can be used by subclasses

package example.foo

import example.MyCommonComponents

trait MyFooComponents extends MyCommonComponents {
    ...
}

Or added to by subclasses

package example.bar

import example.MyCommonComponents

trait MyBarComponents extends MyCommonComponents {
    ...
    override lazy val filters = super.filters :+ wire[Filter4]
    ...
}

Things I have tried

  1. The code above. Can't use super with a lazy val.
  2. Changing httpFilters to def. Needs to be a stable value due to BuiltInComponents
  3. Adding lazy val httpFilters = filters and def filters: Seq[EssentialFilter] = ... and then overriding filters as appropriate. Macwire complains about ambiguous types.

What can I do to achieve the optionally appended list of filters?

1

There are 1 answers

2
SergGr On

I probably don't get your scenario but what's wrong with simple

import com.softwaremill.macwire._
import play.api.BuiltInComponents
import play.api.mvc.{EssentialAction, EssentialFilter}

class Filter1 extends EssentialFilter {
  override def apply(next: EssentialAction) = next
}

class Filter2 extends EssentialFilter {
  override def apply(next: EssentialAction) = next
}

class Filter3 extends EssentialFilter {
  override def apply(next: EssentialAction) = next
}

trait MyCommonComponents extends BuiltInComponents {

  protected lazy val baseFilters: Seq[EssentialFilter] = Seq(
    wire[Filter1],
    wire[Filter2],
  )

  override def httpFilters = baseFilters
}


trait MyFooComponents extends MyCommonComponents {

  protected lazy val fooFilters = baseFilters :+ wire[Filter3]

  override def httpFilters = fooFilters
}

or this

trait MyBarComponents extends MyCommonComponents {

  private lazy val barFilters = Seq[EssentialFilter](wire[Filter3])

  override def httpFilters = super.httpFilters ++ barFilters
}

Why do you want to override your lazy val instead of the base httpFilters that seem to be designed exactly to be overridden.