From 7979ef6e47d66f81a740965c49fab2914c63d965 Mon Sep 17 00:00:00 2001 From: JordenReuter <149687553+JordenReuter@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:51:05 +0200 Subject: [PATCH] feat: added possibility for query hints (#155) * feat: added possibility for query hints * feat: improvements and tests * fix: format --- .../pages/includes/attributes.adoc | 2 +- .../includes/tkit-quarkus-rest-context.adoc | 274 +++++++++--------- .../tkit/quarkus/jpa/daos/AbstractDAO.java | 25 ++ .../org/tkit/quarkus/jpa/daos/PageResult.java | 20 +- .../org/tkit/quarkus/jpa/daos/PagedQuery.java | 30 +- .../java/org/tkit/quarkus/jpa/test/Child.java | 22 ++ .../org/tkit/quarkus/jpa/test/ChildDAO.java | 9 + .../org/tkit/quarkus/jpa/test/Parent.java | 27 ++ .../org/tkit/quarkus/jpa/test/ParentDAO.java | 34 +++ .../jpa/test/ParentRestController.java | 56 ++++ .../tkit/quarkus/jpa/test/ParentDAOTest.java | 64 ++++ 11 files changed, 419 insertions(+), 144 deletions(-) create mode 100644 extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Child.java create mode 100644 extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ChildDAO.java create mode 100644 extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Parent.java create mode 100644 extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentDAO.java create mode 100644 extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentRestController.java create mode 100644 extensions/jpa/tests/src/test/java/org/tkit/quarkus/jpa/test/ParentDAOTest.java diff --git a/docs/modules/tkit-quarkus/pages/includes/attributes.adoc b/docs/modules/tkit-quarkus/pages/includes/attributes.adoc index 083d6f3e..291ab36d 100644 --- a/docs/modules/tkit-quarkus/pages/includes/attributes.adoc +++ b/docs/modules/tkit-quarkus/pages/includes/attributes.adoc @@ -1,4 +1,4 @@ -:project-version: 2.20.0 +:project-version: :quarkus-version: 3.9.3 :examples-dir: ./../examples/ \ No newline at end of file diff --git a/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-rest-context.adoc b/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-rest-context.adoc index c44bef19..13eb8412 100644 --- a/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-rest-context.adoc +++ b/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-rest-context.adoc @@ -27,123 +27,157 @@ endif::add-copy-button-to-env-var[] |`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-enabled[tkit.rs.context.token.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-enabled[tkit.rs.context.principal.name.enabled]` [.description] -- -Enable or disable token parsing. +Enable or disable principal name resolver. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean |`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-mandatory]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-mandatory[tkit.rs.context.token.mandatory]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-mandatory]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-mandatory[tkit.rs.context.principal.name.mandatory]` [.description] -- -Make the token mandatory (not null) +Make the principal name mandatory (not null). ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_MANDATORY+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_MANDATORY+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_MANDATORY+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_MANDATORY+++` endif::add-copy-button-to-env-var[] --|boolean |`false` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-type]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-type[tkit.rs.context.token.type]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-custom-service-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-custom-service-enabled[tkit.rs.context.principal.name.custom-service-enabled]` [.description] -- -Type of the token for new created token +Enabled custom service. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_TYPE+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_CUSTOM_SERVICE_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_TYPE+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_CUSTOM_SERVICE_ENABLED+++` endif::add-copy-button-to-env-var[] ---|string -|`principal-token` +--|boolean +|`false` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-verify]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-verify[tkit.rs.context.token.verify]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-security-context-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-security-context-enabled[tkit.rs.context.principal.name.security-context.enabled]` [.description] -- -Verify token +Enable or disable principal from security context. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_VERIFY+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_SECURITY_CONTEXT_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_VERIFY+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_SECURITY_CONTEXT_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean |`false` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-enabled[tkit.rs.context.token.public-key-location.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-default]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-default[tkit.rs.context.principal.name.default]` [.description] -- -Use token realm for the public key. +Default principal. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_DEFAULT+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_DEFAULT+++` +endif::add-copy-button-to-env-var[] +--|string +| + + +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-enabled[tkit.rs.context.principal.name.token-enabled]` + + +[.description] +-- +Enable principal from token. + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_ENABLED+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean -|`false` +|`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-suffix]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-suffix[tkit.rs.context.token.public-key-location.suffix]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-claim-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-claim-name[tkit.rs.context.principal.name.token-claim-name]` [.description] -- -Public key server suffix +Principal from token claim. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_SUFFIX+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_CLAIM_NAME+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_SUFFIX+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_CLAIM_NAME+++` endif::add-copy-button-to-env-var[] --|string -|`/protocol/openid-connect/certs` +|`sub` -a| [[tkit-quarkus-rest-context_tkit-rs-context-token-header-param]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-header-param[tkit.rs.context.token.header-param]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-enabled[tkit.rs.context.principal.name.header-param-enabled]` [.description] -- -Principal token header parameter. +Enable principal from header parameter ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_HEADER_PARAM+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_HEADER_PARAM+++` +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_ENABLED+++` +endif::add-copy-button-to-env-var[] +--|boolean +|`false` + + +a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-name[tkit.rs.context.principal.name.header-param-name]` + + +[.description] +-- +Principal from header parameter + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_NAME+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_NAME+++` endif::add-copy-button-to-env-var[] --|string -|`apm-principal-token` +|`x-principal-id` a| [[tkit-quarkus-rest-context_tkit-rs-context-tenant-id-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-tenant-id-enabled[tkit.rs.context.tenant-id.enabled]` @@ -333,276 +367,242 @@ endif::add-copy-button-to-env-var[] |`tenantId` -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-enabled[tkit.rs.context.principal.name.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-enabled[tkit.rs.context.enabled]` [.description] -- -Enable or disable principal name resolver. +Enable or disable rest context. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean |`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-mandatory]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-mandatory[tkit.rs.context.principal.name.mandatory]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-correlation-id-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-correlation-id-enabled[tkit.rs.context.correlation-id.enabled]` [.description] -- -Make the principal name mandatory (not null). +Enable or disable correlation ID. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_MANDATORY+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_CORRELATION_ID_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_MANDATORY+++` +Environment variable: `+++TKIT_RS_CONTEXT_CORRELATION_ID_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean -|`false` +|`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-custom-service-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-custom-service-enabled[tkit.rs.context.principal.name.custom-service-enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-correlation-id-header-param-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-correlation-id-header-param-name[tkit.rs.context.correlation-id.header-param-name]` [.description] -- -Enabled custom service. +Header parameter for correlation ID. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_CUSTOM_SERVICE_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_CORRELATION_ID_HEADER_PARAM_NAME+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_CUSTOM_SERVICE_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_CORRELATION_ID_HEADER_PARAM_NAME+++` endif::add-copy-button-to-env-var[] ---|boolean -|`false` +--|string +|`x-correlation-id` -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-security-context-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-security-context-enabled[tkit.rs.context.principal.name.security-context.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-business-context-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-business-context-enabled[tkit.rs.context.business-context.enabled]` [.description] -- -Enable or disable principal from security context. +Enable or disable business context. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_SECURITY_CONTEXT_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_SECURITY_CONTEXT_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean -|`false` +|`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-default]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-default[tkit.rs.context.principal.name.default]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-business-context-default]]`link:#tkit-quarkus-rest-context_tkit-rs-context-business-context-default[tkit.rs.context.business-context.default]` [.description] -- -Default principal. +The default business parameter. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_DEFAULT+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_DEFAULT+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_DEFAULT+++` +Environment variable: `+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_DEFAULT+++` endif::add-copy-button-to-env-var[] --|string | -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-enabled[tkit.rs.context.principal.name.token-enabled]` - - -[.description] --- -Enable principal from token. - -ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_ENABLED+++[] -endif::add-copy-button-to-env-var[] -ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_ENABLED+++` -endif::add-copy-button-to-env-var[] ---|boolean -|`true` - - -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-claim-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-token-claim-name[tkit.rs.context.principal.name.token-claim-name]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-business-context-header-param-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-business-context-header-param-name[tkit.rs.context.business-context.header-param-name]` [.description] -- -Principal from token claim. +Header parameter for business context. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_CLAIM_NAME+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_HEADER_PARAM_NAME+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_TOKEN_CLAIM_NAME+++` +Environment variable: `+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_HEADER_PARAM_NAME+++` endif::add-copy-button-to-env-var[] --|string -|`sub` +|`business-context` -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-enabled[tkit.rs.context.principal.name.header-param-enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-add-token-to-context]]`link:#tkit-quarkus-rest-context_tkit-rs-context-add-token-to-context[tkit.rs.context.add-token-to-context]` [.description] -- -Enable principal from header parameter +Add token to application context. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_ADD_TOKEN_TO_CONTEXT+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_ADD_TOKEN_TO_CONTEXT+++` endif::add-copy-button-to-env-var[] --|boolean -|`false` - - -a| [[tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-principal-name-header-param-name[tkit.rs.context.principal.name.header-param-name]` - - -[.description] --- -Principal from header parameter - -ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_NAME+++[] -endif::add-copy-button-to-env-var[] -ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_PRINCIPAL_NAME_HEADER_PARAM_NAME+++` -endif::add-copy-button-to-env-var[] ---|string -|`x-principal-id` +|`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-enabled[tkit.rs.context.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-enabled[tkit.rs.context.token.enabled]` [.description] -- -Enable or disable rest context. +Enable or disable token parsing. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_ENABLED+++` endif::add-copy-button-to-env-var[] --|boolean |`true` -a| [[tkit-quarkus-rest-context_tkit-rs-context-correlation-id-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-correlation-id-enabled[tkit.rs.context.correlation-id.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-mandatory]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-mandatory[tkit.rs.context.token.mandatory]` [.description] -- -Enable or disable correlation ID. +Make the token mandatory (not null) ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_CORRELATION_ID_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_MANDATORY+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_CORRELATION_ID_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_MANDATORY+++` endif::add-copy-button-to-env-var[] --|boolean -|`true` +|`false` -a| [[tkit-quarkus-rest-context_tkit-rs-context-correlation-id-header-param-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-correlation-id-header-param-name[tkit.rs.context.correlation-id.header-param-name]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-type]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-type[tkit.rs.context.token.type]` [.description] -- -Header parameter for correlation ID. +Type of the token for new created token ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_CORRELATION_ID_HEADER_PARAM_NAME+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_TYPE+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_CORRELATION_ID_HEADER_PARAM_NAME+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_TYPE+++` endif::add-copy-button-to-env-var[] --|string -|`x-correlation-id` +|`principal-token` -a| [[tkit-quarkus-rest-context_tkit-rs-context-business-context-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-business-context-enabled[tkit.rs.context.business-context.enabled]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-verify]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-verify[tkit.rs.context.token.verify]` [.description] -- -Enable or disable business context. +Verify token ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_ENABLED+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_VERIFY+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_ENABLED+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_VERIFY+++` endif::add-copy-button-to-env-var[] --|boolean -|`true` +|`false` -a| [[tkit-quarkus-rest-context_tkit-rs-context-business-context-default]]`link:#tkit-quarkus-rest-context_tkit-rs-context-business-context-default[tkit.rs.context.business-context.default]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-enabled]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-enabled[tkit.rs.context.token.public-key-location.enabled]` [.description] -- -The default business parameter. +Use token realm for the public key. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_DEFAULT+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_ENABLED+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_DEFAULT+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_ENABLED+++` endif::add-copy-button-to-env-var[] ---|string -| +--|boolean +|`false` -a| [[tkit-quarkus-rest-context_tkit-rs-context-business-context-header-param-name]]`link:#tkit-quarkus-rest-context_tkit-rs-context-business-context-header-param-name[tkit.rs.context.business-context.header-param-name]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-suffix]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-public-key-location-suffix[tkit.rs.context.token.public-key-location.suffix]` [.description] -- -Header parameter for business context. +Public key server suffix ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_HEADER_PARAM_NAME+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_SUFFIX+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_BUSINESS_CONTEXT_HEADER_PARAM_NAME+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_PUBLIC_KEY_LOCATION_SUFFIX+++` endif::add-copy-button-to-env-var[] --|string -|`business-context` +|`/protocol/openid-connect/certs` -a| [[tkit-quarkus-rest-context_tkit-rs-context-add-token-to-context]]`link:#tkit-quarkus-rest-context_tkit-rs-context-add-token-to-context[tkit.rs.context.add-token-to-context]` +a| [[tkit-quarkus-rest-context_tkit-rs-context-token-header-param]]`link:#tkit-quarkus-rest-context_tkit-rs-context-token-header-param[tkit.rs.context.token.header-param]` [.description] -- -Add token to application context. +Principal token header parameter. ifdef::add-copy-button-to-env-var[] -Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_ADD_TOKEN_TO_CONTEXT+++[] +Environment variable: env_var_with_copy_button:+++TKIT_RS_CONTEXT_TOKEN_HEADER_PARAM+++[] endif::add-copy-button-to-env-var[] ifndef::add-copy-button-to-env-var[] -Environment variable: `+++TKIT_RS_CONTEXT_ADD_TOKEN_TO_CONTEXT+++` +Environment variable: `+++TKIT_RS_CONTEXT_TOKEN_HEADER_PARAM+++` endif::add-copy-button-to-env-var[] ---|boolean -|`true` +--|string +|`apm-principal-token` a| [[tkit-quarkus-rest-context_tkit-rs-context-tenant-id-mock-data-data]]`link:#tkit-quarkus-rest-context_tkit-rs-context-tenant-id-mock-data-data[tkit.rs.context.tenant-id.mock.data]` diff --git a/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/AbstractDAO.java b/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/AbstractDAO.java index e30cf85c..eb14aba5 100644 --- a/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/AbstractDAO.java +++ b/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/AbstractDAO.java @@ -114,6 +114,18 @@ public PagedQuery createPageQuery(CriteriaQuery query, Page page) { return new PagedQuery<>(getEntityManager(), query, page, idAttributeName); } + /** + * Creates the page query of the DAO {@code } type. + * + * @param query the criteria query + * @param page the page for the query + * @param hint query hint + * @return the new page query instance + */ + public PagedQuery createPageQuery(CriteriaQuery query, Page page, String hint) { + return new PagedQuery<>(getEntityManager(), query, page, idAttributeName, hint); + } + /** * Creates the page query of the DAO {@code } type. * @@ -138,6 +150,19 @@ public PagedQuery createPageQueryCustom(CriteriaQuery query, Page page return new PagedQuery<>(em, query, page, idAttributeName); } + /** + * Creates the page query of the custom {@code } type + * + * @param query the criteria query + * @param page the page for the query + * @param hint query hint + * @param the entity type of the paged query. + * @return the new page query instance + */ + public PagedQuery createPageQueryCustom(CriteriaQuery query, Page page, String hint) { + return new PagedQuery<>(em, query, page, idAttributeName, hint); + } + /** * Finds all entities. * diff --git a/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PageResult.java b/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PageResult.java index 69f08c66..46a2dc30 100644 --- a/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PageResult.java +++ b/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PageResult.java @@ -27,12 +27,12 @@ public static PageResult empty() { /** * The page number. */ - private int number; + private long number; /** * The page size. */ - private int size; + private long size; /** * The number of pages. @@ -52,10 +52,22 @@ public static PageResult empty() { * @param page the page. */ public PageResult(long totalElements, Stream stream, Page page) { + this(totalElements, stream, page.number(), page.size()); + } + + /** + * The default constructor. + * + * @param totalElements the count of all items. + * @param stream the data stream. + * @param number number of the page. + * @param size size of the page. + */ + public PageResult(long totalElements, Stream stream, long number, long size) { this.totalElements = totalElements; this.stream = stream; - this.number = page.number(); - this.size = page.size(); + this.number = number; + this.size = size; this.totalPages = (totalElements + size - 1) / size; } diff --git a/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PagedQuery.java b/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PagedQuery.java index 80448b52..82d9828e 100644 --- a/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PagedQuery.java +++ b/extensions/jpa/runtime/src/main/java/org/tkit/quarkus/jpa/daos/PagedQuery.java @@ -43,6 +43,11 @@ public class PagedQuery { */ private Page page; + /** + * Query hint + */ + private String hint; + /** * Default constructor. * @@ -51,23 +56,44 @@ public class PagedQuery { * @param page the start page. */ public PagedQuery(EntityManager em, CriteriaQuery criteria, Page page, String idAttributeName) { + this(em, criteria, page, idAttributeName, null); + } + + /** + * Constructor including query hint. + * + * @param em the entity manager. + * @param criteria the search criteria + * @param page the start page. + * @param hint custom query hint + */ + public PagedQuery(EntityManager em, CriteriaQuery criteria, Page page, String idAttributeName, String hint) { this.em = em; this.criteria = setDefaultSorting(em, criteria, idAttributeName); this.page = page; this.countCriteria = createCountCriteria(em, criteria); + this.hint = hint; } public PageResult getPageResult() { try { + var q = em.createQuery(countCriteria); + if (hint != null) { + q.setHint(AbstractDAO.HINT_LOAD_GRAPH, em.getEntityGraph(hint)); + } // get count - Long count = em.createQuery(countCriteria).getSingleResult(); + Long count = q.getSingleResult(); // return empty page for count zero if (count == 0) { return PageResult.empty(); } // get stream - Stream stream = em.createQuery(criteria) + var sq = em.createQuery(criteria); + if (hint != null) { + sq.setHint(AbstractDAO.HINT_LOAD_GRAPH, em.getEntityGraph(hint)); + } + Stream stream = sq .setFirstResult(page.number() * page.size()) .setMaxResults(page.size()) .getResultStream(); diff --git a/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Child.java b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Child.java new file mode 100644 index 00000000..4406b07f --- /dev/null +++ b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Child.java @@ -0,0 +1,22 @@ +package org.tkit.quarkus.jpa.test; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import org.tkit.quarkus.jpa.models.TraceableEntity; + +@Entity +@Table(name = "TEST_CHILD") +public class Child extends TraceableEntity { + @Column(name = "MFE_ID", nullable = false) + private String mfeId; + + public String getMfeId() { + return mfeId; + } + + public void setMfeId(String mfeId) { + this.mfeId = mfeId; + } +} diff --git a/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ChildDAO.java b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ChildDAO.java new file mode 100644 index 00000000..73c3727c --- /dev/null +++ b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ChildDAO.java @@ -0,0 +1,9 @@ +package org.tkit.quarkus.jpa.test; + +import jakarta.enterprise.context.ApplicationScoped; + +import org.tkit.quarkus.jpa.daos.AbstractDAO; + +@ApplicationScoped +public class ChildDAO extends AbstractDAO { +} diff --git a/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Parent.java b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Parent.java new file mode 100644 index 00000000..c7161312 --- /dev/null +++ b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/Parent.java @@ -0,0 +1,27 @@ +package org.tkit.quarkus.jpa.test; + +import static jakarta.persistence.FetchType.LAZY; + +import java.util.List; + +import jakarta.persistence.*; + +import org.tkit.quarkus.jpa.models.TraceableEntity; + +@Entity +@NamedEntityGraph(name = "Parent.loadChildren", includeAllAttributes = true) +@Table(name = "TEST_PARENT") +public class Parent extends TraceableEntity { + + @OneToMany(fetch = LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "PARENT_GUID") + private List children; + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } +} diff --git a/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentDAO.java b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentDAO.java new file mode 100644 index 00000000..c4560438 --- /dev/null +++ b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentDAO.java @@ -0,0 +1,34 @@ +package org.tkit.quarkus.jpa.test; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.transaction.Transactional; + +import org.tkit.quarkus.jpa.daos.AbstractDAO; +import org.tkit.quarkus.jpa.daos.Page; +import org.tkit.quarkus.jpa.daos.PageResult; + +@ApplicationScoped +public class ParentDAO extends AbstractDAO { + + @Transactional(Transactional.TxType.NOT_SUPPORTED) + Parent loadById(String id) { + var cb = this.getEntityManager().getCriteriaBuilder(); + var cq = cb.createQuery(Parent.class); + var root = cq.from(Parent.class); + + cq.where(cb.equal(root.get("id"), id)); + Parent p = this.getEntityManager().createQuery(cq) + .setHint(HINT_LOAD_GRAPH, this.getEntityManager().getEntityGraph("Parent.loadChildren")).getSingleResult(); + this.getEntityManager().detach(p); + return p; + } + + PageResult loadPage() { + var cb = this.getEntityManager().getCriteriaBuilder(); + var cq = cb.createQuery(Parent.class); + var root = cq.from(Parent.class); + + cq.where(root.get("id").isNotNull()); + return this.createPageQuery(cq, Page.of(0, 10), "Parent.loadChildren").getPageResult(); + } +} diff --git a/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentRestController.java b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentRestController.java new file mode 100644 index 00000000..5ffbe57f --- /dev/null +++ b/extensions/jpa/tests/src/main/java/org/tkit/quarkus/jpa/test/ParentRestController.java @@ -0,0 +1,56 @@ +package org.tkit.quarkus.jpa.test; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.tkit.quarkus.jpa.models.TraceableEntity; + +@Path("parent") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Transactional(Transactional.TxType.NOT_SUPPORTED) +@ApplicationScoped +public class ParentRestController { + @Inject + ParentDAO parentDAO; + + @GET + @Path("{id}") + public Response find(@PathParam("id") String id) { + Parent tmp = parentDAO.loadById(id); + if (tmp == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + System.out.println("_____________________________________"); + System.out.println(tmp.getChildren().get(0).getMfeId()); + return Response.ok(tmp).build(); + } + + @GET + public Response create() { + Parent tmp = new Parent(); + Child c1 = new Child(); + c1.setMfeId("mfe1"); + Child c2 = new Child(); + c2.setMfeId("mfe2"); + tmp.setChildren(List.of(c1, c2)); + // Sibling sibling = siblingDAO.create(new Sibling()); + // tmp.setSibling(sibling); + parentDAO.create(tmp); + + return Response.ok(tmp).build(); + } + + @GET + @Path("page") + public Response getPageResult() { + return Response.ok(parentDAO.loadPage().getStream() + .map(parent -> parent.getChildren().stream().map(TraceableEntity::getId).toList()).toList()).build(); + } +} diff --git a/extensions/jpa/tests/src/test/java/org/tkit/quarkus/jpa/test/ParentDAOTest.java b/extensions/jpa/tests/src/test/java/org/tkit/quarkus/jpa/test/ParentDAOTest.java new file mode 100644 index 00000000..d5f35e0f --- /dev/null +++ b/extensions/jpa/tests/src/test/java/org/tkit/quarkus/jpa/test/ParentDAOTest.java @@ -0,0 +1,64 @@ +package org.tkit.quarkus.jpa.test; + +import static io.restassured.RestAssured.given; + +import jakarta.ws.rs.core.Response; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.http.ContentType; + +@QuarkusTest +@DisplayName("Parent DAO tests") +public class ParentDAOTest extends AbstractTest { + + private static final Logger log = LoggerFactory.getLogger(ParentDAOTest.class); + + @Test + public void searchParentTest() { + Parent create = given() + .get("parent") + .then() + .log().all() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().as(Parent.class); + + Parent find = given() + .contentType(ContentType.JSON) + .pathParam("id", create.getId()) + .get("parent/{id}") + .then() + .log().all() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().as(Parent.class); + + Assertions.assertNotNull(find); + Assertions.assertEquals(create.getId(), find.getId()); + } + + @Test + public void loadPageResult() { + given() + .get("parent") + .then() + .log().all() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().as(Parent.class); + + var find = given() + .contentType(ContentType.JSON) + .get("parent/page") + .then() + .log().all() + .statusCode(Response.Status.OK.getStatusCode()) + .contentType(ContentType.JSON) + .extract().asString(); + + Assertions.assertNotNull(find); + } +}