├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── build.gradle
├── docs
├── dials.png
├── java8react.png
├── sidebar.png
├── tables.png
└── thumbnail.png
├── package.json
├── pom.xml
└── src
├── main
├── java
│ └── me
│ │ └── roybailey
│ │ ├── http
│ │ ├── DemoService.java
│ │ ├── JsonTransformer.java
│ │ ├── JsonUtil.java
│ │ ├── ReactController.java
│ │ ├── RestResponse.java
│ │ ├── RestfulController.java
│ │ └── RestfulService.java
│ │ ├── model
│ │ ├── Task.java
│ │ └── TaskMeta.java
│ │ └── service
│ │ ├── DemoTaskService.java
│ │ └── TaskService.java
├── js
│ ├── app.js
│ ├── dashboard.js
│ └── nashorn-polyfill.js
├── jsx
│ ├── app.jsx
│ └── dashboard.jsx
└── resources
│ ├── demodata
│ └── DemoTaskService.json
│ ├── log4j.properties
│ └── webapp
│ ├── admin.html
│ ├── assets
│ ├── DT_bootstrap.css
│ ├── DT_bootstrap.js
│ ├── dashboard.html
│ ├── form-validation.js
│ ├── scripts.js
│ └── styles.css
│ ├── bootstrap
│ ├── css
│ │ ├── bootstrap-responsive.css
│ │ ├── bootstrap-responsive.min.css
│ │ ├── bootstrap.css
│ │ └── bootstrap.min.css
│ ├── img
│ │ ├── glyphicons-halflings-white.png
│ │ └── glyphicons-halflings.png
│ └── js
│ │ ├── bootstrap.js
│ │ └── bootstrap.min.js
│ ├── bundle.min.js
│ ├── easypiechart
│ ├── examples
│ │ ├── excanvas.js
│ │ ├── index.html
│ │ └── style.css
│ ├── jquery.easy-pie-chart.css
│ └── jquery.easy-pie-chart.js
│ ├── index.html
│ ├── jquery
│ ├── jquery-1.9.1.js
│ └── jquery-1.9.1.min.js
│ └── react
│ ├── JSXTransformer.js
│ ├── react-with-addons.js
│ ├── react-with-addons.min.js
│ ├── react.js
│ └── react.min.js
└── test
└── java
└── me
└── roybailey
└── http
├── RestResponseTest.java
└── RestfulControllerTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
14 | .idea
15 | .gradle
16 | .module-cache
17 | build/
18 | target/
19 | node_modules/
20 |
21 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 | grunt.loadNpmTasks('grunt-curl');
3 | grunt.loadNpmTasks('grunt-contrib-less');
4 | grunt.loadNpmTasks('grunt-contrib-watch');
5 | grunt.loadNpmTasks('grunt-contrib-jshint');
6 | grunt.loadNpmTasks('grunt-contrib-uglify');
7 | grunt.loadNpmTasks('grunt-contrib-copy');
8 | grunt.loadNpmTasks('grunt-react');
9 |
10 | grunt.initConfig({
11 | pkg: grunt.file.readJSON('package.json'),
12 |
13 | curl: {
14 | 'google-fonts-source': {
15 | src: 'http://fonts.googleapis.com/css?family=Lato:400,300,300italic,400italic,700,700italic',
16 | dest: 'src/main/resources/webapp/assets/google-fonts-lato.css'
17 | }
18 | },
19 |
20 | less: {
21 | development: {
22 | options: {
23 | paths: ["public/css"]
24 | },
25 | files: {
26 | "public/css/style.css": "public/css/less/style.less"
27 | }
28 | }
29 | },
30 |
31 | watch: {
32 | jsx: {
33 | files: 'src/main/jsx/*.jsx',
34 | tasks: 'react'
35 | },
36 | uglify: {
37 | files: 'src/main/js/*.js',
38 | tasks: 'uglify'
39 | }
40 | },
41 |
42 | jshint: {
43 | files: [
44 | '*.js'
45 | ],
46 | options: {
47 | expr: true,
48 | globals: {
49 | jQuery: true,
50 | console: true,
51 | module: true,
52 | document: true
53 | }
54 | }
55 | },
56 |
57 | uglify: {
58 | options: {
59 | mangle: {
60 | except: ['jQuery', 'Backbone']
61 | }
62 | },
63 | bundle: {
64 | files: {
65 | 'src/main/resources/webapp/bundle.min.js': [
66 | 'src/main/js/nashorn-polyfill.js',
67 | 'node_modules/react/dist/react.js',
68 | 'node_modules/moment/min/moment.min.js',
69 | 'src/main/js/app.js',
70 | 'src/main/js/dashboard.js'
71 | ]
72 | }
73 | }
74 | },
75 |
76 | copy: {
77 | main: {
78 | files: [
79 | // includes files within path
80 | {
81 | expand: true,
82 | cwd: 'node_modules/react/dist/',
83 | src: ['*'],
84 | dest: 'src/main/resources/webapp/react/',
85 | filter: 'isFile',
86 | flatten: true
87 | },
88 |
89 | // includes files within path and its sub-directories
90 | //{
91 | // expand: false,
92 | // src: ['node_modules/react/dist/**'],
93 | // dest: 'src/main/resources/webapp/react/'
94 | //},
95 |
96 | // makes all src relative to cwd
97 | // {expand: true, cwd: 'path/', src: ['**'], dest: 'dest/'},
98 |
99 | // flattens results to a single level
100 | // {expand: true, flatten: true, src: ['path/**'], dest: 'dest/', filter: 'isFile'},
101 | ]
102 | }
103 | },
104 |
105 | react: {
106 | mappings: {
107 | files: [
108 | {
109 | expand: true,
110 | cwd: 'src/main/jsx',
111 | src: ['**/*.jsx'],
112 | dest: 'src/main/js',
113 | ext: '.js'
114 | }
115 | ]
116 | }
117 | }
118 | });
119 | };
120 |
121 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Roy Bailey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SparkJava Retrofit React Demonstration
2 |
3 | > ___A Java 8 web application using lightweight frameworks and [ReactJS](https://facebook.github.io/react/) for the UI___
4 |
5 |
6 |
7 | ## Basic Idea
8 |
9 | A Java 8 process with an embedded rest-api and web application, where the web application user interface is constructed using the React JavaScript components via the Nashorn engine with access to Java services.
10 |
11 |
12 | ## Dependencies
13 |
14 | SparkJava and Guava keep the overall dependencies lightweight (not even a single spring library here).
15 |
16 |
17 | * **[SparkJava](http://sparkjava.com/)** - A minimalist Java 8 web application framework
18 | * **[Retrofit](http://square.github.io/retrofit/)** - A type-safe REST client for Java
19 | * **[ReactJS](http://facebook.github.io/react/)** - A Javascript library for building user interfaces
20 | * **[Bootstrap-Admin-Theme](https://github.com/VinceG/Bootstrap-Admin-Theme)** - A web dashboard courtesy of Vincent Gabriel
21 | * **[JMustache](https://github.com/samskivert/jmustache)** - A Java template engine
22 |
23 | Also using **[Quava](https://code.google.com/p/guava-libraries/)** and a choice of **[Gradle](http://gradle)** or **[Maven](http://maven.apache.org)** for Java builds.
24 |
25 |
26 | ## Taking it for a spin
27 |
28 | Make sure you have `JDK 1.8.0_05-b13` or above.
29 |
30 | command | description
31 | --------|------------
32 | `gradle build` | to compile and run the tests
33 | `mvn clean install` | to compile and run the tests
34 | `grunt watch` | compile jsx into js resource (from `src/main/jsx` into `src/main/js`)
35 | [`DemoService`](src/main/java/me/roybailey/http/DemoService.java) | Start Web Application [http://localhost:4545](http://localhost:4545)
36 |
37 | Alternatively run the `gradle installApp` command to create a runnable distribution package in `build/install/sparkjava-retrofit-react` and run the appropriate script in the `bin` folder.
38 |
39 | > These dials are using a JavaScript charting library but are rendered using ReactJS with data from Java:
40 |
41 | 
42 |
43 | > These tables are rendered using ReactJS with data from Java, one table uses a Java service with direct access to the data store, the other Java service calls the rest-api from within Java to obtain the same data:
44 |
45 | 
46 |
47 | _the `?skip=2&limit=4` parameters on the request URL are passed into ReactJS and back to Java services_
48 |
49 |
50 | ## License
51 |
52 | [`MIT license`](LICENSE)
53 |
54 |
55 |
56 | ## Overview
57 |
58 | ##### The REST api
59 |
60 | The rest-api provides a simple (yet richer than the usual todo list) [`task`](src/main/java/me/roybailey/model/Task.java) data model encapsulated behind a [TaskService interface](src/main/java/me/roybailey/service/TaskService.java) (the typical Data-Access-Object pattern). For the purpose of this exercise the tasks are seeded from a small sample of data and kept in-memory. There are only a couple of read operations defined as the main focus is to render data. However, this Data-Access-Object implementation could be swapped out for any Java based database or messaging connection and enriched to include fully functional CRUD (create, read, update, delete) functionality.
61 |
62 | > See [`RestfulController`](src/main/java/me/roybailey/http/RestfulController.java)
63 |
64 |
65 | ##### The User Interface
66 |
67 | The first version of [Bootstrap-Admin-Theme](https://github.com/VinceG/Bootstrap-Admin-Theme) is purely a static copy of the original with the dashboard sidebar changed to provide the menu of demonstration links. Useful for showing how rich static content can be rendered easily with [SparkJava](http://sparkjava.com/).
68 |
69 | 
70 |
71 | The second version is the [Dashboard content rendered by ReactJS](src/main/jsx/dashboard.jsx), with a [minimal HTML template](src/main/resources/webapp/assets/dashboard.html) to keep the surrounding page `
12 |
13 |
16 |
17 |
18 |
19 |
131 |
132 |
133 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
Success
156 | Cut down static demo of Dashboard Loaded Successfully
157 |
158 |
159 |
160 |
161 |
163 |
166 | -
167 | Dashboard /
168 |
169 | -
170 | Settings /
171 |
172 | - Tools
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
186 |
187 |
188 |
73%
189 |
Visitors
190 |
191 |
192 |
193 |
194 |
53%
195 |
Page Views
196 |
197 |
198 |
199 |
200 |
83%
201 |
Users
202 |
203 |
204 |
205 |
206 |
13%
207 |
Orders
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
225 |
226 |
227 |
228 |
229 | # |
230 | First Name |
231 | Last Name |
232 | Username |
233 |
234 |
235 |
236 |
237 | 1 |
238 | Mark |
239 | Otto |
240 | @mdo |
241 |
242 |
243 | 2 |
244 | Jacob |
245 | Thornton |
246 | @fat |
247 |
248 |
249 | 3 |
250 | Vincent |
251 | Gabriel |
252 | @gabrielva |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
269 |
270 |
271 |
272 |
273 | # |
274 | Product |
275 | Date |
276 | Amount |
277 |
278 |
279 |
280 |
281 | 1 |
282 | Coat |
283 | 02/02/2013 |
284 | $25.12 |
285 |
286 |
287 | 2 |
288 | Jacket |
289 | 01/02/2013 |
290 | $335.00 |
291 |
292 |
293 | 3 |
294 | Shoes |
295 | 01/02/2013 |
296 | $29.99 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
315 |
316 |
317 |
318 |
319 | # |
320 | First Name |
321 | Last Name |
322 | Username |
323 |
324 |
325 |
326 |
327 | 1 |
328 | Mark |
329 | Otto |
330 | @mdo |
331 |
332 |
333 | 2 |
334 | Jacob |
335 | Thornton |
336 | @fat |
337 |
338 |
339 | 3 |
340 | Vincent |
341 | Gabriel |
342 | @gabrielva |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
359 |
360 |
361 |
362 |
363 | # |
364 | Date |
365 | Amount |
366 |
367 |
368 |
369 |
370 | 1 |
371 | 02/02/2013 |
372 | $25.12 |
373 |
374 |
375 | 2 |
376 | 01/02/2013 |
377 | $335.00 |
378 |
379 |
380 | 3 |
381 | 01/02/2013 |
382 | $29.99 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
397 |
398 |
399 |
400 |
401 |
402 |
408 |
409 |
410 |