Wisdom, an awesome java web framework

Few years ago, a friend of mine told me about Play Framework (first version). For me it was a great find, and finally I found the Java web development became “childish” and I began to get serious with it (I wasn’t a Java developer, but a C# and ASP.Net developer). I loved this framework. Then there was the next version, splendid, but less “childish” (I had become a lazy Java developer), so, suddenly, I went to JavaScript (Node, Express, …), except the lack of class, I fell in love with JavaScript. I tried other interesting frameworks as SparkJava, SimpleFramework, … They are very nice and simple but they provide much less “helpers”. We can see them as “micro-frameworks” and I play a lot with them. But no more “wizardry”.

Not long ago, an other friend of mine told me about Wisdom and finally, yesterday, I decided to give it a try. And the first few minutes of use, I had this strange feeling that I had found My Framework!

The use I made of this tool (since yesterday, remember) is probably not orthodox, but I hope it will make you want to go deeper.

I know, my English is creepy, but i try to improve it :).

Above all, the installation

You need Java 7+ (Java 8 is also supported \o/) and a recent version of Maven (3.2.1+). And there is nothing to install because the mvn command of Wisdom build process will download everything (remember, I’m a lazy man ;))

So, create a project

I’m working with OSX and Linux, but you can find more details here (even for Windows developers): http://www.wisdom-framework.org/reference/0.6.1/index.html# _your_first_wisdom_project.

Type this command in a terminal to create a new project:

mvn org.wisdom-framework:wisdom-maven-plugin:0.6.1:create \
 -DgroupId=bob \
 -DartifactId=bob \
 -Dversion=1.0-SNAPSHOT \
 -Dpackage=org.k33g.bob

remark: you have to replace bob and org.k33g.bob with your own data.

The command geberate a directory (bob for me) and project, and now you can open it with your preferred IDE. And launch this to run your application:

cd bob
mvn wisdom:run

Wisdom load all what he needs and then you can open your browser to: http://localhost:9000.

The structure of the project is like that:

Modify WelcomeController

We change only the value of the uri (from "/" to "/welcome"):

@Controller
public class WelcomeController extends DefaultController {

    @View("welcome")
    Template welcome;

    @Route(method = HttpMethod.GET, uri = "/welcome")
    public Result welcome() {
        return ok(render(welcome, "welcome", "Welcome to Wisdom Framework!"));
    }

}

Save it, now if you go to http://localhost:9000 you’ll get a “No route found” message and you find again the welcome page if you go to http://localhost:9000/welcome.

This is the first magic trick!!! Hor reload!, thanks to the watch mode, Wisdom picks up all your code changes immediately! Nice!

Create our own controller and the associated template

I just want a simple html home page. So, create a simple controller IndexController in /src/main/java/org.k33g.bob:

package org.k33g.bob;

import org.wisdom.api.DefaultController;
import org.wisdom.api.annotations.Controller;
import org.wisdom.api.annotations.Route;
import org.wisdom.api.annotations.View;
import org.wisdom.api.http.HttpMethod;
import org.wisdom.api.http.Result;
import org.wisdom.api.templates.Template;

@Controller
public class IndexController extends DefaultController {

  @View("index")
  Template index;

  @Route(method = HttpMethod.GET, uri = "/")
  public Result index() {
    return ok(render(index));
  }
}

Note this, we’ve declared a Template object : index, then we’ve to create a template : index.thl.html in src/main/resources/templates/:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8"/>
  <title>Bob</title>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet" href="/libs/css/bootstrap.css" media="screen"/>
</head>
<body>
  <div class="container">
    <h1>Wisdom SPA</h1>

  </div>

  <script src="/libs/jquery.min.js"></script>
  <script src="/libs/js/bootstrap.min.js"></script>
  <script>
    $(function() {
      $("h1").css("color", "white").css("background-color", "green");
    });
  </script>
</body>
</html>
  • Remark 1: Wisdom uses Thymeleaf Template Engine.
  • Remark 2: Wisdom uses WebJars to provide javascript and css frameworks. Regarding to us, jQuery and Bootstrap are already provided, but you can remove dependencies in you pom.xml file.
  • Remark 3: We’ll see how not to use WebJars, but later.

When you’ve saved your two files, you can just verify that all is OK: just refresh http://localhost:9000. Easy, no!?

Create a Json service

Create a new controller HumansController in /src/main/java/org.k33g.bob:

package org.k33g.bob;

import org.wisdom.api.DefaultController;
import org.wisdom.api.annotations.Controller;
import org.wisdom.api.annotations.Route;
import org.wisdom.api.http.HttpMethod;
import org.wisdom.api.http.Result;

import java.util.LinkedList;
import java.util.List;

@Controller
public class HumansController extends DefaultController {

  private class Human {
    public String firstName;
    public String lastName;

    private Human(String firstName, String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
    }
  }

  private List<Human> humansList = null;

  @Route(method = HttpMethod.GET, uri = "/humans")
  public Result getHumansList() {
    this.humansList =new LinkedList<Human>();
    this.humansList.add(new Human("John", "Doe"));
    this.humansList.add(new Human("Jane", "Doe"));
    this.humansList.add(new Human("Bob", "Morane"));

    return ok(this.humansList).json();

  }
}

You have to save your java file, and now go to http://localhost:9000/humans with your browser, and you’ll get this:

[{"firstName":"John","lastName":"Doe"},{"firstName":"Jane","lastName":"Doe"},{"firstName":"Bob","lastName":"Morane"}]

So, you can modify index.thl.htm:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8"/>
  <title>Bob</title>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet" href="/libs/css/bootstrap.css" media="screen"/>
</head>
<body>
  <div class="container">
    <h1>Wisdom SPA</h1>
    <ul></ul>
  </div>

  <script src="/libs/jquery.min.js"></script>
  <script src="/libs/js/bootstrap.min.js"></script>
  <script>
    $(function() {
      $("h1").css("color", "white").css("background-color", "green");
      var ul = $("ul");

      $.ajax({url: "humans", type: "GET"}).done(function(humans){
        humans.forEach(function(human) {
          ul.append("<li>"+ human.firstName+ " " + human.lastName+ "</li>");
        });
      });

    });
  </script>
</body>
</html>

I’ve only added a list <ul></ul> ans some JavaScript code to call Json service and populate the list. Just refresh http://localhost:9000:

Fine!

Playing with Wisdom and Polymer

I’m a big fan of Polymer, but I need all “core elements” and I’ve not found the necessary webjar for them. First, stop your application, we have to modify pom.xml file, and it requires relaunching the watch mode.

I need Bower to install Polymer and it’s dependencies, so I have to deactivate Google Closure minification (Wisdom automatically minify all javascript files of your project) because Bower load a lot of files and minification is too long.

Deactivate minification

In pom.xml replace

<plugin>
    <groupId>org.wisdom-framework</groupId>
    <artifactId>wisdom-maven-plugin</artifactId>
    <version>0.6.1</version>
    <extensions>true</extensions>
</plugin>

by

<plugin>
    <groupId>org.wisdom-framework</groupId>
    <artifactId>wisdom-maven-plugin</artifactId>
    <version>0.6.1</version>
    <extensions>true</extensions>
    <configuration>
        <skipGoogleClosure>true</skipGoogleClosure>
    </configuration>
</plugin>

you can delete jQuery webjar dependency too:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>2.1.0-2</version>
</dependency>

And you can restart your project (mvn wisdom:run)

Install Polymer

Remark: you need Bower then npm then Nodejs.

Inside this directory: src/main/resources/assets/, create 2 files : .bowerrc and bower.json with these contents:

# .bowerrc

{
  "directory": "bower_components"
}

# bower.json

{
  "name": "wisdom-project",
  "version": "0.0.0",
  "dependencies": {
    "jquery": "~2.1.1",
    "polymer": "Polymer/polymer# ~0.3.3",
    "core-elements": "Polymer/core-elements# ~0.3.3"
  }
}

And type this command: bower install. It will create a sub-directory bower_components with all necessary dependencies to play with Polymer (include jQuery).

First WebComponent

Inside this directory: src/main/resources/assets/, create a new sub-directory : components with a new file humans-list.html with this code:

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="humans-list">
  <template>
    <ul>
      <template repeat="{{humans}}">
        <li>{{firstName}} {{lastName}}</li>
      </template>
    </ul>
  </template>

  <script>
    Polymer("humans-list",{
      ready: function(){
        $.ajax({url: "humans", type: "GET"}).done(function(humans){
          this.humans = humans;
        }.bind(this));
      }
    });
  </script>

</polymer-element>

And go to index.thl.html again, and modify it like this:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8"/>
  <title>Bob</title>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet" href="/libs/css/bootstrap.css" media="screen"/>
</head>
<body>
  <div class="container">
    <h1>Wisdom SPA</h1>

remove <ul></ul> and replace it with <humans-list></humans-list>

    <humans-list></humans-list>
  </div>

change jQuery reference and add polymer platform reference

  <script src="/assets/bower_components/jquery/dist/jquery.min.js"></script>
  <script src="/assets/bower_components/platform/platform.js"></script>

  <script src="/libs/js/bootstrap.min.js"></script>

add reference to our new WebComponent humans-list

  <!-- my components -->
  <link rel="import" href="/assets/components/humans-list.html"/>

remove jQuery ajax call

  <script>
    $(function() {
      $("h1").css("color", "white").css("background-color", "orange");
    });
  </script>
</body>
</html>

Refresh your page:

I think I’ve found THE Best Candidate to serve my Single Page Applications :)

blog comments powered by Disqus

Related posts