├── .gitignore
├── README.md
├── client-side
├── .gitignore
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── models
│ ├── transaction.js
│ └── user.js
│ ├── pages
│ ├── detail
│ │ └── detail.page.jsx
│ ├── home
│ │ └── home.page.jsx
│ ├── login
│ │ ├── login.page.css
│ │ └── login.page.jsx
│ ├── profile
│ │ └── profile.page.jsx
│ └── register
│ │ ├── register.page.css
│ │ └── register.page.jsx
│ ├── serviceWorker.js
│ └── services
│ ├── course.service.js
│ └── user.service.js
├── eureka-discovery-service
├── .classpath
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── sha
│ │ │ └── eurekadiscoveryservice
│ │ │ └── EurekaDiscoveryServiceApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── sha
│ └── eurekadiscoveryservice
│ └── EurekaDiscoveryServiceApplicationTests.java
├── microservice-course-management
├── .classpath
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── sha
│ │ │ └── microservicecoursemanagement
│ │ │ ├── MicroserviceCourseManagementApplication.java
│ │ │ ├── controller
│ │ │ └── CourseController.java
│ │ │ ├── intercomm
│ │ │ └── UserClient.java
│ │ │ ├── model
│ │ │ ├── Course.java
│ │ │ └── Transaction.java
│ │ │ ├── repository
│ │ │ ├── CourseRepository.java
│ │ │ └── TransactionRepository.java
│ │ │ └── service
│ │ │ ├── CourseService.java
│ │ │ └── CourseServiceImpl.java
│ └── resources
│ │ ├── application.properties
│ │ └── db
│ │ └── changelog
│ │ ├── db.changelog-1.0.xml
│ │ └── db.changelog-master.xml
│ └── test
│ └── java
│ └── com
│ └── sha
│ └── microservicecoursemanagement
│ └── MicroserviceCourseManagementApplicationTests.java
├── microservice-user-management
├── .classpath
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── sha
│ │ │ └── microserviceusermanagement
│ │ │ ├── MicroserviceUserManagementApplication.java
│ │ │ ├── config
│ │ │ └── WebSecurityConfig.java
│ │ │ ├── controller
│ │ │ └── UserController.java
│ │ │ ├── model
│ │ │ ├── Role.java
│ │ │ └── User.java
│ │ │ ├── repository
│ │ │ └── UserRepository.java
│ │ │ └── service
│ │ │ ├── UserDetailServiceImpl.java
│ │ │ ├── UserService.java
│ │ │ └── UserServiceImpl.java
│ └── resources
│ │ ├── application.properties
│ │ └── db
│ │ └── changelog
│ │ ├── db.changelog-1.0.xml
│ │ └── db.changelog-master.xml
│ └── test
│ └── java
│ └── com
│ └── sha
│ └── microserviceusermanagement
│ └── MicroserviceUserManagementApplicationTests.java
└── zuul-gateway-service
├── .classpath
├── .gitignore
├── .project
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
├── java
│ └── com
│ │ └── sha
│ │ └── zuulgatewayservice
│ │ └── ZuulGatewayServiceApplication.java
└── resources
│ └── application.properties
└── test
└── java
└── com
└── sha
└── zuulgatewayservice
└── ZuulGatewayServiceApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events.json
15 | speed-measure-plugin.json
16 |
17 | # IDEs and editors
18 | /.idea
19 | .c9/
20 | *.launch
21 | *.sublime-workspace
22 |
23 | # IDE - VSCode
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 | .history/*
30 |
31 | # misc
32 | /.sass-cache
33 | /connect.lock
34 | /coverage
35 | /libpeerconnection.log
36 | npm-debug.log
37 | yarn-error.log
38 | testem.log
39 | /typings
40 |
41 | # System Files
42 | .DS_Store
43 | Thumbs.db
44 |
45 | # Server
46 | /.gradle
47 | /build/
48 | /!gradle/wrapper/gradle-wrapper.jar
49 | /out/
50 | /dist/
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Course Enrollment Microservices, Spring Cloud, Spring Boot, React, MySQL, Hibernate, Liquibase
2 |
3 | The application structure is as follows.
4 | - **microservice-user-management** - Microservice implemented using Spring boot. [More info](microservice-user-management/README.md)
5 | - **microservice-course-management** - Microservice implemented using Spring boot. [More info](microservice-course-management/README.md)
6 | - **eureka-discovery-service** - Microservice implemented using Spring eureka. [More info](eureka-discovery-service/README.md)
7 | - **zuul-gateway-service** - Microservice implemented using Spring zuul. [More info](zuul-gateway-service/README.md)
8 | - **client-side** - A NodeJs application implemented using React. This consumes services hosted by server side. [More info](client-side/README.md)
9 |
10 | ### Build
11 |
12 | #### 1) Build Spring Boot microservices
13 |
14 | ```
15 | $ cd microservice path
16 | $ gradlew bootJar
17 | $ gradlew bootRun
18 | ```
19 |
20 | #### 2) Build and run client side application
21 |
22 | ```
23 | $ cd client-side
24 | $ npm install
25 | $ npm start
26 | ```
27 |
28 | ### Access application using following URL
29 |
30 | ```
31 | http://localhost:3000
32 | ```
33 |
--------------------------------------------------------------------------------
/client-side/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/client-side/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `npm start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `npm test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `npm run build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `npm run eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
46 | ### Code Splitting
47 |
48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
49 |
50 | ### Analyzing the Bundle Size
51 |
52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
53 |
54 | ### Making a Progressive Web App
55 |
56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
57 |
58 | ### Advanced Configuration
59 |
60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
61 |
62 | ### Deployment
63 |
64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
65 |
66 | ### `npm run build` fails to minify
67 |
68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
69 |
--------------------------------------------------------------------------------
/client-side/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client-side",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@fortawesome/fontawesome-svg-core": "^1.2.18",
7 | "@fortawesome/free-solid-svg-icons": "^5.8.2",
8 | "@fortawesome/react-fontawesome": "^0.1.4",
9 | "axios": "^0.18.0",
10 | "bootstrap": "^4.3.1",
11 | "jquery": "^3.4.1",
12 | "popper.js": "^1.15.0",
13 | "react": "^16.8.6",
14 | "react-dom": "^16.8.6",
15 | "react-router-dom": "^5.0.0",
16 | "react-scripts": "3.0.1"
17 | },
18 | "scripts": {
19 | "start": "react-scripts start",
20 | "build": "react-scripts build",
21 | "test": "react-scripts test",
22 | "eject": "react-scripts eject"
23 | },
24 | "eslintConfig": {
25 | "extends": "react-app"
26 | },
27 | "browserslist": {
28 | "production": [
29 | ">0.2%",
30 | "not dead",
31 | "not op_mini all"
32 | ],
33 | "development": [
34 | "last 1 chrome version",
35 | "last 1 firefox version",
36 | "last 1 safari version"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/client-side/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senolatac/react-springboot-microservices/727c78ecccb63509325a03f48b7f6624bde6341b/client-side/public/favicon.ico
--------------------------------------------------------------------------------
/client-side/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
27 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/client-side/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/client-side/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 8vmin;
8 | pointer-events: none;
9 | }
10 |
11 | .App-header {
12 | background-color: #282c34;
13 | min-height: 100vh;
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | justify-content: center;
18 | font-size: calc(10px + 2vmin);
19 | color: white;
20 | }
21 |
22 | .App-link {
23 | color: #61dafb;
24 | }
25 |
26 | @keyframes App-logo-spin {
27 | from {
28 | transform: rotate(0deg);
29 | }
30 | to {
31 | transform: rotate(360deg);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/client-side/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import logo from './logo.svg';
3 | import './App.css';
4 | import {Router, Route, Link, Switch, Redirect} from 'react-router-dom';
5 | import {createBrowserHistory} from 'history';
6 |
7 | import HomePage from './pages/home/home.page';
8 | import LoginPage from './pages/login/login.page';
9 | import RegisterPage from './pages/register/register.page';
10 | import ProfilePage from './pages/profile/profile.page';
11 | import DetailPage from './pages/detail/detail.page';
12 |
13 | import UserService from './services/user.service';
14 | import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
15 | import{
16 | faUser,
17 | faUserPlus,
18 | faSignInAlt,
19 | faHome,
20 | faSignOutAlt
21 | } from '@fortawesome/free-solid-svg-icons';
22 | import {User} from './models/user';
23 |
24 | export default class App extends React.Component {
25 | constructor(props) {
26 | super(props);
27 |
28 | this.state = {
29 | history: createBrowserHistory(),
30 | currentUser: new User()
31 | };
32 | }
33 |
34 | componentDidMount() {
35 | UserService.currentUser.subscribe(data => {
36 | this.setState({currentUser: data});
37 | });
38 | }
39 |
40 | logout() {
41 | UserService.logOut().then(data => {
42 | this.state.history.push('/home');
43 | }, error => {
44 | this.setState({
45 | errorMessage: "Unexpected error occurred."
46 | });
47 | });
48 | }
49 |
50 | render() {
51 | const {history, currentUser} = this.state;
52 | return (
53 |
54 |
55 | {this.state.currentUser &&
56 |
75 | }
76 | {!this.state.currentUser &&
77 |
96 | }
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/client-side/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/client-side/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/client-side/src/index.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap/dist/css/bootstrap.min.css';
2 | import $ from 'jquery';
3 | import Popper from 'popper.js';
4 | import 'bootstrap/dist/js/bootstrap.bundle.min';
5 | import React from 'react';
6 | import ReactDOM from 'react-dom';
7 | import './index.css';
8 | import App from './App';
9 | import * as serviceWorker from './serviceWorker';
10 |
11 | ReactDOM.render(, document.getElementById('root'));
12 |
13 | // If you want your app to work offline and load faster, you can change
14 | // unregister() to register() below. Note this comes with some pitfalls.
15 | // Learn more about service workers: https://bit.ly/CRA-PWA
16 | serviceWorker.unregister();
17 |
--------------------------------------------------------------------------------
/client-side/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/client-side/src/models/transaction.js:
--------------------------------------------------------------------------------
1 | export class Transaction {
2 | constructor(userId, course, dateOfIssue, id){
3 | this.userId = userId;
4 | this.course = course;
5 | this.dateOfIssue = dateOfIssue;
6 | this.id = id;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/client-side/src/models/user.js:
--------------------------------------------------------------------------------
1 | export class User {
2 | constructor(username, password, name, id){
3 | this.username = username;
4 | this.password = password;
5 | this.name = name;
6 | this.id = id;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/client-side/src/pages/detail/detail.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import CourseService from '../../services/course.service';
3 |
4 | export default class DefaultPage extends React.Component {
5 |
6 | constructor(props) {
7 | super(props);
8 |
9 | this.state = {
10 | id: this.props.match.params.id,
11 | course: JSON.parse(localStorage.getItem('currentCourse')),
12 | students: [],
13 | };
14 | }
15 |
16 | componentDidMount() {
17 | this.findStudentsOfCourse();
18 | }
19 |
20 | findStudentsOfCourse() {
21 | CourseService.filterStudents(this.state.id).then(students => {
22 | this.setState({students: students.data});
23 | });
24 | }
25 |
26 | render() {
27 | const {students} = this.state;
28 | return (
29 |
30 |
31 |
Course: {this.state.course.title}
32 | Course Id: {this.state.id}
33 |
34 | {students.length &&
35 |
36 |
37 |
38 | # |
39 | Student Name |
40 |
41 |
42 |
43 | {students.map((student, index) =>
44 |
45 | {index + 1} |
46 | {student} |
47 |
48 | )}
49 |
50 |
51 | }
52 |
53 | );
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/client-side/src/pages/home/home.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import UserService from '../../services/user.service';
3 | import CourseService from '../../services/course.service';
4 | import {User} from '../../models/user';
5 | import {Transaction} from '../../models/transaction';
6 |
7 | export default class HomePage extends React.Component {
8 |
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | courses: [],
13 | errorMessage: '',
14 | infoMessage: '',
15 | currentUser: new User()
16 | };
17 | }
18 |
19 | componentDidMount() {
20 | UserService.currentUser.subscribe(data => {
21 | this.setState({
22 | currentUser: data
23 | });
24 | });
25 |
26 | this.getAllCourses();
27 | }
28 |
29 | getAllCourses() {
30 | this.setState({
31 | courses: {loading: true}
32 | });
33 |
34 | CourseService.findAllCourses().then(courses => {
35 | this.setState({courses: courses.data});
36 | });
37 | }
38 |
39 | enroll(course) {
40 | if(!this.state.currentUser){
41 | this.setState({errorMessage: 'To enroll a course, you should sign in.'});
42 | return;
43 | }
44 |
45 | var transaction = new Transaction(this.state.currentUser.id, course);
46 | CourseService.createTransaction(transaction).then(data => {
47 | this.setState({infoMessage: 'You enrolled the course successfully.'});
48 | }, error => {
49 | this.setState({errorMessage: 'Unexpected error occurred.'});
50 | });
51 | }
52 |
53 | detail(course) {
54 | localStorage.setItem('currentCourse', JSON.stringify(course));
55 | this.props.history.push('/detail/' + course.id);
56 | }
57 |
58 | render() {
59 | const {courses, infoMessage, errorMessage} = this.state;
60 | return (
61 |
62 | {infoMessage &&
63 |
64 | Successfull! {infoMessage}
65 |
68 |
69 | }
70 | {errorMessage &&
71 |
72 | Error! {errorMessage}
73 |
76 |
77 | }
78 | {courses.loading &&
Loading courses...}
79 | {courses.length &&
80 |
81 |
82 |
83 | # |
84 | Course Title |
85 | Author |
86 | Detail |
87 | Action |
88 |
89 |
90 |
91 | {courses.map((course, index) =>
92 |
93 | {index + 1} |
94 | {course.title} |
95 | {course.author} |
96 |
97 |
98 | |
99 |
100 |
101 | |
102 |
103 | )}
104 |
105 |
106 | }
107 |
108 | );
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/client-side/src/pages/login/login.page.css:
--------------------------------------------------------------------------------
1 | label{
2 | display: block;
3 | margin-top: 10px;
4 | }
5 |
6 | .btn-link{
7 | display: block;
8 | margin: auto;
9 | width: 100%;
10 | text-align: center;
11 | margin-top: 10px;
12 | color: cornflowerblue;
13 | }
14 |
15 |
16 | .card-container.card {
17 | max-width: 350px!important;
18 | padding: 40px 40px;
19 | }
20 |
21 | .btn {
22 | font-weight: 700;
23 | height: 36px;
24 | -moz-user-select: none;
25 | -webkit-user-select: none;
26 | user-select: none;
27 | cursor: default;
28 | }
29 |
30 | .card {
31 | background-color: #F7F7F7;
32 | /* just in case there no content*/
33 | padding: 20px 25px 30px;
34 | margin: 0 auto 25px;
35 | margin-top: 50px;
36 | /* shadows and rounded borders */
37 | -moz-border-radius: 2px;
38 | -webkit-border-radius: 2px;
39 | border-radius: 2px;
40 | -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
41 | -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
42 | box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
43 | }
44 |
45 | .profile-img-card {
46 | width: 96px;
47 | height: 96px;
48 | margin: 0 auto 10px;
49 | display: block;
50 | -moz-border-radius: 50%;
51 | -webkit-border-radius: 50%;
52 | border-radius: 50%;
53 | }
54 |
55 |
56 | .form-signin #inputEmail,
57 | .form-signin #inputPassword {
58 | direction: ltr;
59 | height: 44px;
60 | font-size: 16px;
61 | }
62 |
63 | .form-signin input[type=email],
64 | .form-signin input[type=password],
65 | .form-signin input[type=text],
66 | .form-signin button {
67 | width: 100%;
68 | display: block;
69 | margin-bottom: 10px;
70 | z-index: 1;
71 | position: relative;
72 | -moz-box-sizing: border-box;
73 | -webkit-box-sizing: border-box;
74 | box-sizing: border-box;
75 | }
76 |
77 | .form-signin .form-control:focus {
78 | border-color: rgb(104, 145, 162);
79 | outline: 0;
80 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
81 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
82 | }
83 |
84 | .btn.btn-signin {
85 | /*background-color: #4d90fe; */
86 | background-color: rgb(104, 145, 162);
87 | /* background-color: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33));*/
88 | padding: 0px;
89 | font-weight: 700;
90 | font-size: 14px;
91 | height: 36px;
92 | -moz-border-radius: 3px;
93 | -webkit-border-radius: 3px;
94 | border-radius: 3px;
95 | border: none;
96 | -o-transition: all 0.218s;
97 | -moz-transition: all 0.218s;
98 | -webkit-transition: all 0.218s;
99 | transition: all 0.218s;
100 | }
101 |
102 |
103 | .btn.btn-signin:hover,
104 | .btn.btn-signin:active,
105 | .btn.btn-signin:focus {
106 | background-color: rgb(12, 97, 33);
107 | }
108 |
--------------------------------------------------------------------------------
/client-side/src/pages/login/login.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import UserService from '../../services/user.service';
3 | import {User} from '../../models/user';
4 | import './login.page.css';
5 |
6 | export default class LoginPage extends React.Component{
7 |
8 | constructor(props) {
9 | super(props);
10 |
11 | if(UserService.currentUserValue) {
12 | this.props.history.push('/');
13 | }
14 |
15 | this.state = {
16 | user: new User('',''),
17 | submitted: false,
18 | loading: false,
19 | errorMessage: ''
20 | };
21 | }
22 |
23 | handleChange(e) {
24 | var {name, value} = e.target;
25 | var user = this.state.user;
26 | user[name] = value;
27 | this.setState({user: user});
28 | }
29 |
30 | handleLogin(e) {
31 | e.preventDefault();
32 |
33 | this.setState({submitted: true});
34 | const {user} = this.state;
35 |
36 | if(!(user.username && user.password)){
37 | return;
38 | }
39 |
40 | this.setState({loading: true});
41 | UserService.login(user).then(data => {
42 | this.props.history.push("/home");
43 | }, error => {
44 | this.setState({
45 | errorMessage: "Username or password is not valid",
46 | loading: false
47 | });
48 | });
49 | }
50 |
51 | render() {
52 | const {user, submitted, loading, errorMessage} = this.state;
53 | return (
54 |
55 |
56 |

57 | {errorMessage &&
58 |
59 | Error! {errorMessage}
60 |
61 | }
62 |
81 |
82 |
83 | );
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/client-side/src/pages/profile/profile.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import UserService from '../../services/user.service';
3 | import CourseService from '../../services/course.service';
4 |
5 | export default class ProfilePage extends React.Component {
6 |
7 | constructor(props) {
8 | super(props);
9 |
10 | if(!UserService.currentUserValue){
11 | this.props.history.push('/');
12 | return;
13 | }
14 |
15 | this.state = {
16 | user: UserService.currentUserValue,
17 | transactions: []
18 | };
19 | }
20 |
21 | componentDidMount() {
22 | this.setState({
23 | transactions: {loading: true}
24 | });
25 | const user = this.state.user;
26 | CourseService.filterTransactions(user.id).then(transactions => {
27 | this.setState({transactions: transactions.data});
28 | });
29 | }
30 |
31 | render() {
32 | const {transactions} = this.state;
33 | return (
34 |
35 |
36 |
Hello, {this.state.user.name}
37 |
38 | {transactions.loading &&
Loading transactions...}
39 | {transactions.length &&
40 |
41 |
42 |
43 | # |
44 | Course Title |
45 | Author |
46 | Category |
47 | Enroll Date |
48 |
49 |
50 |
51 | {transactions.map((transaction, index) =>
52 |
53 | {index + 1} |
54 | {transaction.course.title} |
55 | {transaction.course.author} |
56 | {transaction.course.category} |
57 | {transaction.dateOfIssue} |
58 |
59 | )
60 | }
61 |
62 |
63 | }
64 |
65 | );
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/client-side/src/pages/register/register.page.css:
--------------------------------------------------------------------------------
1 | label{
2 | display: block;
3 | margin-top: 10px;
4 | }
5 |
6 | .btn-link{
7 | display: block;
8 | margin: auto;
9 | width: 100%;
10 | text-align: center;
11 | margin-top: 10px;
12 | color: cornflowerblue;
13 | }
14 |
15 |
16 | .card-container.card {
17 | max-width: 350px!important;
18 | padding: 40px 40px;
19 | }
20 |
21 | .btn {
22 | font-weight: 700;
23 | height: 36px;
24 | -moz-user-select: none;
25 | -webkit-user-select: none;
26 | user-select: none;
27 | cursor: default;
28 | }
29 |
30 | .card {
31 | background-color: #F7F7F7;
32 | /* just in case there no content*/
33 | padding: 20px 25px 30px;
34 | margin: 0 auto 25px;
35 | margin-top: 50px;
36 | /* shadows and rounded borders */
37 | -moz-border-radius: 2px;
38 | -webkit-border-radius: 2px;
39 | border-radius: 2px;
40 | -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
41 | -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
42 | box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
43 | }
44 |
45 | .profile-img-card {
46 | width: 96px;
47 | height: 96px;
48 | margin: 0 auto 10px;
49 | display: block;
50 | -moz-border-radius: 50%;
51 | -webkit-border-radius: 50%;
52 | border-radius: 50%;
53 | }
54 |
55 |
56 | .form-signin #inputEmail,
57 | .form-signin #inputPassword {
58 | direction: ltr;
59 | height: 44px;
60 | font-size: 16px;
61 | }
62 |
63 | .form-signin input[type=email],
64 | .form-signin input[type=password],
65 | .form-signin input[type=text],
66 | .form-signin button {
67 | width: 100%;
68 | display: block;
69 | margin-bottom: 10px;
70 | z-index: 1;
71 | position: relative;
72 | -moz-box-sizing: border-box;
73 | -webkit-box-sizing: border-box;
74 | box-sizing: border-box;
75 | }
76 |
77 | .form-signin .form-control:focus {
78 | border-color: rgb(104, 145, 162);
79 | outline: 0;
80 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
81 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgb(104, 145, 162);
82 | }
83 |
84 | .btn.btn-signin {
85 | /*background-color: #4d90fe; */
86 | background-color: rgb(104, 145, 162);
87 | /* background-color: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33));*/
88 | padding: 0px;
89 | font-weight: 700;
90 | font-size: 14px;
91 | height: 36px;
92 | -moz-border-radius: 3px;
93 | -webkit-border-radius: 3px;
94 | border-radius: 3px;
95 | border: none;
96 | -o-transition: all 0.218s;
97 | -moz-transition: all 0.218s;
98 | -webkit-transition: all 0.218s;
99 | transition: all 0.218s;
100 | }
101 |
102 |
103 | .btn.btn-signin:hover,
104 | .btn.btn-signin:active,
105 | .btn.btn-signin:focus {
106 | background-color: rgb(12, 97, 33);
107 | }
108 |
--------------------------------------------------------------------------------
/client-side/src/pages/register/register.page.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import UserService from '../../services/user.service';
3 | import {User} from '../../models/user';
4 | import './register.page.css';
5 |
6 | export default class RegisterPage extends React.Component {
7 |
8 | constructor(props) {
9 | super(props);
10 |
11 | if(UserService.currentUserValue) {
12 | this.props.history.push('/');
13 | }
14 |
15 | this.state = {
16 | user: new User('','',''),
17 | submitted: false,
18 | loading: false,
19 | errorMessage: ''
20 | };
21 | }
22 |
23 | handleChange(e) {
24 | var { name, value } = e.target;
25 | var user = this.state.user;
26 | user[name] = value;
27 | this.setState({user: user});
28 | }
29 |
30 | handleRegister(e) {
31 | e.preventDefault();
32 | this.setState({submitted: true});
33 | const{user} = this.state;
34 |
35 | if(!(user.username && user.password && user.name)) {
36 | return;
37 | }
38 |
39 | this.setState({loading: true});
40 | UserService.register(user).then(data => {
41 | this.props.history.push("/login");
42 | }, error => {
43 | if(error.response.status === 409) {
44 | this.setState({
45 | errorMessage: "Username is not available",
46 | loading: false
47 | });
48 | }else {
49 | this.setState({
50 | errorMessage: "Unexpected error occurred.",
51 | loading: false
52 | });
53 | }
54 | });
55 | }
56 |
57 | render() {
58 | const {user, submitted, loading, errorMessage} = this.state;
59 | return (
60 |
61 |
62 |

63 | {errorMessage &&
64 |
65 | Error! {errorMessage}
66 |
67 | }
68 |
94 |
95 |
96 | );
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/client-side/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/client-side/src/services/course.service.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | let API_URL = 'http://localhost:8765/api/course/service/';
4 |
5 | class CourseService {
6 | createTransaction(transaction){
7 | return axios.post(API_URL + 'enroll', JSON.stringify(transaction),
8 | {headers: {'Content-Type':'application/json; charset=UTF-8'}});
9 | }
10 |
11 | filterTransactions(userId){
12 | return axios.get(API_URL + 'user/'+ userId,
13 | {headers: {'Content-Type':'application/json; charset=UTF-8'}});
14 | }
15 |
16 | filterStudents(courseId){
17 | return axios.get(API_URL + 'course/' + courseId,
18 | {headers: {'Content-Type':'application/json; charset=UTF-8'}});
19 | }
20 |
21 | findAllCourses(){
22 | return axios.get(API_URL + 'all',
23 | {headers: {'Content-Type':'application/json; charset=UTF-8'}});
24 | }
25 | }
26 | export default new CourseService();
27 |
--------------------------------------------------------------------------------
/client-side/src/services/user.service.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import {BehaviorSubject} from 'rxjs';
3 |
4 | const API_URL = 'http://localhost:8765/api/user/service/';
5 |
6 | const currentUserSubject = new BehaviorSubject(JSON.parse(localStorage.getItem('currentUser')));
7 | class UserService {
8 | get currentUserValue(){
9 | return currentUserSubject.value;
10 | }
11 |
12 | get currentUser(){
13 | return currentUserSubject.asObservable();
14 | }
15 |
16 | login(user){
17 | const headers = {
18 | authorization:'Basic ' + btoa(user.username + ':' + user.password)
19 | };
20 | return axios.get(API_URL + 'login', {headers: headers}).then(response => {
21 | localStorage.setItem('currentUser', JSON.stringify(response.data));
22 | currentUserSubject.next(response.data);
23 | });
24 | }
25 |
26 | logOut(){
27 | return axios.post(API_URL + 'logout', {}).then(response => {
28 | localStorage.removeItem('currentUser');
29 | currentUserSubject.next(null);
30 | })
31 | }
32 |
33 | register(user){
34 | return axios.post(API_URL + 'registration', JSON.stringify(user),
35 | {headers: {'Content-Type':'application/json; charset=UTF-8'}});
36 | }
37 |
38 | }
39 |
40 | export default new UserService();
41 |
--------------------------------------------------------------------------------
/eureka-discovery-service/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/eureka-discovery-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**
6 | !**/src/test/**
7 |
8 | ### STS ###
9 | .apt_generated
10 | .factorypath
11 | .springBeans
12 | .sts4-cache
13 |
14 | ### IntelliJ IDEA ###
15 | .idea
16 | *.iws
17 | *.iml
18 | *.ipr
19 | out/
20 |
21 | ### NetBeans ###
22 | /nbproject/private/
23 | /nbbuild/
24 | /dist/
25 | /nbdist/
26 | /.nb-gradle/
27 |
28 | ### VS Code ###
29 | .vscode/
30 |
--------------------------------------------------------------------------------
/eureka-discovery-service/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | eureka-discovery-service
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/eureka-discovery-service/README.md:
--------------------------------------------------------------------------------
1 | # Eureka-Service
2 |
3 | This project is a Spring Boot, MySQL, Hibernate and Liquibase project.
4 |
5 | ## Development server
6 |
7 | Run `Eureka-Service Main class` for a dev server. Navigate to `http://localhost:8761/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Build
10 |
11 | Run `gradlew clean build`
12 |
13 | java -Djava.security.egd=file:/dev/./urandom -jar app.jar
14 |
--------------------------------------------------------------------------------
/eureka-discovery-service/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'org.springframework.boot' version '2.1.6.RELEASE'
3 | id 'java'
4 | }
5 |
6 | apply plugin: 'io.spring.dependency-management'
7 |
8 | group = 'com.sha'
9 | version = '0.0.1-SNAPSHOT'
10 | sourceCompatibility = '1.8'
11 |
12 | repositories {
13 | mavenCentral()
14 | }
15 |
16 | ext {
17 | set('springCloudVersion', "Greenwich.SR2")
18 | }
19 |
20 | dependencies {
21 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
22 | testImplementation 'org.springframework.boot:spring-boot-starter-test'
23 | }
24 |
25 | dependencyManagement {
26 | imports {
27 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/eureka-discovery-service/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senolatac/react-springboot-microservices/727c78ecccb63509325a03f48b7f6624bde6341b/eureka-discovery-service/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/eureka-discovery-service/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/eureka-discovery-service/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS='"-Xmx64m"'
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/eureka-discovery-service/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS="-Xmx64m"
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/eureka-discovery-service/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | }
5 | }
6 | rootProject.name = 'eureka-discovery-service'
7 |
--------------------------------------------------------------------------------
/eureka-discovery-service/src/main/java/com/sha/eurekadiscoveryservice/EurekaDiscoveryServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.sha.eurekadiscoveryservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaServer
9 | public class EurekaDiscoveryServiceApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(EurekaDiscoveryServiceApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/eureka-discovery-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8761
2 |
3 | #telling the server not to register himself in the service
4 | eureka.client.register-with-eureka=false
5 | #Eureka clients fetch the service registry (ServiceInstance: {URL, PORT, HOST}) from the Eureka server
6 | eureka.client.fetch-registry=true
--------------------------------------------------------------------------------
/eureka-discovery-service/src/test/java/com/sha/eurekadiscoveryservice/EurekaDiscoveryServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.sha.eurekadiscoveryservice;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class EurekaDiscoveryServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/microservice-course-management/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/microservice-course-management/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**
6 | !**/src/test/**
7 |
8 | ### STS ###
9 | .apt_generated
10 | .factorypath
11 | .springBeans
12 | .sts4-cache
13 |
14 | ### IntelliJ IDEA ###
15 | .idea
16 | *.iws
17 | *.iml
18 | *.ipr
19 | out/
20 |
21 | ### NetBeans ###
22 | /nbproject/private/
23 | /nbbuild/
24 | /dist/
25 | /nbdist/
26 | /.nb-gradle/
27 |
28 | ### VS Code ###
29 | .vscode/
30 |
--------------------------------------------------------------------------------
/microservice-course-management/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | microservice-course-management
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/microservice-course-management/README.md:
--------------------------------------------------------------------------------
1 | # Course-Service
2 |
3 | This project is a Spring Boot, MySQL, Hibernate and Liquibase project.
4 |
5 | ## Development server
6 |
7 | Run `Course-Service Main class` for a dev server. Navigate to `http://localhost:8001/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Build
10 |
11 | Run `gradlew clean build`
12 |
13 | java -Djava.security.egd=file:/dev/./urandom -jar app.jar
14 |
--------------------------------------------------------------------------------
/microservice-course-management/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'org.springframework.boot' version '2.1.6.RELEASE'
3 | id 'java'
4 | }
5 |
6 | apply plugin: 'io.spring.dependency-management'
7 |
8 | group = 'com.sha'
9 | version = '0.0.1-SNAPSHOT'
10 | sourceCompatibility = '1.8'
11 |
12 | configurations {
13 | compileOnly {
14 | extendsFrom annotationProcessor
15 | }
16 | }
17 |
18 | repositories {
19 | mavenCentral()
20 | }
21 |
22 | ext {
23 | set('springCloudVersion', "Greenwich.SR2")
24 | }
25 |
26 | dependencies {
27 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
28 | implementation 'org.springframework.boot:spring-boot-starter-data-rest'
29 | implementation 'org.springframework.boot:spring-boot-starter-web'
30 | implementation 'org.liquibase:liquibase-core'
31 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
32 | implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
33 | compileOnly 'org.projectlombok:lombok'
34 | runtimeOnly 'mysql:mysql-connector-java'
35 | annotationProcessor 'org.projectlombok:lombok'
36 | testImplementation 'org.springframework.boot:spring-boot-starter-test'
37 | }
38 |
39 | dependencyManagement {
40 | imports {
41 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/microservice-course-management/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senolatac/react-springboot-microservices/727c78ecccb63509325a03f48b7f6624bde6341b/microservice-course-management/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/microservice-course-management/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/microservice-course-management/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS='"-Xmx64m"'
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/microservice-course-management/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS="-Xmx64m"
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/microservice-course-management/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | }
5 | }
6 | rootProject.name = 'microservice-course-management'
7 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/MicroserviceCourseManagementApplication.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
10 |
11 | @SpringBootApplication
12 | @EnableDiscoveryClient
13 | @EnableFeignClients
14 | public class MicroserviceCourseManagementApplication {
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(MicroserviceCourseManagementApplication.class, args);
18 | }
19 |
20 | @Bean
21 | public WebMvcConfigurer corsConfigurer() {
22 | return new WebMvcConfigurer() {
23 | @Override
24 | public void addCorsMappings(CorsRegistry registry) {
25 | registry.addMapping("/**").allowedOrigins("*");
26 | }
27 | };
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/controller/CourseController.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.controller;
2 |
3 | import com.sha.microservicecoursemanagement.intercomm.UserClient;
4 | import com.sha.microservicecoursemanagement.model.Transaction;
5 | import com.sha.microservicecoursemanagement.service.CourseService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.beans.factory.annotation.Value;
8 | import org.springframework.cloud.client.discovery.DiscoveryClient;
9 | import org.springframework.core.env.Environment;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.util.CollectionUtils;
13 | import org.springframework.web.bind.annotation.*;
14 |
15 | import java.time.LocalDateTime;
16 | import java.util.List;
17 | import java.util.stream.Collectors;
18 |
19 | @RestController
20 | public class CourseController {
21 |
22 | @Autowired
23 | private UserClient userClient;
24 |
25 | @Autowired
26 | private CourseService courseService;
27 |
28 | @Autowired
29 | private DiscoveryClient discoveryClient;
30 |
31 | @Autowired
32 | private Environment env;
33 |
34 | @Value("${spring.application.name}")
35 | private String serviceId;
36 |
37 | @GetMapping("/service/port")
38 | public String getPort(){
39 | return "Service is working at port : " + env.getProperty("local.server.port");
40 | }
41 |
42 | @GetMapping("/service/instances")
43 | public ResponseEntity> getInstances() {
44 | return ResponseEntity.ok(discoveryClient.getInstances(serviceId));
45 | }
46 |
47 | @GetMapping("/service/user/{userId}")
48 | public ResponseEntity> findTransactionsOfUser(@PathVariable Long userId){
49 | return ResponseEntity.ok(courseService.findTransactionsOfUser(userId));
50 | }
51 |
52 | @GetMapping("/service/all")
53 | public ResponseEntity> findAllCourses(){
54 | return ResponseEntity.ok(courseService.allCourses());
55 | }
56 |
57 | @PostMapping("/service/enroll")
58 | public ResponseEntity> saveTransaction(@RequestBody Transaction transaction) {
59 | transaction.setDateOfIssue(LocalDateTime.now());
60 | transaction.setCourse(courseService.findCourseById(transaction.getCourse().getId()));
61 | return new ResponseEntity<>(courseService.saveTransaction(transaction), HttpStatus.CREATED);
62 | }
63 |
64 | @GetMapping("/service/course/{courseId}")
65 | public ResponseEntity> findStudentsOfCourse(@PathVariable Long courseId){
66 | List transactions = courseService.findTransactionsOfCourse(courseId);
67 | if(CollectionUtils.isEmpty(transactions)){
68 | return ResponseEntity.notFound().build();
69 | }
70 | List userIdList = transactions.parallelStream().map(t -> t.getUserId()).collect(Collectors.toList());
71 | List students = userClient.getUserNames(userIdList);
72 | return ResponseEntity.ok(students);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/intercomm/UserClient.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.intercomm;
2 |
3 | import org.springframework.cloud.openfeign.FeignClient;
4 | import org.springframework.web.bind.annotation.RequestBody;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RequestMethod;
7 |
8 | import java.util.List;
9 |
10 | @FeignClient("user-service")
11 | public interface UserClient {
12 |
13 | @RequestMapping(method = RequestMethod.POST, value = "/service/names", consumes = "application/json")
14 | List getUserNames(@RequestBody List userIdList);
15 | }
16 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/model/Course.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.model;
2 |
3 | import lombok.Data;
4 |
5 | import javax.persistence.*;
6 | import java.io.Serializable;
7 | import java.time.LocalDate;
8 |
9 | @Data
10 | @Entity
11 | @Table(name = "course")
12 | public class Course implements Serializable {
13 |
14 | @Id
15 | @GeneratedValue(strategy = GenerationType.IDENTITY)
16 | private Long id;
17 |
18 | @Column(name = "title")
19 | private String title;
20 |
21 | @Column(name = "author")
22 | private String author;
23 |
24 | @Column(name = "category")
25 | private String category;
26 |
27 | @Column(name = "publish_date")
28 | private LocalDate publishDate;
29 | }
30 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/model/Transaction.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.model;
2 |
3 | import lombok.Data;
4 |
5 | import javax.persistence.*;
6 | import java.io.Serializable;
7 | import java.time.LocalDateTime;
8 |
9 | @Data
10 | @Entity
11 | @Table(name = "transaction")
12 | public class Transaction implements Serializable {
13 |
14 | @Id
15 | @GeneratedValue(strategy = GenerationType.IDENTITY)
16 | private Long id;
17 |
18 | @ManyToOne(fetch = FetchType.EAGER)
19 | @JoinColumn(name = "course_id", referencedColumnName = "id")
20 | private Course course;
21 |
22 | @Column(name = "user_id")
23 | private Long userId;
24 |
25 | @Column(name = "date_of_issue")
26 | private LocalDateTime dateOfIssue;
27 | }
28 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/repository/CourseRepository.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.repository;
2 |
3 | import com.sha.microservicecoursemanagement.model.Course;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface CourseRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/repository/TransactionRepository.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.repository;
2 |
3 | import com.sha.microservicecoursemanagement.model.Transaction;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | import java.util.List;
7 |
8 | public interface TransactionRepository extends JpaRepository {
9 |
10 | List findAllByUserId(Long userId);
11 |
12 | List findAllByCourseId(Long courseId);
13 | }
14 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/service/CourseService.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.service;
2 |
3 | import com.sha.microservicecoursemanagement.model.Course;
4 | import com.sha.microservicecoursemanagement.model.Transaction;
5 |
6 | import java.util.List;
7 |
8 | public interface CourseService {
9 | List allCourses();
10 |
11 | Course findCourseById(Long courseId);
12 |
13 | List findTransactionsOfUser(Long userId);
14 |
15 | List findTransactionsOfCourse(Long courseId);
16 |
17 | Transaction saveTransaction(Transaction transaction);
18 | }
19 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/java/com/sha/microservicecoursemanagement/service/CourseServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement.service;
2 |
3 | import com.sha.microservicecoursemanagement.model.Course;
4 | import com.sha.microservicecoursemanagement.model.Transaction;
5 | import com.sha.microservicecoursemanagement.repository.CourseRepository;
6 | import com.sha.microservicecoursemanagement.repository.TransactionRepository;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.util.List;
11 |
12 | @Service
13 | public class CourseServiceImpl implements CourseService{
14 |
15 | @Autowired
16 | private CourseRepository courseRepository;
17 |
18 | @Autowired
19 | private TransactionRepository transactionRepository;
20 |
21 | @Override
22 | public List allCourses() {
23 | return courseRepository.findAll();
24 | }
25 |
26 | @Override
27 | public Course findCourseById(Long courseId) {
28 | return courseRepository.findById(courseId).orElse(null);
29 | }
30 |
31 | @Override
32 | public List findTransactionsOfUser(Long userId) {
33 | return transactionRepository.findAllByUserId(userId);
34 | }
35 |
36 | @Override
37 | public List findTransactionsOfCourse(Long courseId) {
38 | return transactionRepository.findAllByCourseId(courseId);
39 | }
40 |
41 | @Override
42 | public Transaction saveTransaction(Transaction transaction) {
43 | return transactionRepository.save(transaction);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=course-service
2 | server.port=8001
3 |
4 | #datasource
5 | spring.datasource.url=jdbc:mysql://localhost:3306/micro_course?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=UTC&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=true
6 | #you should change them according to your credentials.
7 | spring.datasource.username=root
8 | spring.datasource.password=1234
9 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
10 |
11 | #disable hibernate auto ddl changes
12 | spring.jpa.hibernate.ddl-auto=none
13 |
14 | #liquibase
15 | spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.xml
16 |
17 |
18 | #eureka
19 | eureka.client.service-url.default-zone=http://localhost:8761/eureka/
20 | #indicates the frequency the client sends heartbeats to server to indicate that it is alive.
21 | eureka.instance.lease-renewal-interval-in-seconds=30
22 | #indicates the duration the server waits since it received the last heartbeat before it can evict an instance from its registry.
23 | eureka.instance.lease-expiration-duration-in-seconds=90
24 |
25 | #load balancing
26 | ribbon.eureka.enabled=true
--------------------------------------------------------------------------------
/microservice-course-management/src/main/resources/db/changelog/db.changelog-1.0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 | CREATE TABLE course (
13 | id BIGINT NOT NULL AUTO_INCREMENT,
14 | title VARCHAR(255) NOT NULL,
15 | author VARCHAR(255) NOT NULL,
16 | category VARCHAR(255),
17 | publish_date DATE,
18 | CONSTRAINT pk_id PRIMARY KEY (id)
19 | );
20 |
21 |
22 | DROP TABLE course;
23 |
24 |
25 |
26 |
27 | CREATE TABLE transaction (
28 | id BIGINT NOT NULL AUTO_INCREMENT,
29 | course_id BIGINT NOT NULL,
30 | user_id BIGINT NOT NULL,
31 | date_of_issue DATETIME,
32 | CONSTRAINT pk_id PRIMARY KEY (id),
33 | CONSTRAINT fk_tran_course FOREIGN KEY (course_id) REFERENCES course(id) ON DELETE CASCADE ON UPDATE CASCADE
34 | );
35 |
36 |
37 | DROP TABLE transaction;
38 |
39 |
40 |
41 |
42 | INSERT INTO course (title, author, category, publish_date) VALUES('Microservices', 'Instructor 1', 'Programming', NOW());
43 | INSERT INTO course (title, author, category, publish_date) VALUES('Java Programming', 'Instructor 2', 'Programming', NOW());
44 | INSERT INTO course (title, author, category, publish_date) VALUES('Web Development', 'Instructor 3', 'Web', NOW());
45 | INSERT INTO course (title, author, category, publish_date) VALUES('Mobile Application', 'Instructor 4', 'Mobile', NOW());
46 | INSERT INTO course (title, author, category, publish_date) VALUES('Amazon Web Services', 'Instructor 5', 'Administration', NOW());
47 |
48 |
49 | TRUNCATE TABLE course;
50 |
51 |
52 |
--------------------------------------------------------------------------------
/microservice-course-management/src/main/resources/db/changelog/db.changelog-master.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/microservice-course-management/src/test/java/com/sha/microservicecoursemanagement/MicroserviceCourseManagementApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.sha.microservicecoursemanagement;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class MicroserviceCourseManagementApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/microservice-user-management/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/microservice-user-management/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**
6 | !**/src/test/**
7 |
8 | ### STS ###
9 | .apt_generated
10 | .factorypath
11 | .springBeans
12 | .sts4-cache
13 |
14 | ### IntelliJ IDEA ###
15 | .idea
16 | *.iws
17 | *.iml
18 | *.ipr
19 | out/
20 |
21 | ### NetBeans ###
22 | /nbproject/private/
23 | /nbbuild/
24 | /dist/
25 | /nbdist/
26 | /.nb-gradle/
27 |
28 | ### VS Code ###
29 | .vscode/
30 |
--------------------------------------------------------------------------------
/microservice-user-management/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | microservice-user-management
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/microservice-user-management/README.md:
--------------------------------------------------------------------------------
1 | # User-Service
2 |
3 | This project is a Spring Boot, MySQL, Hibernate and Liquibase project.
4 |
5 | ## Development server
6 |
7 | Run `User-Service Main class` for a dev server. Navigate to `http://localhost:8000/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Build
10 |
11 | Run `gradlew clean build`
12 |
13 | java -Djava.security.egd=file:/dev/./urandom -jar app.jar
14 |
--------------------------------------------------------------------------------
/microservice-user-management/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'org.springframework.boot' version '2.1.6.RELEASE'
3 | id 'java'
4 | }
5 |
6 | apply plugin: 'io.spring.dependency-management'
7 |
8 | group = 'com.sha'
9 | version = '0.0.1-SNAPSHOT'
10 | //You should change it according to your java version.
11 | sourceCompatibility = '1.8'
12 |
13 | configurations {
14 | compileOnly {
15 | extendsFrom annotationProcessor
16 | }
17 | }
18 |
19 | repositories {
20 | mavenCentral()
21 | }
22 |
23 | ext {
24 | set('springCloudVersion', "Greenwich.SR1")
25 | }
26 |
27 | dependencies {
28 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
29 | implementation 'org.springframework.boot:spring-boot-starter-data-rest'
30 | implementation 'org.springframework.boot:spring-boot-starter-security'
31 | implementation 'org.springframework.boot:spring-boot-starter-web'
32 | implementation 'org.liquibase:liquibase-core'
33 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
34 | compileOnly 'org.projectlombok:lombok'
35 | runtimeOnly 'mysql:mysql-connector-java'
36 | annotationProcessor 'org.projectlombok:lombok'
37 | testImplementation 'org.springframework.boot:spring-boot-starter-test'
38 | testImplementation 'org.springframework.security:spring-security-test'
39 | }
40 |
41 | dependencyManagement {
42 | imports {
43 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/microservice-user-management/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senolatac/react-springboot-microservices/727c78ecccb63509325a03f48b7f6624bde6341b/microservice-user-management/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/microservice-user-management/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/microservice-user-management/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS='"-Xmx64m"'
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/microservice-user-management/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS="-Xmx64m"
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/microservice-user-management/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | }
5 | }
6 | rootProject.name = 'microservice-user-management'
7 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/MicroserviceUserManagementApplication.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 |
7 | @SpringBootApplication
8 | @EnableDiscoveryClient
9 | public class MicroserviceUserManagementApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(MicroserviceUserManagementApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.config;
2 |
3 | import com.sha.microserviceusermanagement.service.UserDetailServiceImpl;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
11 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
12 | import org.springframework.security.crypto.password.PasswordEncoder;
13 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
14 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
15 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
16 |
17 | @Configuration
18 | @EnableWebSecurity
19 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
20 |
21 | @Autowired
22 | private UserDetailServiceImpl userDetailsService;
23 |
24 | @Bean
25 | public PasswordEncoder passwordEncoder(){
26 | return new BCryptPasswordEncoder();
27 | }
28 |
29 | @Override
30 | protected void configure(HttpSecurity http) throws Exception {
31 | //Cross origin resource sharing
32 | http.cors().and()
33 | //starts authorizing configurations.
34 | .authorizeRequests()
35 | //ignoring the guest's urls...
36 | .antMatchers("/resources/**", "/error", "/service/**").permitAll()
37 | //authenticate all remaining URLs.
38 | .anyRequest().fullyAuthenticated()
39 | .and()
40 | .logout().permitAll()
41 | .logoutRequestMatcher(new AntPathRequestMatcher("/service/logout", "POST"))
42 | //login form
43 | .and()
44 | .formLogin().loginPage("/service/login").and()
45 | //enable basic header authentication.
46 | .httpBasic().and()
47 | //cross-side request forgery.
48 | .csrf().disable();
49 | }
50 |
51 | @Override
52 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
53 | auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
54 | }
55 |
56 | @Bean
57 | public WebMvcConfigurer corsConfigurer(){
58 | return new WebMvcConfigurer() {
59 | @Override
60 | public void addCorsMappings(CorsRegistry registry) {
61 | registry.addMapping("/**").allowedOrigins("*");
62 | }
63 | };
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.controller;
2 |
3 | import com.sha.microserviceusermanagement.model.Role;
4 | import com.sha.microserviceusermanagement.model.User;
5 | import com.sha.microserviceusermanagement.service.UserService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.beans.factory.annotation.Value;
8 | import org.springframework.cloud.client.discovery.DiscoveryClient;
9 | import org.springframework.core.env.Environment;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.*;
13 |
14 | import javax.servlet.http.HttpServletRequest;
15 | import java.security.Principal;
16 | import java.util.List;
17 |
18 | @RestController
19 | public class UserController {
20 |
21 | @Autowired
22 | private UserService userService;
23 |
24 | @Autowired
25 | private DiscoveryClient discoveryClient;
26 |
27 | @Autowired
28 | private Environment env;
29 |
30 | @Value("${spring.application.name}")
31 | private String serviceId;
32 |
33 | @GetMapping("/service/port")
34 | public String getPort(){
35 | return "Service port number : " + env.getProperty("local.server.port");
36 | }
37 |
38 | @GetMapping("/service/instances")
39 | public ResponseEntity> getInstances(){
40 | return new ResponseEntity<>(discoveryClient.getInstances(serviceId), HttpStatus.OK);
41 | }
42 |
43 | @GetMapping("/service/services")
44 | public ResponseEntity> getServices(){
45 | return new ResponseEntity<>(discoveryClient.getServices(), HttpStatus.OK);
46 | }
47 |
48 | @PostMapping("/service/registration")
49 | public ResponseEntity> saveUser(@RequestBody User user){
50 | if(userService.findByUsername(user.getUsername()) != null){
51 | //Status Code: 409
52 | return new ResponseEntity<>(HttpStatus.CONFLICT);
53 | }
54 | //Default role = user
55 | user.setRole(Role.USER);
56 | return new ResponseEntity<>(userService.save(user), HttpStatus.CREATED);
57 | }
58 |
59 | @GetMapping("/service/login")
60 | public ResponseEntity> getUser(Principal principal){
61 | //Principal principal = request.getUserPrincipal();
62 | if(principal == null || principal.getName() == null){
63 | //This means; logout will be successful. login?logout
64 | return new ResponseEntity<>(HttpStatus.OK);
65 | }
66 | //username = principal.getName()
67 | return ResponseEntity.ok(userService.findByUsername(principal.getName()));
68 | }
69 |
70 | @PostMapping("/service/names")
71 | public ResponseEntity> getNamesOfUsers(@RequestBody List idList){
72 | return ResponseEntity.ok(userService.findUsers(idList));
73 | }
74 |
75 | @GetMapping("/service/test")
76 | public ResponseEntity> test(){
77 | return ResponseEntity.ok("It is working...");
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/model/Role.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.model;
2 |
3 | public enum Role {
4 | USER,
5 | ADMIN
6 | }
7 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/model/User.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.model;
2 |
3 | import lombok.Data;
4 |
5 | import javax.persistence.*;
6 |
7 | @Data
8 | @Entity
9 | @Table(name = "user")
10 | public class User {
11 |
12 | @Id
13 | //Generation Types:
14 | //Auto: Default one. It does not take any specific action.
15 | //Identity: Auto increment.
16 | //Sequence: Oracle or Posgresql creates variable to auto increment.
17 | //Table: Hibernate uses a database table to simulate a sequence.
18 | @GeneratedValue(strategy = GenerationType.IDENTITY)
19 | private Long id;
20 |
21 | @Column(name = "name")
22 | private String name;
23 |
24 | @Column(name = "username")
25 | private String username;
26 |
27 | @Column(name = "password")
28 | private String password;
29 |
30 | @Enumerated(value = EnumType.STRING)
31 | @Column(name = "role")
32 | private Role role;
33 | }
34 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.repository;
2 |
3 | import com.sha.microserviceusermanagement.model.User;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.data.jpa.repository.Query;
6 | import org.springframework.data.repository.query.Param;
7 |
8 | import java.util.List;
9 | import java.util.Optional;
10 |
11 | public interface UserRepository extends JpaRepository {
12 |
13 | Optional findByUsername(String username);
14 |
15 | @Query("select u.name from User u where u.id in (:pIdList)")
16 | List findByIdList(@Param("pIdList") List idList);
17 | }
18 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/service/UserDetailServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.service;
2 |
3 | import com.sha.microserviceusermanagement.model.User;
4 | import com.sha.microserviceusermanagement.repository.UserRepository;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.GrantedAuthority;
7 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
8 | import org.springframework.security.core.userdetails.UserDetails;
9 | import org.springframework.security.core.userdetails.UserDetailsService;
10 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
11 | import org.springframework.stereotype.Service;
12 |
13 | import java.util.HashSet;
14 | import java.util.Set;
15 |
16 | @Service
17 | public class UserDetailServiceImpl implements UserDetailsService {
18 |
19 | @Autowired
20 | private UserRepository userRepository;
21 |
22 | @Override
23 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
24 | User user = userRepository.findByUsername(username).orElse(null);
25 | if(user == null){
26 | throw new UsernameNotFoundException(username);
27 | }
28 | Set authorities = new HashSet<>();
29 | authorities.add(new SimpleGrantedAuthority(user.getRole().name()));
30 |
31 | return new org.springframework.security.core.userdetails.User(username, user.getPassword(), authorities);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.service;
2 |
3 | import com.sha.microserviceusermanagement.model.User;
4 |
5 | import java.util.List;
6 |
7 | public interface UserService {
8 | User save(User user);
9 |
10 | User findByUsername(String username);
11 |
12 | List findUsers(List idList);
13 | }
14 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/java/com/sha/microserviceusermanagement/service/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement.service;
2 |
3 | import com.sha.microserviceusermanagement.model.User;
4 | import com.sha.microserviceusermanagement.repository.UserRepository;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.crypto.password.PasswordEncoder;
7 | import org.springframework.stereotype.Service;
8 |
9 | import java.util.List;
10 |
11 | @Service
12 | public class UserServiceImpl implements UserService {
13 |
14 | @Autowired
15 | private UserRepository userRepository;
16 |
17 | //We will create bean for it in security config.
18 | @Autowired
19 | private PasswordEncoder passwordEncoder;
20 |
21 | @Override
22 | public User save(User user){
23 | user.setPassword(passwordEncoder.encode(user.getPassword()));
24 | return userRepository.save(user);
25 | }
26 |
27 | @Override
28 | public User findByUsername(String username){
29 | return userRepository.findByUsername(username).orElse(null);
30 | }
31 |
32 | @Override
33 | public List findUsers(List idList){
34 | return userRepository.findByIdList(idList);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8000
2 | spring.application.name=user-service
3 | spring.datasource.url=jdbc:mysql://localhost:3306/micro_user?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=UTC&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=false
4 | spring.datasource.username=root
5 | spring.datasource.password=1234
6 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
7 |
8 | #none,create,update,validate
9 | spring.jpa.hibernate.ddl-auto=none
10 |
11 | #liquibase
12 | spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.xml
13 |
14 | #eureka
15 | eureka.client.service-url.default-zone=http://localhost:8761/eureka/
16 | #indicates the frequency the client sends heartbeat to server to indicate that it is alive.
17 | eureka.instance.lease-renewal-interval-in-seconds=30
18 | #indicates the duration the server waits since it received the last heartbeat before it can evict an instance from its registry
19 | eureka.instance.lease-expiration-duration-in-seconds=90
20 |
21 | #load balancing
22 | ribbon.eureka.enabled=true
--------------------------------------------------------------------------------
/microservice-user-management/src/main/resources/db/changelog/db.changelog-1.0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 | CREATE TABLE user (
13 | id BIGINT NOT NULL AUTO_INCREMENT,
14 | username VARCHAR(255) NOT NULL,
15 | password VARCHAR(255) NOT NULL,
16 | name VARCHAR(255) NOT NULL,
17 | role VARCHAR(10) NOT NULL,
18 | CONSTRAINT pk_id PRIMARY KEY (id)
19 | );
20 |
21 |
22 | DROP TABLE user;
23 |
24 |
25 |
26 |
27 |
28 | ALTER TABLE user ADD email varchar(255);
29 |
30 |
31 | ALTER TABLE user DROP COLUMN email;
32 |
33 |
34 |
--------------------------------------------------------------------------------
/microservice-user-management/src/main/resources/db/changelog/db.changelog-master.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/microservice-user-management/src/test/java/com/sha/microserviceusermanagement/MicroserviceUserManagementApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.sha.microserviceusermanagement;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class MicroserviceUserManagementApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/zuul-gateway-service/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/zuul-gateway-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | .gradle
3 | build/
4 | !gradle/wrapper/gradle-wrapper.jar
5 | !**/src/main/**
6 | !**/src/test/**
7 |
8 | ### STS ###
9 | .apt_generated
10 | .factorypath
11 | .springBeans
12 | .sts4-cache
13 |
14 | ### IntelliJ IDEA ###
15 | .idea
16 | *.iws
17 | *.iml
18 | *.ipr
19 | out/
20 |
21 | ### NetBeans ###
22 | /nbproject/private/
23 | /nbbuild/
24 | /dist/
25 | /nbdist/
26 | /.nb-gradle/
27 |
28 | ### VS Code ###
29 | .vscode/
30 |
--------------------------------------------------------------------------------
/zuul-gateway-service/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | zuul-gateway-service
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/zuul-gateway-service/README.md:
--------------------------------------------------------------------------------
1 | # Gateway-Service
2 |
3 | This project is a Spring Boot, Spring Zuul project.
4 |
5 | ## Development server
6 |
7 | Run `Gateway-Service Main class` for a dev server. Navigate to `http://localhost:8765/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Build
10 |
11 | Run `gradlew clean build`
12 |
13 | java -Djava.security.egd=file:/dev/./urandom -jar app.jar
14 |
--------------------------------------------------------------------------------
/zuul-gateway-service/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'org.springframework.boot' version '2.1.6.RELEASE'
3 | id 'java'
4 | }
5 |
6 | apply plugin: 'io.spring.dependency-management'
7 |
8 | group = 'com.sha'
9 | version = '0.0.1-SNAPSHOT'
10 | sourceCompatibility = '1.8'
11 |
12 | repositories {
13 | mavenCentral()
14 | }
15 |
16 | ext {
17 | set('springCloudVersion', "Greenwich.SR2")
18 | }
19 |
20 | dependencies {
21 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
22 | implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul'
23 | testImplementation 'org.springframework.boot:spring-boot-starter-test'
24 | }
25 |
26 | dependencyManagement {
27 | imports {
28 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/zuul-gateway-service/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/senolatac/react-springboot-microservices/727c78ecccb63509325a03f48b7f6624bde6341b/zuul-gateway-service/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/zuul-gateway-service/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/zuul-gateway-service/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS='"-Xmx64m"'
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/zuul-gateway-service/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS="-Xmx64m"
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/zuul-gateway-service/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | }
5 | }
6 | rootProject.name = 'zuul-gateway-service'
7 |
--------------------------------------------------------------------------------
/zuul-gateway-service/src/main/java/com/sha/zuulgatewayservice/ZuulGatewayServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.sha.zuulgatewayservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
10 |
11 | @SpringBootApplication
12 | @EnableZuulProxy
13 | @EnableEurekaClient
14 | public class ZuulGatewayServiceApplication {
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(ZuulGatewayServiceApplication.class, args);
18 | }
19 |
20 | @Bean
21 | public WebMvcConfigurer corsConfigurer() {
22 | return new WebMvcConfigurer() {
23 | @Override
24 | public void addCorsMappings(CorsRegistry registry) {
25 | registry.addMapping("/**").allowedOrigins("*");
26 | }
27 | };
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/zuul-gateway-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=gateway-service
2 | server.port=8765
3 |
4 | zuul.ignored-headers=Access-Control-Allow-Credentials, Access-Control-Allow-Origin
5 | #Pass the headers from gateway to sub-microservices.
6 | zuul.sensitiveHeaders=Cookie,Set-Cookie
7 |
8 | zuul.prefix=/api
9 | #When path starts with /api/user/**, redirect it to user-service.
10 | zuul.routes.user.path=/user/**
11 | zuul.routes.user.serviceId=user-service
12 | #When path starts with /api/course/**, redirect it to course-service.
13 | zuul.routes.course.path=/course/**
14 | zuul.routes.course.serviceId=course-service
15 |
16 | #eureka
17 | eureka.client.service-url.default-zone=http://localhost:8761/eureka/
18 | #indicates the frequency the client sends heartbeats to indicate that it is still alive.
19 | eureka.instance.lease-renewal-interval-in-seconds=30
20 | #indicates the duration the server waits since it received the last heartbeat before it can evict an instance from its registry
21 | eureka.instance.lease-expiration-duration-in-seconds=90
22 |
23 | #load balancing
24 | ribbon.eureka.enabled=true
25 |
26 | #timeout
27 | #this will help you load services eagerly. Otherwise for first time, we will get timeout exception.
28 | zuul.ribbon.eager-load.enabled=true
29 | #The read timeout in milliseconds. Default is 1000ms
30 | ribbon.ReadTimeout=60000
31 | #The Connection timeout in milliseconds. Default is 1000ms.
32 | ribbon.ConnectTimeout=10000
--------------------------------------------------------------------------------
/zuul-gateway-service/src/test/java/com/sha/zuulgatewayservice/ZuulGatewayServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.sha.zuulgatewayservice;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ZuulGatewayServiceApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------