Is it possible to invoke a non-static java method from inside a scala template?

java
dependency-injection
configuration

(Kenny West) #1

Hi All,

This is a newbie question, but I can’t find the answer anywhere.
Given this class:

@Singleton
public class AtomicCounter implements Counter {
    private final AtomicInteger atomicCounter = new AtomicInteger();

    @Override
    public int nextCount() {
       return atomicCounter.getAndIncrement();
    }
}

I’d like to call it from a welcome.scala.html template like this:

<p>COUNT: @counter.nextCount()</p>

I can call static methods, but get compiler errors when I try to call non-static methods.

This code is from the play-java-starter-example on GitHub.

Thanks


(Greg Methvin) #2

How are you passing the Counter instance to your template?


(Kenny West) #3

I’m not. I was hoping I wouldn’t have to and could pull it from the container. Can you only call static methods if the instance isn’t passed as a parameter?


(Greg Methvin) #4

I think what you probably want is dependency injection in templates: https://www.playframework.com/documentation/2.6.x/ScalaTemplatesDependencyInjection

You need to add a @this(counter: Counter) at the top of your template and then inject an instance of your template where you need it.


(Kenny West) #5

With Greg’s help and a GitHub issue, I ended up solving it. Here is my code

Here is my index.scala.html template:

@this(counter: services.Counter)
@(message: String)

@main("Welcome to Play") {
    @welcome(message, counter)
}

Here is welcome.scala.html

@(message: String, counter: services.Counter)

<section id="top">
    <div class="wrapper">
        <h1>MESSAGE:  @message</h1>
    </div>
</section>

<div id="content" class="wrapper doc">
    <article>
        <h1>COUNT:  @{counter.nextCount()}</h1>
    </article>
</div>

Here is my Counter implementation:

@Singleton
public class AtomicCounter implements Counter {

    private final AtomicInteger atomicCounter = new AtomicInteger();

    @Override
    public int nextCount() {
       return atomicCounter.getAndIncrement();
    }
}

And here is my Controller

public class HomeController extends Controller {

    private final views.html.index indexTemplate;

    @Inject
    public HomeController(views.html.index indexTemplate) {
        this.indexTemplate = indexTemplate;
    }

    public Result index() {
        return ok(indexTemplate.render("It works !!!"));
    }
}