Compare commits

...

54 Commits

Author SHA1 Message Date
Fabio Formosa
e0011913c2 bump version to 4.0.9 2024-02-06 23:58:07 +01:00
Fabio Formosa
a59b6a6c96 #115 fixed the liquibase DB migration execution 2024-02-06 23:43:54 +01:00
Fabio Formosa
68aaab6ac4 #115 fixed the liquibase DB migration execution 2024-02-06 23:42:38 +01:00
Fabio Formosa
a1d8b12e98 Merge pull request #112 from fabioformosa/feature/#109_configure_trigger_job_data
Feature/#109 configure trigger job data
2024-02-02 23:59:20 +01:00
Fabio Formosa
45d6a4c59a Merge branch 'feature/#109_configure_trigger_job_data' of github.com:fabioformosa/quartz-manager into feature/#109_configure_trigger_job_data 2024-02-02 23:54:31 +01:00
Midhun A Darvin
e6f6fb5f06 feat: configure Trigger JobData
- add `jobDataMap` property to SimpleTriggerInputDTO
- update SimpleTriggerCommandDTOToSimpleTrigger converter
- update SimpleTriggerToSimpleTriggerDTO converter
- update unit tests
- add .idea and .iml to .gitignore for ignoring intellij files
2024-02-02 23:43:27 +01:00
Fabio Formosa
13c438d097 Merge branch 'master' into develop 2024-02-02 23:38:22 +01:00
Fabio Formosa
75d630aad0 Merge pull request #110 from midhunadarvin/feat/configure-trigger-job-data
feat: configure `Trigger` JobDataMap
2024-02-02 22:56:20 +01:00
Midhun A Darvin
9eddc0b1fd feat: configure Trigger JobData
- add `jobDataMap` property to SimpleTriggerInputDTO
- update SimpleTriggerCommandDTOToSimpleTrigger converter
- update SimpleTriggerToSimpleTriggerDTO converter
- update unit tests
- add .idea and .iml to .gitignore for ignoring intellij files
2024-02-02 13:11:00 +05:30
Fabio Formosa
fa4ede5179 Merge pull request #108 from midhunadarvin/feat/configure-auto-startup
feat: make autoStartup configurable for SchedulerFactoryBean
2024-02-01 00:24:21 +01:00
Fabio Formosa
3aa672031a Updated the sonarcloud.io integration 2024-01-31 23:40:26 +01:00
Midhun A Darvin
82ca186bff feat: make autoStartup configurable for SchedulerFactoryBean
- check property `org.quartz.scheduler.isAutoStartup` and enable autoStartup if it is true
2024-01-31 13:28:15 +05:30
Fabio Formosa
527ee1200a #103 added some comments 2022-12-11 20:38:55 +01:00
Fabio Formosa
82a60eb651 Update README.md 2022-12-10 16:59:31 +01:00
Fabio Formosa
7fd174b313 bump version to 4.0.9-SNAPSHOT 2022-12-10 16:56:05 +01:00
Fabio Formosa
7c910196e1 upgraded README and CHANGELOG 2022-12-10 16:54:50 +01:00
Fabio Formosa
554e7e5e25 #80 bump version to 4.0.8 2022-12-10 16:39:26 +01:00
Fabio Formosa
8b70319436 #80 upgraded node and npm into the quartz-manager-starter-ui 2022-12-10 16:38:34 +01:00
Fabio Formosa
053f196b6b Merge pull request #100 from fabioformosa/develop
v4.0.7
2022-12-10 16:29:16 +01:00
Fabio Formosa
86f8cc8347 bump version to 4.0.7 2022-12-10 16:25:17 +01:00
Fabio Formosa
e91d02ba9f #80 added moment to the allowed commonJS module 2022-12-10 16:19:39 +01:00
Fabio Formosa
109d2868d9 #80 upgraded to the new linter and added prettier 2022-12-10 16:15:00 +01:00
Fabio Formosa
4673e41fc5 #80 removed unnecessary asterisks 2022-12-10 14:53:35 +01:00
Fabio Formosa
a2122351d6 #80 removed extractCss 2022-12-10 13:31:45 +01:00
Fabio Formosa
375aaf71d3 #80 fixed the build command as angular v14 2022-12-10 13:25:14 +01:00
Fabio Formosa
b752af948d #80 downgraded jest to v28 2022-12-10 13:21:18 +01:00
Fabio Formosa
52ed016073 #80 fixed tests 2022-12-10 12:20:57 +01:00
Fabio Formosa
632288726b #80 upgraded some deps 2022-12-10 11:55:00 +01:00
Fabio Formosa
1dc9bee987 #80 upgraded to angular v14 2022-12-10 11:27:14 +01:00
Fabio Formosa
387c440e06 #80 step into angular v14 2022-12-10 11:20:01 +01:00
Fabio Formosa
136afa0fca #80 step into angular v14 2022-12-10 11:17:39 +01:00
Fabio Formosa
8ba3daa2f0 #80 upgraded angular to v13 2022-12-08 00:15:48 +01:00
Fabio Formosa
b3fe337203 #80 upgraded angular to v13 2022-12-08 00:15:39 +01:00
Fabio Formosa
da7375ea0d #80 first step to angular v13 2022-12-07 00:38:30 +01:00
Fabio Formosa
d9487d1106 #80 completed the migration to angular12 2022-12-07 00:37:25 +01:00
Fabio Formosa
3110496630 #80 completed the migration to angular12 2022-12-07 00:36:59 +01:00
Fabio Formosa
22e90dc7d1 #80 step into angular v12 2022-12-07 00:29:20 +01:00
Fabio Formosa
5943243e62 #80 step into angular v12 2022-12-07 00:27:20 +01:00
Fabio Formosa
1244a64d34 #80 fixes for angular v11 2022-12-07 00:25:50 +01:00
Fabio Formosa
40a6ecd159 #80 fixes for angular v11 2022-12-07 00:24:56 +01:00
Fabio Formosa
9df68dccac #80 first step to angular v11 2022-12-06 23:35:35 +01:00
Fabio Formosa
72bba6f80c #80 reverted deps to angular 10 2022-12-06 23:29:29 +01:00
Fabio Formosa
cf803bb1dd #80 reverted deps to angular 10 2022-12-06 23:29:13 +01:00
Fabio Formosa
13c78ed5d3 #80 removed the package-lock.json 2022-12-06 23:19:08 +01:00
Fabio Formosa
3bd878a978 #80 reverted deps to angular 10 2022-12-06 23:14:45 +01:00
Fabio Formosa
c9d3528f4b #80 reverted deps to angular 10 2022-12-06 23:14:32 +01:00
Fabio Formosa
3b2f8fc780 #80 reverted deps to angular 10 2022-12-06 23:08:17 +01:00
Fabio Formosa
bc3da09d60 #80 step into angular upgrade to v11 2022-12-06 19:33:42 +01:00
Fabio Formosa
284f56302c #80 fixed tests 2022-12-06 01:08:17 +01:00
Fabio Formosa
cdd5047bbc #80 jest setup fix for angular 10 2022-12-06 00:39:45 +01:00
Fabio Formosa
5d3ba95bd9 #80 upgraded angular to v10 2022-12-05 23:42:36 +01:00
Fabio Formosa
ec384113eb angular material upgrade to v4 2022-12-05 23:36:36 +01:00
Fabio Formosa
8b2651876c new package-lock.json 2022-12-05 23:31:55 +01:00
Fabio Formosa
a3852c421e bump version to 4.0.7-SNAPSHOT 2022-12-05 23:09:51 +01:00
51 changed files with 28032 additions and 12520 deletions

View File

@@ -7,27 +7,27 @@ on:
# paths: [ 'quartz-manager-parent/**' ]
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build and analyze
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 11
uses: actions/setup-java@v1
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: 11
java-version: 17
distribution: 'zulu' # Alternative distribution options are available.
- name: Cache SonarCloud packages
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

2
.gitignore vendored
View File

@@ -1 +1,3 @@
/.project
.idea
*.iml

View File

@@ -1,3 +1,23 @@
## **v4.0.9**
Fixed a bug which prevented to run the liquibase migration scripts in case of usage of quartz-manager-starter-persistence
## **v4.0.8**
Upgraded the frontend to angular v14
## **v4.0.6**
Minor bug fixes
## **v4.0.5**
Fixed potential security issues
## **v4.0.4**
* Conformed the trigger configuration to the Simple Trigger of Quartz
* **BREAKING CHANGE** Changed accordingly the API and the UI
* Made Quartz Manager embeddable in projects with existing quartz instance, security layer, swagger ui.
## **v3.1.0**
* Added a new persistence module to persist the quartz triggers in a postgresql database
## **v3.0.1**
Quartz-Manager is now publicly available into the maven central repo into 3 different packages.

View File

@@ -80,12 +80,12 @@ Add the dependency, make eligible for Quart Manager the job classes and set the
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-api</artifactId>
<version>4.0.5</version>
<version>4.0.8</version>
</dependency>
```
#### Gradle
```
implementation group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-api', version: '4.0.5'
implementation group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-api', version: '4.0.8'
```
### Step 2. Quartz Manager Job Classes
@@ -168,12 +168,12 @@ You can optionally import the following dependency to have the UI Dashboard to i
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-ui</artifactId>
<version>4.0.5</version>
<version>4.0.8</version>
</dependency>
```
#### Gradle
```
implementation group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-ui', version: '4.0.5'
implementation group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-ui', version: '4.0.8'
```
### Reach out the UI Console at URL
@@ -203,14 +203,14 @@ Future development: the Quart Manager Security OAuth2 client.
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-security</artifactId>
<version>4.0.5</version>
<version>4.0.8</version>
</dependency>
```
#### Gradle
```
compile group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-security', version: '4.0.5'
compile group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-security', version: '4.0.8'
```
@@ -240,14 +240,14 @@ The pre-requesite is the availability of Postgresql database where Quartz Manage
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-persistence</artifactId>
<version>4.0.5</version>
<version>4.0.8</version>
</dependency>
```
#### Gradle
```
compile group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-persistence', version: '4.0.5'
compile group: 'it.fabioformosa.quartz-manager', name: 'quartz-manager-starter-persistence', version: '4.0.8'
```
### Quartz Manager Persistence Lib - App Props

View File

@@ -0,0 +1,214 @@
/*
👋 Hi! This file was autogenerated by tslint-to-eslint-config.
https://github.com/typescript-eslint/tslint-to-eslint-config
It represents the closest reasonable ESLint configuration to this
project's original TSLint configuration.
We recommend eventually switching this configuration to extend from
the recommended rulesets in typescript-eslint.
https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md
Happy linting! 💖
*/
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
},
"plugins": [
"eslint-plugin-import",
"@angular-eslint/eslint-plugin",
"@typescript-eslint",
"@typescript-eslint/tslint"
],
"root": true,
"rules": {
"@angular-eslint/component-class-suffix": "error",
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
],
"@angular-eslint/directive-class-suffix": "error",
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "error",
"@angular-eslint/no-input-rename": "error",
"@angular-eslint/no-inputs-metadata-property": "error",
"@angular-eslint/no-output-rename": "error",
"@angular-eslint/no-outputs-metadata-property": "error",
"@angular-eslint/use-lifecycle-interface": "error",
"@angular-eslint/use-pipe-transform-interface": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/indent": "off",
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/member-ordering": "error",
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"format": [
"camelCase",
"UPPER_CASE"
],
"leadingUnderscore": "forbid",
"trailingUnderscore": "forbid"
}
],
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-inferrable-types": [
"error",
{
"ignoreParameters": true
}
],
"@typescript-eslint/no-shadow": [
"error",
{
"hoist": "all"
}
],
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/quotes": [
"error",
"single"
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/tslint/config": [
"error",
{
"rules": {
"import-spacing": true,
"invoke-injectable": true,
"no-access-missing-member": true,
"templates-use-public": true,
"whitespace": true
}
}
],
"@typescript-eslint/type-annotation-spacing": "off",
"@typescript-eslint/unified-signatures": "error",
"brace-style": [
"error",
"1tbs"
],
"curly": "error",
"dot-notation": "off",
"eol-last": "off",
"eqeqeq": [
"error",
"smart"
],
"guard-for-in": "error",
"id-denylist": "off",
"id-match": "off",
"import/no-deprecated": "warn",
"indent": "off",
"max-len": [
"error",
{
"code": 140
}
],
"no-bitwise": "error",
"no-caller": "error",
"no-console": [
"error",
{
"allow": [
"log",
"warn",
"dir",
"timeLog",
"assert",
"clear",
"count",
"countReset",
"group",
"groupEnd",
"table",
"dirxml",
"error",
"groupCollapsed",
"Console",
"profile",
"profileEnd",
"timeStamp",
"context"
]
}
],
"no-debugger": "error",
"no-empty": "off",
"no-empty-function": "off",
"no-eval": "error",
"no-fallthrough": "error",
"no-new-wrappers": "error",
"no-redeclare": "error",
"no-restricted-imports": "error",
"no-shadow": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "off",
"no-underscore-dangle": "off",
"no-unused-expressions": "off",
"no-unused-labels": "error",
"no-var": "error",
"prefer-const": "error",
"quotes": "off",
"radix": "error",
"semi": "off",
"spaced-comment": [
"error",
"always",
{
"markers": [
"/"
]
}
],
"valid-typeof": "error"
}
}

View File

@@ -40,3 +40,4 @@ testem.log
# System Files
.DS_Store
Thumbs.db
/.angular/

View File

@@ -0,0 +1,47 @@
src/polyfills.ts
src/typings.d.ts
_test.ts
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# dependencies
/node_modules
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
# System Files
.DS_Store
Thumbs.db
/.angular/

View File

@@ -0,0 +1,11 @@
{
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": true,
"bracketSpacing": true,
"arrowParens": "avoid",
"trailingComma": "es5",
"bracketSameLine": true,
"printWidth": 80
}

View File

@@ -18,6 +18,9 @@
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"allowedCommonJsDependencies": [
"stompjs", "sockjs-client", "moment"
],
"assets": [
"src/assets",
"src/favicon.ico"
@@ -38,7 +41,6 @@
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
@@ -71,13 +73,10 @@
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"builder": "@angular-eslint/builder:lint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": []
"eslintConfig": ".eslintrc.json",
"lintFilePatterns": ["**/*.spec.ts", "**/*.ts"]
}
}
}
@@ -106,7 +105,6 @@
}
}
},
"defaultProject": "angular-spring-starter",
"schematics": {
"@schematics/angular:component": {
"prefix": "qrzmng",
@@ -115,5 +113,8 @@
"@schematics/angular:directive": {
"prefix": "qrzmng"
}
},
"cli": {
"analytics": false
}
}

View File

@@ -1 +1 @@
import 'jest-preset-angular';
import 'jest-preset-angular/setup-jest';

File diff suppressed because it is too large Load Diff

View File

@@ -5,67 +5,81 @@
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build --prod",
"build": "ng build --configuration production",
"test": "jest",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular-material-components/datetime-picker": "2.0.4",
"@angular-material-components/moment-adapter": "2.0.2",
"@angular/animations": "9.1.4",
"@angular/cdk": "9.2.1",
"@angular/common": "9.1.4",
"@angular/compiler": "9.1.4",
"@angular/core": "9.1.4",
"@angular/flex-layout": "9.0.0-beta.29",
"@angular/forms": "9.1.4",
"@angular/material": "9.2.1",
"@angular/platform-browser": "9.1.4",
"@angular/platform-browser-dynamic": "9.1.4",
"@angular/platform-server": "9.1.4",
"@angular/router": "9.1.4",
"@auth0/angular-jwt": "^4.0.0",
"@angular-material-components/datetime-picker": "8.0.0",
"@angular-material-components/moment-adapter": "8.0.0",
"@angular/animations": "14.2.12",
"@angular/cdk": "^14.0.1",
"@angular/common": "14.2.12",
"@angular/compiler": "14.2.12",
"@angular/core": "14.2.12",
"@angular/flex-layout": "14.0.0-beta.41",
"@angular/forms": "14.2.12",
"@angular/material": "^14.0.1",
"@angular/platform-browser": "14.2.12",
"@angular/platform-browser-dynamic": "14.2.12",
"@angular/platform-server": "14.2.12",
"@angular/router": "14.2.12",
"@auth0/angular-jwt": "5.1.0",
"@fortawesome/fontawesome": "^1.1.4",
"@fortawesome/fontawesome-free-regular": "^5.0.8",
"@fortawesome/fontawesome-free-solid": "^5.0.8",
"@stomp/ng2-stompjs": "^0.6.3",
"@types/jest": "^27.0.2",
"core-js": "2.5.1",
"hammerjs": "2.0.8",
"moment": "^2.29.1",
"net": "^1.0.2",
"rxjs": "6.5.5",
"sockjs-client": "^1.1.1",
"stompjs": "^2.3.3",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
"tslib": "~2.4.1",
"zone.js": "~0.12.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.901.4",
"@angular-devkit/core": "^9.1.4",
"@angular/cli": "9.1.4",
"@angular/compiler-cli": "9.1.4",
"@angular/language-service": "9.1.4",
"@angular-devkit/build-angular": "14.2.10",
"@angular-devkit/core": "^14.2.10",
"@angular-eslint/builder": "14.4.0",
"@angular-eslint/eslint-plugin": "14.4.0",
"@angular-eslint/eslint-plugin-template": "14.4.0",
"@angular-eslint/schematics": "14.4.0",
"@angular-eslint/template-parser": "14.4.0",
"@angular/cli": "14.2.10",
"@angular/compiler-cli": "14.2.12",
"@angular/language-service": "14.2.12",
"@types/hammerjs": "2.0.34",
"@types/jasmine": "2.5.54",
"@types/jasminewd2": "2.0.3",
"@types/jest": "28.1.1",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"jasmine-core": "2.6.4",
"jasmine-spec-reporter": "4.1.1",
"jest": "^26.0.1",
"jest-preset-angular": "^8.2.0",
"karma": "1.7.1",
"karma-chrome-launcher": "2.1.1",
"karma-cli": "1.0.1",
"karma-coverage-istanbul-reporter": "1.3.0",
"karma-jasmine": "1.1.0",
"karma-jasmine-html-reporter": "0.2.2",
"protractor": "5.1.2",
"ts-node": "3.0.6",
"tslint": "5.7.0",
"typescript": "3.8.3"
"@typescript-eslint/eslint-plugin": "5.43.0",
"@typescript-eslint/eslint-plugin-tslint": "^5.46.0",
"@typescript-eslint/parser": "5.43.0",
"codelyzer": "~6.0.2",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"jasmine-core": "~4.5.0",
"jasmine-spec-reporter": "~7.0.0",
"jest": "28.1.3",
"jest-preset-angular": "~12.2.3",
"karma": "~6.4.1",
"karma-chrome-launcher": "~3.1.1",
"karma-cli": "2.0.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.0.0",
"prettier": "^2.8.1",
"prettier-eslint": "^15.0.1",
"protractor": "~7.0.0",
"ts-node": "10.9.1",
"typescript": "4.6.4"
},
"jest": {
"preset": "jest-preset-angular",

View File

@@ -46,7 +46,7 @@ export const routes: Routes = [
@NgModule({
imports: [RouterModule.forRoot(routes, {
initialNavigation: false
initialNavigation: 'disabled'
})],
exports: [RouterModule],
providers: []

View File

@@ -1,4 +1,4 @@
import { TestBed, async } from '@angular/core/testing';
import {TestBed, async, waitForAsync} from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
@@ -18,7 +18,7 @@ import {
} from './services';
describe('AppComponent', () => {
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent,

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { ComponentFixture, TestBed, inject, waitForAsync} from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
@@ -18,7 +18,7 @@ describe('AccountMenuComponent', () => {
let component: AccountMenuComponent;
let fixture: ComponentFixture<AccountMenuComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule

View File

@@ -1,4 +1,4 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {SchedulerControlComponent} from './scheduler-control.component';
import {ApiService, ConfigService, SchedulerService, UserService} from '../../services';
import {HttpClient} from '@angular/common/http';
@@ -19,7 +19,7 @@ describe('SchedulerControlComponent', () => {
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [MatCardModule, MatDividerModule, MatIconModule, HttpClientTestingModule, RouterTestingModule],
declarations: [SchedulerControlComponent],

View File

@@ -20,7 +20,7 @@
<mat-form-field
[appearance]="enabledTriggerForm && !trigger ? 'standard': 'none'"
class="full-size-input">
<mat-label>Trigger Name *</mat-label>
<mat-label>Trigger Name</mat-label>
<input id="triggerName"
[readonly]="!enabledTriggerForm || trigger"
matInput placeholder="name of the trigger (unique)"
@@ -36,7 +36,7 @@
[appearance]="enabledTriggerForm ? 'standard': 'none'"
class="full-size-input"
>
<mat-label>Job Class *</mat-label>
<mat-label>Job Class</mat-label>
<mat-select id="jobClass" name="jobClass" formControlName="jobClass" [disabled]="!enabledTriggerForm">
<mat-option *ngFor="let job of jobs" [value]="job" style="font-size: 0.8em">
{{job}}
@@ -53,7 +53,7 @@
[appearance]="enabledTriggerForm ? 'standard': 'none'"
class="full-size-input"
>
<mat-label>Misfire Instruction *</mat-label>
<mat-label>Misfire Instruction</mat-label>
<mat-select id="misfireInstruction" name="misfireInstruction" formControlName="misfireInstruction"
[disabled]="!enabledTriggerForm" style="font-size: 0.8em">
<mat-option value="MISFIRE_INSTRUCTION_FIRE_NOW">FIRE NOW</mat-option>
@@ -93,9 +93,6 @@
formControlName="startDate" name="startDate">
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #startDatePicker showSpinners="true" showSeconds="true">
<!-- [stepHour]="stepHour"-->
<!-- [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi" [color]="color"-->
<!-- [enableMeridian]="enableMeridian" [disableMinute]="disableMinute" [hideTime]="hideTime">-->
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
@@ -114,9 +111,6 @@
>
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #endDatePicker showSpinners="true" showSeconds="true">
<!-- [stepHour]="stepHour"-->
<!-- [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi" [color]="color"-->
<!-- [enableMeridian]="enableMeridian" [disableMinute]="disableMinute" [hideTime]="hideTime">-->
</ngx-mat-datetime-picker>
</mat-form-field>
<mat-error *ngIf="simpleTriggerReactiveForm.controls.triggerPeriod.errors?.invalidTriggerPeriod" style="font-size: small">
@@ -141,9 +135,6 @@
repeatCount and repeatInterval must be <strong>both</strong> set or unset
</mat-error>
</mat-form-field>
<!-- <mat-error *ngIf="simpleTriggerReactiveForm.controls.triggerRecurrence.errors?.invalidTriggerRecurrence" style="font-size: small">-->
<!-- repeatCount and repeatInterval must be <strong>both</strong> set or unset-->
<!-- </mat-error>-->
</div>
<div>
<mat-form-field

View File

@@ -1,4 +1,4 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {MatCardModule} from '@angular/material/card';
import {SimpleTriggerConfigComponent} from './simple-trigger-config.component';
import {ApiService, ConfigService, CONTEXT_PATH, SchedulerService} from '../../services';
@@ -12,7 +12,7 @@ import {FormBuilder, FormsModule, ReactiveFormsModule} from '@angular/forms';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatNativeDateModule} from '@angular/material/core';
import {MatInputModule} from '@angular/material/input';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {TriggerKey} from '../../model/triggerKey.model';
import {Trigger} from '../../model/trigger.model';
import {JobDetail} from '../../model/jobDetail.model';
@@ -29,9 +29,9 @@ describe('SimpleTriggerConfig', () => {
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
beforeEach(async( () => {
beforeEach(waitForAsync( () => {
TestBed.configureTestingModule({
imports: [FormsModule, MatFormFieldModule, MatFormFieldModule, MatSelectModule, MatInputModule, BrowserAnimationsModule,
imports: [FormsModule, MatFormFieldModule, MatFormFieldModule, MatSelectModule, MatInputModule, NoopAnimationsModule,
MatNativeDateModule, ReactiveFormsModule,
MatCardModule, MatIconModule, HttpClientTestingModule, RouterTestingModule],
declarations: [SimpleTriggerConfigComponent],
@@ -198,6 +198,10 @@ describe('SimpleTriggerConfig', () => {
it('should fetch and display the trigger when the triggerKey is passed as input', () => {
const mockTriggerKey = new TriggerKey('my-simple-trigger', null);
component.triggerKey = mockTriggerKey;
component.trigger = new SimpleTrigger();
component.trigger.triggerKeyDTO = mockTriggerKey;
fixture.detectChanges();
const mockTrigger = new Trigger();
@@ -226,6 +230,9 @@ describe('SimpleTriggerConfig', () => {
getJobsReq.flush([]);
fixture.detectChanges();
component.openTriggerForm();
fixture.detectChanges();
const componentDe: DebugElement = fixture.debugElement;
const warningCard = componentDe.query(By.css('#noEligibleJobsAlert'));
expect(warningCard).toBeTruthy();
@@ -237,6 +244,9 @@ describe('SimpleTriggerConfig', () => {
getJobsReq.flush(['sampleJob']);
fixture.detectChanges();
component.openTriggerForm();
fixture.detectChanges();
const componentDe: DebugElement = fixture.debugElement;
const warningCard = componentDe.query(By.css('#noEligibleJobsAlert'));
expect(warningCard).toBeFalsy();

View File

@@ -3,12 +3,11 @@ import {SchedulerService} from '../../services';
import {Scheduler} from '../../model/scheduler.model';
import {SimpleTriggerCommand} from '../../model/simple-trigger.command';
import {SimpleTrigger} from '../../model/simple-trigger.model';
import {SimpleTriggerForm} from '../../model/simple-trigger.form';
import * as moment from 'moment';
import {TriggerKey} from '../../model/triggerKey.model';
import JobService from '../../services/job.service';
import {MisfireInstruction, MisfireInstructionCaption} from '../../model/misfire-instruction.model';
import {AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators} from '@angular/forms';
import {AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidationErrors, Validators} from '@angular/forms';
@Component({
selector: 'qrzmng-simple-trigger-config',
@@ -17,9 +16,9 @@ import {AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors,
})
export class SimpleTriggerConfigComponent implements OnInit {
trigger: SimpleTrigger;
trigger: SimpleTrigger = null;
simpleTriggerReactiveForm: FormGroup = this.formBuilder.group({
simpleTriggerReactiveForm: UntypedFormGroup = this.formBuilder.group({
triggerName: [this.trigger?.triggerKeyDTO.name, Validators.required],
jobClass: [this.trigger?.jobDetailDTO.jobClassName, Validators.required],
triggerPeriod: this.formBuilder.group({
@@ -50,7 +49,7 @@ export class SimpleTriggerConfigComponent implements OnInit {
onNewTrigger = new EventEmitter<SimpleTrigger>();
constructor(
private formBuilder: FormBuilder,
private formBuilder: UntypedFormBuilder,
private schedulerService: SchedulerService,
private jobService: JobService
) {

View File

@@ -1,4 +1,4 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {ApiService, ConfigService, CONTEXT_PATH, TriggerService} from '../../services';
import {HttpClient} from '@angular/common/http';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
@@ -21,7 +21,7 @@ describe('TriggerListComponent', () => {
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [MatCardModule, MatDialogModule, MatDividerModule,
MatIconModule, MatListModule, HttpClientTestingModule, RouterTestingModule],

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {GenericErrorComponent} from './genericError.component';
@@ -6,7 +6,7 @@ describe('GenericComponent', () => {
let component: GenericErrorComponent;
let fixture: ComponentFixture<GenericErrorComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ GenericErrorComponent ]
})

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import { ForbiddenComponent } from './forbidden.component';
@@ -6,7 +6,7 @@ describe('ForbiddenComponent', () => {
let component: ForbiddenComponent;
let fixture: ComponentFixture<ForbiddenComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ForbiddenComponent ]
})

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { RouterTestingModule } from '@angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@@ -16,7 +16,7 @@ describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LoginComponent],
imports: [

View File

@@ -1,5 +1,5 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router';
import {DisplayMessage} from '../../shared/models/display-message';
import {Subject} from 'rxjs';
@@ -15,7 +15,7 @@ import {AuthService, UserService} from '../../services';
export class LoginComponent implements OnInit, OnDestroy {
title = 'Login';
githubLink = 'https://github.com/fabioformosa/quartz-manager';
form: FormGroup;
form: UntypedFormGroup;
submitted = false;
@@ -29,7 +29,7 @@ export class LoginComponent implements OnInit, OnDestroy {
private authService: AuthService,
private router: Router,
private route: ActivatedRoute,
private formBuilder: FormBuilder
private formBuilder: UntypedFormBuilder
) {
}

View File

@@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import { NotFoundComponent } from './not-found.component';
@@ -6,7 +6,7 @@ describe('NotFoundComponent', () => {
let component: NotFoundComponent;
let fixture: ComponentFixture<NotFoundComponent>;
beforeEach(async(() => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [NotFoundComponent]
})

View File

@@ -10,7 +10,7 @@
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2015",
"target": "es2020",
"typeRoots": [
"node_modules/@types"
],
@@ -18,6 +18,6 @@
"es2016",
"dom"
],
"module": "esnext"
"module": "es2020"
}
}

View File

@@ -12,6 +12,9 @@
"curly": true,
"eofline": true,
"forin": true,
"deprecation": {
"severity": "warning"
},
"import-blacklist": [true],
"import-spacing": true,
"indent": [
@@ -53,7 +56,6 @@
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [

View File

@@ -4,3 +4,4 @@
.classpath
.project
.idea
*.iml

View File

@@ -58,13 +58,13 @@ Replace the dummy job (class: `it.fabioformosa.quartzmanager.jobs.SampleJob`) wi
**Backend Stack** Java 9, Spring Boot 2.5.6 (Spring MVC 5.3.12, Spring Security 5.5.3), Quartz Scheduler 2.3.2
**Frontend** Angular 9.1.4, Web-Socket (stompjs 2.3.3)
**Frontend** Angular 14.2.12, Web-Socket (stompjs 2.3.3)
**Style** Angular Material 9, FontAwesome 5
**Style** Angular Material 14, FontAwesome 5
Starting from Quartz Manager v2.x.x, the new structure of project is:
* Multi-module maven project: REST API backend
* Angular 9: Single Page Application frontend
* Angular 14: Single Page Application frontend
(The first version of quartz manager was a monolithic backend that provided also frontend developed with angularjs 1.6.x. You can find it at the branch 1.x.x)

View File

@@ -10,7 +10,7 @@
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
<packaging>pom</packaging>
@@ -78,27 +78,27 @@
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-common</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</dependency>
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-api</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</dependency>
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-security</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</dependency>
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-persistence</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</dependency>
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-ui</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</parent>
<artifactId>quartz-manager-common</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</parent>
<artifactId>quartz-manager-starter-api</artifactId>

View File

@@ -55,7 +55,8 @@ public class SchedulerConfig {
if (quartzProperties != null && quartzProperties.size() > 0)
mergedProperties.putAll(quartzProperties);
factory.setQuartzProperties(mergedProperties);
factory.setAutoStartup(false);
boolean isAutoStartup = mergedProperties.getProperty("org.quartz.scheduler.isAutoStartup") != null && mergedProperties.getProperty("org.quartz.scheduler.isAutoStartup").equals("true");
factory.setAutoStartup(isAutoStartup);
return factory;
}
}

View File

@@ -1,5 +1,6 @@
package it.fabioformosa.quartzmanager.api.configuration;
import it.fabioformosa.quartzmanager.api.common.config.QuartzManagerPaths;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
@@ -14,14 +15,16 @@ public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/job");
config.enableSimpleBroker("/topic"); //enable a simple memory-based message broker
// on destinations prefixed with /topic
config.setApplicationDestinationPrefixes("/job"); // it designates the prefix for messages
// that are bound for methods annotated with @MessageMapping
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/quartz-manager/logs").setAllowedOrigins("/**").withSockJS();
registry.addEndpoint("/quartz-manager/progress").setAllowedOrigins("/**").withSockJS();
registry.addEndpoint(QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/logs").setAllowedOrigins("/**").withSockJS();
registry.addEndpoint(QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/progress").setAllowedOrigins("/**").withSockJS();
}
}

View File

@@ -8,7 +8,10 @@ import org.springframework.stereotype.Controller;
@Controller
public class WebsocketController {
@MessageMapping({ QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/logs", QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/progress" })
@MessageMapping({
QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/logs",
QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/progress"
})
@SendTo("/topic/logs")
public String subscribe() {
return "subscribed";

View File

@@ -2,6 +2,7 @@ package it.fabioformosa.quartzmanager.api.converters;
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerCommandDTO;
import org.quartz.JobDataMap;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
@@ -19,6 +20,8 @@ public class SimpleTriggerCommandDTOToSimpleTrigger implements Converter<SimpleT
if (triggerCommandDTO.getSimpleTriggerInputDTO().getEndDate() != null)
triggerTriggerBuilder.endAt(triggerCommandDTO.getSimpleTriggerInputDTO().getEndDate());
if (triggerCommandDTO.getSimpleTriggerInputDTO().getJobDataMap() != null)
triggerTriggerBuilder.usingJobData(new JobDataMap(triggerCommandDTO.getSimpleTriggerInputDTO().getJobDataMap()));
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
if (triggerCommandDTO.getSimpleTriggerInputDTO().getRepeatInterval() != null)

View File

@@ -14,6 +14,7 @@ public class SimpleTriggerToSimpleTriggerDTO extends TriggerToTriggerDTO<SimpleT
target.setRepeatCount(source.getRepeatCount());
target.setRepeatInterval(source.getRepeatInterval());
target.setMisfireInstruction(source.getMisfireInstruction());
target.setJobDataMap(source.getJobDataMap());
}
@Override

View File

@@ -3,8 +3,9 @@ package it.fabioformosa.quartzmanager.api.dto;
import it.fabioformosa.quartzmanager.api.validators.ValidTriggerRepetition;
import lombok.*;
import lombok.experimental.SuperBuilder;
import javax.annotation.Nullable;
import javax.validation.constraints.Positive;
import java.util.Map;
@ValidTriggerRepetition
@SuperBuilder
@@ -18,4 +19,7 @@ public class SimpleTriggerInputDTO extends TriggerCommandDTO implements TriggerR
@Positive
private Long repeatInterval;
@Nullable
private Map<String, ?> jobDataMap;
}

View File

@@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.quartz.JobDataMap;
import java.util.Date;
@@ -23,4 +24,5 @@ public class TriggerDTO {
private JobKeyDTO jobKeyDTO;
private JobDetailDTO jobDetailDTO;
private boolean mayFireAgain;
private JobDataMap jobDataMap;
}

View File

@@ -14,7 +14,7 @@ public class WebSocketLogsNotifier implements WebhookSender<LogRecord> {
private SimpMessageSendingOperations messagingTemplate;
@Override
public void send(LogRecord logRecord) {
public void send(LogRecord logRecord) {
messagingTemplate.convertAndSend(TOPIC_LOGS, logRecord);
}
}

View File

@@ -21,7 +21,8 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.util.Date;
import java.util.Map;
import static java.util.Map.entry;
import static org.mockito.ArgumentMatchers.any;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -68,6 +69,10 @@ class SimpleTriggerControllerTest {
}
private SimpleTriggerInputDTO buildACompleteSimpleTriggerCommandDTO() {
Map<String, ?> triggerJobDataMap = Map.ofEntries(
entry("customTriggerData1", "value1"),
entry("customTriggerData2", "value2")
);
return SimpleTriggerInputDTO.builder()
.jobClass("it.fabioformosa.quartzmanager.api.jobs.SampleJob")
.startDate(new Date())
@@ -75,6 +80,7 @@ class SimpleTriggerControllerTest {
.misfireInstruction(MisfireInstruction.MISFIRE_INSTRUCTION_FIRE_NOW)
.repeatCount(5)
.repeatInterval(1000L * 60 * 60)
.jobDataMap(triggerJobDataMap)
.build();
}

View File

@@ -2,12 +2,23 @@ package it.fabioformosa.quartzmanager.api.controllers.utils;
import it.fabioformosa.quartzmanager.api.common.utils.DateUtils;
import it.fabioformosa.quartzmanager.api.dto.*;
import org.quartz.JobDataMap;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import static java.util.Map.entry;
public class TriggerUtils {
static public TriggerDTO getTriggerInstance(String triggerName){
static public TriggerDTO getTriggerInstance(String triggerName) {
return TriggerDTO.builder()
.description("sample trigger")
.endTime(DateUtils.addHoursToNow(2L))
@@ -28,7 +39,7 @@ public class TriggerUtils {
.build();
}
static public SimpleTriggerDTO getSimpleTriggerInstance(String triggerName, SimpleTriggerInputDTO simpleTriggerInputDTO){
static public SimpleTriggerDTO getSimpleTriggerInstance(String triggerName, SimpleTriggerInputDTO simpleTriggerInputDTO) {
return SimpleTriggerDTO.builder()
.description("simple trigger")
.repeatCount(simpleTriggerInputDTO.getRepeatCount())
@@ -48,10 +59,11 @@ public class TriggerUtils {
.nextFireTime(DateUtils.addHoursToNow(1L))
.priority(1)
.startTime(DateUtils.fromLocalDateTimeToDate(LocalDateTime.now()))
.jobDataMap(new JobDataMap(simpleTriggerInputDTO.getJobDataMap()))
.build();
}
static public SimpleTriggerDTO getSimpleTriggerInstance(String triggerName){
static public SimpleTriggerDTO getSimpleTriggerInstance(String triggerName) {
return SimpleTriggerDTO.builder()
.description("simple trigger")
.repeatCount(2)
@@ -71,6 +83,44 @@ public class TriggerUtils {
.nextFireTime(DateUtils.addHoursToNow(1L))
.priority(1)
.startTime(DateUtils.fromLocalDateTimeToDate(LocalDateTime.now()))
.jobDataMap(new JobDataMap(Map.ofEntries(entry("customTriggerData1", "value1"))))
.build();
}
static public SimpleTrigger buildSimpleTrigger() {
TriggerBuilder<Trigger> triggerTriggerBuilder = TriggerBuilder.newTrigger();
triggerTriggerBuilder.startAt(new Date());
triggerTriggerBuilder.endAt(DateUtils.addHoursToNow(1));
triggerTriggerBuilder.usingJobData(new JobDataMap(Map.ofEntries(entry("data", "value"))));
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
scheduleBuilder.withIntervalInMilliseconds(1000);
scheduleBuilder.withRepeatCount(1);
scheduleBuilder.withMisfireHandlingInstructionFireNow();
return triggerTriggerBuilder.withSchedule(
scheduleBuilder
)
.withIdentity("simpleTrigger").build();
}
static public SimpleTriggerCommandDTO buildSimpleTriggerCommandDTO(String triggerName) throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = dateFormat.parse("2024-02-02");
Date endDate = dateFormat.parse("2024-03-02");
SimpleTriggerInputDTO triggerInputDTO = SimpleTriggerInputDTO.builder()
.misfireInstruction(MisfireInstruction.MISFIRE_INSTRUCTION_FIRE_NOW)
.jobClass("sample.jobClass")
.repeatCount(1)
.repeatInterval(1000L)
.startDate(startDate)
.endDate(endDate)
.jobDataMap(Map.ofEntries(entry("data", "value")))
.build();
return SimpleTriggerCommandDTO.builder()
.triggerName(triggerName)
.simpleTriggerInputDTO(triggerInputDTO)
.build();
}

View File

@@ -0,0 +1,41 @@
package it.fabioformosa.quartzmanager.api.converters;
import it.fabioformosa.quartzmanager.api.controllers.utils.TriggerUtils;
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerCommandDTO;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.quartz.SimpleTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.convert.ConversionService;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@SpringBootTest
class SimpleTriggerCommandDTOToSimpleTriggerTest {
@Autowired
private ConversionService conversionService;
@Order(1)
@Test
void givenSimpleTriggerCommandDTO_whenItIsConverted_thenASimpleTriggerIsReturned() throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = dateFormat.parse("2024-02-02");
Date endDate = dateFormat.parse("2024-03-02");
SimpleTriggerCommandDTO simpleTriggerCommandDTO = TriggerUtils.buildSimpleTriggerCommandDTO("mytrigger");
SimpleTrigger simpleTrigger = conversionService.convert(simpleTriggerCommandDTO, SimpleTrigger.class);
Assertions.assertThat(simpleTrigger).isNotNull();
Assertions.assertThat(simpleTrigger.getRepeatCount()).isEqualTo(simpleTriggerCommandDTO.getSimpleTriggerInputDTO().getRepeatCount());
Assertions.assertThat(simpleTrigger.getRepeatInterval()).isEqualTo(simpleTriggerCommandDTO.getSimpleTriggerInputDTO().getRepeatInterval());
Assertions.assertThat(simpleTrigger.getJobDataMap()).containsEntry("data", "value");
Assertions.assertThat(simpleTrigger.getStartTime()).isEqualTo(startDate);
Assertions.assertThat(simpleTrigger.getEndTime()).isEqualTo(endDate);
}
}

View File

@@ -0,0 +1,36 @@
package it.fabioformosa.quartzmanager.api.converters;
import it.fabioformosa.quartzmanager.api.controllers.utils.TriggerUtils;
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerDTO;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.quartz.SimpleTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.convert.ConversionService;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@SpringBootTest
class SimpleTriggerToSimpleTriggerDTOTest {
@Autowired
private ConversionService conversionService;
@Order(1)
@Test
void givenSimpleTrigger_whenItIsConverted_thenADtoIsReturned() {
SimpleTrigger simpleTrigger = TriggerUtils.buildSimpleTrigger();
SimpleTriggerDTO simpleTriggerDTO = conversionService.convert(simpleTrigger, SimpleTriggerDTO.class);
Assertions.assertThat(simpleTriggerDTO).isNotNull();
Assertions.assertThat(simpleTriggerDTO.getRepeatCount()).isEqualTo(simpleTrigger.getRepeatCount());
Assertions.assertThat(simpleTriggerDTO.getRepeatInterval()).isEqualTo(simpleTrigger.getRepeatInterval());
Assertions.assertThat(simpleTriggerDTO.getJobDataMap()).containsEntry("data", "value");
Assertions.assertThat(simpleTriggerDTO.getStartTime()).isEqualTo(simpleTrigger.getStartTime());
Assertions.assertThat(simpleTriggerDTO.getEndTime()).isEqualTo(simpleTrigger.getEndTime());
}
}

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</parent>
<artifactId>quartz-manager-starter-persistence</artifactId>

View File

@@ -11,7 +11,6 @@ import org.springframework.context.annotation.*;
import javax.sql.DataSource;
@Configuration
@PropertySource("classpath:quartz-persistence.properties")
public class PersistenceConfig {
@Value("${quartz-manager.persistence.quartz.datasource.url}")
@@ -57,7 +56,7 @@ public class PersistenceConfig {
@Primary
@Bean
public DataSource quartzManagerDatasource(PersistenceDatasourceProps persistenceDatasourceProps) {
public DataSource quartzManagerDatasource() {
return DataSourceBuilder.create()
.url(quartzDatasourceUrl)
.driverClassName("org.postgresql.Driver")

View File

@@ -5,6 +5,6 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<includeAll path="./migrations" relativeToChangelogFile="true"/>
<includeAll path="classpath:db/quartz-scheduler/migrations" relativeToChangelogFile="false" errorIfMissingOrEmpty="true"/>
</databaseChangeLog>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</parent>
<artifactId>quartz-manager-starter-security</artifactId>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</parent>
<artifactId>quartz-manager-starter-ui</artifactId>
@@ -19,8 +19,8 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>9</java.version>
<frontend.folderName>quartz-manager-frontend</frontend.folderName>
<node.version>v10.16.3</node.version>
<npm.version>6.9.0</npm.version>
<node.version>v16.14.1</node.version>
<npm.version>8.19.3</npm.version>
</properties>
<dependencies>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-parent</artifactId>
<version>4.0.6</version>
<version>4.0.9</version>
</parent>
<artifactId>quartz-manager-web-showcase</artifactId>