|<<>>|224 of 274 Show listMobile Mode

Override an Implementation in HiveMind

Published by marco on

This article was originally published on the Encodo Blogs. Browse on over to see more!


If you are not already familier with HiveMind, read Setting up a Service in HiveMind for an introduction.[1]

In the article mentioned above, we learned how to set up a new HiveMind service. What if we want to replace the implementation for an existing service? Is it even possible? Why would you want to do that? This article answers these questions in the context of a real-life example from one of our applications.

Extending Tapestry

In our Tapestry applications, we use the ExternalLink because it provides a standard URL that can be bookmarked and refreshed across sessions (which is handy during development as well). This link relies on the ExternalService, which is configured and created by HiveMind. We wanted to experiment with this implementation to include more flexibility as to which method would be called[2]; at first, we just replaced the class in our application and worked with it from there.

This worked fine until we wanted to be able to configure some basic properties we’d added to the service from our application’s configuration file. The easiest way to do this would be to give the external service access to the custom application service we’d created in our own HiveMind file. So, we’re faced with the problem of injecting an application-specific service into a library service from another module.

Overriding in HiveMind

As usual with HiveMind, you just have to know that there is a specific element for doing this called <implementation>. If you declare a service using this element instead of <service-point>, HiveMind searches for the previous service declaration and replaces the entire creation clause for that service. That means that any service properties set by the initial declaration have to be copy/pasted into the implementation override or HiveMind won’t set those properties anymore.

The declaration below does this for the external service, adding in the application-specific property in addition to the two properties stipulated by the original implementation (copied from Tapestry’s configuration).

  <implementation service-id="tapestry.services.External">
    <invoke-factory>
      <construct class="com.encodo.tapestry.ConfigurableExternalService">
        <set-object property="responseRenderer" value="infrastructure:responseRenderer"/>
        <set-object property="linkFactory" value="infrastructure:linkFactory"/>
        <set-service property="applicationService" service-id="CustomApplicationService" />
      </construct>
    </invoke-factory>
  </implementation>  

Once you know how, it’s quite simple … and powerful. Any component of Tapestry can be replaced in this rather elegant way to make application-specific implementations of common services. If you’re simply extending existing functionality, you have to remember to copy the entire prior specification; if you’ve replaced the implementation wholesale, then it’s possible you no longer need the properties set by the prior implementation and can leave them out.


[1] The examples in this article assume the same module declaration as in that article, namely, using id = com.encodo.customer.project
[2] Finding Conforming Methods and Inherited Method Annotations provide more information about our development of this feature.

Using Java 1.5, Tapestry 4.02, HiveMind 1.1.1