You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2018/04/26 15:13:40 UTC

[5/8] tomee git commit: Make a simple test case to wire up everything and start adding a simple UI on top

Make a simple test case to wire up everything and start adding a simple UI on top


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/b4a44e40
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/b4a44e40
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/b4a44e40

Branch: refs/heads/fb_tomee8
Commit: b4a44e401a916985caec4b8ea309fe9ab0cbf7c5
Parents: def443a
Author: Jean-Louis Monteiro <je...@gmail.com>
Authored: Thu Apr 19 23:28:51 2018 +0200
Committer: Jean-Louis Monteiro <je...@gmail.com>
Committed: Thu Apr 19 23:28:51 2018 +0200

----------------------------------------------------------------------
 examples/pom.xml                                |   1 +
 examples/rest-mp-jwt/README.md                  |   0
 examples/rest-mp-jwt/pom.xml                    | 278 +++++++++++++++++++
 .../main/java/org/superbiz/moviefun/Movie.java  | 102 +++++++
 .../java/org/superbiz/moviefun/MoviesBean.java  |  91 ++++++
 .../moviefun/rest/ApplicationConfig.java        |  28 ++
 .../org/superbiz/moviefun/rest/LoadRest.java    |  42 +++
 .../rest/MoviesMPJWTConfigurationProvider.java  |  63 +++++
 .../org/superbiz/moviefun/rest/MoviesRest.java  | 113 ++++++++
 .../java/org/superbiz/rest/GreetingService.java |  41 +++
 .../src/main/resources/META-INF/persistence.xml |  31 +++
 examples/rest-mp-jwt/src/main/tomee/tomee.xml   |  27 ++
 .../rest-mp-jwt/src/main/webapp/WEB-INF/web.xml |  46 +++
 .../rest-mp-jwt/src/main/webapp/app/app.less    |  62 +++++
 .../rest-mp-jwt/src/main/webapp/app/config.js   |  45 +++
 .../src/main/webapp/app/js/application.js       | 193 +++++++++++++
 .../rest-mp-jwt/src/main/webapp/app/js/i18n.js  |  66 +++++
 .../rest-mp-jwt/src/main/webapp/app/js/id.js    |  43 +++
 .../rest-mp-jwt/src/main/webapp/app/js/log.js   |  40 +++
 .../src/main/webapp/app/js/model/movie.js       |  48 ++++
 .../src/main/webapp/app/js/model/movies.js      |  35 +++
 .../rest-mp-jwt/src/main/webapp/app/js/start.js |  29 ++
 .../src/main/webapp/app/js/templates.js         |  69 +++++
 ...pplication-table-paginator-button.handlebars |   1 +
 .../templates/application-table-row.handlebars  |   8 +
 .../app/js/templates/application.handlebars     |  50 ++++
 .../app/js/templates/container.handlebars       |  10 +
 .../app/js/templates/load-data-link.handlebars  |   1 +
 .../webapp/app/js/templates/movie.handlebars    |  56 ++++
 .../app/js/view/application-table-paginator.js  |  77 +++++
 .../webapp/app/js/view/application-table-row.js |  63 +++++
 .../src/main/webapp/app/js/view/application.js  | 135 +++++++++
 .../src/main/webapp/app/js/view/container.js    |  62 +++++
 .../src/main/webapp/app/js/view/movie.js        |  75 +++++
 examples/rest-mp-jwt/src/main/webapp/index.jsp  |  36 +++
 .../java/org/superbiz/moviefun/MoviesTest.java  |  88 ++++++
 .../java/org/superbiz/moviefun/TokenUtils.java  | 257 +++++++++++++++++
 .../org/superbiz/rest/GreetingServiceTest.java  |  61 ++++
 .../resources/META-INF/application-client.xml   |   1 +
 .../rest-mp-jwt/src/test/resources/Token1.json  |  20 ++
 .../rest-mp-jwt/src/test/resources/Token2.json  |  12 +
 .../src/test/resources/arquillian.xml           |  32 +++
 .../src/test/resources/privateKey.pem           |  28 ++
 .../src/test/resources/publicKey.pem            |   9 +
 .../microprofile/jwt/cdi/MPJWTCDIExtension.java |  45 +--
 .../jwt/config/JWTAuthContextInfoProvider.java  |  61 ----
 .../jwt/JWTAuthContextInfoProvider.java         |  63 +++++
 .../jwt/AppDeploymentExtension.java             |   3 +-
 48 files changed, 2646 insertions(+), 101 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index fab0d95..18d4971 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -119,6 +119,7 @@ BROKEN, see TOMEE-2140
     <module>rest-applicationcomposer</module>
     <module>rest-cdi</module>
     <module>rest-jaas</module>
+    <module>rest-mp-jwt</module>
     <module>rest-on-ejb</module>
     <module>rest-example</module>
     <module>rest-example-with-application</module>

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/README.md
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/README.md b/examples/rest-mp-jwt/README.md
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/pom.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/pom.xml b/examples/rest-mp-jwt/pom.xml
new file mode 100644
index 0000000..f2656b3
--- /dev/null
+++ b/examples/rest-mp-jwt/pom.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.superbiz</groupId>
+  <artifactId>rest-mp-jwt</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+  <name>OpenEJB :: Examples :: REST MP-JWT</name>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <tomee.version>8.0.0-SNAPSHOT</tomee.version>
+    <version.shrinkwrap.resolver>2.0.0</version.shrinkwrap.resolver>
+    <mp-jwt.version>1.1-SNAPSHOT</mp-jwt.version>
+  </properties>
+
+  <build>
+    <defaultGoal>install</defaultGoal>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.18.1</version>
+        <configuration>
+          <reuseForks>false</reuseForks>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <version>3.1.0</version>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.5.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.tomee.maven</groupId>
+        <artifactId>tomee-maven-plugin</artifactId>
+        <version>${tomee.version}</version>
+        <configuration>
+          <tomeeClassifier>microprofile</tomeeClassifier>
+          <args>-Xmx512m -XX:PermSize=256m</args>
+          <config>${project.basedir}/src/main/tomee/</config>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencyManagement>
+    <dependencies>
+      <!-- Override dependency resolver with test version. This must go *BEFORE*
+        the Arquillian BOM. -->
+      <dependency>
+        <groupId>org.jboss.shrinkwrap.resolver</groupId>
+        <artifactId>shrinkwrap-resolver-bom</artifactId>
+        <version>${version.shrinkwrap.resolver}</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+      <!-- Now pull in our server-based unit testing framework -->
+      <dependency>
+        <groupId>org.jboss.arquillian</groupId>
+        <artifactId>arquillian-bom</artifactId>
+        <version>1.0.3.Final</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <repositories>
+    <repository>
+      <id>apache-m2-snapshot</id>
+      <name>Apache Snapshot Repository</name>
+      <url>https://repository.apache.org/content/groups/snapshots</url>
+    </repository>
+  </repositories>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>javaee-api</artifactId>
+      <version>8.0-SNAPSHOT</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.microprofile.jwt</groupId>
+      <artifactId>microprofile-jwt-auth-api</artifactId>
+      <version>${mp-jwt.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.nimbusds</groupId>
+      <artifactId>nimbus-jose-jwt</artifactId>
+      <version>4.23</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+
+    <!--
+    The <scope>test</scope> guarantees that non of your runtime
+    code is dependent on any OpenEJB classes.
+    -->
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>openejb-cxf-rs</artifactId>
+      <version>${tomee.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>openejb-core</artifactId>
+      <version>${tomee.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.arquillian.junit</groupId>
+      <artifactId>arquillian-junit-container</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.shrinkwrap.resolver</groupId>
+      <artifactId>shrinkwrap-resolver-depchain</artifactId>
+      <type>pom</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomee</groupId>
+      <artifactId>ziplock</artifactId>
+      <version>${tomee.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>backbonejs</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>bootstrap</artifactId>
+      <version>3.1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>handlebars</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>jquery</artifactId>
+      <version>2.1.0-1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>json2</artifactId>
+      <version>20110223</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>less</artifactId>
+      <version>1.6.0-1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>requirejs</artifactId>
+      <version>2.1.10</version>
+    </dependency>
+    <dependency>
+      <groupId>org.webjars</groupId>
+      <artifactId>requirejs-text</artifactId>
+      <version>2.0.10</version>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>arquillian-tomee-embedded</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>arquillian-tomee-embedded</artifactId>
+          <version>${tomee.version}</version>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>tomee-embedded</artifactId>
+          <version>${tomee.version}</version>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>mp-jwt</artifactId>
+          <version>${tomee.version}</version>
+          <scope>provided</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>arquillian-tomee-remote</id>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>arquillian-tomee-remote</artifactId>
+          <version>${tomee.version}</version>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>apache-tomee</artifactId>
+          <version>${tomee.version}</version>
+          <type>zip</type>
+          <classifier>microprofile</classifier>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
+
+  <!--
+  This section allows you to configure where to publish libraries for sharing.
+  It is not required and may be deleted.  For more information see:
+  http://maven.apache.org/plugins/maven-deploy-plugin/
+  -->
+  <distributionManagement>
+    <repository>
+      <id>localhost</id>
+      <url>file://${basedir}/target/repo/</url>
+    </repository>
+    <snapshotRepository>
+      <id>localhost</id>
+      <url>file://${basedir}/target/snapshot-repo/</url>
+    </snapshotRepository>
+  </distributionManagement>
+</project>

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java
new file mode 100644
index 0000000..4e067bb
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/Movie.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@Entity
+@XmlRootElement(name = "movie")
+public class Movie {
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    private long id;
+
+    private String director;
+    private String title;
+    private int year;
+    private String genre;
+    private int rating;
+
+    public Movie() {
+    }
+
+    public Movie(String title, String director, String genre, int rating, int year) {
+        this.director = director;
+        this.title = title;
+        this.year = year;
+        this.genre = genre;
+        this.rating = rating;
+    }
+
+    public Movie(String director, String title, int year) {
+        this.director = director;
+        this.title = title;
+        this.year = year;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getDirector() {
+        return director;
+    }
+
+    public void setDirector(String director) {
+        this.director = director;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public int getYear() {
+        return year;
+    }
+
+    public void setYear(int year) {
+        this.year = year;
+    }
+
+    public String getGenre() {
+        return genre;
+    }
+
+    public void setGenre(String genre) {
+        this.genre = genre;
+    }
+
+    public int getRating() {
+        return rating;
+    }
+
+    public void setRating(int rating) {
+        this.rating = rating;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java
new file mode 100644
index 0000000..2580c9f
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/MoviesBean.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun;
+
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.EntityType;
+import java.util.List;
+
+@Stateless
+public class MoviesBean {
+
+    @PersistenceContext(unitName = "movie-unit")
+    private EntityManager entityManager;
+
+    public Movie find(Long id) {
+        return entityManager.find(Movie.class, id);
+    }
+
+    public void addMovie(Movie movie) {
+        entityManager.persist(movie);
+    }
+
+    public void editMovie(Movie movie) {
+        entityManager.merge(movie);
+    }
+
+    public void deleteMovie(long id) {
+        Movie movie = entityManager.find(Movie.class, id);
+        entityManager.remove(movie);
+    }
+
+    public List<Movie> getMovies(Integer firstResult, Integer maxResults, String field, String searchTerm) {
+        CriteriaBuilder qb = entityManager.getCriteriaBuilder();
+        CriteriaQuery<Movie> cq = qb.createQuery(Movie.class);
+        Root<Movie> root = cq.from(Movie.class);
+        EntityType<Movie> type = entityManager.getMetamodel().entity(Movie.class);
+        if (field != null && searchTerm != null && !"".equals(field.trim()) && !"".equals(searchTerm.trim())) {
+            Path<String> path = root.get(type.getDeclaredSingularAttribute(field.trim(), String.class));
+            Predicate condition = qb.like(path, "%" + searchTerm.trim() + "%");
+            cq.where(condition);
+        }
+        TypedQuery<Movie> q = entityManager.createQuery(cq);
+        if (maxResults != null) {
+            q.setMaxResults(maxResults);
+        }
+        if (firstResult != null) {
+            q.setFirstResult(firstResult);
+        }
+        return q.getResultList();
+    }
+
+    public int count(String field, String searchTerm) {
+        CriteriaBuilder qb = entityManager.getCriteriaBuilder();
+        CriteriaQuery<Long> cq = qb.createQuery(Long.class);
+        Root<Movie> root = cq.from(Movie.class);
+        EntityType<Movie> type = entityManager.getMetamodel().entity(Movie.class);
+        cq.select(qb.count(root));
+        if (field != null && searchTerm != null && !"".equals(field.trim()) && !"".equals(searchTerm.trim())) {
+            Path<String> path = root.get(type.getDeclaredSingularAttribute(field.trim(), String.class));
+            Predicate condition = qb.like(path, "%" + searchTerm.trim() + "%");
+            cq.where(condition);
+        }
+        return entityManager.createQuery(cq).getSingleResult().intValue();
+    }
+
+    public void clean() {
+        entityManager.createQuery("delete from Movie").executeUpdate();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java
new file mode 100644
index 0000000..5a7bd4d
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/ApplicationConfig.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.eclipse.microprofile.auth.LoginConfig;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@ApplicationPath("/rest")
+@LoginConfig(authMethod = "MP-JWT")
+public class ApplicationConfig extends Application {
+    // let the server discover the endpoints
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java
new file mode 100644
index 0000000..6969221
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/LoadRest.java
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.superbiz.moviefun.Movie;
+import org.superbiz.moviefun.MoviesBean;
+
+import javax.ejb.EJB;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+@Path("load")
+public class LoadRest {
+    @EJB
+    private MoviesBean moviesBean;
+
+    @POST
+    public void load() {
+        moviesBean.addMovie(new Movie("Wedding Crashers", "David Dobkin", "Comedy", 7, 2005));
+        moviesBean.addMovie(new Movie("Starsky & Hutch", "Todd Phillips", "Action", 6, 2004));
+        moviesBean.addMovie(new Movie("Shanghai Knights", "David Dobkin", "Action", 6, 2003));
+        moviesBean.addMovie(new Movie("I-Spy", "Betty Thomas", "Adventure", 5, 2002));
+        moviesBean.addMovie(new Movie("The Royal Tenenbaums", "Wes Anderson", "Comedy", 8, 2001));
+        moviesBean.addMovie(new Movie("Zoolander", "Ben Stiller", "Comedy", 6, 2001));
+        moviesBean.addMovie(new Movie("Shanghai Noon", "Tom Dey", "Comedy", 7, 2000));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java
new file mode 100644
index 0000000..3bea531
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesMPJWTConfigurationProvider.java
@@ -0,0 +1,63 @@
+/*
+ *     Licensed to the Apache Software Foundation (ASF) under one or more
+ *     contributor license agreements.  See the NOTICE file distributed with
+ *     this work for additional information regarding copyright ownership.
+ *     The ASF licenses this file to You under the Apache License, Version 2.0
+ *     (the "License"); you may not use this file except in compliance with
+ *     the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *     Unless required by applicable law or agreed to in writing, software
+ *     distributed under the License is distributed on an "AS IS" BASIS,
+ *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *     See the License for the specific language governing permissions and
+ *     limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Optional;
+
+@Dependent
+public class MoviesMPJWTConfigurationProvider {
+
+    @Produces
+    Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
+        JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
+
+        // todo use MP Config to load the configuration
+        contextInfo.setIssuedBy("https://server.example.com");
+
+        final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
+                "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
+                "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
+                "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
+                "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
+                "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
+                "nQIDAQAB";
+        byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+        final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+        final KeyFactory kf = KeyFactory.getInstance("RSA");
+        final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
+
+        contextInfo.setSignerKey(pk);
+
+        return Optional.of(contextInfo);
+    }
+
+    @Produces
+    JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
+        return getOptionalContextInfo().get();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java
new file mode 100644
index 0000000..7020864
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/moviefun/rest/MoviesRest.java
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.moviefun.rest;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+import org.superbiz.moviefun.Movie;
+import org.superbiz.moviefun.MoviesBean;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJB;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.SecurityContext;
+import java.util.List;
+
+@Path("movies")
+@Produces({"application/json"})
+public class MoviesRest {
+
+    @EJB
+    private MoviesBean service;
+
+    @Inject
+    @Claim("raw_token")
+    private ClaimValue<String> rawToken;
+
+    @Inject
+    @Claim("iss")
+    private ClaimValue<String> issuer;
+
+    @Inject
+    @Claim("jti")
+    private ClaimValue<String> jti;
+
+    @Inject
+    private JsonWebToken jwtPrincipal;
+
+    @Context
+    private SecurityContext securityContext;
+
+    @GET
+    @Path("{id}")
+    public Movie find(@PathParam("id") Long id) {
+        return service.find(id);
+    }
+
+    @GET
+    public List<Movie> getMovies(@QueryParam("first") Integer first, @QueryParam("max") Integer max,
+                                 @QueryParam("field") String field, @QueryParam("searchTerm") String searchTerm) {
+        return service.getMovies(first, max, field, searchTerm);
+    }
+
+    @POST
+    @Consumes("application/json")
+    @RolesAllowed("create")
+    public Movie addMovie(Movie movie) {
+        service.addMovie(movie);
+        return movie;
+    }
+
+    @PUT
+    @Path("{id}")
+    @Consumes("application/json")
+    @RolesAllowed("update")
+    public Movie editMovie(
+            @PathParam("id") final long id,
+            Movie movie
+    ) {
+        service.editMovie(movie);
+        return movie;
+    }
+
+    @DELETE
+    @Path("{id}")
+    @RolesAllowed("delete")
+    public void deleteMovie(@PathParam("id") long id) {
+        service.deleteMovie(id);
+    }
+
+    @GET
+    @Path("count")
+    @Produces(MediaType.TEXT_PLAIN)
+    public int count(@QueryParam("field") String field, @QueryParam("searchTerm") String searchTerm) {
+        return service.count(field, searchTerm);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java b/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java
new file mode 100644
index 0000000..eb4434e
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/java/org/superbiz/rest/GreetingService.java
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.rest;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.Locale;
+
+@Path("/greeting")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class GreetingService {
+
+    @GET
+    public String message() {
+        return "Hi Microprofile JWT!";
+    }
+
+    @POST
+    public String lowerCase(final String message) {
+        return message.toLowerCase(Locale.ENGLISH);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml b/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..ec38aaa
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+  <persistence-unit name="movie-unit">
+    <jta-data-source>movieDatabase</jta-data-source>
+    <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
+    <class>org.superbiz.moviefun.Movie</class>
+
+    <properties>
+      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+    </properties>
+  </persistence-unit>
+</persistence>

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/tomee/tomee.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/tomee/tomee.xml b/examples/rest-mp-jwt/src/main/tomee/tomee.xml
new file mode 100644
index 0000000..f25d5f8
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/tomee/tomee.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<tomee>
+  <Resource id="HSQLDB Database" type="DataSource">
+    JdbcDriver org.hsqldb.jdbcDriver
+    JdbcUrl jdbc:hsqldb:file:target/db/moviefun
+    UserName sa
+    Password
+  </Resource>
+</tomee>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml b/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..328247d
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
+  <welcome-file-list>
+    <welcome-file>index.jsp</welcome-file>
+  </welcome-file-list>
+
+  <!-- The trick is to put all your static files under the same directory and map the "default" servlet to it -->
+  <servlet-mapping>
+    <servlet-name>default</servlet-name>
+    <url-pattern>/app/*</url-pattern>
+  </servlet-mapping>
+  <servlet-mapping>
+    <servlet-name>default</servlet-name>
+    <url-pattern>/webjars/*</url-pattern>
+  </servlet-mapping>
+
+  <!-- Any other request will point to the "index.jsp" page. This way Backbone knows how to manage page transitions
+   at the client side in case the user starts the application from a permalink. -->
+  <servlet>
+    <servlet-name>application</servlet-name>
+    <jsp-file>/index.jsp</jsp-file>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>application</servlet-name>
+    <url-pattern>/*</url-pattern>
+  </servlet-mapping>
+
+</web-app>
+

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/app.less
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/app.less b/examples/rest-mp-jwt/src/main/webapp/app/app.less
new file mode 100644
index 0000000..61fd5e2
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/app.less
@@ -0,0 +1,62 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+body {
+  @content-margin-top: 80px;
+
+  .ux-movie-window {
+    .modal-dialog {
+      padding-top: 90px;
+      padding-bottom: 0px;
+    }
+  }
+
+  .ux-landing {
+    margin-top: @content-margin-top;
+  }
+
+  .ux-setup {
+    margin-top: @content-margin-top;
+  }
+
+  .ux-application {
+    margin-top: @content-margin-top;
+
+    .pagination {
+      margin-top: 0px;
+      margin-bottom: 0px;
+    }
+
+    th:last-child {
+      width: 5px;
+    }
+
+    .ux-add-btn {
+      position: absolute;
+      bottom: 20px;
+      right: 30px;
+    }
+
+    a.ux-delete-row:hover, a.ux-edit-row:hover {
+      cursor: hand;
+    }
+
+    .panel-body>.input-group {
+      margin-bottom: 15px;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/config.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/config.js b/examples/rest-mp-jwt/src/main/webapp/app/config.js
new file mode 100644
index 0000000..bbdc5e1
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/config.js
@@ -0,0 +1,45 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+var APP_CONFIG = {
+    baseUrl: window.ux.ROOT_URL,
+    paths: {
+        'text': 'webjars/requirejs-text/2.0.10/text',
+        'lib/less': 'webjars/less/1.6.0/less.min',
+        'lib/jquery': 'webjars/jquery/2.1.0/jquery.min',
+        'lib/bootstrap': 'webjars/bootstrap/3.1.0/js/bootstrap.min',
+        'lib/handlebars': 'webjars/handlebars/1.2.1/handlebars.min',
+        'lib/underscore': 'webjars/underscorejs/1.4.3/underscore-min',
+        'lib/json2': 'webjars/json2/20110223/json2.min',
+        'lib/backbone': 'webjars/backbonejs/1.0.0/backbone'
+    },
+    shim: {
+        'lib/bootstrap': {
+            deps: ['lib/jquery']
+        },
+        'lib/underscore': {
+            exports: '_'
+        },
+        'lib/backbone': {
+            deps: ['lib/jquery', 'lib/json2', 'lib/underscore']
+        },
+        'app/js/templates': {
+            deps: ['lib/underscore', 'app/js/i18n']
+        }
+    }
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/application.js b/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
new file mode 100644
index 0000000..9ec4cab
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/application.js
@@ -0,0 +1,193 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var deps = [
+        'app/js/view/container',
+        'app/js/view/application',
+        'app/js/view/application-table-paginator',
+        'app/js/view/movie',
+        'lib/underscore',
+        'app/js/model/movies',
+        'app/js/model/movie',
+        'app/js/i18n',
+        'lib/less', 'lib/backbone', 'lib/jquery', 'lib/bootstrap'
+    ];
+    define(deps, function (containerView, applicationView, paginator, MovieView, underscore, moviesList, MovieModel) {
+        var max = 5;
+        var appState = {
+            page: null,
+            fieldName: null,
+            fieldValue: null
+        };
+        containerView.render();
+
+        $.ajaxSetup({ cache: false });
+
+        function loadPage(pageNumber, fieldName, fieldValue) {
+            var data = {
+                max: max,
+                first: ((pageNumber - 1) * max)
+            };
+            if (fieldName && fieldValue) {
+                data.field = fieldName;
+                data.searchTerm = fieldValue;
+            }
+            applicationView.setFilter(fieldName, fieldValue);
+            moviesList.fetch({
+                data: data,
+                success: function (result) {
+                    applicationView.addRows(result.models);
+
+                    $.ajax({
+                        url: window.ux.ROOT_URL + 'rest/movies/count/',
+                        method: 'GET',
+                        dataType: 'json',
+                        data: {
+                            field: appState.fieldName,
+                            searchTerm: appState.fieldValue
+                        },
+                        success: function (total) {
+                            var count = Math.ceil(total / max);
+                            paginator.setCount(count);
+                            applicationView.setPaginator(count);
+                        }
+                    });
+                }
+            });
+        }
+
+        function start() {
+            //Starting the backbone router.
+            var Router = Backbone.Router.extend({
+                routes: {
+                    '': 'showApplication',
+                    'application': 'showApplication',
+                    'application/:page': 'showApplication',
+                    'application/:page/:field/:value': 'showApplication'
+                },
+
+                showApplication: function (page, fieldName, fieldValue) {
+                    var me = this;
+                    appState.page = page;
+                    appState.fieldName = fieldName;
+                    appState.fieldValue = fieldValue;
+                    containerView.showView(applicationView);
+                    if (!page || !underscore.isNumber(Number(page))) {
+                        me.showApplication(1);
+                    } else {
+                        loadPage(Number(page), fieldName, fieldValue);
+                        if (fieldName) {
+                            me.navigate('application/' + page + '/' + fieldName + '/' + fieldValue, {
+                                trigger: false
+                            });
+                        } else {
+                            me.navigate('application/' + page, {
+                                trigger: false
+                            });
+                        }
+                    }
+                }
+            });
+            var router = new Router();
+
+            applicationView.on('load-sample', function () {
+                $.ajax({
+                    url: window.ux.ROOT_URL + 'rest/load/',
+                    method: 'POST',
+                    dataType: 'json',
+                    data: {},
+                    success: function (data) {
+                        router.showApplication();
+                    }
+                });
+            });
+
+            applicationView.on('delete', function (data) {
+                data.model.destroy({
+                    success: function () {
+                        router.showApplication(appState.page, appState.fieldName, appState.fieldValue);
+                    }
+                });
+            });
+
+            function showMovieWindow(model) {
+                var view = new MovieView({
+                    model: model
+                });
+                view.render();
+                view.on('save-model', function (data) {
+                    data.model.save({}, {
+                        success: function () {
+                            view.remove();
+                            loadPage(appState.page, appState.fieldName, appState.fieldValue);
+                        }
+                    });
+                });
+                $('body').append(view.$el);
+                view.$el.modal({});
+            }
+
+            applicationView.on('add', function () {
+                showMovieWindow(new MovieModel({}));
+            });
+
+            applicationView.on('edit', function (data) {
+                showMovieWindow(data.model);
+            });
+
+            applicationView.on('filter', function (data) {
+                router.navigate('application/1/' + data.filterType + '/' + data.filterValue, {
+                    trigger: true
+                });
+            });
+
+            applicationView.on('clear-filter', function (data) {
+                router.navigate('application/1', {
+                    trigger: true
+                });
+            });
+
+            paginator.on('go-to-page', function (data) {
+                var page = data.number;
+                if (page === 'last') {
+                    page = paginator.getCount();
+                }
+                router.showApplication(page, appState.fieldName, appState.fieldValue);
+            });
+
+            //Starting the backbone history.
+            Backbone.history.start({
+                pushState: true,
+                root: window.ux.ROOT_URL // This value is set by <c:url>
+            });
+
+            return {
+                getRouter: function () {
+                    return router;
+                }
+            };
+        }
+
+        return {
+            start: start
+        };
+    });
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js b/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
new file mode 100644
index 0000000..2603dec
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/i18n.js
@@ -0,0 +1,66 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ "use strict";
+ */
+
+define(['lib/underscore', 'lib/handlebars', 'app/js/log'], function (underscore) {
+    'use strict';
+
+    var missing = Handlebars.compile('[!{{key}}!]');
+    var messages = {
+        'application.name': 'Moviefun',
+        'load.dada': 'Click here to load sample data',
+        'movies': 'Movies',
+        'title': 'Title',
+        'director': 'Director',
+        'genre': 'Genre',
+        'rating': 'Rating',
+        'year': 'Year',
+        'add.movie': 'Add movie',
+        'movie': 'Movie',
+        'close': 'Close',
+        'save': 'Save',
+
+        'dummy': ''
+    };
+
+    underscore.each(underscore.keys(messages), function (key) {
+        var template = Handlebars.compile(messages[key]);
+        messages[key] = template;
+    });
+
+    var get = function (key, values) {
+        var template = messages[key];
+        var cfg = values;
+        if (!template) {
+            template = missing;
+            cfg = {
+                key: key
+            };
+            window.console.error('Missing i18n message.', key);
+        }
+        return template(cfg);
+    };
+
+    Handlebars.registerHelper('i18n', function (key) {
+        return get(key);
+    });
+
+    return {
+        get: get
+    };
+});

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/id.js b/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
new file mode 100644
index 0000000..fc4c56a
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/id.js
@@ -0,0 +1,43 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ "use strict";
+ */
+
+define(['lib/underscore', 'lib/handlebars'], function (underscore) {
+    'use strict';
+
+    var value = underscore.uniqueId('moviefun_');
+
+    var current = function () {
+        return value;
+    };
+    var next = function () {
+        value = underscore.uniqueId('moviefun_');
+        return value;
+    };
+    Handlebars.registerHelper('id_current', function (key) {
+        return current();
+    });
+    Handlebars.registerHelper('id_next', function (key) {
+        return next();
+    });
+
+    return {
+        current: current,
+        next: next
+    };
+});

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/log.js b/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
new file mode 100644
index 0000000..6e79b98
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/log.js
@@ -0,0 +1,40 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+define([], function () {
+    'use strict';
+
+    var noOp = function () {
+        return ''; // no-op
+    };
+
+    if (!window.console) {
+        window.console = {};
+    }
+
+    function createIfNull(functionName) {
+        if (!window.console[functionName]) {
+            window.console[functionName] = noOp;
+        }
+    }
+
+    createIfNull('error');
+    createIfNull('warn');
+    createIfNull('log');
+    createIfNull('info');
+});

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
new file mode 100644
index 0000000..36be222
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movie.js
@@ -0,0 +1,48 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var deps = ['lib/backbone'];
+    define(deps, function () {
+        var isString = function (obj) {
+            return Object.prototype.toString.call(obj) === '[object String]';
+        };
+        return Backbone.Model.extend({
+            urlRoot: window.ux.ROOT_URL + 'rest/movies',
+            idAttribute: 'id',
+            toJSON: function () {
+                if (!!this.attributes.rating && isString(this.attributes.rating)) {
+                    this.attributes.rating = parseInt(this.attributes.rating, 10);
+                }
+                if (!!this.attributes.year && isString(this.attributes.year)) {
+                    this.attributes.year = parseInt(this.attributes.year, 10);
+                }
+                if (!!this.attributes.id && isString(this.attributes.id)) {
+                    this.attributes.id = parseInt(this.attributes.id, 10);
+                }
+                return this.attributes;
+            },
+            defaults: {
+                rating: 5,
+                year: new Date().getFullYear()
+            }
+        });
+    });
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
new file mode 100644
index 0000000..828d2f8
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/model/movies.js
@@ -0,0 +1,35 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var deps = ['app/js/model/movie', 'lib/backbone'];
+    define(deps, function (Movie) {
+        var Cls = Backbone.Collection.extend({
+            model: Movie,
+            url: window.ux.ROOT_URL + 'rest/movies',
+            parse: function (response) {
+                return response;
+            }
+        });
+        return new Cls();
+    });
+}());
+
+

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/start.js b/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
new file mode 100644
index 0000000..33f7fbd
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/start.js
@@ -0,0 +1,29 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+require.config(APP_CONFIG);
+
+requirejs(['app/js/application'], function (app) {
+    'use strict';
+
+    $(window.document).ready(function () {
+        // all the action is in app
+        app.start();
+    });
+});
+

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js b/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
new file mode 100644
index 0000000..e3f3300
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates.js
@@ -0,0 +1,69 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var files = [
+        'container',
+        'application',
+        'application-table-row',
+        'application-table-paginator-button',
+        'load-data-link',
+        'movie'
+    ];
+
+    function loop(values, callback) {
+        var index;
+        for (index = 0; index < values.length; index += 1) {
+            callback(values[index], index);
+        }
+    }
+
+    // Preparing the "requirements" paths.
+    var requirements = [];
+    loop(files, function (file) {
+        requirements.push('text!app/js/templates/' + file + '.handlebars');
+    });
+
+    define(requirements, function () {
+        var templates = {};
+
+        var myArgs = arguments;
+        loop(files, function (file, i) {
+            templates[file] = Handlebars.compile(myArgs[i]);
+        });
+
+        return {
+            getValue: function (templateName, cfg) {
+                var template = templates[templateName];
+                if (!template) {
+                    throw 'Template not registered. "' + templateName + '"';
+                }
+                var result;
+                if (cfg) {
+                    result = template(cfg);
+                } else {
+                    result = template({});
+                }
+                return result;
+            }
+        };
+    });
+}());
+

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
new file mode 100644
index 0000000..0031aba
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-paginator-button.handlebars
@@ -0,0 +1 @@
+<li><a href="{{pageNumber}}">{{pageText}}</a></li>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
new file mode 100644
index 0000000..dc9bf7c
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application-table-row.handlebars
@@ -0,0 +1,8 @@
+<td><a href="edit" class="ux-edit-row">{{title}}</a></td>
+<td>{{director}}</td>
+<td>{{genre}}</td>
+<td>{{rating}}</td>
+<td>{{year}}</td>
+<td>
+    <a href="delete" class="ux-delete-row"><span class="glyphicon glyphicon-trash"></span></a>
+</td>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
new file mode 100644
index 0000000..f15d1a9
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/application.handlebars
@@ -0,0 +1,50 @@
+<div class="row">
+    <div class="col-md-12">
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <h3 class="panel-title">{{i18n "movies"}}</h3>
+            </div>
+            <div class="panel-body">
+                <div class="input-group">
+                    <div class="input-group-btn">
+                        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
+                            <span class="ux-selected-filter">{{i18n "title"}}</span> <span class="caret"></span>
+                        </button>
+                        <ul class="dropdown-menu" role="menu">
+                            <li><a href="title" class="ux-filter">{{i18n "title"}}</a></li>
+                            <li><a href="director" class="ux-filter">{{i18n "director"}}</a></li>
+                            <li><a href="genre" class="ux-filter">{{i18n "genre"}}</a></li>
+                            <li><a href="rating" class="ux-filter">{{i18n "rating"}}</a></li>
+                            <li><a href="year" class="ux-filter">{{i18n "year"}}</a></li>
+                        </ul>
+                    </div><!-- /btn-group -->
+                    <input type="text" class="form-control ux-filter-field">
+                    <span class="input-group-btn">
+                        <button class="btn btn-primary ux-clear-filter-action" type="button">
+                            <span class="glyphicon glyphicon-remove-circle"></span>
+                        </button>
+                        <button class="btn btn-primary ux-filter-action" type="button">
+                            <span class="glyphicon glyphicon-search"></span>
+                        </button>
+                    </span>
+                </div>
+                <table class="table table-bordered table-striped table-hover">
+                    <thead>
+                    <tr>
+                        <th>{{i18n "title"}}</th>
+                        <th>{{i18n "director"}}</th>
+                        <th>{{i18n "genre"}}</th>
+                        <th>{{i18n "rating"}}</th>
+                        <th>{{i18n "year"}}</th>
+                        <th></th>
+                    </tr>
+                    </thead>
+                    <tbody></tbody>
+                </table>
+                <button type="button" class="btn btn-primary ux-add-btn">{{i18n "add.movie"}}</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
new file mode 100644
index 0000000..dba60dd
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/container.handlebars
@@ -0,0 +1,10 @@
+<div class="navbar navbar-inverse navbar-fixed-top">
+    <div class="container">
+        <div class="navbar-header">
+            <a class="navbar-brand" href="#">{{i18n "application.name"}}</a>
+        </div>
+    </div>
+</div>
+<div class="container">
+    <div class="ux-contentarea"></div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
new file mode 100644
index 0000000..1785578
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/load-data-link.handlebars
@@ -0,0 +1 @@
+<a href="load-data">{{i18n "load.dada"}}</a>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
new file mode 100644
index 0000000..97c511c
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/templates/movie.handlebars
@@ -0,0 +1,56 @@
+<div class="modal-dialog">
+    <div class="modal-content">
+        <div class="modal-header">
+            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+            <h4 class="modal-title">{{i18n "movie"}}</h4>
+        </div>
+        <div class="modal-body">
+            <form class="form-horizontal" role="form">
+                <div class="form-group">
+                    <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "title"}}</label>
+
+                    <div class="col-lg-10">
+                        <input class="form-control ux-title" id="{{id_current}}" placeholder="{{i18n 'title'}}"
+                               type="text" value="{{title}}">
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "director"}}</label>
+
+                    <div class="col-lg-10">
+                        <input class="form-control ux-director" id="{{id_current}}"
+                               type="text" placeholder="{{i18n 'director'}}" value="{{director}}">
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "genre"}}</label>
+
+                    <div class="col-lg-10">
+                        <input class="form-control ux-genre" id="{{id_current}}" placeholder="{{i18n 'genre'}}"
+                               type="text" value="{{genre}}">
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "rating"}}</label>
+
+                    <div class="col-lg-10">
+                        <input class="form-control ux-rating" id="{{id_current}}"
+                               type="number" min="0" max="10" placeholder="{{i18n 'rating'}}" value="{{rating}}">
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label for="{{id_next}}" class="col-lg-2 control-label">{{i18n "year"}}</label>
+
+                    <div class="col-lg-10">
+                        <input class="form-control ux-year" id="{{id_current}}" placeholder="{{i18n 'year'}}"
+                               type="number" min="1900" max="{{currentYear}}" value="{{year}}">
+                    </div>
+                </div>
+            </form>
+        </div>
+        <div class="modal-footer">
+            <button type="button" class="btn btn-default ux-close" data-dismiss="modal">{{i18n "close"}}</button>
+            <button type="button" class="btn btn-primary ux-save" data-dismiss="modal">{{i18n "save"}}</button>
+        </div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
new file mode 100644
index 0000000..c5d2422
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-paginator.js
@@ -0,0 +1,77 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var deps = ['app/js/templates', 'lib/backbone'];
+    define(deps, function (templates) {
+
+        var View = Backbone.View.extend({
+            tagName: 'ul',
+            className: 'pagination',
+
+            count: 0,
+
+            events: {
+                'click a': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    var myLink = $(evt.target);
+                    var href = myLink.attr('href');
+                    me.trigger('go-to-page', {
+                        number: href
+                    });
+                }
+            },
+
+            render: function () {
+                var me = this;
+                me.$el.empty();
+                me.$el.append(templates.getValue('application-table-paginator-button', {
+                    pageNumber: '1',
+                    pageText: '<<'
+                }));
+                var i;
+                for (i = 1; i < me.count + 1; i += 1) {
+                    me.$el.append(templates.getValue('application-table-paginator-button', {
+                        pageNumber: i,
+                        pageText: i
+                    }));
+                }
+                me.$el.append(templates.getValue('application-table-paginator-button', {
+                    pageNumber: 'last',
+                    pageText: '>>'
+                }));
+                return this;
+            },
+
+            setCount: function (count) {
+                var me = this;
+                me.count = count;
+                me.render();
+            },
+
+            getCount: function () {
+                var me = this;
+                return me.count;
+            }
+        });
+        return new View().render();
+    });
+}());

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
new file mode 100644
index 0000000..771a062
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application-table-row.js
@@ -0,0 +1,63 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var deps = ['app/js/templates', 'lib/backbone'];
+    define(deps, function (templates) {
+
+        var View = Backbone.View.extend({
+            tagName: 'tr',
+            events: {
+                'click .ux-delete-row': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    me.trigger('delete', {
+                        model: me.model
+                    });
+                    me.remove();
+                },
+                'click .ux-edit-row': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    me.trigger('edit', {
+                        model: me.model
+                    });
+                }
+            },
+
+            render: function () {
+                var me = this;
+                if (!this.options.isRendered) {
+                    me.$el.empty();
+                    me.$el.append(templates.getValue('application-table-row', {
+                        title: me.model.get('title'),
+                        director: me.model.get('director'),
+                        genre: me.model.get('genre'),
+                        rating: me.model.get('rating'),
+                        year: me.model.get('year')
+                    }));
+                    me.options.isRendered = true;
+                }
+                return this;
+            }
+        });
+        return View;
+    });
+}());

http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
new file mode 100644
index 0000000..7dae6b3
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/application.js
@@ -0,0 +1,135 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    var deps = ['app/js/templates', 'app/js/view/application-table-row', 'app/js/view/application-table-paginator',
+        'lib/underscore', 'app/js/i18n', 'lib/backbone'];
+    define(deps, function (templates, TableRowView, paginator, underscore, i18n) {
+
+        var View = Backbone.View.extend({
+            tagName: 'div',
+            className: 'ux-application',
+
+            loadDataLink: $(templates.getValue('load-data-link', {})),
+
+            filterOption: 'title',
+
+            events: {
+                'click .ux-filter': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    var selected = $(me.$el.find('.ux-selected-filter').get(0));
+                    var myLink = $(evt.target);
+                    me.filterOption = myLink.attr('href');
+                    selected.html(i18n.get(me.filterOption, {}));
+                },
+                'click .ux-filter-action': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    var filterValue = $(me.$el.find('.ux-filter-field').get(0)).val();
+                    filterValue = $.trim(filterValue);
+                    if (filterValue !== '') {
+                        me.trigger('filter', {
+                            filterType: me.filterOption,
+                            filterValue: filterValue
+                        });
+                    }
+                },
+                'click .ux-clear-filter-action': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    me.trigger('clear-filter', {});
+                },
+                'click .ux-application': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    me.trigger('navigate', {
+                        path: 'application'
+                    });
+                },
+                'click .ux-add-btn': function (evt) {
+                    evt.preventDefault();
+                    var me = this;
+                    me.trigger('add', {});
+                }
+            },
+
+            setFilter: function (fieldName, fieldValue) {
+                var field = fieldName;
+                var value = fieldValue;
+                if (!fieldName || $.trim(fieldName) === '') {
+                    field = 'title';
+                    value = '';
+                }
+                var me = this;
+                me.filterOption = field;
+                $(me.$el.find('.ux-selected-filter').get(0)).html(i18n.get(me.filterOption, {}));
+                $(me.$el.find('.ux-filter-field').get(0)).val(value);
+            },
+
+            render: function () {
+                var me = this;
+                if (!this.options.isRendered) {
+                    me.$el.empty();
+                    me.$el.append(templates.getValue('application', {}));
+                    me.loadDataLink.on('click', function (evt) {
+                        evt.preventDefault();
+                        me.trigger('load-sample', {});
+                    });
+                    me.options.isRendered = true;
+                }
+                return this;
+            },
+
+            addRows: function (rows) {
+                var me = this;
+                var tbody = $(me.$el.find('tbody').get(0));
+                tbody.empty();
+                paginator.$el.detach();
+                me.loadDataLink.detach();
+                underscore.each(rows, function (model) {
+                    var row = new TableRowView({
+                        model: model
+                    });
+                    row.on('delete', function (data) {
+                        me.trigger('delete', data);
+                    });
+                    row.on('edit', function (data) {
+                        me.trigger('edit', data);
+                    });
+                    tbody.append(row.render().$el);
+                });
+            },
+
+            setPaginator: function (count) {
+                var me = this;
+                paginator.$el.detach();
+                me.loadDataLink.detach();
+                var table = $(me.$el.find('.table').get(0));
+                if (count) {
+                    table.after(paginator.$el);
+                } else {
+                    table.after(me.loadDataLink);
+                }
+            }
+        });
+        return new View();
+    });
+}());