├── .bowerrc
├── .gitignore
├── .travis.yml
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── package.json
├── pom.xml
└── src
├── main
├── .gitignore
├── java
│ └── net
│ │ └── egemsoft
│ │ └── mvc
│ │ └── controller
│ │ └── HomeController.java
├── resources
│ └── spring
│ │ ├── bootstrap.xml
│ │ └── context-web.xml
├── webapp
│ └── WEB-INF
│ │ └── web.xml
└── webappResources
│ ├── .gitignore
│ ├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
│ ├── images
│ └── .gitignore
│ ├── index.html
│ ├── scripts
│ ├── app.js
│ ├── controllers
│ │ └── home.js
│ ├── directives
│ │ └── .gitignore
│ ├── filters
│ │ └── .gitignore
│ └── services
│ │ └── .gitignore
│ ├── styles
│ └── main.css
│ └── views
│ └── home.html
└── test
└── javascript
├── karma.conf.js
└── spec
├── controllers
└── home.js
├── directives
└── .gitignore
├── filters
└── .gitignore
└── services
└── .gitignore
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "src/main/webappResources/bower_components"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | node
3 | .idea
4 | *.iml
5 | docs
6 | target
7 | .tmp
8 | coverage
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
4 |
5 | module.exports = function (grunt) {
6 | require('load-grunt-tasks')(grunt);
7 | require('time-grunt')(grunt);
8 |
9 | grunt.initConfig({
10 | appConfig: {
11 | // configurable paths
12 | app: require('./bower.json').appPath || 'app',
13 | name: 'Spring MVC Angular',
14 | dist: 'src/main/webappDist',
15 | webapp: 'src/main/webappResources'
16 | },
17 | watch: {
18 | styles: {
19 | files: ['<%= appConfig.webapp %>/styles/{,*/}*.css'],
20 | tasks: ['copy:styles', 'autoprefixer']
21 | },
22 | livereload: {
23 | options: {
24 | livereload: 35729
25 | },
26 | files: [
27 | '<%= appConfig.webapp %>/{,*/}*.html',
28 | '.tmp/styles/{,*/}*.css',
29 | '{.tmp/,}<%= appConfig.webapp %>/scripts/{,*/}*.js',
30 | '<%= appConfig.webapp %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
31 | ]
32 | }
33 | },
34 | autoprefixer: {
35 | options: ['last 1 version'],
36 | dist: {
37 | files: [{
38 | expand: true,
39 | cwd: '.tmp/styles/',
40 | src: '{,*/}*.css',
41 | dest: '.tmp/styles/'
42 | }]
43 | }
44 | },
45 | connect: {
46 | proxies: [
47 | {
48 | context: '/',
49 | host: 'localhost',
50 | port: 8080,
51 | https: false,
52 | changeOrigin: false
53 | },
54 | ],
55 | options: {
56 | port: 9000,
57 | // Change this to 'localhost' to deny access to the server from outside.
58 | hostname: '0.0.0.0',
59 | livereload: 35729
60 | },
61 | livereload: {
62 | options: {
63 | open: true,
64 | base: [
65 | '.tmp',
66 | '<%= appConfig.webapp %>'
67 | ],
68 | middleware: function (connect) {
69 | return [
70 | proxySnippet,
71 | connect.static(require('path').resolve('<%= appConfig.webapp %>'))
72 | ];
73 | }
74 | }
75 | },
76 | test: {
77 | options: {
78 | port: 9001,
79 | base: [
80 | '.tmp',
81 | 'test',
82 | '<%= appConfig.webapp %>'
83 | ]
84 | }
85 | },
86 | dist: {
87 | options: {
88 | base: '<%= appConfig.dist %>'
89 | }
90 | }
91 | },
92 | clean: {
93 | dist: {
94 | files: [{
95 | dot: true,
96 | src: [
97 | '.tmp',
98 | '<%= appConfig.dist %>/*',
99 | '!<%= appConfig.dist %>/.git*'
100 | ]
101 | }]
102 | },
103 | server: '.tmp',
104 | bower: '<%= appConfig.webapp %>/bower_components'
105 | },
106 | jshint: {
107 | options: {
108 | jshintrc: '.jshintrc'
109 | },
110 | all: [
111 | 'Gruntfile.js',
112 | '<%= appConfig.webapp %>/scripts/{,*/}*.js'
113 | ]
114 | },
115 | coffee: {
116 | options: {
117 | sourceMap: true,
118 | sourceRoot: ''
119 | },
120 | dist: {
121 | files: [{
122 | expand: true,
123 | cwd: '<%= appConfig.webapp %>/scripts',
124 | src: '{,*/}*.coffee',
125 | dest: '.tmp/scripts',
126 | ext: '.js'
127 | }]
128 | },
129 | test: {
130 | files: [{
131 | expand: true,
132 | cwd: 'test/spec',
133 | src: '{,*/}*.coffee',
134 | dest: '.tmp/spec',
135 | ext: '.js'
136 | }]
137 | }
138 | },
139 | // not used since Uglify task does concat,
140 | // but still available if needed
141 | /*concat: {
142 | dist: {}
143 | },*/
144 | // Automatically inject Bower components into the app
145 | bowerInstall: {
146 | app: {
147 | src: ['<%= appConfig.webapp %>/index.html'],
148 | ignorePath: '<%= appConfig.app %>/'
149 | }
150 | },
151 | rev: {
152 | dist: {
153 | files: {
154 | src: [
155 | '<%= appConfig.dist %>/scripts/{,*/}*.js',
156 | '<%= appConfig.dist %>/styles/{,*/}*.css',
157 | '<%= appConfig.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
158 | '<%= appConfig.dist %>/fonts/*'
159 | ]
160 | }
161 | }
162 | },
163 | useminPrepare: {
164 | html: '<%= appConfig.webapp %>/{,*/}*.html',
165 | options: {
166 | dest: '<%= appConfig.dist %>'
167 | }
168 | },
169 | usemin: {
170 | html: ['<%= appConfig.dist %>/{,*/}*.html'],
171 | css: ['<%= appConfig.dist %>/styles/{,*/}*.css'],
172 | options: {
173 | dirs: ['<%= appConfig.dist %>']
174 | }
175 | },
176 | imagemin: {
177 | dist: {
178 | files: [{
179 | expand: true,
180 | cwd: '<%= appConfig.webapp %>/images',
181 | src: '{,*/}*.{jpg,jpeg}', // we don't optimize PNG files as it doesn't work on Linux. If you are not on Linux, feel free to use '{,*/}*.{png,jpg,jpeg}'
182 | dest: '<%= appConfig.dist %>/images'
183 | }]
184 | }
185 | },
186 | svgmin: {
187 | dist: {
188 | files: [{
189 | expand: true,
190 | cwd: '<%= appConfig.webapp %>/images',
191 | src: '{,*/}*.svg',
192 | dest: '<%= appConfig.dist %>/images'
193 | }]
194 | }
195 | },
196 | cssmin: {
197 | // By default, your `index.html` will take care of
198 | // minification. This option is pre-configured if you do not wish to use
199 | // Usemin blocks.
200 | // dist: {
201 | // files: {
202 | // '<%= appConfig.dist %>/styles/main.css': [
203 | // '.tmp/styles/{,*/}*.css',
204 | // 'styles/{,*/}*.css'
205 | // ]
206 | // }
207 | // }
208 | },
209 | htmlmin: {
210 | dist: {
211 | options: {
212 | /*removeCommentsFromCDATA: true,
213 | // https://github.com/appConfig/grunt-usemin/issues/44
214 | //collapseWhitespace: true,
215 | collapseBooleanAttributes: true,
216 | removeAttributeQuotes: true,
217 | removeRedundantAttributes: true,
218 | useShortDoctype: true,
219 | removeEmptyAttributes: true,
220 | removeOptionalTags: true*/
221 | },
222 | files: [{
223 | expand: true,
224 | cwd: '<%= appConfig.webapp %>',
225 | src: ['*.html', 'views/*.html'],
226 | dest: '<%= appConfig.dist %>'
227 | }]
228 | }
229 | },
230 | // Put files not handled in other tasks here
231 | copy: {
232 | dist: {
233 | files: [{
234 | expand: true,
235 | dot: true,
236 | cwd: '<%= appConfig.webapp %>',
237 | dest: '<%= appConfig.dist %>',
238 | src: [
239 | '*.{ico,png,txt}',
240 | '.htaccess',
241 | 'images/{,*/}*.{png,gif,webp}',
242 | 'fonts/*'
243 | ]
244 | }, {
245 | expand: true,
246 | cwd: '.tmp/images',
247 | dest: '<%= appConfig.dist %>/images',
248 | src: [
249 | 'generated/*'
250 | ]
251 | }]
252 | },
253 | styles: {
254 | expand: true,
255 | cwd: '<%= appConfig.webapp %>/styles',
256 | dest: '.tmp/styles/',
257 | src: '{,*/}*.css'
258 | }
259 | },
260 | concurrent: {
261 | server: [
262 | 'copy:styles'
263 | ],
264 | test: [
265 | 'copy:styles'
266 | ],
267 | dist: [
268 | 'copy:styles',
269 | 'imagemin',
270 | 'svgmin',
271 | 'htmlmin'
272 | ]
273 | },
274 | karma: {
275 | unit: {
276 | configFile: 'src/test/javascript/karma.conf.js',
277 | singleRun: true
278 | }
279 | },
280 | cdnify: {
281 | dist: {
282 | html: ['<%= appConfig.dist %>/*.html']
283 | }
284 | },
285 | ngmin: {
286 | dist: {
287 | files: [{
288 | expand: true,
289 | cwd: '.tmp/concat/scripts',
290 | src: '*.js',
291 | dest: '.tmp/concat/scripts'
292 | }]
293 | }
294 | },
295 | uglify: {
296 | dist: {
297 | files: {
298 | '<%= appConfig.dist %>/scripts/scripts.js': [
299 | '<%= appConfig.dist %>/scripts/scripts.js'
300 | ]
301 | }
302 | }
303 | },
304 | ngdocs: {
305 | options: {
306 | dest: 'docs/javascript',
307 | html5Mode: false,
308 | title: '<%= appConfig.name %> Documentation'
309 | },
310 | all: ['<%= appConfig.webapp %>/scripts/{,*/}*.js']
311 | }
312 | });
313 |
314 | grunt.registerTask('serve', function (target) {
315 | if (target === 'dist') {
316 | return grunt.task.run(['build', 'connect:dist:keepalive']);
317 | }
318 |
319 | grunt.task.run([
320 | 'clean:server',
321 | 'concurrent:server',
322 | 'autoprefixer',
323 | 'configureProxies',
324 | 'connect:livereload',
325 | 'watch'
326 | ]);
327 | });
328 |
329 | grunt.registerTask('test', [
330 | 'clean:server',
331 | 'concurrent:test',
332 | 'autoprefixer',
333 | 'connect:test',
334 | 'karma'
335 | ]);
336 |
337 | grunt.registerTask('build', [
338 | 'clean:dist',
339 | 'bowerInstall',
340 | 'useminPrepare',
341 | 'concurrent:dist',
342 | 'autoprefixer',
343 | 'concat',
344 | 'copy:dist',
345 | 'ngmin',
346 | 'cssmin',
347 | 'uglify',
348 | 'rev',
349 | 'usemin'
350 | ]);
351 |
352 | grunt.registerTask('default', [
353 | 'test',
354 | 'build'
355 | ]);
356 | };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Egemsoft
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
13 | all 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
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Spring MVC Angular JS Seed Project [](https://travis-ci.org/egemsoft/spring-mvc-angular)
2 | -----------------------
3 |
4 | This is a one handy seed project includes Spring Framework, Spring MVC, Maven, Angular JS with both Java and Javascript tests.
5 |
6 | 
7 |
8 | ##Install
9 | Project has various dependencies managed through Maven, NPM and Bower. Luckily they have all connected in Maven with frontend-maven-plugin.
10 |
11 | To install all dependencies and run tests run:
12 | ```
13 | $ mvn install
14 | ```
15 | This command builds the application with default dev profile.
16 | There are two profiles that build cycles include: `dev` (development) and `prod` (production). Each profile has its own build scenarios.
17 |
18 | To install with explicit profile run `mvn install -P dev|prod`.
19 |
20 | ####Build cycle for dev profile
21 |
22 | - Install Node and npm locally (If not installed).
23 | - Install Node dependencies.
24 | - npm runs `bower install` after dependency installation. See `package.json`.
25 | - Install Bower dependencies.
26 | - Run Javascript tests and code coverage tool.
27 | - Run Java tests with surefire.
28 | - Compile and build WAR file.
29 |
30 | ####Build cycle for prod profile
31 |
32 | Difference between dev and prod profiles is, Javascript files are **built** in prod profile unlike dev. After running Javascript tests all javascript files are minified, concatenated, revved and prepared to the production, thanks to the various Grunt plugins. Please see the `build` task in `Gruntfile.js`.
33 | All the other steps are applied here too.
34 |
35 | ##App Structure
36 | ```
37 | coverage/ - Code coverage results
38 | docs/
39 | javascript - Javascript documentations created with ngdoc
40 | java - Java documentations
41 | src/
42 | main/
43 | java/
44 | resources/
45 | webapp/ - Web app source files
46 | fonts/
47 | images/
48 | scripts/
49 | controllers/ - Angular controller files - each controller in one file (HomeCtrl -> home.js)
50 | directives/ - Angular directive files
51 | filters/ - Angular filter files
52 | services/ - Angular service and factory files
53 | app.js - Main Angular module
54 | style/ - Stylesheets
55 | views/ - Angular JS partial views
56 | test/
57 | java/ - Java tests
58 | javascript/
59 | spec/ - Javascript unit tests tests are placed into relevant subdirectory
60 | controllers/
61 | directives/
62 | filters/
63 | services/
64 | karma.conf.js - Karma configuration
65 | .bowerrc - Bower directory configuration
66 | bower.json - Bower configuration including dependencies
67 | Gruntfile.js - Grunt tasks configuration
68 | package.json - Node configuration including dependencies managed by npm
69 | pom.xml - Maven configuration
70 | ```
71 |
72 | ##Run
73 | Project can be run with Jetty:
74 | ```
75 | $ mvn jetty:run
76 | ```
77 |
78 | ##Watch
79 | With watch and connect plugins of grunt, web app files (js, html) can be watched and reloaded simultaneously when a source fie is changed.
80 | To activate watching run the command below after running application.
81 | ```
82 | $ grunt serve
83 | ```
84 |
85 | ##Author
86 | İsmail Demirbilek ([@dbtek](http://twitter.com/dbtek))
87 |
88 | ##License
89 | [MIT](http://opensource.org/licenses/MIT)
90 |
91 | ##Credits
92 |
93 | - [Spring](http://spring.io)
94 | - [Mustache.java](https://github.com/spullara/mustache.java)
95 | - [Mustache Spring View](https://github.com/sps/mustache-spring-view)
96 | - [Maven Frontend Plugin](https://github.com/eirslett/frontend-maven-plugin)
97 | - [Angular JS](http://angularjs.org)
98 | - [Bower](http://bower.io)
99 | - [Grunt](http://gruntjs.com) and its awesome plugins.
100 | - [Phantom JS](http://phantomjs.org/)
101 | - [Karma](http://karma-runner.github.io/0.12/index.html) and inside it Jasmine, İstanbul.
102 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spring-mvc-angular",
3 | "version": "0.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "angular": "1.2.13",
7 | "angular-route": "1.2.13",
8 | "angular-resource": "1.2.13",
9 | "bootstrap": "~3.1.1"
10 | },
11 | "devDependencies": {
12 | "angular-mocks": "1.2.13",
13 | "angular-scenario": "1.2.13"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {},
3 | "devDependencies": {
4 | "bower": "~1.3.8",
5 | "event-stream": "3.1.2",
6 | "grunt": "~0.4.4",
7 | "grunt-autoprefixer": "~0.7.5",
8 | "grunt-bower-install": "~1.3.0",
9 | "grunt-cli": "~0.1.13",
10 | "grunt-concurrent": "~0.5.0",
11 | "grunt-connect-proxy": "~0.1.10",
12 | "grunt-contrib-clean": "~0.5.0",
13 | "grunt-contrib-concat": "~0.3.0",
14 | "grunt-contrib-connect": "~0.7.1",
15 | "grunt-contrib-copy": "~0.5.0",
16 | "grunt-contrib-cssmin": "~0.9.0",
17 | "grunt-contrib-htmlmin": "~0.2.0",
18 | "grunt-contrib-imagemin": "~0.5.0",
19 | "grunt-contrib-jshint": "~0.9.2",
20 | "grunt-contrib-uglify": "~0.4.0",
21 | "grunt-contrib-watch": "~0.6.1",
22 | "grunt-karma": "~0.8.2",
23 | "grunt-ngdocs": "~0.2.2",
24 | "grunt-ngmin": "~0.0.3",
25 | "grunt-rev": "~0.1.0",
26 | "grunt-svgmin": "~0.4.0",
27 | "grunt-usemin": "~2.1.0",
28 | "karma": "~0.12.1",
29 | "karma-html2js-preprocessor": "~0.1.0",
30 | "karma-jasmine": "~0.2.2",
31 | "karma-phantomjs-launcher": "~0.1.2",
32 | "karma-requirejs": "~0.2.1",
33 | "karma-script-launcher": "~0.1.0",
34 | "load-grunt-tasks": "~0.4.0",
35 | "time-grunt": "~0.2.7",
36 | "karma-coverage": "~0.2.4"
37 | },
38 | "scripts": {
39 | "postinstall": "node_modules/.bin/bower install"
40 | },
41 | "engines": {
42 | "node": ">=0.10.0"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |