exoer on the grill: how to develop nice juzu portlet for exo platform

61
How to develop nice JUZU Portlet for eXo Platform Copyright 2015 eXo Platform

Upload: exo-platform

Post on 16-Jul-2015

9.007 views

Category:

Software


0 download

TRANSCRIPT

How to develop nice

JUZUPortlet for eXo Platform

Copyright 2015 eXo Platform

A presentation

by Tuyen - Portal Team Copyright 2015 eXo Platform

Agenda

Copyright 2015 eXo Platform

Enjoy...

1. Introduction to Juzu2. Juzu feature3. Develop Juzu Portlet for eXo Platform4. Migrate your 0.6.2 Juzu Portlet to 1.0.0

You said

JUZUJuzu what…?

Copyright 2015 eXo Platform

JUZU What…?

Copyright 2015 eXo Platform

Juzu is a Web Framework base on MVC

concepts for developing powerful web/portlets

applications

But… WHY Juzu ? (Too many MVC web framework?)

Copyright 2015 eXo Platform

WHY Juzu ? (Why don’t use existing one)

Copyright 2015 eXo Platform

● All framework target for developing web app

● Too Complex in configuration with XML

● Play framework is simple and good but does not follow JavaEE

standard

Juzu combine idea of Play framework with JavaEE standard and target for developing both Portlet and Web application.

History and technology

Copyright 2015 eXo Platform

● Inspired from Play framework

● Base on MVC concepts

● Modular oriented

● Integrates with IoC frameworks

● Groovy and Mustache template engine

Juzu applications (Chat application)

Copyright 2015 eXo Platform

Juzu applications (homepage and branding portlets)

Copyright 2015 eXo Platform

A review of nice

CONCEPTSof Juzu

Copyright 2015 eXo Platform

Concepts of Juzu

Copyright 2015 eXo Platform

● Simplicity

● Typesafe

● Extensibility

Simplicity

Copyright 2015 eXo Platform

@Inject@Path("index.gtmpl")Template index;

@Viewpublic Response.Content index() { return index.ok();}

<action name="hello" class="com.tutorialspoint.struts2.HelloWorldAction" method="execute"> <result name="success">/HelloWorld.jsp</result> </action>● No more XML

● Use Annotation

Typesafe (Detect error at Compile time)

Copyright 2015 eXo Platform

@Inject@Path("index.gtmpl")package.template.index index;

@Viewpublic Response.Content index() { return index.with().location("Ha Noi").ok();}

@Viewpublic Response.Content more() {...}

#{param name=location/}

You are at ${location}.

<a href="@{Controller.more()}">get more information</a>

Typesafe (Detect error at Compile time)

Copyright 2015 eXo Platform

@Inject@Path("index.gtmpl")package.template.index index;

@Viewpublic Response.Content index() { return index.with().location("Ha Noi").ok();}

@Viewpublic Response.Content more() {...}

#{param name=myLocation/}

You are at ${location}.

<a href="@{Controller.more()}">get more information</a>

compile error

Extensibility (Easy to develop and deliver plugin)

Copyright 2015 eXo Platform

public class AjaxService extends ApplicationService {...}

ajax-plugin.jar

org.exoplatform.commons.juzu.ajax.AjaxService

META-INF/services/juzu.impl.plugin.application.ApplicationService

uses the java.util.ServiceLoader discovery mechanism for finding plugin services

How to develop nice

JUZU PORTLETfor eXo Platform

Copyright 2015 eXo Platform

Develop Juzu portlet

Copyright 2015 eXo Platform

● Create new Juzu project● Controller● Business service and Injector● Template● Asset manager● Plugin: Ajax, WebJar

Create new Juzu project

Copyright 2015 eXo Platform

From maven archetype:mvn archetype:generate \ -DarchetypeGroupId=org.juzu \ -DarchetypeArtifactId=juzu-archetype \ -DarchetypeVersion=1.0.0-cr1 \ -DjuzuServer=gatein \ -DgroupId=org.juzu.tutorial \ -DartifactId=tutorial-juzcret \ -Dversion=1.0.0-SNAPSHOT \ -DinteractiveMode=false

Project structure

Copyright 2015 eXo Platform

WEB-INFapplication deployment descriptor

package-info.javaconfiguration for application

ControllerJuzu controller

templatestemplates used in application

Project structure (JuZcret application)

Copyright 2015 eXo Platform

Juzu Controller (simple controller)

Copyright 2015 eXo Platform

public class JuZcretApplication {...}

@View

public Response.Content index() {

return Response.ok("Hello world!!!");

}

@Application(defaultController = org.juzu.tutorial.JuZcretApplication.class)

package org.juzu.tutorial;

package-info.java

Juzu Service

Copyright 2015 eXo Platform

public interface SecretService {...}

@Application(defaultController = ...)@Bindings({ @Binding( value = org.juzu.tutorial.services.SecretService.class, implementation = org.juzu.tutorial.services.SecretServiceMemImpl.class )})package org.juzu.tutorial;

package-info.java

public class SecretServiceMemImpl implements SecretService {...}

Juzu Service (inject to controller)

Copyright 2015 eXo Platform

public interface SecretService {...}

public class JuZcretApplication { @Inject SecretService secretService;

@Inject @Path("secretWall.gtmpl") templates.secretWall secretWall; ...}

@View

public Response.Content index() {

return secretWall.with()

.secretList(secretService.getScretsList()).ok();}

Juzu Template

Copyright 2015 eXo Platform

public class JuZcretApplication { ... @Inject @Path("secretWall.gtmpl") org.juzu.tutorial.templates.secretWall secretWall; ...}

@View

public Response.Content index() {

return secretWall.with().secretsList("My list of secret").ok();

}

#{param name=secretsList/}Here is my secret list: ${secretsList}

secretWall.gtmpl

Juzu Template (template expression)

Copyright 2015 eXo Platform

@View

public Response.Content index() {

return secretWall.with().secretsList(secretService.getSecrets()).ok();

}

#{param name=secretsList/}

<ul class="secret-wall-list"><% secretsList.each { secret -> %> <li> ${secret.message} </li><%}%></ul>

secretWall.gtmpl

Form and Action controller

Copyright 2015 eXo Platform

<form action="@{JuZcretApplication.addSecret()}" method="POST" role="form">

...

<textarea rows="3" name="msg" placeholder="Write your secret here"></textarea> Image URL: <input name="imgURL" placeholder="..."> ... <button type="submit">Share</button></form>

@Actionpublic Response.View addSecret(String msg, String imgURL) { secretService.addSecret(msg, imgURL); return JuZcretApplication_.index();}

JuZcret application

Copyright 2015 eXo Platform

CSS and Javascript

Copyright 2015 eXo Platform

vs

Asset manager (@Stylesheet and Less plugin)

Copyright 2015 eXo Platform

Less plugin will take care of compiling automatically the Less file to CSS file during the maven compilation

<dependency> <groupId>org.juzu</groupId> <artifactId>juzu-plugins-less4j</artifactId> <version>1.0.0-cr1</version></dependency>

@Less(@Stylesheet("styles/juzcret.less"))

@Stylesheets({@Stylesheet(value = "styles/my.css")})

@Assets("*")

package org.juzu.tutorial;

package-info.java

JuZcret UI

Copyright 2015 eXo Platform

Asset manager (@Script and WebJar plugin)

Copyright 2015 eXo Platform

@WebJars(@WebJar("jquery"))@Scripts({ @Script(id = "jquery", value = "jquery/1.10.2/jquery.js"), @Script(value = "javascripts/secret.js", depends = "jquery")}) @Assets("*")package org.juzu.tutorial;

package-info.java

<dependency> <artifactId>juzu-plugins-webjars</artifactId> <groupId>org.juzu</groupId></dependency>

<dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId></dependency>

Resource Controller

Copyright 2015 eXo Platform

@Resourcepublic Response addComment(String secretId, @Mapped Comment comment, SecurityContext context) { ... Comment result = secretService.addComment(secretId, comment); if (result != null) { return Response.ok(new JSONObject(result).toString()).withMimeType("text/json"); } else { return Response.status(503); }}

@Resource

public Response addLike(String secretId, SecurityContext context) {...}

Controller (map request parameter to Bean types)

Copyright 2015 eXo Platform

@Resourcepublic Response addComment(String secretId, @Mapped Comment comment, SecurityContext context) { ...}

public class Comment extends Model {

private String userId;

private String content;

...

}

Ajax plugin

Copyright 2015 eXo Platform

@Ajax

@Resource

public Response addComment(String secretId, @Mapped Comment comment, SecurityContext context) {...}

$(document).on('click.juzu.secret.addComment', '.btn-comment', function () { ... var jLike = $(this); jLike.jzAjax('JuZcretApplication.addComment()', { data: {...}, success: function (data) { ... } }); return false;});

JuZcret Like and Comment

Copyright 2015 eXo Platform

Internalization and Localization

Copyright 2015 eXo Platform

Juzu support i18n natively in the core. We just need to modify all the labels in all our templates.

<form action="@{JuZcretApplication.enableComment()}" method="POST" role="form">

<h5>&{label.configuration}</h5> <input type="checkbox" name="enableComment" <%=enableComment ? "checked" : "" %>/>

&{label.enableComment} <button type="submit">&{label.save}</button></form>

@InjectResourceBundle bundle;

Controller.java

template.gtmpl

Internalization and Localization

Copyright 2015 eXo Platform

Template (tag)

Copyright 2015 eXo Platform

#{foo}bar#{/foo}

#{foo/}

#{include path=dispatched.gtmpl/}

#{decorate path=box.gtmpl/}

<div style="border: 1px solid black">

#{insert/}

</div>

#{title value=Home/}

#{param name=color/}

Template (Java Custom tag)

Copyright 2015 eXo Platform

public class TitleTag extends TagHandler { public TitleTag() { super("title"); }

@Override public void render(TemplateRenderContext context, Renderable body, Map<String, String> args) throws IOException { String title = args.get("value"); if (title != null) { context.setTitle(title); } body.render(context); }}

Template (Simple Custom tag)

Copyright 2015 eXo Platform

@Application@Tags(@Tag(name = "mytag", path = "mytag.gtmpl"))package my.application;

Hello ${parameters.name}

#{mytag name=”my name”/}

mytag.gtmpl

template

Template (reuse simple custom tag)

Copyright 2015 eXo Platform

custom-tags.jar

my.application.tags.mytag

META-INF/services/juzu.template.TagHandler

@Application@Tags(@Tag(name = "mytag", path = "mytag.gtmpl"))package my.application;

Juzu 1.0

New Features

Copyright 2015 eXo Platform

Juzu 1.0 (new features)

Copyright 2015 eXo Platform

● Asset minification

● Bean validation plugin

● Request parameter types

● JSON responding

● Jackson plugin

● Application error handler

Juzu 1.0 New Features (asset minification)

Copyright 2015 eXo Platform

@Scripts(@Script(value = "jquery.js", minified = "jquery.min.js"))package my.application;

@Scripts(@Script(value = "jquery.js"), minifier = NormalizeJSMinifier.class),package my.application;

Juzu allows to provide a minified version of an asset that will be used in prod run mode

@Scripts(@Script(value = "jquery.js"), minifier = ClosureMinifier.class),package my.application;

On-the-fly minification

Generate minified version at runtime

Juzu 1.0 New Features (asset minification - Less plugin)

Copyright 2015 eXo Platform

In Less plugin: a minify option can be used to minify generated css file. This option will trim the white-space when processing the file

@Less(@Stylesheet(value = "stylesheet.less", minify = true))package my.application;

Juzu 1.0 New Features (Request parameter type)

Copyright 2015 eXo Platform

@Action@Route("/login")public Response login(@Mapped User user) { ...}

@Actionpublic Response.Content sum(Integer left, int right) { ...}

@Viewpublic Response.Content show(@Format("yyyy.MM.dd G 'at' HH:mm:ss z") Date date) throws Exception { ...}

@Viewpublic Response.Content sum(int[] values) { ...}

Primary type

Date time

Bean type Multivalued type

Juzu 1.0 New Features (JSON Responding - too complex in 0.6)

Copyright 2015 eXo Platform

private Response.Content<Stream.Char> createJSONResponse(final Map<String, String> data) { return new Response.Content<Stream.Char>(200, Stream.Char.class) { @Override public String getMimeType() { return "application/json"; }

@Override public void send(Stream.Char stream) throws IOException { stream.append("{"); Iterator<Map.Entry<String, String>> i = data.entrySet().iterator(); while (i.hasNext()) { Map.Entry<String, String> entry = i.next(); stream.append("\"" + entry.getKey() + "\"").append(":").append("\"" + entry.getValue() + "\""); if (i.hasNext()) { stream.append(","); } } stream.append("}"); } }; }}

Juzu 1.0 New Features (JSON Responding - very easily in 1.0.0)

Copyright 2015 eXo Platform

@Resoucespublic Response.Content getResources() { JSONObject json = new JSONObject(); parameters.put("key", "value"); … return Response.ok(json.toString()).withMimeType("application/json");}

Juzu 1.0 New Features (Jackson plugin)

Copyright 2015 eXo Platform

@Actionpublic void post(com.fasterxml.jackson.databind.JsonNode tree) { ...}

@Action@Route("/post")public Response.View action(@Jackson MyObj obj) throws IOException { ...}

The Jackson plugin decodes json entities using the Jackson framework. It can decode to a Jackson native tree or perform mapping to Java object using Jackson mapper.

Juzu 1.0 New Features (Jackson plugin - response JSON)

Copyright 2015 eXo Platform

Producing a JSON response can done using the Jackson plugin. It can encode a native JsonTree or an object using the Jackson mapper.

@[email protected]@Jacksonpublic MyObj index() { return new MyObj("Hello World");}

@[email protected] TreeNode index() { JsonNodeFactory factory = JsonNodeFactory.instance; return factory.factory.textNode("Hello World");}

Juzu 1.0 New Features (Validation)

Copyright 2015 eXo Platform

@View public Response.Content doSomething(@javax.validation.constraints.NotNull String s) { return Response.ok("The parameter 's' should never be null"); }

Juzu provides controller handler parameter validation via the Bean Validation framework.

Juzu 1.0 New Features (Application error handler)

Copyright 2015 eXo Platform

public class ErrorHandler implements Handler<Response.Error, Response> {

@Override public Response handle(Response.Error argument) { return Response.content(500, "An error occured"); }}

@Application(errorController = ErrorHandler.class)package my.application;

@View public Response.Content doSomething(@javax.validation.constraints.NotNull String s) { return Response.ok("The parameter 's' should never be null"); } If validation error

package-info.java

How to

MIGRATEfrom 0.6.2 to 1.0.0

Copyright 2015 eXo Platform

Controller method

Copyright 2015 eXo Platform

Controller method must return Response object

@Viewpublic void index() { index.render(parameters);}

@Viewpublic Response index() { return index.ok(parameters);}

Template#render() is removed

Copyright 2015 eXo Platform

use method juzu.template.Template#ok()

@Viewpublic void index() { index.render(parameters);}

@Viewpublic Response index() { return index.ok(parameters);}

RenderContext is removed

Copyright 2015 eXo Platform

If you want to use these context objects:juzu.request.ApplicationContextjuzu.request.UserContextjuzu.request.SecurityContext….

Just inject them into controller method

@Viewpublic Response.Content index(ApplicationContext applicationContext, SecurityContext securityContext, UserContext userContext){...}

Localization

Copyright 2015 eXo Platform

<form action="@{JuZcretApplication.enableComment()}" method="POST" role="form">

<h5>&{label.configuration}</h5> <input type="checkbox" name="enableComment" <%=enableComment ? "checked" : "" %>/>

&{label.enableComment} <button type="submit">&{label.save}</button></form>

@InjectResourceBundle bundle;

Controller.java

template.gtmpl

class *Plugin is renamed to *Service

Copyright 2015 eXo Platform

public class AjaxService extends ApplicationService {...}

ajax-plugin.jar

org.exoplatform.commons.juzu.ajax.AjaxService

META-INF/services/juzu.impl.plugin.application.ApplicationService

ApplicationPlugin

rename to

META-INF/services/juzu.impl.plugin.application.ApplicationPlugin

rename to

It’s time for

THANK YOUsee you soon ...

Copyright 2015 eXo Platform