Over a million developers have joined DZone.
Platinum Partner

MacWire 0.2: Scopes are Simple!

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

MacWire generates new instance creation code of given classes, using values in the enclosing type for constructor parameters, with the help of Scala Macros. DI container replacement.

Version 0.2 has just landed!

First things first …

First, some bad news. Due to limitations of the current macros implementation in Scala (for more details see this discussion) in order to avoid occasional compilation errors it is necessary to add type ascriptions to the dependencies. This is a way of helping the type-checker that is invoked by the macro to figure out the types of the values which can be wired.

In practice it is good to always write the type ascription. For example:

trait MyModule {
   lazy val theUserFinder: UserFinder = wire[UserFinder]

This is a major inconvenience, but hopefully will get resolved some day. See the “Limitations” section in the README for more details.

… to the point

Now, to the good news. Especially when developing web applications, it is very useful to scope some of the dependencies, so that there’s a new instance for each request (but for each dependency usage, it is the same instance in one request), or that there’s a single instance per http session.

So far MacWire had two “built-in” scopes: singleton (declare the dependency as lazy val) and dependent (def). Now it is possible to create custom scopes, by implementing the Scope trait.

Scopes often seem “magical”; in traditional frameworks it is usually necessary to add an annotation to the class and then the dependency is automagically turned into a scoped one by the container.

In fact implementing a scoped bean is quite simple. We need two things. Firstly, instead of using instances directly, we need to use a proxy which delegates method calls to the “current instance”. What “current instance” means is scope-specific.

Secondly, we need a way to read a value from the scope, and store a value in the scope, if there’s no value yet. The two methods in the Scope trait correspond directly to the two cases outlined above.

Using a scope is quite straightforward; the scope of a dependency is declared in the wiring code, in the module. For example:

trait WebModule {
   lazy val loggedInUser: LoggedInUser = session(wire[LoggedInUser])
   def session: Scope

Note that the scope here is abstract (only the name suggests that it is a session scope). This has a couple of advantages. For testing, we can substitute a NoOpScope. Also, we can move the framework-integration code to the integration layer, or even provide a couple of implementations depending on the framework/container used.

MacWire comes with a Scope implementation targeted at synchronous web frameworks, ThreadLocalScope. The scope needs to be associated and disassociated with a scope storage. To implement a:

  • request scope, we need a new empty storage for every request (associateWithEmptyStorage method)
  • session scope, the storage (a Map) should be stored in the HttpSession (associate(Map) method)

This association can be done, for example, in a servlet filter:

class ScopeFilter(sessionScope: ThreadLocalScope) extends Filter {
  def init(filterConfig: FilterConfig) {}
  def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
    val httpRequest = request.asInstanceOf[HttpServletRequest]
    val sessionScopeStorage = new ScopeStorage {
      def get(key: String) = Option(httpRequest.getSession.getAttribute(key))
      def set(key: String, value: Any) {
        httpRequest.getSession.setAttribute(key, value)
    sessionScope.withStorage(sessionScopeStorage) {
      chain.doFilter(request, response)
  def destroy() {}

Note also that it is trivial to use a scoped value e.g. in an asynchronous process, where no web request is available: simply associate the scope with any storage, can be a temporary map. In traditional web frameworks this usually requires some amount of hacking.

To sum up, to use a scope in MacWire you need to:

  • declare a Scope in your module, use if for scoped dependencies
  • provide an implementation of the scope, e.g. ThreadLocalScope
  • associate the scope with a storage, e.g. in a servlet filter

You can see how this works in practice by browsing & running a Scalatra+MacWire example application. To run, clone MacWire and use this command: sbt examples-scalatra/run. To browse the code, simply head to GitHub.


The example contains a request-scoped dependency (SubmittedData), session-scoped dependency (LoggedInUser) and three main services (Service1, Service2, Service3). Each class has some dependencies (declared in the constructor), and is wired using wire[]. The code is organised in two modules: logic and servlet. The services have methods to return a string-status, containing the current request and session-scoped values, so that it is possible to verify that indeed the values are shared properly. The servlet module contains a servlet which shows the service status, plus the scopes implementations.

Note that the scopes subproject is completely independent, and can be used stand-alone with manual wiring or any other library/framework. Its only dependency is javassist.

Have fun!


The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


Published at DZone with permission of Adam Warski , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}