Skip to content

Commit 01caa8a

Browse files
author
JHades
committed
sample Spring MVC/Angular App
1 parent e5b6a27 commit 01caa8a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+7513
-1
lines changed

Diff for: .bowerrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"directory" : "src/main/webapp/resources/bower_components"
3+
}

Diff for: .gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules
2+
.tmp
3+
.sass-cache
4+
.idea
5+
*.iml
6+
target/
7+
target/**
8+
bower_components
9+

Diff for: README.md

+103-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,103 @@
1-
# spring-mvc-angularjs-sample-app
1+
# Spring MVC | AngularJs Sample App #
2+
3+
A test project for a daily calories consumption tracker. The project can be run with two different profiles, one using a postgresql database and the other is a test mode that starts an in-memory database and fills it with some test data.
4+
5+
### How to run the project in test mode ###
6+
7+
After cloning the repository, run the following command on the root folder of the repository:
8+
9+
mvn clean install tomcat7:run-war -Dspring.profiles.active=test
10+
11+
After the server starts, the application is accessible at the following URL:
12+
13+
http://localhost:8080/
14+
15+
To see a user with existing data (16 meals, 8 days from 1st of January 2015 to the 8th), login with the following credentials:
16+
17+
username: test123 / password: Password2
18+
19+
This is how the application looks like after login:
20+
21+
![alt Calories Tracker](TODO)
22+
23+
### Frontend Overview ###
24+
25+
The test project is a web application with an AngularJs-based frontend and a Spring/Hibernate based backend. The application is responsive, as it adapts to different screen sizes.
26+
27+
On the frontend, these libraries where used (besides Angular): [Yahoo PureCss](http://http://purecss.io/) (pure CSS baseline) and [lodash](https://lodash.com/) for functional data manipulation. The module system [require.js](http://requirejs.org/) was used to load frontend dependencies. The dependencies where obtained via [bower](http://bower.io/).
28+
29+
The angular module [angular-messages](https://egghead.io/lessons/angularjs-introduction-to-ng-messages-for-angularjs) was used for frontend form validation, and this [jQuery plugin](http://plugins.jquery.com/datetimepicker/) was used as the datetimepicker component.
30+
31+
### Backend Overview ###
32+
33+
The backend is based on Java 8, Spring 4, JPA 2/ Hibernate 4. The Spring configuration is based on Java. The main Spring modules used where Spring MVC and Spring Security. The backend was built using the DDD approach, which includes a domain model, services, repositories and DTOs for frontend/backend data transfer.
34+
35+
The REST web services are based on Spring MVC and JSON. The unit tests are made with spring test and the REST API functional tests where made using [Spring test MVC](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework).
36+
37+
#### Backend Security ####
38+
39+
The Spring Security module was used to secure the REST backend (these [guidelines](https://www.owasp.org/index.php/REST_Security_Cheat_Sheet) are in general applied). The application can be made to run in HTTPS-only mode via a server parameter, meaning no pages will be served if the user tries to access it via HTTP.
40+
41+
The Spring Security Form Login mode was used, with fallback to HTTP-Basic Authentication for non-browser based HTTP clients. Protection is in-place against CSRF ([cross-site request forgery](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29)).
42+
43+
Frontend validations are for user convenience only, and where also made on the backend. The use of Angular gives good protection against common problems like [cross-site scripting or HTML injection](https://docs.angularjs.org/misc/faq). The queries on the backend are made using either named queries or the criteria API, which gives good protection against SQL injection.
44+
45+
The password policy is of at least 6 characters with minimum one lower case, one upper case and one numeric. The passwords are not stored in the database in plain text but in a digested form, using the Spring Security [Bcrypt](http://docs.spring.io/autorepo/docs/spring-security/3.2.0.RELEASE/apidocs/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.html) password encoder (transparently includes a salt).
46+
47+
#### REST API ####
48+
49+
The REST API of the backend is composed of 3 services:
50+
51+
##### Authentication Service #####
52+
53+
Url |Verb | Description
54+
--------------|------------- | -------------
55+
/authenticate |POST | authenticates the user
56+
/logout |POST | ends the current session
57+
58+
59+
##### User Service #####
60+
61+
Url |Verb | Description
62+
--------------|------------- | -------------
63+
/user |GET | retrieves info for the currently logged-in user (number of calories of today, etc.)
64+
/user| PUT| Used to save the user max calories per day
65+
/user|POST| creates a new user
66+
67+
68+
69+
##### Meal Service #####
70+
71+
Url |Verb | Description
72+
--------------|------------- | -------------
73+
/meal |GET | searches meals for the current user by date/time
74+
/meal|POST|saves a modified set of meals, might included new ones
75+
/meal|DELETE| deletes a set of meals
76+
77+
78+
79+
80+
### Testing code coverage ###
81+
82+
This snapshot shows the test code coverage for the app package:
83+
84+
![alt Calories Tracker test Code Coverage](http://d2huq83j2o5dyd.cloudfront.net/CodeCoverage.png)
85+
86+
87+
### How to run the project against a non-in-memory database ###
88+
89+
This command starts the application with a local postgresql database:
90+
91+
mvn clean install tomcat7:run-war -Dspring.profiles.active=development
92+
93+
### How to run the project in HTTPS-only mode ###
94+
95+
The application can be started in HTTPS only mode by using the flag httpsOnly=true. This works in both modes, this is an example of how to start the application in test mode and HTTPS only:
96+
97+
mvn clean install tomcat7:run-war -Dspring.profiles.active=test -DhttpsOnly=true
98+
99+
The project can be accessed via this URL:
100+
101+
https://localhost:8443/
102+
103+
A warning message is displayed because the test certificate is not accepted by the browser, by accepting the certificate the login page is then displayed.

Diff for: bower.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "spring-mvc-angularjs-calories-tracker",
3+
"version": "1.0",
4+
"authors": [
5+
6+
],
7+
"description": "Sample Spring MVC | AngularJs project - Calories tracker",
8+
"dependencies": {
9+
"angular": "1.3.8",
10+
"angular-messages": "1.3.8",
11+
"lodash": "2.4.1",
12+
"pure": "0.5.0",
13+
"requirejs": "2.1.15",
14+
"spring-security-csrf-token-interceptor": "0.1.5"
15+
}
16+
}

Diff for: other/keystore.jks

2.16 KB
Binary file not shown.

Diff for: other/test-data.sql

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
insert into users values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546013', 0, '[email protected]', 650, 'xpto', 'test123');
3+
4+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546000', 0, 1000, '2015-01-01', '1 - Mitraillette', '12:00', 1);
5+
6+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546001', 0, 2000, '2015-01-01', '1 - Eggplant Parmesan', '19:00', 1);
7+
8+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546002', 0, 1000, '2015-01-02', '2 - Chickpea with roasted cauliflower', '12:00', 1);
9+
10+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546003', 0, 2000, '2015-01-02', '2 - Chicken Stew with Turnips & Mushrooms', '19:00', 1);
11+
12+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546004', 0, 1000, '2015-01-03', '3 - Rosemary Lentils & Greens on Toasted Bread', '12:00', 1);
13+
14+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546005', 0, 2000, '2015-01-03', '3 - Salmon Cakes with Olives, Lemon & Dill', '19:00', 1);
15+
16+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546006', 0, 1000, '2015-01-04', '4 - Cowboy Beef & Bean Chili', '12:00', 1);
17+
18+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546007', 0, 2000, '2015-01-04', '4 - Duck Chiles Rellenos', '19:00', 1);
19+
20+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546008', 0, 1000, '2015-01-05', '5 - Brussels Sprout & Potato Hash', '12:00', 1);
21+
22+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546009', 0, 2000, '2015-01-05', '5 - Creamy Green Chile Chicken Soup', '19:00', 1);
23+
24+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546010', 0, 1000, '2015-01-06', '6 - Duck Chiles Rellenos', '12:00', 1);
25+
26+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546011', 0, 2000, '2015-01-06', '6 - Apricot-Chile Glazed Salmon', '19:00', 1);
27+
28+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546012', 0, 1000, '2015-01-07', '7 - Creamy Mustard Chicken', '12:00', 1);
29+
30+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546013', 0, 2000, '2015-01-07', '7 - Grape Chutney', '19:00', 1);
31+
32+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546014', 0, 1000, '2015-01-08', '8 - Broccoli Rabe', '12:00', 1);
33+
34+
insert into meals values(nextval ('hibernate_sequence'), 'de305d54-75b4-431b-adb2-eb6b9e546015', 0, 1000, '2015-01-08', '8 - Moules Frites', '19:00', 1);
35+
36+
37+
38+
39+
40+

Diff for: pom.xml

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.spring.mvc.angularjs</groupId>
5+
<artifactId>calories-tracker</artifactId>
6+
<packaging>war</packaging>
7+
<version>1.0-SNAPSHOT</version>
8+
<name>calories-tracker Maven Webapp</name>
9+
10+
<properties>
11+
<java-version>1.8</java-version>
12+
<org.springframework-version>4.1.3.RELEASE</org.springframework-version>
13+
<spring-security-version>3.2.5.RELEASE</spring-security-version>
14+
<hibernate.version>4.3.7.Final</hibernate.version>
15+
<org.slf4j-version>1.6.1</org.slf4j-version>
16+
<jackson-version>2.4.4</jackson-version>
17+
<postgres.driver.version>9.3-1100-jdbc41</postgres.driver.version>
18+
</properties>
19+
20+
21+
<dependencies>
22+
23+
<!-- Spring -->
24+
<dependency>
25+
<groupId>org.springframework</groupId>
26+
<artifactId>spring-context</artifactId>
27+
<version>${org.springframework-version}</version>
28+
<exclusions>
29+
<!-- Exclude Commons Logging in favor of SLF4j -->
30+
<exclusion>
31+
<groupId>commons-logging</groupId>
32+
<artifactId>commons-logging</artifactId>
33+
</exclusion>
34+
</exclusions>
35+
</dependency>
36+
37+
<dependency>
38+
<groupId>org.springframework</groupId>
39+
<artifactId>spring-webmvc</artifactId>
40+
<version>${org.springframework-version}</version>
41+
</dependency>
42+
43+
<dependency>
44+
<groupId>org.springframework</groupId>
45+
<artifactId>spring-tx</artifactId>
46+
<version>${org.springframework-version}</version>
47+
</dependency>
48+
49+
<dependency>
50+
<groupId>org.springframework</groupId>
51+
<artifactId>spring-orm</artifactId>
52+
<version>${org.springframework-version}</version>
53+
</dependency>
54+
55+
<dependency>
56+
<groupId>org.postgresql</groupId>
57+
<artifactId>postgresql</artifactId>
58+
<version>${postgres.driver.version}</version>
59+
</dependency>
60+
61+
<dependency>
62+
<groupId>org.springframework</groupId>
63+
<artifactId>spring-test</artifactId>
64+
<version>${org.springframework-version}</version>
65+
</dependency>
66+
67+
<!-- Hibernate -->
68+
<dependency>
69+
<groupId>org.hibernate</groupId>
70+
<artifactId>hibernate-core</artifactId>
71+
<version>${hibernate.version}</version>
72+
</dependency>
73+
74+
<dependency>
75+
<groupId>org.hibernate</groupId>
76+
<artifactId>hibernate-entitymanager</artifactId>
77+
<version>${hibernate.version}</version>
78+
</dependency>
79+
80+
<!-- Spring security -->
81+
<dependency>
82+
<groupId>org.springframework.security</groupId>
83+
<artifactId>spring-security-core</artifactId>
84+
<version>${spring-security-version}</version>
85+
</dependency>
86+
87+
<dependency>
88+
<groupId>org.springframework.security</groupId>
89+
<artifactId>spring-security-web</artifactId>
90+
<version>${spring-security-version}</version>
91+
</dependency>
92+
93+
<dependency>
94+
<groupId>org.springframework.security</groupId>
95+
<artifactId>spring-security-config</artifactId>
96+
<version>${spring-security-version}</version>
97+
</dependency>
98+
99+
<dependency>
100+
<groupId>com.allanditzel</groupId>
101+
<artifactId>spring-security-csrf-token-filter</artifactId>
102+
<version>1.1</version>
103+
</dependency>
104+
105+
<!-- Logging -->
106+
<dependency>
107+
<groupId>org.slf4j</groupId>
108+
<artifactId>slf4j-api</artifactId>
109+
<version>${org.slf4j-version}</version>
110+
</dependency>
111+
<dependency>
112+
<groupId>org.slf4j</groupId>
113+
<artifactId>jcl-over-slf4j</artifactId>
114+
<version>${org.slf4j-version}</version>
115+
<scope>runtime</scope>
116+
</dependency>
117+
<dependency>
118+
<groupId>org.slf4j</groupId>
119+
<artifactId>slf4j-log4j12</artifactId>
120+
<version>${org.slf4j-version}</version>
121+
<scope>runtime</scope>
122+
</dependency>
123+
<dependency>
124+
<groupId>log4j</groupId>
125+
<artifactId>log4j</artifactId>
126+
<version>1.2.16</version>
127+
</dependency>
128+
129+
<!-- Jackson JSON Processor -->
130+
<dependency>
131+
<groupId>com.fasterxml.jackson.core</groupId>
132+
<artifactId>jackson-databind</artifactId>
133+
<version>${jackson-version}</version>
134+
</dependency>
135+
136+
<!-- servlet container provided dependencies -->
137+
<dependency>
138+
<groupId>org.apache.tomcat</groupId>
139+
<artifactId>tomcat-servlet-api</artifactId>
140+
<version>7.0.30</version>
141+
<scope>provided</scope>
142+
</dependency>
143+
144+
<!-- test dependencies -->
145+
<dependency>
146+
<groupId>com.jayway.jsonpath</groupId>
147+
<artifactId>json-path</artifactId>
148+
<version>0.8.1</version>
149+
<scope>test</scope>
150+
</dependency>
151+
152+
<dependency>
153+
<groupId>org.apache.commons</groupId>
154+
<artifactId>commons-lang3</artifactId>
155+
<version>3.3.2</version>
156+
</dependency>
157+
158+
<dependency>
159+
<groupId>junit</groupId>
160+
<artifactId>junit</artifactId>
161+
<version>4.12</version>
162+
<scope>test</scope>
163+
</dependency>
164+
165+
<dependency>
166+
<groupId>org.hsqldb</groupId>
167+
<artifactId>hsqldb</artifactId>
168+
<version>2.3.2</version>
169+
</dependency>
170+
171+
</dependencies>
172+
173+
<build>
174+
<finalName>calories-tracker</finalName>
175+
<plugins>
176+
<plugin>
177+
<groupId>org.apache.maven.plugins</groupId>
178+
<artifactId>maven-compiler-plugin</artifactId>
179+
<version>2.3.2</version>
180+
<configuration>
181+
<source>${java-version}</source>
182+
<target>${java-version}</target>
183+
</configuration>
184+
</plugin>
185+
<plugin>
186+
<groupId>org.apache.maven.plugins</groupId>
187+
<artifactId>maven-dependency-plugin</artifactId>
188+
<executions>
189+
<execution>
190+
<id>install</id>
191+
<phase>install</phase>
192+
<goals>
193+
<goal>sources</goal>
194+
</goals>
195+
</execution>
196+
</executions>
197+
</plugin>
198+
<plugin>
199+
<groupId>org.apache.tomcat.maven</groupId>
200+
<artifactId>tomcat7-maven-plugin</artifactId>
201+
<configuration>
202+
<path>/</path>
203+
<httpsPort>8443</httpsPort>
204+
<keystoreFile>${basedir}/other/keystore.jks</keystoreFile>
205+
<keystorePass>secret</keystorePass>
206+
</configuration>
207+
</plugin>
208+
</plugins>
209+
</build>
210+
</project>

0 commit comments

Comments
 (0)