diff --git a/.github/workflows/push-trigger.yml b/.github/workflows/push-trigger.yml index 2d875000..4f7655d2 100644 --- a/.github/workflows/push-trigger.yml +++ b/.github/workflows/push-trigger.yml @@ -91,7 +91,6 @@ jobs: - SERVICE_LOCATION: '../print' SERVICE_NAME: 'print' BUILD_ARTIFACT: 'print' - SQUASH_LAYERS: '11' fail-fast: false name: ${{ matrix.SERVICE_NAME }} uses: mosip/kattu/.github/workflows/docker-build.yml@master-java21 @@ -99,7 +98,6 @@ jobs: SERVICE_LOCATION: ${{ matrix.SERVICE_LOCATION }} SERVICE_NAME: ${{ matrix.SERVICE_NAME }} BUILD_ARTIFACT: ${{ matrix.BUILD_ARTIFACT }} - SQUASH_LAYERS: ${{ matrix.SQUASH_LAYERS }} secrets: DEV_NAMESPACE_DOCKER_HUB: ${{ secrets.DEV_NAMESPACE_DOCKER_HUB }} ACTOR_DOCKER_HUB: ${{ secrets.ACTOR_DOCKER_HUB }} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..fb70a189 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,265 @@ +# AGENTS.md — MOSIP Print Service + +This file provides guidance to AI agents when working with code in this repository. + +--- + +## Project Overview + +The **MOSIP Print Service** is a Spring Boot microservice that generates PDF identity credentials (eUIN cards, reprint cards, QR code cards) for residents enrolled in MOSIP — the Modular Open Source Identity Platform. + +It sits at the tail end of the **ID Lifecycle Management** pipeline: +1. A resident registers or updates their ID at a registration centre. +2. Demographic and biometric data are captured and processed by Registration Processor. +3. Credentials are issued and an event is published to WebSub. +4. **This service** consumes the credential event, decrypts resident data, renders a template, generates a PDF, uploads it to DataShare, and publishes a completion event. + +The service is a **reference implementation** for credential partner onboarding. Deployers are expected to customise templates and partner certificates. + +--- + +## Technology Stack + +| Layer | Technology | +|---|--------------------------------------------| +| Language | Java 21 | +| Framework | Spring Boot 3.2.3 + Spring Cloud Config | +| Build | Maven 3.9.6 | +| PDF generation | pdfbox +| Template engine | Apache Velocity 1.7 | +| QR codes | ZXing (Google) 3.4.1 | +| Cryptography | BouncyCastle 1.66, JWT 3.8.1 | +| Messaging | MOSIP WebSub (kernel-websub-client-api) | +| Biometrics | CBEFF format via kernel-cbeffutil | +| Tests | JUnit 5, Mockito 4.11.0, JaCoCo | +| Containerisation | Docker (Alpine-based), Helm for Kubernetes | + +--- + +## Repository Layout + +``` +print/ +├── src/main/java/io/mosip/print/ +│ ├── PrintPDFApplication.java # Spring Boot entry point +│ ├── controller/Print.java # Single REST endpoint (WebSub callback) +│ ├── service/ +│ │ ├── PrintService.java # Interface +│ │ └── impl/ +│ │ ├── PrintServiceImpl.java # Core orchestration logic (~500 lines) +│ │ ├── PDFGeneratorImpl.java # iText PDF generation +│ │ ├── QrcodeGeneratorImpl.java # ZXing QR code generation +│ │ ├── TemplateManagerImpl.java # Velocity template processing +│ │ ├── CbeffImpl.java # Biometric (CBEFF) handling +│ │ └── UinCardGeneratorImpl.java +│ ├── util/ # 50+ utility classes +│ │ ├── CryptoUtil.java # Encryption / decryption +│ │ ├── DataShareUtil.java # DataShare upload +│ │ ├── TemplateGenerator.java # Template instantiation +│ │ ├── DigitalSignatureUtility.java # PDF digital signing +│ │ ├── WebSubSubscriptionHelper.java # WebSub subscription management +│ │ └── RestApiClient.java # HTTP client wrapper +│ ├── dto/ # 65+ Data Transfer Objects +│ ├── constant/ # 35+ constant classes +│ ├── exception/ # 35+ custom exception classes +│ ├── model/ # Domain models (Event, StatusEvent) +│ └── entity/ # CBEFF entity models +├── src/main/resources/ +│ ├── application-local1.properties # Local dev config (port 8088) +│ ├── bootstrap.properties # Spring Cloud Config bootstrap +│ └── partner.p12 # Sample partner certificate +├── src/test/java/io/mosip/print/ # 45+ unit test files +├── docs/ +│ ├── build-and-run.md +│ ├── configuration.md +│ └── print-service.png # Architecture diagram +├── deploy/ # Shell scripts for bare-metal deploy +├── helm/ # Kubernetes Helm charts +├── Dockerfile +└── pom.xml +``` + +--- + +## Build and Run + +### Build (skip tests) +```bash +mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dgpg.skip=true +``` + +### Build with tests +```bash +mvn clean install -Dmaven.javadoc.skip=true -Dgpg.skip=true +``` + +### Run tests only +```bash +mvn test +``` + +### Run the JAR +```bash +java -Dloader.path= \ + -Dspring.profiles.active=local1 \ + -jar target/print-*.jar +``` + +### Docker +```bash +# Build image +docker build -t print-service:local . + +# Run container +docker run -d -p 8099:8099 --name print-service print-service:local +``` + +Service listens on **port 8099** (default) or **port 8088** (local1 profile). + +--- + +## Key Configuration Properties + +All runtime configuration is sourced from a **Spring Cloud Config Server** (mosip-config repository). Local overrides live in `application-local1.properties`. + +| Property | Purpose | +|---|---| +| `mosip.event.hubURL` | WebSub hub URL | +| `mosip.partner.id` | This service's partner ID (`mpartner-default-print`) | +| `mosip.event.topic` | WebSub topic to subscribe to | +| `mosip.event.callBackUrl` | Public URL of the `/print/callback/notifyPrint` endpoint | +| `mosip.event.secret` | WebSub HMAC secret | +| `mosip.datashare.partner.id` | DataShare partner (`mpartner-default-resident`) | +| `mosip.datashare.policy.id` | DataShare policy (`mpolicy-default-resident`) | +| `mosip.print.crypto.p12.filename` | Partner P12 certificate filename | +| `mosip.print.crypto.p12.password` | P12 password | +| `mosip.print.crypto.p12.alias` | P12 key alias | +| `mosip.template-language` | Language code for template lookup (e.g. `eng`) | +| `mosip.kernel.pdf_owner_password` | PDF encryption owner password | +| `mosip.supported-languages` | Comma-separated ISO language codes | +| `mosip.iam.adapter.clientid` | Keycloak client ID for this service | +| `mosip.iam.adapter.issuerURL` | Keycloak realm issuer URL | +| `TEMPLATES` | Masterdata templates endpoint | +| `CREATEDATASHARE` | DataShare create endpoint | +| `PDFSIGN` | Keymanager PDF sign endpoint | + +--- + +## REST API + +### `POST /v1/print/print/callback/notifyPrint` + +The single public endpoint. Called by the WebSub hub when a credential event is published. + +**Headers required:** +- `x-hub-signature` — HMAC-SHA256 signature from WebSub hub (validated by the service) + +**Body:** WebSub notification JSON containing the credential event payload. + +**Flow:** +1. Validates WebSub signature and intent. +2. Extracts and decrypts credential data using the partner P12 key. +3. Fetches the HTML template for the card type from Masterdata. +4. Renders the template with resident data using Velocity. +5. Converts HTML to PDF via iText html2pdf. +6. Optionally embeds a QR code and applies a digital signature. +7. Uploads the PDF to DataShare. +8. Publishes a `CREDENTIAL_STATUS_UPDATE` event back to WebSub. + +--- + +## Data Flow and Integration Points + +``` +WebSub Hub + │ POST /print/callback/notifyPrint + ▼ +Print.java (controller) + │ generateCard(event) + ▼ +PrintServiceImpl.java + ├── KeyManager / CryptoUtil — decrypt credential data + ├── Masterdata (TEMPLATES) — fetch HTML template + ├── TemplateManagerImpl — merge template + data (Velocity) + ├── PDFGeneratorImpl — HTML → PDF (PDF Box) + ├── QrcodeGeneratorImpl — embed QR code (ZXing) + ├── DigitalSignatureUtility — sign PDF (Keymanager PDFSIGN) + ├── DataShareUtil — upload PDF (DataShare) + └── WebSubSubscriptionHelper — publish status event +``` + +External services consumed: +- **Keymanager** — decryption and PDF signing +- **Masterdata** — HTML templates +- **DataShare** — secure PDF upload +- **WebSub** — event subscription and publication +- **IAM (Keycloak)** — token-based authentication for all REST calls + +--- + +## ID Lifecycle Context + +MOSIP's ID Lifecycle Management covers the full journey of an identity: + +- **Registration** — Resident attends a registration centre; demographic and biometric data are captured. +- **Processing** — Registration Processor de-duplicates and validates the data. +- **Activation** — A UIN (Unique Identification Number) is issued; the ID is active. +- **Credential Issuance** — Credentials (VCs, PDF cards) are generated for configured partners. +- **Updates** — Resident can update demographics or biometrics; a new credential is re-issued. +- **Deactivation / Reactivation** — IDs can be deactivated and reactivated via resident services. +- **Print / Reprint** — This service handles the print partner use case: it receives credential events and produces PDF identity cards. + +This service handles the **Credential Issuance → Print** leg. The `UinCardType` constant class enumerates supported card types: `EUIN`, `REPRINT`, `QRCODE`. + +--- + +## Working with This Codebase + +### Before making changes +1. Read `PrintServiceImpl.java` — it is the central orchestrator; most changes flow through it. +2. Check `PrintRestClientServiceImpl.java` for how external REST calls are made before adding new ones. +3. Verify properties exist in `application-local1.properties` or `docs/configuration.md` before introducing new config keys. + +### Adding a new card type +1. Add a constant to `UinCardType.java`. +2. Add a template to Masterdata and reference it in `PrintServiceImpl.generateCard()`. +3. Add a corresponding branch in `TemplateGenerator.java` if template rendering differs. + +### Modifying template rendering +Templates are HTML files processed by Velocity. Variables are injected via `VelocityContext`. See `TemplateManagerImpl.java` and `TemplateGenerator.java`. + +### Cryptography +Do not modify `CryptoUtil.java` without understanding the P12 key usage. The partner certificate must match the credential encryption key registered in Keymanager. + +### Tests +- Unit tests are in `src/test/java/io/mosip/print/`. +- Tests use Mockito; external service calls are mocked. +- Run `mvn test` before committing any change. +- JaCoCo generates a coverage report under `target/site/jacoco/`. + +### Docker image +The `Dockerfile` copies the built JAR and runs it. The image is published to Docker Hub as `mosipid/print-service`. + +--- + +## Conventions + +- Package root: `io.mosip.print` +- All Spring beans follow constructor injection where possible. +- REST responses are wrapped in a standard `ResponseWrapper` DTO. +- Exceptions extend `BaseCheckedException` or `BaseUncheckedException` from the MOSIP kernel. +- Logging uses `io.mosip.print.logger.PrintLogger` (SLF4J wrapper); do not use `System.out`. +- Constants live in dedicated files under the `constant/` package; do not hard-code strings inline. +- All external HTTP calls go through `PrintRestClientService` — do not use `RestTemplate` directly in service classes. + +--- + +## Useful References + +- MOSIP documentation: https://docs.mosip.io/1.2.0/ +- ID Lifecycle Management: https://docs.mosip.io/1.2.0/id-lifecycle-management +- mosip-config repository: contains `print-default.properties` with all runtime properties +- MOSIP functional tests: https://github.com/mosip/mosip-functional-tests +- Docker Hub image: `mosipid/print-service` +- Build and run guide: `docs/build-and-run.md` +- Configuration guide: `docs/configuration.md` diff --git a/NOTICE b/NOTICE index ee8a5b9a..9c143eec 100644 --- a/NOTICE +++ b/NOTICE @@ -75,19 +75,19 @@ This project includes components licensed under BSD licenses: • PostgreSQL JDBC Driver (BSD-2-Clause) • Jakarta Activation API (BSD-3-Clause) - • Jakarta Persistence API (BSD-3-Clause) + • Jakarta Persistence API (BSD-3-Clause or EPL-2.0) • Additional transitive BSD-licensed components ------------------------------------------------------------------------------- -Eclipse Public License Attribution (EPL-2.0) +Eclipse Public License Attribution (EPL-1.0 / EPL-2.0) ------------------------------------------------------------------------------- The following components are licensed under EPL: - • JUnit (EPL-2.0) + • JUnit (EPL-1.0 / EPL-2.0) • JUnit Vintage Engine (EPL-2.0) • JaCoCo Maven Plugin (EPL-2.0) • Jakarta XML Bind API (EPL-2.0) - + • H2 Database (dual-licensed EPL-1.0 / MPL-2.0) ------------------------------------------------------------------------------- MIT License Attribution diff --git a/README.md b/README.md index 82fc0278..3473fd1d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ To deploy print service in production follow the given steps: 1. Onboard your organisation as [Credential Partner](https://docs.mosip.io/1.2.0/partners). 2. Place your `.p12` file in `../src/main/resources` folder. -3. Set configuration as in given [here](https://github.com/mosip/mosip-config/blob/develop/print-default.properties). +3. Set configuration as in given [here](https://github.com/mosip/mosip-config/blob/master/print-default.properties). 4. Build and run as given [here](docs/build-and-run.md). ## Test @@ -73,7 +73,7 @@ Ensure the following artifacts are available in the classpath or loader path: ### Configuration Print uses properties from **mosip-config**. -You can check the configuration here: [print-default.properties](https://github.com/mosip/mosip-config/blob/develop/print-default.properties) +You can check the configuration here: [print-default.properties](https://github.com/mosip/mosip-config/blob/master/print-default.properties) ### Local Setup (for Development or Contribution) 1. Ensure the **Config Server** is running and accessible.To run config server [check here.](https://github.com/mosip/mosip-config/blob/master/README.md) diff --git a/helm/print/templates/deployment.yaml b/helm/print/templates/deployment.yaml index 2a7ad164..2c852425 100644 --- a/helm/print/templates/deployment.yaml +++ b/helm/print/templates/deployment.yaml @@ -105,10 +105,8 @@ spec: {{- end }} {{- end }} {{- if .Values.extraEnvVarsSecret }} - {{- range .Values.extraEnvVarsSecret }} - secretRef: - name: {{ . }} - {{- end }} + name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }} {{- end }} ports: - name: spring-service diff --git a/helm/print/values.yaml b/helm/print/values.yaml index 6c5e12c5..891f0eef 100644 --- a/helm/print/values.yaml +++ b/helm/print/values.yaml @@ -12,23 +12,18 @@ ## commonLabels: app.kubernetes.io/component: mosip - ## Add annotations to all the deployed resources ## commonAnnotations: {} - ## Kubernetes Cluster Domain ## clusterDomain: cluster.local - ## Extra objects to deploy (value evaluated as a template) ## extraDeploy: [] - ## Number of nodes ## replicaCount: 1 - service: type: ClusterIP port: 80 @@ -49,7 +44,6 @@ service: ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip ## externalTrafficPolicy: Cluster - image: registry: docker.io repository: mosipqa/print @@ -65,10 +59,8 @@ image: ## # pullSecrets: # - myRegistryKeySecretName - ## Port on which this particular spring service module is running. springServicePort: 8088 - ## Configure extra options for liveness and readiness probes ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes ## @@ -82,7 +74,6 @@ startupProbe: timeoutSeconds: 5 failureThreshold: 10 successThreshold: 1 - livenessProbe: enabled: true httpGet: @@ -93,7 +84,6 @@ livenessProbe: timeoutSeconds: 5 failureThreshold: 6 successThreshold: 1 - readinessProbe: enabled: true httpGet: @@ -104,7 +94,6 @@ readinessProbe: timeoutSeconds: 5 failureThreshold: 6 successThreshold: 1 - ## # existingConfigmap: @@ -112,12 +101,10 @@ readinessProbe: ## command: [] args: [] - ## Deployment pod host aliases ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ ## hostAliases: [] - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ ## resources: @@ -129,39 +116,33 @@ resources: cpu: 300m memory: 3000Mi requests: - cpu: 300m - memory: 1000Mi - + cpu: 150m + memory: 1800Mi additionalResources: ## Specify any JAVA_OPTS string here. These typically will be specified in conjunction with above resources ## Example: java_opts: "-Xms500M -Xmx500M" - javaOpts: "-Xms2250M -Xmx2250M" - + javaOpts: "-Xms1350M -Xmx2250M" ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container ## Clamav container already runs as 'mosip' user, so we may not need to enable this containerSecurityContext: enabled: false runAsUser: mosip runAsNonRoot: true - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod ## podSecurityContext: enabled: false fsGroup: 1001 - ## Pod affinity preset ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity ## Allowed values: soft, hard ## podAffinityPreset: "" - ## Pod anti-affinity preset ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity ## Allowed values: soft, hard ## podAntiAffinityPreset: soft - ## Node affinity preset ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity ## Allowed values: soft, hard @@ -183,32 +164,26 @@ nodeAffinityPreset: ## - e2e-az2 ## values: [] - ## Affinity for pod assignment. Evaluated as a template. ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity ## affinity: {} - ## Node labels for pod assignment. Evaluated as a template. ## ref: https://kubernetes.io/docs/user-guide/node-selection/ ## nodeSelector: {} - ## Tolerations for pod assignment. Evaluated as a template. ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ ## tolerations: [] - ## Pod extra labels ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ ## podLabels: {} - ## Annotations for server pods. ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ ## podAnnotations: {} - ## pods' priority. ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ ## @@ -223,19 +198,14 @@ lifecycleHooks: - sh - -c - sleep 30 - ## Termination grace perios : the maximum amount of time (in seconds) Kubernetes will wait for a container to gracefully shut down terminationGracePeriodSeconds: 60 - - ## Custom Liveness probes for ## customLivenessProbe: {} - ## Custom Rediness probes ## customReadinessProbe: {} - ## Update strategy - only really applicable for deployments with RWO PVs attached ## If replicas = 1, an update can get "stuck", as the previous pod remains attached to the ## PV, and the "incoming" pod can never start. Changing the strategy to "Recreate" will @@ -243,7 +213,6 @@ customReadinessProbe: {} ## updateStrategy: type: RollingUpdate - ## Additional environment variables to set ## Example: ## extraEnvVars: @@ -251,26 +220,21 @@ updateStrategy: ## value: "bar" ## extraEnvVars: [] - ## ConfigMap with extra environment variables that used ## extraEnvVarsCM: - global - config-server-share - artifactory-share - ## Secret with extra environment variables ## -extraEnvVarsSecret: [] - +extraEnvVarsSecret: ## Extra volumes to add to the deployment ## extraVolumes: [] - ## Extra volume mounts to add to the container ## extraVolumeMounts: [] - ## Add init containers to the pods. ## Example: ## initContainers: @@ -282,7 +246,6 @@ extraVolumeMounts: [] ## containerPort: 1234 ## initContainers: {} - ## Add sidecars to the pods. ## Example: ## sidecars: @@ -294,7 +257,6 @@ initContainers: {} ## containerPort: 1234 ## sidecars: {} - persistence: enabled: false ## If defined, storageClassName: @@ -316,7 +278,6 @@ persistence: existingClaim: # Dir where config and keys are written inside container mountDir: - ## Init containers parameters: ## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. ## @@ -350,12 +311,10 @@ volumePermissions: ## cpu: 100m ## memory: 128Mi ## - ## Specifies whether RBAC resources should be created ## rbac: create: true - ## Specifies whether a ServiceAccount should be created ## serviceAccount: @@ -364,7 +323,6 @@ serviceAccount: ## If not set and create is true, a name is generated using the fullname template ## name: - ## Prometheus Metrics ## metrics: @@ -374,9 +332,7 @@ metrics: ## podAnnotations: prometheus.io/scrape: "true" - endpointPath: /v1/print/actuator/prometheus - ## Prometheus Service Monitor ## ref: https://github.com/coreos/prometheus-operator ## @@ -403,7 +359,6 @@ metrics: ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#prometheusspec ## additionalLabels: {} - ## Custom PrometheusRule to be defined ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions @@ -421,7 +376,6 @@ metrics: # labels: # severity: error rules: [] - ## Partner management needs public access. istio: enabled: true diff --git a/pom.xml b/pom.xml index 0c111368..c34dead7 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ io.mosip.print print - 1.2.1-SNAPSHOT + 1.4.0-SNAPSHOT print https://github.com/mosip/print This is a project for MOSIP printing functionality. @@ -39,7 +39,6 @@ 3.0.2 3.1.0 0.8.11 - 0.7.0 3.7.0.1746 3.2.0 5.0.5.RELEASE @@ -50,7 +49,8 @@ **/dto/**,**/config/**,**/api/** 1.4.2 2.8.4 - 1.2.1-SNAPSHOT + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT 7.1.0 2.0.0 5.5.13.3 @@ -60,9 +60,11 @@ 1.66 3.8.1 3.4.1 + 3.1.1 + 0.7.0 - 4.11.0 + 4.11.0 5.10.2 @@ -71,10 +73,23 @@ + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + io.mosip.kernel kernel-bom - 1.2.1-SNAPSHOT + ${kernel.core.version} pom import @@ -276,30 +291,21 @@ org.mockito mockito-inline - ${mockito.inline.version} + ${mockito.version} test - - ossrh - LegacyMavenSnapshot - https://oss.sonatype.org/content/repositories/snapshots - default - - true - - - - ossrh-central - MavenCentralRepository - https://central.sonatype.com/repository/maven-snapshots - default - - true - - + + ossrh-central + MavenCentralRepository + https://central.sonatype.com/repository/maven-snapshots + default + + true + + central MavenCentral @@ -314,7 +320,7 @@ ossrh - https://central.sonatype.com/repository/maven-snapshots/ + https://central.sonatype.com/repository/maven-snapshots ossrh @@ -440,6 +446,25 @@ + + maven-deploy-plugin + ${maven.deploy.plugin.version} + + true + + + + default-deploy + none + + deploy + + + true + + + + org.apache.maven.plugins maven-war-plugin diff --git a/src/main/java/io/mosip/print/service/impl/PrintServiceImpl.java b/src/main/java/io/mosip/print/service/impl/PrintServiceImpl.java index 6dab815b..e7c5219d 100644 --- a/src/main/java/io/mosip/print/service/impl/PrintServiceImpl.java +++ b/src/main/java/io/mosip/print/service/impl/PrintServiceImpl.java @@ -32,6 +32,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import io.mosip.kernel.core.util.DateUtils2; import io.mosip.vercred.CredentialsVerifier; import io.mosip.vercred.exception.ProofDocumentNotFoundException; import io.mosip.vercred.exception.ProofTypeNotFoundException; @@ -91,13 +92,11 @@ import io.mosip.print.util.CryptoCoreUtil; import io.mosip.print.util.CryptoUtil; import io.mosip.print.util.DataShareUtil; -import io.mosip.print.util.DateUtils; import io.mosip.print.util.JsonUtil; import io.mosip.print.util.RestApiClient; import io.mosip.print.util.TemplateGenerator; import io.mosip.print.util.Utilities; import io.mosip.print.util.WebSubSubscriptionHelper; -import io.mosip.vercred.CredentialsVerifier; @Service public class PrintServiceImpl implements PrintService { @@ -774,7 +773,7 @@ private String getCrdentialSubject(String crdential) { private void printStatusUpdate(String requestId, String status, String datashareUrl) { CredentialStatusEvent creEvent = new CredentialStatusEvent(); - LocalDateTime currentDtime = DateUtils.getUTCCurrentDateTime(); + LocalDateTime currentDtime = DateUtils2.getUTCCurrentDateTime(); StatusEvent sEvent = new StatusEvent(); sEvent.setId(UUID.randomUUID().toString()); sEvent.setRequestId(requestId); diff --git a/src/main/java/io/mosip/print/service/impl/UinCardGeneratorImpl.java b/src/main/java/io/mosip/print/service/impl/UinCardGeneratorImpl.java index 5cd1e350..bb281dce 100644 --- a/src/main/java/io/mosip/print/service/impl/UinCardGeneratorImpl.java +++ b/src/main/java/io/mosip/print/service/impl/UinCardGeneratorImpl.java @@ -6,6 +6,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import io.mosip.kernel.core.util.DateUtils2; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +34,6 @@ import io.mosip.print.service.PrintRestClientService; import io.mosip.print.service.UinCardGenerator; import io.mosip.print.spi.PDFGenerator; -import io.mosip.print.util.DateUtils; import io.mosip.print.util.RestApiClient; /** @@ -99,9 +99,9 @@ public byte[] generateUinCard(InputStream in, UinCardType type, String password) request.setData(Base64.encodeBase64String(out.toByteArray())); DateTimeFormatter format = DateTimeFormatter.ofPattern(env.getProperty(DATETIME_PATTERN)); LocalDateTime localdatetime = LocalDateTime - .parse(DateUtils.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); + .parse(DateUtils2.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); - request.setTimeStamp(DateUtils.getUTCCurrentDateTimeString()); + request.setTimeStamp(DateUtils2.getUTCCurrentDateTimeString()); RequestWrapper requestWrapper = new RequestWrapper<>(); requestWrapper.setRequest(request); diff --git a/src/main/java/io/mosip/print/util/AuditLogRequestBuilder.java b/src/main/java/io/mosip/print/util/AuditLogRequestBuilder.java index 48e1f23b..1dfcbf88 100644 --- a/src/main/java/io/mosip/print/util/AuditLogRequestBuilder.java +++ b/src/main/java/io/mosip/print/util/AuditLogRequestBuilder.java @@ -3,6 +3,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import io.mosip.kernel.core.util.DateUtils2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -69,7 +70,7 @@ public ResponseWrapper createAuditRequestBuilder(String descri ResponseWrapper responseWrapper = new ResponseWrapper<>(); try { auditRequestDto.setDescription(description); - auditRequestDto.setActionTimeStamp(DateUtils.getUTCCurrentDateTimeString()); + auditRequestDto.setActionTimeStamp(DateUtils2.getUTCCurrentDateTimeString()); auditRequestDto.setApplicationId(AuditLogConstant.MOSIP_4.toString()); auditRequestDto.setApplicationName(AuditLogConstant.REGISTRATION_PROCESSOR.toString()); auditRequestDto.setCreatedBy(AuditLogConstant.SYSTEM.toString()); @@ -89,7 +90,7 @@ public ResponseWrapper createAuditRequestBuilder(String descri requestWrapper.setRequest(auditRequestDto); DateTimeFormatter format = DateTimeFormatter.ofPattern(env.getProperty(DATETIME_PATTERN)); LocalDateTime localdatetime = LocalDateTime - .parse(DateUtils.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); + .parse(DateUtils2.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); requestWrapper.setRequesttime(localdatetime); requestWrapper.setVersion(env.getProperty(REG_PROC_APPLICATION_VERSION)); responseWrapper = (ResponseWrapper) registrationProcessorRestService.postApi(apiname, "", @@ -123,7 +124,7 @@ public ResponseWrapper createAuditRequestBuilder(String descri auditRequestDto = new AuditRequestDto(); auditRequestDto.setDescription(description); - auditRequestDto.setActionTimeStamp(DateUtils.getUTCCurrentDateTimeString()); + auditRequestDto.setActionTimeStamp(DateUtils2.getUTCCurrentDateTimeString()); auditRequestDto.setApplicationId(AuditLogConstant.MOSIP_4.toString()); auditRequestDto.setApplicationName(AuditLogConstant.REGISTRATION_PROCESSOR.toString()); auditRequestDto.setCreatedBy(AuditLogConstant.SYSTEM.toString()); @@ -143,7 +144,7 @@ public ResponseWrapper createAuditRequestBuilder(String descri requestWrapper.setRequest(auditRequestDto); DateTimeFormatter format = DateTimeFormatter.ofPattern(env.getProperty(DATETIME_PATTERN)); LocalDateTime localdatetime = LocalDateTime - .parse(DateUtils.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); + .parse(DateUtils2.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); requestWrapper.setRequesttime(localdatetime); requestWrapper.setVersion(env.getProperty(REG_PROC_APPLICATION_VERSION)); responseWrapper = (ResponseWrapper) registrationProcessorRestService diff --git a/src/main/java/io/mosip/print/util/DigitalSignatureUtility.java b/src/main/java/io/mosip/print/util/DigitalSignatureUtility.java index f21f86dc..8850c248 100644 --- a/src/main/java/io/mosip/print/util/DigitalSignatureUtility.java +++ b/src/main/java/io/mosip/print/util/DigitalSignatureUtility.java @@ -4,6 +4,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import io.mosip.kernel.core.util.DateUtils2; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; @@ -53,7 +54,7 @@ public String getDigitalSignature(String data) { request.setMetadata(null); DateTimeFormatter format = DateTimeFormatter.ofPattern(env.getProperty(DATETIME_PATTERN)); LocalDateTime localdatetime = LocalDateTime - .parse(DateUtils.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); + .parse(DateUtils2.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN)), format); request.setRequesttime(localdatetime); request.setVersion(env.getProperty(REG_PROC_APPLICATION_VERSION)); diff --git a/src/main/java/io/mosip/print/util/PrintExceptionHandler.java b/src/main/java/io/mosip/print/util/PrintExceptionHandler.java index 3424751b..17106c97 100644 --- a/src/main/java/io/mosip/print/util/PrintExceptionHandler.java +++ b/src/main/java/io/mosip/print/util/PrintExceptionHandler.java @@ -4,6 +4,7 @@ import java.util.Objects; import java.util.stream.Collectors; +import io.mosip.kernel.core.util.DateUtils2; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; @@ -167,7 +168,7 @@ private ResponseEntity buildPrintApiExceptionResponse(Exception e .collect(Collectors.toList()); response.setErrors(errors); } - response.setResponsetime(DateUtils.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN))); + response.setResponsetime(DateUtils2.getUTCCurrentDateTimeString(env.getProperty(DATETIME_PATTERN))); response.setVersion(env.getProperty(REG_PRINT_SERVICE_VERSION)); return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(response); diff --git a/src/main/java/io/mosip/print/util/TokenHandlerUtil.java b/src/main/java/io/mosip/print/util/TokenHandlerUtil.java index d9999f6b..78f6137c 100644 --- a/src/main/java/io/mosip/print/util/TokenHandlerUtil.java +++ b/src/main/java/io/mosip/print/util/TokenHandlerUtil.java @@ -3,6 +3,7 @@ import java.time.LocalDateTime; import java.util.Map; +import io.mosip.kernel.core.util.DateUtils2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,12 +43,12 @@ public static boolean isValidBearerToken(String accessToken, String issuerUrl, S try { DecodedJWT decodedJWT = JWT.decode(accessToken); Map claims = decodedJWT.getClaims(); - LocalDateTime expiryTime = DateUtils - .convertUTCToLocalDateTime(DateUtils.getUTCTimeFromDate(decodedJWT.getExpiresAt())); + LocalDateTime expiryTime = DateUtils2 + .convertUTCToLocalDateTime(DateUtils2.getUTCTimeFromDate(decodedJWT.getExpiresAt())); if (!decodedJWT.getIssuer().equals(issuerUrl)) { return false; - } else if (!DateUtils.before(DateUtils.getUTCCurrentDateTime(), expiryTime)) { + } else if (!DateUtils2.before(DateUtils2.getUTCCurrentDateTime(), expiryTime)) { return false; } else if (!claims.get("clientId").asString().equals(clientId)) { return false; diff --git a/src/main/resources/bootstrap.properties b/src/main/resources/bootstrap.properties index 5ebcb87d..3eb1b27f 100644 --- a/src/main/resources/bootstrap.properties +++ b/src/main/resources/bootstrap.properties @@ -8,4 +8,4 @@ management.endpoints.web.exposure.include=info,health,refresh server.port=8088 server.servlet.context-path=/v1/print -health.config.enabled=false +health.config.enabled=false \ No newline at end of file diff --git a/src/test/java/io/mosip/print/util/PrintExceptionHandlerTest.java b/src/test/java/io/mosip/print/util/PrintExceptionHandlerTest.java index 809d8b84..c9201620 100644 --- a/src/test/java/io/mosip/print/util/PrintExceptionHandlerTest.java +++ b/src/test/java/io/mosip/print/util/PrintExceptionHandlerTest.java @@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import io.mosip.kernel.core.util.DateUtils2; import io.mosip.print.dto.PrintResponse; import io.mosip.print.exception.AccessDeniedException; import io.mosip.print.exception.InvalidTokenException; @@ -58,7 +59,7 @@ class PrintExceptionHandlerTest { private static final String SERVICE_ID = "mosip.print.service"; private static final String SERVICE_VERSION = "1.0"; private static final String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; - private static final String CURRENT_DATETIME = "2025-08-03T10:00:00.000Z"; + private static final String CURRENT_DATETIME = "2026-06-05T11:19:48.774Z"; /** * Sets up test fixtures before each test method execution. @@ -80,13 +81,13 @@ void setUp() { void regPrintAppExceptionHandlerShouldReturnProperResponse() { RegPrintAppException exception = new RegPrintAppException("ERR-001", "Test error message"); - try (MockedStatic dateUtilsMock = mockStatic(DateUtils.class); + try (MockedStatic dateUtilsMock = mockStatic(DateUtils2.class); MockedStatic printLoggerMock = mockStatic(PrintLogger.class)) { Logger mockLogger = mock(Logger.class); printLoggerMock.when(() -> PrintLogger.getLogger(PrintExceptionHandler.class)) .thenReturn(mockLogger); - dateUtilsMock.when(() -> DateUtils.getUTCCurrentDateTimeString(DATETIME_PATTERN)) + dateUtilsMock.when(() -> DateUtils2.getUTCCurrentDateTimeString(DATETIME_PATTERN)) .thenReturn(CURRENT_DATETIME); ResponseEntity response = printExceptionHandler.regPrintAppException(exception);