MattHicks.com

Programming on the Edge

Hyperscala: An Introduction

Published by Matt Hicks under , , , , , , , on Tuesday, January 08, 2013

It has been well over a year since my last post. In 2011 I went to work for Overstock and moved to Utah. Life got busy and I worked during the day and when I had time I programmed on Sgine at night (http://www.sgine.org).  In February of 2012 I left Overstock and moved back to Oklahoma to start my own company writing software for businesses around the world (http://www.outr.com).  Life got busier. :)  Now, here it is, 2013 and I've resolved to blog at least once a week on the many amazing things I get to do.

Today I want to introduce you to Hyperscala (https://github.com/darkfrog26/hyperscala).  It's a web framework I've been working on for a few months in Scala to provide type-safe HTML, CSS, SVG, and JavaScript to developers.  The first question out of my mouth when I hear another person talking about another web framework is, "Why another web framework?" and I've asked myself that question many times both before creating and since creating it. Each time I come up with the same answer, and one that by the end of this introduction I hope you all will agree: It was necessary.

First, as any good introduction should, I'll show you a little Hello World example:

Obviously this is a very simplistic example and simply sets the page title and adds a String to the body of the page. If you'd like a far more detailed example of the bare-metal type-safe HTML writing capabilities I would recommend looking at the TodoMVC example.

This is all well and good if there are no designers and you prefer working in Scala to HTML and CSS. Unfortunately, this is not always the case and the goal of Hyperscala is not to make presumptions on how it will be used, so we try to accommodate everyone.

So, what do you do when you have existing HTML that needs to be brought into your project?

The first option is to convert it into Scala using the handy-dandy code conversion utility in Hyperscala. The code in the TodoMVC above was generated using this neat little tool. This works great when you have a snippet or large amount of HTML that needs to be converted into code to work with. For more information about this tool take a look HTMLToScala.scala. You can run the main method to get a nice visual file selector and tell it where to output the resulting Scala source file. This route works great until you need a designer to make a change to your HTML and they are unwilling to edit your Scala source files. ;)

This brings us to the second option. This is sort of a hybrid approach and I believe really gives you the best of both worlds in the case that you have externally maintained HTML and CSS that needs dynamic content integration. I created the DynamicContent trait and utilization of this trait allows you to dynamically import HTML and load only the elements you want to work with. See the following HTML snippet:

In this example we care about the two inputs and the button but we don't care about the rest of the content. So, utilizing DynamicContent we create SimpleDynamicForm:

This is a bit more elaborate than is necessary, but shows some of the power of PowerScala Properties in the mix with Hyperscala. Look specifically at the line where the button is loaded:

DynamicContent finds the button by its id in the dynamic.html file and loads it as a Hyperscala tag.Button and any changes I make to the loaded button are reflected at render time. I could have simply loaded the name and age inputs as well, but using bind I cross-bind the value of the input to their reflected field names in the Person class. This means that when I change the value of the inputs it updates the 'person' Property to reflect the change. DynamicContent.bind introduces two other features of Hyperscala we need to briefly discuss: Modules and Realtime.

Modules provide the ability to define shared functionality between applications, components, features, etc. For example, a big problem in web site development is avoiding multiple includes of jQuery. In Hyperscala there is a built-in module for jQuery that any tag or page that needs to make use of can simply 'require' in their code. For example:

The above code requires jQuery be present by referencing the jQuery Interface and passing a default implementation of jQuery182. This will inject jQuery182 if no other implementation of jQuery is specifically provided before render of the page. The require method may be invoked with just an Interface (and an exception will be thrown at render time if no implementation has been provided), an Interface and a default Module (as seen above), or just a Module (at render time the module will be used if it is the highest version number provided for the same module name).

Modules are extremely easy to write. For example, the jQuery182 module looks like this:

Every Module needs a name and version. If they implement an Interface they can override the implements method to provide a list of those they implement (see we are implementing jQuery interface). The init method is invoked the very first time the module is used within a Website. This allows one-time actions to be taken like registering a JavaScript resource to a path as seen above. The load method is invoked at first render of every page that requires this module. This gives the module the ability to interact with the page prior to rendering to the client. As you can see in the jQuery182 module we simply add a tag.Script instance to the head of the page.

Realtime is actually a Module like we just discussed, but an extremely powerful one. This allows two-way communication between the client and server via WebSockets falling back to AJAX polling. It is incredibly easy to use as seen below:

That's all that's necessary in order to allow cross-communication to a loaded webpage. Now any changes to the HTML after page load will automatically synchronize to the browser. Further, you can begin listening to JavaScript events on the server by specifying what events you want to be sent down. For example:

This is an extremely simple example of hooking up a button that sends click events to the server. Notice on line 12 the use of "event.click". All HTML tags expose JavaScript events via the "event" object. In this case we are assigning the result of calling JavaScriptEvent() that interacts with Realtime to send the event down to the server. We could do something like this instead if we wanted just basic JavaScript:

Notice on line 14 we add a synchronous listener to handle a ClickEvent (the JavaScript event that is thrown when clicked). When clicked we simply log that the button has been clicked to the server-side console.

This has been a pretty long post, but barely scratches the surface of what Hyperscala can do. My goal is to spend the next few weeks blogging about the features and capabilities of Hyperscala and get into some even more powerful features of the framework. Again, the biggest advantage of Hyperscala is that at its core it is simply a webpage rendering framework. Everything else is just icing on the cake. This means anyone that has other needs for the features of Hyperscala can simply build their own abstraction layer on top to provide whatever they want.

11 comments:

Raman Gupta said... @ January 8, 2013 at 1:54 PM

Neat stuff Matt... Hyperscala seems to be a better GWT than GWT, and a better Vaadin than Vaadin.

I look forward to seeing more.

Sandeep Bhandari said... @ January 9, 2013 at 12:16 AM

Is there any concept of interceptors or filters in case of hyperscala to implement features like auto session timeout

Henri said... @ January 9, 2013 at 1:29 AM

Interesting! I like the API, it seems to be very useful if you don't mind working with DOM and HTML. On the other hand Vaadin's API is more abstracted, and allows you to ignore the browser stuff if you so prefer.

In any case we'll take a look at Hyperscala and keep it in mind while we develop Scaladin.

Btw, if you haven't seen it, here's a complete Scaladin example including a MongoDB backend in under 100 lines: https://github.com/ripla/vaadin-scala-mongo/blob/master/src/main/scala/vaadin/scala/example/mongo/min/MongoExampleMin.scala

--
Henri Muurimaa, Vaadin

Papapetrou P.Patroklos said... @ January 9, 2013 at 4:17 AM

Hi Matt
Let me introduce myself. My name is Patroklos Papapetrou and I recently started the scala-topics.org project.
My intention is to create a community with the best content about scala, functional programming, akka etc.
I believe that your articles are really valuable so I invite you to take a look at our partner program and get in touch with me if you're interested.
Looking forward to hearing from you
Regards
Patroklos

Papapetrou P.Patroklos said... @ January 9, 2013 at 4:18 AM

And here is the link http://scala-topics.org/join-us/

Matt Hicks said... @ January 9, 2013 at 7:28 AM

Sandeep, sure, the Session can be overridden to define your own auto-timeout (it defaults to 30 minutes). Additionally, each Webpage has a timeout if it is associated with a stored Scope (Application, Session, or Page). The page will timeout if it hasn't received any data in the timeout period (defaults to 2 minutes). If there's something more specific you'd like to accomplish let me know and I'm sure it can be done.

Matt Hicks said... @ January 9, 2013 at 7:32 AM

Henri, though I agree that Vaadin is still a better abstraction my initial goal was a bare-metal foundation that can be built upon and the hyperscala-ui sub-project provides much more of an abstraction similar to Vaadin. My ultimate goal is to allow development abstraction similar to Vaadin but to not hinder the developer with limitations of what I might have forgotten to consider in my abstraction. In those cases you can always get down to the HTML and CSS to accomplish whatever you need.

jtict said... @ January 9, 2013 at 5:58 PM

Interesting framework. What I like is that it allows you to write HTML using an API and it seem to be easy. Also interesting is that simply adding the Realtime module results in two-way communication.

I don't think that this frameworks falls in the category of GWT and Vaadin, because those are JavaScript outputting frameworks, while HyperScala is based on outputting HTML. (Which allows SEO while Javascript output barely does.) HyperScala is closer to frameworks like Wicket (Java), Lift (Scala), ASP.NET (C#/VB) and maybe JSF (Java) a bit (but JSF is not very flexible when it comes to building HTML using an API).

Interesting in these kinds of framework is how state if transfered over a span of multiple HTML requests to the same page by the same client. In your comment you mention a "stored Scope" with options Application, Session, or Page, where Page has an associated timeout. So your using server sided state to store the state of each page, I assume. (As most frameworks do, using a serversided session.)
It would be interesting if you also give Hyperscala an option to use clientsided state like ASP.NET using its viewstate (where the state is genereted hiddenly in the HTML output that can be transferred back using Javascript), because that would eliminate timeout problems and results in zero serversided memory usage. (But is can give security problems.) Of every more interesting (a new), to use HTML5 webstorage.

I'm also interested in seeing how you can generate custom page elements that are stored in a list. So how loops can be used to output multiple custom page elements. Of even further, how a nested loop can be used when you have for example a list of products to be shown, where each product has a list of tags that you also want to show with each product.
Such problems can often be cumbersome and complex in these kind of frameworks (Wicket, ASP.NET and especially in Lift where functional code can get very complex).

Matt Hicks said... @ January 9, 2013 at 9:04 PM

jtict, there's also Scope.Request that is stateless meaning the page is disposed immediately after rendering to the client. It wouldn't be very difficult to leverage Scope.Request and a Module to add client-side state to Hyperscala as a third-party module. This is what is so great about Hyperscala is you aren't bound by what my limited abilities can fathom and write but only by your willingness to build upon. :)

As far as loops and such go this is actually fairly trivial in Hyperscala since it isn't a templating engine it doesn't even consider those things. However, you have many options for how to handle it:

1.) Generate the HTML via a for loop: results.foreach(r => myDiv.contents += new CustomResult(r))
2.) Use a DynamicContent (as stated above) but do so in a loop instantiating it multiple times into the page instead of just once.
3.) Defer it to JavaScript and send a div back that the JavaScript will dynamically load content into.

There are dozens of other ways to solve the problem, but again, the idea with Hyperscala is to empower the developer, not to push a methodology for solving problems. I provide several options to give suggestions, but if there's another way to solve the problem Hyperscala can accomplish it. :)

Anton Kulaga said... @ April 10, 2013 at 8:08 PM

Rather interesting idea, but implementation looks ugly.
All this multiple content+= and new create a huge mess.
What about doing it more Scalish way?

For instance in ScalaTest you write your test like:

"something" should{
"work somehow" in {
}
}

Matt Hicks said... @ April 10, 2013 at 8:59 PM

@Anton, I'm open to ideas if you have a better approach? I initially designed the scenegraph to be immutable but I quickly had a lot of problems with flexibility and easy manipulation. Please feel free to send me some ideas as I want this to be the best framework it can be.

Post a Comment