DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • OpenAPI: Extend Functionality of Generator Plugin Using Custom Mustache Templates

Trending

  • Navigating Double and Triple Extortion Tactics
  • Simplifying Multi-LLM Integration With KubeMQ
  • Designing for Sustainability: The Rise of Green Software
  • Mastering Advanced Traffic Management in Multi-Cloud Kubernetes: Scaling With Multiple Istio Ingress Gateways

Dropwizard From the Start — Part 2: Building a UI Using Mustache

If you’ve been following along with my first two articles, I am on a journey of discovery through the land of Dropwizard. I’m finding out what all the fuss is about, and whether I can learn to like frameworks again. We had a simple chat system working which was purely JSON on top of REST. The next logical thing is to build a UI.

By 
Sam Atkinson user avatar
Sam Atkinson
·
Jan. 19, 16 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
16.8K Views

Join the DZone community and get the full member experience.

Join For Free

Image title

If you’ve been following along with my first two articles, I am on a journey of discovery through the land of Dropwizard. I’m trying to discover what all the fuss is about, and whether I can learn to like frameworks again. We had a simple chat system working which was purely JSON on top of REST. The next logical thing is to build a UI.

Along with everything that comes in Dropwizard core (Jetty, Jersey, and Jackson), there’s a whole heap of extra stuff Dropwizard throws in as optional, one of which being the *dropwizard-views* packages. These give the developer access to both Freemarker and Mustache templating engines with a little bit of Dropwizard magic over the top.

Mustache

I’ve always been a big fan of Handlebars, which is effectively a derivative of Mustache. It’s really simple to use; you simply write plain old HTML, but where you want variables from Java land you simply wrap them in double curly braces. You’re fairly limited to object access and not much more, so the UIs end up clean; no JSP-esque UI logic hell here.

The HTML/mustache mashup is a template which is compiled against a Java class, where the knowledge comes from.

 <html>
<head></head>
<body>
<div class="top">
    <div class="user">Logged in as {{currentUser}}</div>
</div>
</body></html>

Compiled against:

 public class MyView{
    public String getCurrentUser() {
        return “Bobby”;
    }
    ]

Will result in:

    <html>
<head></head>
<body>
<div class="top">
    <div class="user">Logged in as Bobby</div>
</div>
</body></html>

Easy peasy! Mustache has basic syntax for going through loops and I’ve found it to be simple to use and sufficiently powerful. It’s apparently being used by Twitter according to the Mustache Github page, so it should hopefully be sufficiently performant.

Where I’ve been reasonably impressed is the extra value that Dropwizard adds. Normal usage requires you to create a Mustache factory, compile the template and write the data out from it; whilst not particularly onerous, it’s extrenuous boiler plate would be nice to be rid of. Fortunately, Dropwizard takes care of it. By returning a class that extends a Dropwizard View class, it will automatically render the page.

I want a single page for my UI: a list of people I’m chatting with on the left and the current chat on the right. This means my view needs a list of all my chats, plus the current chat and the usernames to allow me to submit chats.

public class ChatroomView extends View {

    private final List<ChatView> allChatsForThisUser;
    private final String currentUser;
    private final Chat currentChat;
    private final String otherUser;


    public ChatroomView(String currentUser, String otherUser, Chat currentChat, List<ChatView> allChatsForThisUser) {
        super("chat.mustache");
        this.currentUser = currentUser;
        this.otherUser = otherUser;
        this.currentChat = currentChat;
        this.allChatsForThisUser = allChatsForThisUser;
    }

    public List<ChatView> getChats(){
        return allChatsForThisUser;
    }

    public Chat getCurrentChat() {
        return currentChat;
    }

    public String getCurrentUser() {
        return currentUser;
    }

    public String getOtherUser() {
        return otherUser;
    }
}

This is a simple POJO. The only interesting parts are “extends View” which we discussed before, and the first line of the constructor. Here, we tell the superclass the name of the template which we wish to compile, in our case chat.mustache. Here’s the full template:

    <!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/assets/css/skeleton.css"/>
    <link rel="stylesheet" href="/assets/css/main.css"/>
</head>
<body>
<div class="top">
    <div class="user">Logged in as {{currentUser}}</div>
</div>
<div class="container">
<row>
    <div class = "three columns">
        <h1>Chats</h1>
        <ul>
            {{#chats}}<li><a href="/chat/{{userOne}}/{{userTwo}}">{{userTwo}}</a></li>{{/chats}}
        </ul>
    </div>
    <div class = "nine columns">
        {{#currentChat}}
            <h1>Chat between {{currentUser}} and {{otherUser}}</h1>
            {{#chat}}
                {{.}}<br/>
            {{/chat}}
            <br>
            <form method="post" action="/chat/{{currentUser}}/{{otherUser}}">
                <textarea name="message"></textarea>
                <br/><button>Submit</button>
            </form>
        {{/currentChat}}
    </div>
</row>

</div>
</body>
</html>

The only new syntax can be seen here:

{{#chat}}

{{.}}<br/>

{{/chat}}

Using #chat allows us to loop through all of the objects in the field “chat”. The {{.}} syntax is simply for using “this”; if instead of a String we had a complex object we could just call the fields on that object here.

@Path("/chat/{userOne}/{userTwo}")
@Produces({MediaType.TEXT_HTML})
public class ChatResource {
    @GET
    public ChatroomView chatBetween(@PathParam("userOne") final Optional<String> userOne,
                                    @PathParam("userTwo") final Optional<String> userTwo) {

By modifying the return type in our ChatroomResource to be our new view, our mustache template is correctly rendered.

Image title

I had to refactor the code somewhat to get everything working. I’d originally allowed the userOne/userTwo of the chat object to be in any order which reeked havok on the views. As a result, I created a ChatView object which represents each chat from the perspective of the “logged in” user.

And for My Next Trick

Hopefully, you were screaming “but what about the REST API? You’ve just killed it in favour of your view!” I was certainly concerned, until I discovered a lovely little trick in Dropwizard. It is possible to specify more than one type in the “produces” field. In this case the default is HTML, but if the client specifies an accept header of JSON then Dropwizard will use Jackson to serialise the view. We can have a single API point return HTML or JSON depending on the clients wish! This is so cool.

@Path("/chat/{userOne}/{userTwo}")
@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
public class ChatResource {

Here’s a picture of the call from postman, the exact same URL, just with the JSON request header.

Image title

At the moment, the result isn’t great (the chat’s returned twice!) but that can be easily optomized.

Thoughts and Concerns

I must admit that overall I’ve been quite impressed so far. It’s been pretty quick to get going to build an application and for the most part it has all kind of “just worked”. However, I have struggled with poor documentation on this part. Dropwizard refers to the Mustache Java docs, which are really pretty poor at this juncture. There’s literally nothing on the Dropwizard additions to mustache; this makes it near impossible to figure out how to do some of the deeper integrations in the Mustache Java documentation in Dropwizard because it’s been abastracted away. On a simple app like this it’s not been too much of an issue but it would make me nervous going into a bigger application. However, there’s literally nothing tying you to the Dropwizard version. I could easily just use the standard library if it were to become a big problem.

Next up for the application is login and persistance. After this, it’ll be a fully functional chat application; it still does full page refresh for each message which isn’t ideal but that’s certainly something to improve.

You can view the full code at https://github.com/samberic/wizchat.

Please leave comments in the box, and follow me on Twitter @SambaHK for updates and whimsy.

Mustache (template system)

Opinions expressed by DZone contributors are their own.

Related

  • OpenAPI: Extend Functionality of Generator Plugin Using Custom Mustache Templates

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!