From b9411229a8877805dff207da2584d9c0fba407d9 Mon Sep 17 00:00:00 2001 From: Gavin Baumanis Date: Tue, 25 Aug 2026 15:35:07 +1000 Subject: [PATCH] Release 8.0.0: Java 8 / javax --- .cursor/rules/hi-b2b-project.mdc | 47 +++- .cursor/rules/multi-branch-worktrees.mdc | 22 +- .cursor/rules/worktrees.mdc | 2 +- .github/workflows/ci.yml | 4 +- CHANGELOG.md | 15 +- CLIENT-FEATURES.md | 217 ++++++++++++++++++ CONTRIBUTING.md | 18 +- MAINTAINERS.md | 100 +++++--- README.md | 36 +-- WSDL-CLIENT-PURPOSES.md | 106 +++++++++ pom.xml | 9 +- .../vendorlibrary/hi/client/BaseClient_3.java | 4 +- ...ForProviderIndividualBatchAsyncClient.java | 7 +- ...rProviderOrganisationBatchAsyncClient.java | 7 +- .../ihi/ConsumerSearchIHIBatchSyncClient.java | 5 +- ...roviderIndividualBatchAsyncClientTest.java | 80 +++++++ ...viderOrganisationBatchAsyncClientTest.java | 80 +++++++ .../ConsumerSearchIHIBatchSyncClientTest.java | 26 +++ .../wsdl/HiRequestElementOrderParityTest.java | 118 ++++++++++ wsdls/readme.txt | 14 +- 20 files changed, 829 insertions(+), 88 deletions(-) create mode 100644 CLIENT-FEATURES.md create mode 100644 WSDL-CLIENT-PURPOSES.md create mode 100644 src/test/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClientTest.java create mode 100644 src/test/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClientTest.java create mode 100644 src/test/java/au/gov/nehta/vendorlibrary/hi/wsdl/HiRequestElementOrderParityTest.java diff --git a/.cursor/rules/hi-b2b-project.mdc b/.cursor/rules/hi-b2b-project.mdc index e41cf59..e5a307d 100644 --- a/.cursor/rules/hi-b2b-project.mdc +++ b/.cursor/rules/hi-b2b-project.mdc @@ -5,32 +5,61 @@ alwaysApply: true # hi-b2b-client-java -Healthcare Identifiers (HI) B2B facade client — **not** MHR/PCEHR. +Healthcare Identifiers (HI) B2B facade client - **not** MHR/PCEHR. -## Release lines (integrator docs use Maven Central versions only) +## Documentation + +Follow **`documentation-standards.mdc`**. Integrator docs use **version numbers** - not Git branch names. + +The **first number** of the Maven version is the **Java SE** target. **`hi-b2b-client`** and **`hi-wsdl`** always share the **same** version. | Version | Java | APIs | Facades | | ------- | ---- | ---- | ------- | -| **1.6.3** | 8 | javax | **14** | -| **1.6.5** | 11 | Jakarta | **14** | -| **1.7.0** | 11 | Jakarta | **26** (full MCA) | +| **8.0.0** | 8 | **javax** | **14** (standard HI B2B) | +| **11.0.0.1** | 11 | **Jakarta** | **26** (full MCA) | +| **17.0.0.1** | 17 | **Jakarta** | **26** (full MCA) | +| **21.0.0.1** | 21 | **Jakarta** | **26** (full MCA) | +| **24.0.0.1** | 24 | **Jakarta** | **26** (full MCA) | + +**Git branch mapping (maintainers only - never in integrator docs):** + +| Version | Official Git branch | +| ------- | ------------------- | +| **8.0.0** | `java-8` | +| **11.0.0.1** | `java-11` | +| **17.0.0.1** | `java-17` | +| **21.0.0.1** | `java-21` | +| **24.0.0.1** | `java-24` | -**This checkout:** **`1.6.3-SNAPSHOT`** — **`au.gov.nehta:hi-wsdl`** from Maven Central (or matching **`mvn install`** for SNAPSHOT), Java **8** / **`javax.*`**. +## This 8.0.0 line + +**`8.0.0-SNAPSHOT`**: Java **8**, **`javax`**, **14** facades, types from **`au.gov.nehta:hi-wsdl`** at **`${project.version}`** (no in-repo **`wsimport`**). See **MAINTAINERS.md**. ## Build from source -- JDK **8**: `mvn -B "-Dgpg.skip=true" clean verify` -- **Local / unpublished:** install **`hi-wsdl`** at **`${project.version}`** then **`verify`** — see **`CONTRIBUTING.md`** +- JDK **8**: `mvn -B "-Dgpg.skip=true" clean verify` (quote `-D` on PowerShell). +- **Local / unpublished:** install matching **`hi-wsdl`** then **`verify`** - see **`CONTRIBUTING.md`** - **`jaxws-rt` 2.3.7** - Default Surefire: offline tests; **`-Pintegration`** for mutual-TLS ## Consumer Search IHI - `basicSearch` requires **IHI number**; demographics-only = `detailedSearch`. +- Messages `searchIHI`: `electronicCommunication` before `dateOfBirth`. +- Interface `searchIHI`: optional `electronicCommunication` before `dateOfBirth`; unstructured address before international. + +## vs hi-wsdl-java + +| | **hi-wsdl-java** | **hi-b2b-client-java** | +|---|---|---| +| Delivers | WSDL on classpath + generated types | Facade clients, TLS, signing | +| Artifact | `hi-wsdl` | `hi-b2b-client` | + +Align **`hi-wsdl`** and **`hi-b2b-client`** at the **same version** per release line (**8.0.0** with **8.0.0**, **11.0.0.1** with **11.0.0.1**, and so on). ## Doc split - **`documentation-standards.mdc`**: implementor-first, Maven Central default, local/OS sections, relative paths, no secrets -- **`README.md`**: integrators (Maven Central default) +- **`README.md`**, **`CLIENT-FEATURES.md`**: integrators (Maven Central default) - **`CONTRIBUTING.md`**: build from source, local SNAPSHOT, OS wrappers - **`MAINTAINERS.md`**: POM / dependency internals diff --git a/.cursor/rules/multi-branch-worktrees.mdc b/.cursor/rules/multi-branch-worktrees.mdc index 8671bc9..2f03424 100644 --- a/.cursor/rules/multi-branch-worktrees.mdc +++ b/.cursor/rules/multi-branch-worktrees.mdc @@ -3,13 +3,13 @@ description: Use git worktree when editing multiple branches of the same reposit alwaysApply: true --- -# Multi-branch work — use git worktree +# Multi-branch work - use git worktree -When a task requires **changes on two or more branches of the same Git repository**, use **`git worktree`** — do **not** hop branches with `git checkout` while carrying uncommitted edits or stashes. +When a task requires **changes on two or more branches of the same Git repository**, use **`git worktree`** - do **not** hop branches with `git checkout` while carrying uncommitted edits or stashes. ## When this applies -- Same-repo edits across release lines (e.g. `java-8-javax`, `java-11-jakarta`, `master`) +- Same-repo edits across release lines (e.g. `java-8`, `java-11`, ...) - Applying the same fix to several branches before commit - Comparing or building two branches side by side @@ -22,7 +22,7 @@ When a task requires **changes on two or more branches of the same Git repositor ## Workflow 1. **Primary clone** stays on the main working branch; do not stash-and-hop to edit other branches. -2. **Add a worktree per extra branch** (paths are local — never commit them to tracked docs): +2. **Add a worktree per extra branch** (paths are local - never commit them to tracked docs): ```bash git worktree add ../- @@ -34,18 +34,12 @@ When a task requires **changes on two or more branches of the same Git repositor ## Do not - `git checkout` other branches with uncommitted changes (Git will block or force stash churn). -- Stash the same files across multiple branch switches — causes merge conflicts on `stash pop`. +- Stash the same files across multiple branch switches - causes merge conflicts on `stash pop`. - Put worktree directory paths in README, CONTRIBUTING, or other tracked docs (see repo **`worktrees.mdc`** / **`documentation-standards.mdc`**). ## Example (maintainer-local paths only) ```bash -# In hi-wsdl-java primary clone (on java-11-jakarta-full-wsdl) -git worktree add ../hi-wsdl-java-java-8-javax java-8-javax -git worktree add ../hi-wsdl-java-java-11-jakarta java-11-jakarta - -# Apply edits in each ../hi-wsdl-java-* folder; commit per branch -# When finished: -git worktree remove ../hi-wsdl-java-java-8-javax -git worktree remove ../hi-wsdl-java-java-11-jakarta -``` \ No newline at end of file +git worktree add java-8 +git worktree add java-11 +``` diff --git a/.cursor/rules/worktrees.mdc b/.cursor/rules/worktrees.mdc index 07f208a..60c6ce7 100644 --- a/.cursor/rules/worktrees.mdc +++ b/.cursor/rules/worktrees.mdc @@ -13,7 +13,7 @@ Follow **`documentation-standards.mdc`** (implementor-first, Maven Central defau | Doc | Audience | Use | | --- | -------- | --- | -| **README**, integrator guides | Implementors | **Maven version** (`1.7.0`), Central coordinates, runtime config | +| **README**, integrator guides | Implementors | **Maven version** (`8.0.0`), Central coordinates, runtime config | | **CONTRIBUTING** | Contributors | Build from source, **Local builds**, OS-specific steps | | **MAINTAINERS**, **`.cursor/rules/`** | Maintainers | POM/wsimport internals; **branch mapping** only when labelled maintainer-only | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4afeb91..b641d04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,9 @@ name: CI on: push: + branches: [ java-8 ] pull_request: + branches: [ java-8 ] permissions: contents: read @@ -13,7 +15,7 @@ jobs: verify: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - uses: actions/setup-java@v5 with: distribution: temurin diff --git a/CHANGELOG.md b/CHANGELOG.md index 48755c7..2305153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,17 @@ # Change Log/Revision History -= 1.6.3-SNAPSHOT = -====== -Changes not yet assigned to a numbered release; **`pom.xml`** **``** is **`1.6.3-SNAPSHOT`** until release **1.6.3** is tagged. += 8.0.0 = +======= +- Maven **`au.gov.nehta:hi-b2b-client`** **8.0.0** (Java **8** / **`javax`**, **14** facade clients). Pair with **`hi-wsdl`** **8.0.0**. The first number of both Maven versions is the targeted Java SE version. +- **`common-library`** **8.0.0** (`nehta.lib.version` = **`${project.version}`**). **`smi-xsp`** **8.0.0** (`nehta.xsp.lib.version` = **`${project.version}`**). +- **`HiRequestElementOrderParityTest`**: asserts JAXB `propOrder` for Messages `searchIHI` (`electronicCommunication` before `dateOfBirth`), Interface inquiry `searchIHI`, and batch `SearchIHIRequestType`. See **`wsdls/readme.txt`**. +- IHI sync batch and HPI batch-async facades reject a null request (and a null per-request user id) with **`IllegalArgumentException`**. +- **`BaseClient_3`** constructor names the signing-certificate argument **`signingCertificate`**. +- README: IHI **sync** batch (`SearchBatch.ArgumentValidator`) uses the same search-field rules as `ConsumerSearchIHIClient`. + += 1.6.3 = +========= +Historical past release (superseded by **8.0.0** on this line). - Root license file renamed to **`LICENSE.md`** (Apache 2.0 canonical text plus ADHA production disclaimer); references updated from **`LICENSE.txt`**. - **`hi-wsdl`** at **`hi.wsdl.version`** = **`${project.version}`** (SNAPSHOT locally; GA **`1.6.3`** pair on Maven Central); **`javax.*`** / Java **8** bytecode in generated types; default lifecycle does not run **`wsimport`**. Batch Search IHI types use **`au.net.electronichealth.ns.hi.xsd.consumermessages.*`** packages from **`hi-wsdl`**; tests use **`String`** country codes (no **`CountryType`** enum on this stub line). diff --git a/CLIENT-FEATURES.md b/CLIENT-FEATURES.md new file mode 100644 index 0000000..9b3bfcf --- /dev/null +++ b/CLIENT-FEATURES.md @@ -0,0 +1,217 @@ +# HI B2B Client - feature overview + +Broad list of what you can do with **`au.gov.nehta:hi-b2b-client`**: typed Java facades over Australia's **Healthcare Identifiers (HI) Service** (SOAP/JAX-WS). Operation details and field rules are in ADHA specs and Javadoc; this document maps **library surface -> capability**. + +**Audience:** integrators choosing APIs for **`8.0.0`** (**14** facade classes). Setup (Maven Central dependency, keystores, endpoints) is in **`README.md`**. + +Full MCA coverage (**26** facades, **Jakarta**) is available from **11.0.0.1** onward (**17.0.0.1**, **21.0.0.1**, **24.0.0.1**, and later). See **`README.md`** **Versioning** before assuming a class exists in your version. + +--- + +## What the library gives you + +| Capability | How | +| ---------- | --- | +| Call HI SOAP operations from Java | One facade class per WSDL service (see tables below) | +| Mutual TLS to HI endpoints | Pass `SSLSocketFactory` (often from PKCS#12 via `KeystoreUtil`) | +| Sign outbound SOAP; verify inbound | `HISecurityHandler` on every facade (`ClientBase`) | +| HI SOAP headers (product, user, org, timestamps) | `HIHeaderHandler` + constructors on `BaseClient_3` | +| Resolve licensed WSDL/XSD at runtime | `HiWsdlArtifactRoot` (env, system property, `local.properties`, or `setRoot`) | +| Optional SOAP message logging | `LoggingHandler` | +| Request payload guardrails | Per-operation `ArgumentValidator` / `SearchBatch` before SOAP | +| Per-call user identity override | Many clients expose overloads with `QualifiedId` per request | +| Example wiring | `src/sample/java/.../hi/sample/*` (not on default classpath) | + +You still need ADHA/Services Australia **registration**, **certificates**, **product metadata (PCIN)**, and **endpoint URLs** for live calls. + +--- + +## Individual Healthcare Identifier (IHI) + +Package: `au.gov.nehta.vendorlibrary.hi.ihi`. + +### Search (single request) + +**`ConsumerSearchIHIClient`** - find/validate an individual's IHI. Client methods enforce which `SearchIHI` fields may be set. + +| Method | Typical use | +| ------ | ----------- | +| `basicSearch` | Lookup by **IHI number** (+ demographics) | +| `basicMedicareSearch` | Lookup by **Medicare card number** (+ demographics) | +| `basicDvaSearch` | Lookup by **DVA file number** (+ demographics) | +| `detailedSearch` | **Demographics only** (no IHI, Medicare, DVA, or address blocks) | +| `australianPostalAddressSearch` | Demographics + Australian postal address | +| `australianStreetAddressSearch` | Demographics + Australian street address | +| `internationalAddressSearch` | Demographics + international address | + +Common mandatory demographics: family name, date of birth, sex (given name optional). **`basicSearch` requires an IHI number**; demographics-only lookup must use **`detailedSearch`**, not `basicSearch`. + +### Search (batch) + +| Class | What you can do | +| ----- | ---------------- | +| **`ConsumerSearchIHIBatchSyncClient`** | Submit many IHI searches in **one synchronous** batch (`batchSearch` + `SearchBatch` helper) | +| **`ConsumerSearchIHIBatchAsyncClient`** | **Submit** batch (`submitSearchIHIBatch`), **poll status** (`getSearchIHIBatchStatus`), **retrieve results** (`retrieveSearchIHIBatch`), **delete** batch (`deleteSearchIHIBatch`) | + +`SearchBatch` supports the same search shapes as sync batch (basic, Medicare, DVA, detailed, address variants) with the same field rules as single search. + +### Create, update, merge, resolve (lifecycle) + +| Class | Operation (SOAP) | Purpose (high level) | +| ----- | ------------------ | --------------------- | +| **`ConsumerCreateProvisionalIHIClient`** | Create provisional IHI | Allocate provisional identifier | +| **`ConsumerUpdateProvisionalIHIClient`** | Update provisional IHI | Change provisional record | +| **`ConsumerMergeProvisionalIHIClient`** | Merge provisional IHI | Combine provisional with existing IHI | +| **`ConsumerResolveProvisionalIHIClient`** | Resolve provisional IHI | Finalise provisional -> active IHI | +| **`ConsumerCreateUnverifiedIHIClient`** | Create unverified IHI | Create unverified identifier | +| **`ConsumerCreateVerifiedIHIClient`** | Create verified IHI | Create verified identifier | +| **`ConsumerUpdateIHIClient`** | Update IHI | Update active IHI demographics/details | + +### Notifications to HI Service + +| Class | Operation | Purpose (high level) | +| ----- | --------- | --------------------- | +| **`ConsumerNotifyDuplicateIHIClient`** | Notify duplicate IHI | Report duplicate IHI situation | +| **`ConsumerNotifyReplicaIHIClient`** | Notify replica IHI | Report replica IHI situation | + +Exact payloads and business rules are defined by HI Service specifications, not this library. + +--- + +## Healthcare Provider Identifier - Individual (HPI-I) + +Package: `au.gov.nehta.vendorlibrary.hi.hpii`. + +| Class | Methods / capability | +| ----- | -------------------- | +| **`ProviderSearchForProviderIndividualClient`** | `identifierSearch`, `demographicSearch` - find provider individuals in HI | +| **`ProviderSearchHIProviderDirectoryForIndividualClient`** | `identifierSearch`, `demographicSearch` - search **HI Provider Directory** for individuals | +| **`SearchForProviderIndividualBatchAsyncClient`** | `submitSearch`, `retrieveSearch` - **async batch** provider-individual search | +| **`ProviderSearchTdsProviderIndividualClient`** | `searchTdsProviderIndividual` - search **TDS** (terminated/deactivated) provider individuals | +| **`ProviderManageTdsProviderIndividualClient`** | `manageTdsProviderIndividual` - manage TDS provider individual records | + +--- + +## Healthcare Provider Identifier - Organisation (HPI-O) + +Package: `au.gov.nehta.vendorlibrary.hi.hpio`. + +### Search and directory + +| Class | Methods / capability | +| ----- | -------------------- | +| **`ProviderSearchForProviderOrganisationClient`** | `identifierSearch` - find organisations by identifier | +| **`ProviderSearchHIProviderDirectoryForOrganisationClient`** | `identifierSearch`, `demographicSearch` - HI Provider Directory for organisations | +| **`SearchForProviderOrganisationBatchAsyncClient`** | `submitSearch`, `retrieveSearch` - async batch organisation search | + +### Read + +| Class | Operation | Purpose (high level) | +| ----- | --------- | --------------------- | +| **`ProviderReadProviderOrganisationClient`** | `readProvider` | Read organisation (HPI-O) details | +| **`ProviderReadAdministrativeIndividualClient`** | `readProviderAdministrativeIndividual` | Read administrative individual linked to provider context | + +### Manage (mutating operations) + +Payloads use HI "manage" request types (create/update/deactivate etc. per spec). Facades pass them through after optional validation. + +| Class | Operation | +| ----- | --------- | +| **`ProviderManageProviderOrganisationClient`** | `manageProviderOrganisation` | +| **`ProviderManageProviderDirectoryEntryClient`** | `manageProviderDirectoryEntry` | +| **`ProviderManageProviderAdministrativeIndividualClient`** | `manageProviderAdministrativeIndividual` | + +--- + +## Reference data + +Package: `au.gov.nehta.vendorlibrary.hi.readreferencedata`. + +| Class | Capability | +| ----- | ---------- | +| **`ReadReferenceDataClient`** | `readReferenceData` - fetch current allowed code lists from HI (e.g. provider type, speciality, organisation type, organisation service, operating system). Request lists **element names**; response returns acceptable values. | + +--- + +## Cross-cutting integration patterns + +### Constructing any facade + +Typical constructor inputs: + +- HI **endpoint URL** (cert vs production from registration) +- **`SSLSocketFactory`** for mutual TLS +- **Signing** private key + X.509 certificate (SOAP XML signature) +- **Product** header (`ProductType` / wrapped variant) - PCIN +- **Qualified user ID** (and sometimes **organisation qualified ID** for contracted service providers) +- Optional **`CertificateValidator`** for inbound signature trust + +### Security and transport stack + +- TLS client authentication via your socket factory +- Outbound signing of SOAP body and required header elements; inbound signature verification +- Stripping of `wsa:FaultTo` on outbound messages (Medicare/HI interoperability) +- Optional omission of HPI-O CSP header when no organisation qualified ID is configured + +### WSDL and generated types + +- Published JAR does **not** include licensed WSDL/XSD; you supply the ADHA bundle at runtime (`wsdl/` + `schema/` under one root). See **`README.md`** and **`wsdls/README.md`**. +- JAXB/JAX-WS types for requests/responses are generated at library build time from that bundle; your app uses those types in method arguments. + +### Helpers in other packages + +| Area | Examples | +| ---- | -------- | +| `au.gov.nehta.vendorlibrary.common.security` | `KeystoreUtil` - load keys/certs for TLS and signing | +| `au.gov.nehta.vendorlibrary.ws` | `WebServiceClientUtil`, `TimeUtility` | +| `au.gov.nehta.vendorlibrary.hi.wsdl` | `HiWsdlArtifactRoot` | +| `au.gov.nehta.vendorlibrary.hi.client.wrapped` | Wrapped `QualifiedId`, `ProductType` for simpler construction | + +### Errors + +Service faults surface as generated **`StandardErrorMsg`** (and related) types from the HI WSDL; handle in application code like any SOAP fault. + +--- + +## Learning and verification + +| Resource | Content | +| -------- | ------- | +| **`README.md`** | Dependency, WSDL root, config keys, search IHI rules summary | +| **`src/sample/java`** | Runnable-style examples for search IHI, batch sync, reference data, directory search, read/manage org | +| **Javadoc** | Attached to releases on Maven Central | +| **`CONTRIBUTING.md`** | Build, offline vs `-Pintegration` tests | +| **ADHA implementer portal** | Registration, certificates, authoritative operation specs | + +--- + +## Quick index - all facade classes (**11.0.0.1** and later) + +| # | Class | +| - | ----- | +| 1 | `ConsumerSearchIHIClient` | +| 2 | `ConsumerSearchIHIBatchSyncClient` | +| 3 | `ConsumerSearchIHIBatchAsyncClient` | +| 4 | `ConsumerCreateProvisionalIHIClient` | +| 5 | `ConsumerUpdateProvisionalIHIClient` | +| 6 | `ConsumerMergeProvisionalIHIClient` | +| 7 | `ConsumerResolveProvisionalIHIClient` | +| 8 | `ConsumerCreateUnverifiedIHIClient` | +| 9 | `ConsumerCreateVerifiedIHIClient` | +| 10 | `ConsumerUpdateIHIClient` | +| 11 | `ConsumerNotifyDuplicateIHIClient` | +| 12 | `ConsumerNotifyReplicaIHIClient` | +| 13 | `ProviderSearchForProviderIndividualClient` | +| 14 | `ProviderSearchHIProviderDirectoryForIndividualClient` | +| 15 | `SearchForProviderIndividualBatchAsyncClient` | +| 16 | `ProviderSearchTdsProviderIndividualClient` | +| 17 | `ProviderManageTdsProviderIndividualClient` | +| 18 | `ProviderSearchForProviderOrganisationClient` | +| 19 | `ProviderSearchHIProviderDirectoryForOrganisationClient` | +| 20 | `SearchForProviderOrganisationBatchAsyncClient` | +| 21 | `ProviderReadProviderOrganisationClient` | +| 22 | `ProviderReadAdministrativeIndividualClient` | +| 23 | `ProviderManageProviderOrganisationClient` | +| 24 | `ProviderManageProviderDirectoryEntryClient` | +| 25 | `ProviderManageProviderAdministrativeIndividualClient` | +| 26 | `ReadReferenceDataClient` | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc4416f..c7eb364 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,10 @@ Dependencies resolve from **[Maven Central](https://central.sonatype.com/)** unless you are doing a **local build** (below). +## Versioning + +The **first number** of the Maven version is the **Java SE** version that line targets. **`hi-b2b-client`** and **`hi-wsdl`** always share the **same** version (**8.0.0** with **8.0.0** on this line). **11.0.0.1** and later use **Jakarta** and **26** facades; **8.0.0** uses **`javax`** and **14** facades. See **`README.md`**. + --- ## Build from source @@ -21,7 +25,7 @@ From the repository root (directory containing **`pom.xml`**): mvn -B "-Dgpg.skip=true" clean verify ``` -This line (**`1.6.3`**) compiles against **`au.gov.nehta:hi-wsdl`** — it does **not** run **`wsimport`**. +This line (**`8.0.0`**) compiles against **`au.gov.nehta:hi-wsdl`** **`8.0.0`** - it does **not** run **`wsimport`**. The first number of both Maven versions is the targeted Java SE version (**8**). Optional faster local **`verify`** without the Javadoc JAR: **`mvn -B -Pdev-javadoc-off -Dgpg.skip=true clean verify`**. @@ -47,13 +51,19 @@ Set environment variable **`MVN_SETTINGS`** to pass **`-s`** to Maven (path to y ## Local builds (unpublished artifacts) -When co-developing with **`hi-wsdl-java`**, install matching **`au.gov.nehta:hi-wsdl`** at **`${project.version}`** before **`verify`** here: +Install matching siblings at **`${project.version}`** (**8.0.0** / **`8.0.0-SNAPSHOT`**) before **`verify`** here: ```text -# hi-wsdl (same SNAPSHOT or GA as this pom.xml) +# hi-wsdl-java +mvn -B "-Dgpg.skip=true" clean install + +# smi-xsp-java +mvn -B "-Dgpg.skip=true" clean install + +# common-library-java (needs smi-xsp) mvn -B "-Dgpg.skip=true" clean install -# hi-b2b-client (this repository) +# hi-b2b-client-java (this repository) mvn -B "-Dgpg.skip=true" clean verify ``` diff --git a/MAINTAINERS.md b/MAINTAINERS.md index e801451..5dffb31 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -2,70 +2,96 @@ **Audience:** people changing the build, dependency coordinates, tests, or WSDL layout - not library integrators. Integrators should use **README.md**, published Javadoc, and **`pom.xml`** coordinates. -## Release lines +## Versioning -| Version | Java | APIs | `Service` stubs | -| ------- | ---- | ---- | ----------------- | -| **1.6.3** | 8 | **`javax.xml.ws`**, **`javax.xml.bind`** | **14** (standard HI B2B) | -| **1.6.5** | 11 | **Jakarta** XML WS / Bind | **14** (standard HI B2B) | -| **1.7.0** | 11 | **Jakarta** XML WS / Bind | **26** (full MCA) | +The **first number** of the Maven version is the **Java SE** version that line targets. **`hi-b2b-client`** and **`hi-wsdl`** always share the **same** version (same SNAPSHOT or GA) on a given line. -**Git branch mapping (maintainers / checkout only — do not use in integrator docs):** +| Maven version | Java SE | +| ------------- | ------- | +| **8.0.0** | **8** | +| **11.0.0.1** | **11** | +| **17.0.0.1** | **17** | +| **21.0.0.1** | **21** | +| **24.0.0.1** | **24** | -| Version | Git branch | -| ------- | ---------- | -| **1.6.3** | `java-8-javax` | -| **1.6.5** | `java-11-jakarta` | -| **1.7.0** | `java-11-jakarta-full-wsdl` | +**Documentation convention:** README, CONTRIBUTING, CHANGELOG, and integrator-facing text use **version numbers only** - never Git branch names. -**`master`** is frozen and must stay in sync with **`origin/master`** — do not edit; use **`git worktree`** locally (**`CONTRIBUTING.md`**). +| Version | Java | APIs | Facade clients | +| ------- | ---- | ---- | -------------- | +| **8.0.0** | 8 | **`javax.xml.ws`**, **`javax.xml.bind`** | **14** (standard HI B2B) | +| **11.0.0.1** | 11 | **Jakarta** XML WS / Bind | **26** (full MCA) | +| **17.0.0.1** | 17 | **Jakarta** XML WS / Bind | **26** (full MCA) | +| **21.0.0.1** | 21 | **Jakarta** XML WS / Bind | **26** (full MCA) | +| **24.0.0.1** | 24 | **Jakarta** XML WS / Bind | **26** (full MCA) | -**This checkout:** **`1.6.3-SNAPSHOT`** (**`1.6.3`** release line). +**Git branch mapping (maintainers / checkout only - do not use in integrator docs):** -## Release scope (`1.6.3`) +| Version | Official Git branch | +| ------- | ------------------- | +| **8.0.0** | `java-8` | +| **11.0.0.1** | `java-11` | +| **17.0.0.1** | `java-17` | +| **21.0.0.1** | `java-21` | +| **24.0.0.1** | `java-24` | -- **Goal:** Java **8** bytecode (`maven.compiler.release` **8**) with **`javax.xml.ws`** / JAXB usage in application code; SOAP types **`au.net.electronichealth.*`** come from **`au.gov.nehta:hi-wsdl`** on the classpath ( **`hi.wsdl.version`** ). The default lifecycle does **not** run **`wsimport`** in this artifact. +**`hi-wsdl-java`** uses the **same branch names** and the **same Maven version** on each pair (`hi-wsdl` **8.0.0** on `java-8` with **`hi-b2b-client`** **8.0.0**, and so on). Artifact ids stay **`hi-wsdl`** and **`hi-b2b-client`**; the version distinguishes the Java SE line. + +On a given branch, **do not change the first number** of **``**. Next GA on **`java-8`** is **`8.0.0.2`** (then **`8.0.1-SNAPSHOT`**), not **`11.x`**. A new Java SE target is a **new branch**, not a bump on this one. + +**This checkout (`8.0.0-SNAPSHOT`):** Java **8**, **14** facades, types from **`au.gov.nehta:hi-wsdl`** at **`${project.version}`** (no in-repo **`wsimport`**). Stack, Surefire includes, and **`.github/workflows/ci.yml`** (branch **`java-8`**, JDK **8**) below apply to **this line only**. Other branches keep their own **`pom.xml`**, CI branch filter, and JDK. + +## Release scope (`8.0.0`) + +- **Goal:** Java **8** bytecode (`maven.compiler.release` **8**) with **`javax.xml.ws`** / JAXB usage in application code; SOAP types **`au.net.electronichealth.*`** come from **`au.gov.nehta:hi-wsdl`** on the classpath (**`hi.wsdl.version`**). The default lifecycle does **not** run **`wsimport`** in this artifact. - **`wsdls/`** is optional reference and Ant **`wsimport`** material (see **`wsdls/readme.txt`**), not required to compile this library. ## Contributors vs release publisher (`pom.xml`) -**Contributors (PRs, ordinary commits):** Do not change **``** (stay on **`-SNAPSHOT`** unless the maintainer requests a bump), **``**, or **`distributionManagement`**. Leave **`maven-gpg-plugin`** **`skip`** **`true`** so default **`mvn verify`** does not require a signing key. Record user-visible work under **`CHANGELOG.md`** in the **`= =`** block that matches **`pom.xml`** **``**. +**Contributors (PRs, ordinary commits):** Do not change **``** (stay on **`-SNAPSHOT`** unless the maintainer requests a bump), **``**, or **`distributionManagement`**. If a maintainer requests a SNAPSHOT bump on this branch, change only the trailing numbers (**`8.0.1-SNAPSHOT`**), never the Java SE digit. Leave **`maven-gpg-plugin`** **`skip`** **`true`** so default **`mvn verify`** does not require a signing key. Record user-visible work under **`CHANGELOG.md`** in the **`= =`** block that matches **`pom.xml`** **``**. -**Release publisher:** In the release change set: set **``** to the GA coordinate (no **`-SNAPSHOT`**); set **``** to the Git tag you will publish (match existing tag naming). Move **`CHANGELOG.md`** bullets from the snapshot section into a new **`= =`** section; add a fresh **`-SNAPSHOT`** block for the next development cycle. Deploy via Sonatype Central Portal (**`central-publishing-maven-plugin`**; copy **`settings.xml.example`** → **`settings.xml`**, server id **`central`**). See **Release** below. +**Release publisher:** In the release change set: set **``** to the GA coordinate (no **`-SNAPSHOT`**); set **``** to the Git tag you will publish (match existing tag naming). Move **`CHANGELOG.md`** bullets from the snapshot section into a new **`= =`** section; add a fresh **`-SNAPSHOT`** block for the next development cycle. Deploy via Sonatype Central Portal (**`central-publishing-maven-plugin`**; copy **`settings.xml.example`** -> **`settings.xml`**, server id **`central`**). See **Release** below. ## Release -Publishing uses **`central-publishing-maven-plugin`** (Sonatype Central Portal). Copy **`settings.xml.example`** → **`settings.xml`**, server id **`central`**. +Publishing uses **`central-publishing-maven-plugin`** (Sonatype Central Portal). Copy **`settings.xml.example`** -> **`settings.xml`**, server id **`central`**. + +**Parallel release lines (maintainers only):** each Git branch publishes a **different Maven version** - integrators choose by coordinate, not branch name. The first number of that version is the targeted Java SE version. Run **`release:prepare` / `release:perform`** (or manual deploy) **on that branch** (not detached HEAD). -**Parallel release lines (maintainers only):** each Git branch publishes a **different Maven version** — integrators choose by coordinate, not branch name. +| Branch (both repos) | Java | `hi-wsdl` / `hi-b2b-client` | Facades | +| ------------------- | ---- | --------------------------- | ------- | +| **`java-8`** | 8 / javax | **8.0.0** | 14 | +| **`java-11`** | 11 / Jakarta | **11.0.0.1** | 26 | +| **`java-17`** | 17 / Jakarta | **17.0.0.1** | 26 | +| **`java-21`** | 21 / Jakarta | **21.0.0.1** | 26 | +| **`java-24`** | 24 / Jakarta | **24.0.0.1** | 26 | -| Branch | Java | HI client / WSDL version | Facades | -| ------ | ---- | ------------------------ | ------- | -| **`java-8-javax`** → **`master`** | 8 / javax | **1.6.3** | 14 | -| **`java-11-jakarta`** | 11 / Jakarta | **1.6.5** | 14 | -| **`java-11-jakarta-full-wsdl`** | 11 / Jakarta | **1.7.0** | 26 | +**Order:** publish **`hi-wsdl-java`** first (same branch and GA), then this repo. Client **`verify`** / **`release:perform`** needs **`hi-wsdl`** at that GA on Central (or a prior local **`mvn install`**). Do not reverse the order. -Release **`hi-wsdl`** and **`hi-b2b-client`** at the **same GA version** on the matching branch pair before integrators upgrade. +**`-DdevelopmentVersion`:** keep the same first number as **`-DreleaseVersion`** (example on this line: **`8.0.0`** then **`8.0.1-SNAPSHOT`**). ### SNAPSHOT or manual GA +Matching **`hi-wsdl`** at **`${project.version}`** must already resolve (Central GA or local **`mvn install`** from **`hi-wsdl-java`** on the same branch). + 1. Update **CHANGELOG.md** (and **`pom.xml`** / SCM **``** for manual GA). 2. **`mvn -B "-Prelease" clean verify`** 3. **`mvn -B "-Prelease" deploy`** -Git/SCM settings for **`maven-release-plugin`** live in **`pom.xml`** properties (**`scm.repo.url`**, **`release.*`**). Tags default to **`{artifactId}-{version}`** (e.g. **`hi-b2b-client-1.7.0`**). +Git/SCM settings for **`maven-release-plugin`** live in **`pom.xml`** properties (**`scm.repo.url`**, **`release.*`**). Tags default to **`{artifactId}-{version}`** (e.g. **`hi-b2b-client-8.0.0`**). ### Automated GA (`maven-release-plugin`) Run on the **target branch** with a **clean** working tree. The plugin commits version bumps, creates the release tag, deploys from the tag checkout, bumps to the next **`-SNAPSHOT`**, and **pushes branch + tag** (**`pushChanges`** / **`remoteTagging`** in **`pom.xml`**). Git remote credentials (SSH or HTTPS) must work non-interactively. ```text -mvn -B "-Prelease" release:prepare release:perform -DreleaseVersion=1.7.0 -DdevelopmentVersion=1.7.1-SNAPSHOT -Dtag=hi-b2b-client-1.7.0 +mvn -B "-Prelease" release:prepare release:perform -DreleaseVersion=8.0.0 -DdevelopmentVersion=8.0.1-SNAPSHOT -Dtag=hi-b2b-client-8.0.0 ``` -Replace versions and **`-Dtag`** for the branch you are on (**`hi-wsdl-1.6.5`**, **`hi-b2b-client-1.6.3`**, etc.). Omit **`-D…`** only if you accept interactive prompts. +Replace **`-DreleaseVersion`**, **`-DdevelopmentVersion`**, and **`-Dtag`** for the branch you are on (same first number; e.g. **`hi-wsdl-11.0.0.1`** / **`hi-b2b-client-11.0.0.1`** on **`java-11`**). Omit **`-D...`** only if you accept interactive prompts. -**After success:** confirm the artifact on Central; repeat on the paired types/client repo. No extra Git steps unless push failed (then **`git push origin `** and **`git push origin `**). +**After success:** confirm **`hi-wsdl`** GA on Central, then this artifact. No extra Git steps unless push failed; then from the release branch: + +`git push origin java-8` (or **`java-11`**, **`java-17`**, **`java-21`**, **`java-24`**) and **`git push origin `**. **`-Dgpg.skip=false`** is equivalent to **`-Prelease`** for signing. @@ -73,12 +99,22 @@ Replace versions and **`-Dtag`** for the branch you are on (**`hi-wsdl-1.6.5`**, **`CHANGELOG.md`** uses **`= version =`** section headers. Match the snapshot header to **`pom.xml`** **``** until the publisher cuts GA. +## New Java SE line + +When adding a line (e.g. Java **25**): create **`java-25`** on **both** **`hi-wsdl-java`** and **`hi-b2b-client-java`** from the nearest existing line; set **``** first number to **25** (e.g. **`25.0.0.1-SNAPSHOT`**); set **`maven.compiler.release`**, JAX-WS coordinates, CI **`java-version`** / branch filter, and docs to that line. Do not retarget an existing branch. + ## Java / JAX stack (`pom.xml` properties) +This subsection is **this `java-8` checkout**. Other lines document their stack in their own **MAINTAINERS** / **`pom.xml`**. + - **`maven.compiler.release` 8** - bytecode and language level for Java 8 consumers. - **`ee4j.jaxws.version`** - **`com.sun.xml.ws:jaxws-rt`** on **Maven Central** (**2.3.7** is the last **2.3.x** for this branch). Transitive API JARs may use **`jakarta.*`** **groupId** coordinates while still exposing **`javax.*`** packages - do not exclude them from **`jaxws-rt`** in consumer POMs. This project only excludes **`webservices-rt`** from **`common-library`** (old stack conflict with **`jaxws-rt`**). -- **`hi.wsdl.version`** — **`${project.version}`** (same SNAPSHOT or GA as **`hi-b2b-client`**); **`mvn install`** in **`hi-wsdl-java`** before unpublished **`verify`**; coordinate GA releases with **`hi-wsdl-java`**. -- **`nehta.lib.version`** - **`au.gov.nehta:common-library`** and explicit **`au.gov.nehta:smi-xsp`** ( **`smi-common-utils`** removed; **`ArgumentUtils`** and **`CertificateValidator`** come from **`smi-xsp`** / **`common-library`** transitives). +- **`hi.wsdl.version`** - **`${project.version}`** (same SNAPSHOT or GA as **`hi-b2b-client`**; first number is the Java SE target). Unpublished **`verify`**: **`mvn install`** matching **`hi-wsdl-java`** on the **same branch** first. GA: publish **`hi-wsdl`** then this artifact. +- **`nehta.lib.version`** - **`au.gov.nehta:common-library`** (**8.0.0**; SNAPSHOT while unpublished). **`nehta.xsp.lib.version`** - **`au.gov.nehta:smi-xsp`**. **`smi-common-utils`** is not a direct dependency; **`ArgumentUtils`** and **`CertificateValidator`** come from **`smi-xsp`** / **`common-library`** transitives. + +## Default tests + +Default Surefire **``** (see **`pom.xml`**): **`TimeUtilityTest`**, **`TestConfigurationTest`**, **`HiWsdlArtifactRootTest`**, **`HiRequestElementOrderParityTest`**, **`ConsumerSearchIHIClientArgumentValidatorTest`**. **`-Pintegration`** runs mutual-TLS tests with **`local.properties`** / **`HI_*`**. ## Fast builds diff --git a/README.md b/README.md index 6653158..edb98ca 100644 --- a/README.md +++ b/README.md @@ -25,31 +25,39 @@ Registration: https://implementer.digitalhealth.gov.au/resources/hi-service-regi ## Dependency -Add the artifact from [Maven Central](https://central.sonatype.com/). Use a **``** that matches your JDK and API stack (see **Release lines**). +Add the artifact from [Maven Central](https://central.sonatype.com/). Use a **``** that matches your JDK (see **Versioning**). ```xml au.gov.nehta hi-b2b-client - 1.6.3 + 8.0.0 ``` -**This line (`1.6.3`):** Java **8**, **`javax.xml.ws`** / **`javax.xml.bind`**, **14** standard HI B2B facade clients. Add **`com.sun.xml.ws:jaxws-rt`** **2.3.7** at runtime in your application. +**This line (`8.0.0`):** Java **8**, **`javax.xml.ws`** / **`javax.xml.bind`**, **14** standard HI B2B facade clients. Add **`com.sun.xml.ws:jaxws-rt`** **2.3.7** at runtime in your application. Pair with **`au.gov.nehta:hi-wsdl`** **`8.0.0`**. --- -## Release lines +## Versioning -| Version | Java | APIs | Facade clients | -| ------- | ---- | ---- | -------------- | -| **1.6.3** | 8 | **`javax.xml.ws`**, **`javax.xml.bind`** | **14** (standard HI B2B) | -| **1.6.5** | 11 | **Jakarta** XML WS / Bind | **14** (standard HI B2B) | -| **1.7.0** | 11 | **Jakarta** XML WS / Bind | **26** (full MCA) | +The **first number** of the Maven version is the **Java SE** version that line targets. **`hi-b2b-client`** and **`hi-wsdl`** always use the **same** version on a given line (same SNAPSHOT or GA). -All published versions are on **[Maven Central](https://central.sonatype.com/)**. +| Maven version | Java SE | APIs | Facade clients | +| ------------- | ------- | ---- | -------------- | +| **8.0.0** | **8** | **`javax.xml.ws`**, **`javax.xml.bind`** | **14** (standard HI B2B) | +| **11.0.0.1** | **11** | **Jakarta** XML WS / Bind | **26** (full MCA) | +| **17.0.0.1** | **17** | **Jakarta** XML WS / Bind | **26** (full MCA) | +| **21.0.0.1** | **21** | **Jakarta** XML WS / Bind | **26** (full MCA) | +| **24.0.0.1** | **24** | **Jakarta** XML WS / Bind | **26** (full MCA) | -SOAP application code on **`1.6.3`** uses **`javax.xml.ws`**, **`javax.xml.bind`**, and related **`javax`** APIs. SOAP types come from **`au.gov.nehta:hi-wsdl`** at the same version when both artifacts are on the classpath. +Pick the coordinate that matches your JDK. Do not mix **`hi-b2b-client`** and **`hi-wsdl`** versions. All published versions are on **[Maven Central](https://central.sonatype.com/)**. + +--- + +## Note + +The **8.0.0** release does not support the full WSDL specification (**14** facades, **`javax`**). **11.0.0.1** and later lines use **Jakarta** and expose all **26** facades. --- @@ -110,7 +118,7 @@ Copy **`local.properties.example`** to **`local.properties`**, fill in values, a ## Client classes -Package base: **`au.gov.nehta.vendorlibrary.hi`**. This artifact line (**1.6.3**) exposes **14** standard HI B2B facade classes. Full MCA coverage (**26** stubs) is version **1.7.0**. +Package base: **`au.gov.nehta.vendorlibrary.hi`**. This artifact line (**8.0.0**) exposes **14** standard HI B2B facade classes. Full MCA coverage (**26** facades, **Jakarta** XML WS / Bind) is available from **11.0.0.1** onward - see **`CLIENT-FEATURES.md`** and **`WSDL-CLIENT-PURPOSES.md`**. | Area | Classes | | ---- | ------- | @@ -136,7 +144,7 @@ Samples under **`src/sample/java`** (`...hi.sample`) are not on the default clas Address searches (`australianPostalAddressSearch`, `australianStreetAddressSearch`, `internationalAddressSearch`) also require **`ihiNumber`** to be unset. Use **`detailedSearch`** for demographics-only lookup, not **`basicSearch`**. -Batch sync/async clients apply the same rules in **`SearchBatch.ArgumentValidator`**. +IHI **sync** batch (`ConsumerSearchIHIBatchSyncClient` / `SearchBatch`) applies the same field rules in **`SearchBatch.ArgumentValidator`**. --- @@ -144,6 +152,8 @@ Batch sync/async clients apply the same rules in **`SearchBatch.ArgumentValidato | Document | Content | | -------- | ------- | +| **`CLIENT-FEATURES.md`** | Capability overview by facade class | +| **`WSDL-CLIENT-PURPOSES.md`** | WSDL service to facade mapping (**14** vs **26** lines) | | **`wsdls/readme.txt`** | WSDL download, layout, runtime property names | | **`SECURITY.md`** | Secrets and reporting | | **`CONTRIBUTING.md`** | Building or changing this repository from source | diff --git a/WSDL-CLIENT-PURPOSES.md b/WSDL-CLIENT-PURPOSES.md new file mode 100644 index 0000000..6ee0229 --- /dev/null +++ b/WSDL-CLIENT-PURPOSES.md @@ -0,0 +1,106 @@ +# WSDL functionality by client purpose (HI vs myHR) + +Cross-repo reference for **Healthcare Identifiers (HI)** and **My Health Record (PCEHR / myHR)** B2B SOAP contracts. These are separate national services: different WSDL trees, different Maven artifacts, and no shared SOAP operations. + +| | **hi-b2b-client-java** | **mhr-b2b-client-java** | +|---|---|---| +| **National service** | Healthcare Identifiers (HI) Service | My Health Record (PCEHR / myHR) B2B | +| **WSDL prefix** | `HI_*` (Medicare Australia (MCA) licensed bundle) | `B2B_*` under `wsdls/src/main/resources/wsdl/External/` | +| **Identifiers handled** | IHI, HPI-I, HPI-O | Individual myHR record (IHI as context in headers, not managed here) | +| **Typical use** | Look up / validate / manage healthcare identifiers | Access record, register consumer, upload/retrieve documents, read views | +| **Service WSDLs codegen'd** | **26** (+ paired `*Interface` WSDLs in licensed bundle) | **12** `B2B_*` services | +| **Facade classes** | **26** from **11.0.0.1** onward; **14** in **8.0.0** | +| **Maven artifact** | `au.gov.nehta:hi-b2b-client` | `au.gov.nehta:mhr-b2b-client` | + +Apps needing both depend on **two libraries**. HI-only detail: **`CLIENT-FEATURES.md`** in this repo. MHR third-party scope: **`ADHA-THIRD-PARTY-SCOPE.md`** in `mhr-b2b-client-java`. Three-client matrix: **`WSDL-CLIENT-PURPOSES.md`** in `myhr-b2b-client-java`. + +--- + +## HI (`hi-b2b-client-java`) - MCA `HI_*` WSDL + +Grouped by **client purpose**. WSDL filenames in the licensed bundle include version suffixes (e.g. `HI_ConsumerSearchIHI-3.0.wsdl`); logical names below omit versions. + +| Purpose | WSDL service | What it does | Java facade | In **`8.0.0`** (14 facades) | +|---|---|---|---|:---:| +| **IHI - search** | `HI_ConsumerSearchIHI` | Find/validate an individual's IHI (by IHI, Medicare, DVA, or demographics) | `ConsumerSearchIHIClient` | Yes | +| **IHI - batch search** | `HI_ConsumerSearchIHIBatchSync` | Synchronous batch IHI search | `ConsumerSearchIHIBatchSyncClient` | Yes | +| **IHI - batch search** | `HI_ConsumerSearchIHIBatchAsync` | Submit/retrieve async batch IHI search | `ConsumerSearchIHIBatchAsyncClient` | **11.0.0.1+** | +| **IHI - create** | `HI_ConsumerCreateProvisionalIHI` | Create provisional IHI | `ConsumerCreateProvisionalIHIClient` | **11.0.0.1+** | +| **IHI - update** | `HI_ConsumerUpdateProvisionalIHI` | Update provisional IHI | `ConsumerUpdateProvisionalIHIClient` | **11.0.0.1+** | +| **IHI - merge** | `HI_ConsumerMergeProvisionalIHI` | Merge provisional IHIs | `ConsumerMergeProvisionalIHIClient` | **11.0.0.1+** | +| **IHI - resolve** | `HI_ConsumerResolveProvisionalIHI` | Resolve provisional IHI | `ConsumerResolveProvisionalIHIClient` | **11.0.0.1+** | +| **IHI - create** | `HI_ConsumerCreateUnverifiedIHI` | Create unverified IHI | `ConsumerCreateUnverifiedIHIClient` | **11.0.0.1+** | +| **IHI - create** | `HI_ConsumerCreateVerifiedIHI` | Create verified IHI | `ConsumerCreateVerifiedIHIClient` | **11.0.0.1+** | +| **IHI - update** | `HI_ConsumerUpdateIHI` | Update IHI details | `ConsumerUpdateIHIClient` | **11.0.0.1+** | +| **IHI - notify** | `HI_ConsumerNotifyDuplicateIHI` | Notify duplicate IHI | `ConsumerNotifyDuplicateIHIClient` | **11.0.0.1+** | +| **IHI - notify** | `HI_ConsumerNotifyReplicaIHI` | Notify replica IHI | `ConsumerNotifyReplicaIHIClient` | **11.0.0.1+** | +| **HPI-I - search** | `HI_ProviderSearchForProviderIndividual` | Search provider individual (HPI-I) | `ProviderSearchForProviderIndividualClient` | Yes | +| **HPI-I - directory search** | `HI_ProviderSearchHIProviderDirectoryForIndividual` | Search HI provider directory for individual | `ProviderSearchHIProviderDirectoryForIndividualClient` | Yes | +| **HPI-I - batch search** | `HI_ProviderBatchAsyncSearchForProviderIndividual` | Async batch search for provider individual | `SearchForProviderIndividualBatchAsyncClient` | Yes | +| **HPI-I - TDS search** | `HI_ProviderSearchTdsProviderIndividual` | Search TDS provider individual | `ProviderSearchTdsProviderIndividualClient` | **11.0.0.1+** | +| **HPI-I - TDS manage** | `HI_ProviderManageTdsProviderIndividual` | Manage TDS provider individual | `ProviderManageTdsProviderIndividualClient` | **11.0.0.1+** | +| **HPI-O - search** | `HI_ProviderSearchForProviderOrganisation` | Search provider organisation (HPI-O) | `ProviderSearchForProviderOrganisationClient` | Yes | +| **HPI-O - directory search** | `HI_ProviderSearchHIProviderDirectoryForOrganisation` | Search HI provider directory for organisation | `ProviderSearchHIProviderDirectoryForOrganisationClient` | Yes | +| **HPI-O - batch search** | `HI_ProviderBatchAsyncSearchForProviderOrganisation` | Async batch search for organisation | `SearchForProviderOrganisationBatchAsyncClient` | Yes | +| **HPI-O - read** | `HI_ProviderReadProviderOrganisation` | Read provider organisation details | `ProviderReadProviderOrganisationClient` | Yes | +| **HPI-O - read** | `HI_ProviderReadProviderAdministrativeIndividual` | Read administrative individual | `ProviderReadAdministrativeIndividualClient` | Yes | +| **HPI-O - manage** | `HI_ProviderManageProviderOrganisation` | Manage provider organisation | `ProviderManageProviderOrganisationClient` | Yes | +| **HPI-O - manage** | `HI_ProviderManageProviderDirectoryEntry` | Manage provider directory entry | `ProviderManageProviderDirectoryEntryClient` | Yes | +| **HPI-O - manage** | `HI_ProviderManageProviderAdministrativeIndividual` | Manage administrative individual | `ProviderManageProviderAdministrativeIndividualClient` | Yes | +| **Reference data** | `HI_ProviderReadReferenceData` | Read HI reference data (codes, lists) | `ReadReferenceDataClient` | Yes | + +**Notes** + +- Each service WSDL has a paired `*Interface` WSDL in the licensed bundle; facades bind to the service WSDL. +- **11.0.0.1** and later (**17.0.0.1**, **21.0.0.1**, **24.0.0.1**, …) expose all **26** rows above. **8.0.0** exposes the rows marked **Yes** in the last column only. + +--- + +## myHR / PCEHR (`mhr-b2b-client-java`) - `B2B_*` WSDL + +Grouped by **client purpose**. All **12** WSDLs are codegen'd from `wsdls/src/main/resources/wsdl/External/`; **15** facade classes wrap them. + +| Purpose | WSDL | SOAP / functional capability | Java facade(s) | +|---|---|---|---| +| **Record access** | `B2B_PCEHRProfile` | Check whether a myHR exists for an individual | `DoesPCEHRExistClient` | +| **Record access** | `B2B_PCEHRProfile` | Gain access to a consumer's myHR (incl. access code flow) | `GainPCEHRAccessClient` | +| **Registration** | `B2B_RegisterPCEHR` | Register a consumer for myHR | `RegisterPCEHRClient` | +| **Document exchange - registry** | `B2B_DocumentRegistry` | Register document metadata (XDS.b); also used to **list** documents in the record | `UploadDocumentMetadataClient`, `GetDocumentListClient` | +| **Document exchange - repository** | `B2B_DocumentRepository` | Upload document content (Provide & Register, **MTOM**) | `UploadDocumentClient` | +| **Document exchange - repository** | `B2B_DocumentRepository` | Retrieve document content (Retrieve Document Set) | `GetDocumentClient` | +| **Document exchange - removal** | `B2B_RemoveDocument` | Remove a document from the record | `RemoveDocumentClient` | +| **Clinical / record views** | `B2B_GetView` | Third-party view types (7): health record overview, Medicare overview, pathology, diagnostic imaging, observations, prescriptions/dispenses, health check schedule - see **`ADHA-THIRD-PARTY-SCOPE.md`** in `mhr-b2b-client-java` | `GetViewClient` | +| **Record views - individual** | `B2B_GetIndividualDetailsView` | Individual details held in myHR | `GetIndividualDetailsViewClient` | +| **Record views - representatives** | `B2B_GetRepresentativeList` | List authorised representatives | `GetRepresentativeListClient` | +| **Record views - audit** | `B2B_GetAuditView` | Audit trail view | `GetAuditViewClient` | +| **Record views - change history** | `B2B_GetChangeHistoryView` | Change history view | `GetChangeHistoryViewClient` | +| **Templates - read** | `B2B_GetTemplate` | Fetch a document template | `GetTemplateClient` | +| **Templates - search** | `B2B_SearchTemplate` | Search available templates | `SearchTemplateClient` | + +**Notes** + +- Document flows use **IHE XDS.b** (`DocumentRegistry` / `DocumentRepository`) plus PCEHR-specific remove/register/view WSDLs. +- `GetViewClient` is one facade over **`B2B_GetView`** with typed overloads for each supported view type (see **`ADHA-THIRD-PARTY-SCOPE.md`** in `mhr-b2b-client-java`). + +--- + +## Side-by-side: what each library is for + +| Client purpose | HI (`hi-b2b-client`) | myHR (`mhr-b2b-client`) | +|---|---|---| +| **Person identifier lookup / validation** | Yes - IHI search & lifecycle | No (uses IHI as record key only) | +| **Provider person (HPI-I)** | Search, directory, batch, TDS | No | +| **Provider organisation (HPI-O)** | Search, read, manage org/directory/admin | No | +| **Reference / code lists** | `ReadReferenceData` | No | +| **Consumer myHR registration** | No | `RegisterPCEHRClient` | +| **Check / open myHR access** | No | `DoesPCEHRExist`, `GainPCEHRAccess` | +| **Upload / download clinical documents** | No | XDS registry + repository (+ MTOM upload) | +| **Remove documents from myHR** | No | `RemoveDocumentClient` | +| **Clinical summaries & record views** | No | Multiple `Get*View` clients | +| **Document templates** | No | `GetTemplate`, `SearchTemplate` | + +--- + +## Typical integration flow + +Many myHR B2B calls require an **IHI** (and often HPI-I / HPI-O) in SOAP headers. That identifier is usually obtained via **`hi-b2b-client`**, then passed into **`mhr-b2b-client`** facades - two artifacts, one application workflow. diff --git a/pom.xml b/pom.xml index b927a9f..7a65244 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ au.gov.nehta hi-b2b-client - 1.6.5-SNAPSHOT + 8.0.0-SNAPSHOT HI B2B client Example client implementations of Healthcare Identifiers (HI) service https://github.com/AuDigitalHealth/hi-b2b-client-java @@ -99,10 +99,10 @@ 0.8.14 3.6.2 - + ${project.version} - 1.2.2 - 1.2.1 + ${project.version} + ${project.version} 3.5.0 3.6.2 @@ -263,6 +263,7 @@ **/TestConfigurationTest.java **/HiWsdlArtifactRootTest.java **/ConsumerSearchIHIClientArgumentValidatorTest.java + **/HiRequestElementOrderParityTest.java diff --git a/src/main/java/au/gov/nehta/vendorlibrary/hi/client/BaseClient_3.java b/src/main/java/au/gov/nehta/vendorlibrary/hi/client/BaseClient_3.java index e2c63ce..f789a71 100644 --- a/src/main/java/au/gov/nehta/vendorlibrary/hi/client/BaseClient_3.java +++ b/src/main/java/au/gov/nehta/vendorlibrary/hi/client/BaseClient_3.java @@ -62,7 +62,7 @@ public BaseClient_3( ArgumentUtils.checkNotNull(individualQualifiedId, "individualQualifiedId"); ArgumentUtils.checkNotNull(productHeader, "productHeader"); ArgumentUtils.checkNotNull(signingPrivateKey, "signingPrivateKey"); - ArgumentUtils.checkNotNull(signingCertificate, "signingPrivateKey"); + ArgumentUtils.checkNotNull(signingCertificate, "signingCertificate"); ArgumentUtils.checkNotNull(sslSocketFactory, "sslSocketFactory"); // supply an optional certificate Validator @@ -114,7 +114,7 @@ public BaseClient_3( ArgumentUtils.checkNotNullNorBlank(serviceEndpoint, "serviceEndpoint"); ArgumentUtils.checkNotNull(productHeader, "productHeader"); ArgumentUtils.checkNotNull(signingPrivateKey, "signingPrivateKey"); - ArgumentUtils.checkNotNull(signingCertificate, "signingPrivateKey"); + ArgumentUtils.checkNotNull(signingCertificate, "signingCertificate"); ArgumentUtils.checkNotNull(sslSocketFactory, "sslSocketFactory"); diff --git a/src/main/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClient.java b/src/main/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClient.java index 915e08b..6b7b265 100644 --- a/src/main/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClient.java +++ b/src/main/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClient.java @@ -139,6 +139,7 @@ public SearchForProviderIndividualBatchAsyncClient( */ public SubmitSearchForProviderIndividualResponse submitSearch(ProviderIndividualBatchSearch request) throws StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); checkUserID(); submitSearchCheck(request.getSearchRequest()); Holder signatureHeader = null; @@ -164,7 +165,8 @@ public SubmitSearchForProviderIndividualResponse submitSearch(ProviderIndividual public SubmitSearchForProviderIndividualResponse submitSearch(ProviderIndividualBatchSearch request, au.gov.nehta.vendorlibrary.hi.client.wrapped.QualifiedId individualId) throws StandardErrorMsg { - + ArgumentUtils.checkNotNull(request, "request"); + ArgumentUtils.checkNotNull(individualId, "individualId"); submitSearchCheck(request.getSearchRequest()); Holder signatureHeader = null; Holder productHolder = new Holder<>(productHeader); @@ -189,6 +191,8 @@ public SubmitSearchForProviderIndividualResponse submitSearch(ProviderIndividual public RetrieveSearchForProviderIndividualResponse retrieveSearch(RetrieveSearchForProviderIndividual request, au.gov.nehta.vendorlibrary.hi.client.wrapped.QualifiedId individualId ) throws StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); + ArgumentUtils.checkNotNull(individualId, "individualId"); retrieveSearchCheck(request); Holder signatureHeader = null; Holder productHolder = new Holder<>(productHeader); @@ -210,6 +214,7 @@ public RetrieveSearchForProviderIndividualResponse retrieveSearch(RetrieveSearch * @throws StandardErrorMsg if the Web Service call fails. */ public RetrieveSearchForProviderIndividualResponse retrieveSearch(RetrieveSearchForProviderIndividual request) throws StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); checkUserID(); retrieveSearchCheck(request); Holder signatureHeader = null; diff --git a/src/main/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClient.java b/src/main/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClient.java index d0ac8e3..db48816 100644 --- a/src/main/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClient.java +++ b/src/main/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClient.java @@ -138,6 +138,7 @@ public SearchForProviderOrganisationBatchAsyncClient(String serviceEndpoint, */ public SubmitSearchForProviderOrganisationResponse submitSearch(ProviderOrganisationBatchSearch request) throws au.net.electronichealth.ns.hi.svc.providerbatchasyncsearchforproviderorganisation._5_1.StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); checkUserID(); submitSearchCheck(request.getSearchRequest()); Holder signatureHeader = null; @@ -163,7 +164,8 @@ public SubmitSearchForProviderOrganisationResponse submitSearch(ProviderOrganisa public SubmitSearchForProviderOrganisationResponse submitSearch(ProviderOrganisationBatchSearch request, au.gov.nehta.vendorlibrary.hi.client.wrapped.QualifiedId individualId) throws StandardErrorMsg { - + ArgumentUtils.checkNotNull(request, "request"); + ArgumentUtils.checkNotNull(individualId, "individualId"); submitSearchCheck(request.getSearchRequest()); Holder signatureHeader = null; Holder productHolder = new Holder<>(productHeader); @@ -188,6 +190,8 @@ public SubmitSearchForProviderOrganisationResponse submitSearch(ProviderOrganisa public RetrieveSearchForProviderOrganisationResponse retrieveSearch(RetrieveSearchForProviderOrganisation request, au.gov.nehta.vendorlibrary.hi.client.wrapped.QualifiedId individualId ) throws StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); + ArgumentUtils.checkNotNull(individualId, "individualId"); retrieveSearchCheck(request); Holder signatureHeader = null; Holder productHolder = new Holder<>(productHeader); @@ -209,6 +213,7 @@ public RetrieveSearchForProviderOrganisationResponse retrieveSearch(RetrieveSear * @throws StandardErrorMsg if the Web Service call fails. */ public RetrieveSearchForProviderOrganisationResponse retrieveSearch(RetrieveSearchForProviderOrganisation request) throws StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); checkUserID(); retrieveSearchCheck(request); Holder signatureHeader = null; diff --git a/src/main/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClient.java b/src/main/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClient.java index 1b448d3..ffefe6b 100644 --- a/src/main/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClient.java +++ b/src/main/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClient.java @@ -13,6 +13,7 @@ */ package au.gov.nehta.vendorlibrary.hi.ihi; +import au.gov.nehta.common.utils.ArgumentUtils; import au.gov.nehta.vendorlibrary.hi.client.BaseClient_3; import au.gov.nehta.xsp.CertificateValidator; import au.net.electronichealth.ns.hi.svc.consumersearchihibatchsyncrequest._3.ConsumerSearchIHIBatchSyncPortType; @@ -198,6 +199,7 @@ private ConsumerSearchIHIBatchSyncClient(final String serviceEndpoint, * @throws StandardErrorMsg if the Web Service call fails. */ public final SearchIHIBatchResponse batchSearch(SearchBatch request) throws StandardErrorMsg { + ArgumentUtils.checkNotNull(request, "request"); checkUserID(); TimestampType timestampHeader = getTimestampHeader(); Holder signatureHeader = null; @@ -222,7 +224,8 @@ public final SearchIHIBatchResponse batchSearch(SearchBatch request) throws Stan */ public final SearchIHIBatchResponse batchSearch(SearchBatch request, au.gov.nehta.vendorlibrary.hi.client.wrapped.QualifiedId individualId) throws StandardErrorMsg { - + ArgumentUtils.checkNotNull(request, "request"); + ArgumentUtils.checkNotNull(individualId, "individualId"); TimestampType timestampHeader = getTimestampHeader(); Holder signatureHeader = null; Holder productHolder = new Holder<>(productHeader); diff --git a/src/test/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClientTest.java b/src/test/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClientTest.java new file mode 100644 index 0000000..10f5a8a --- /dev/null +++ b/src/test/java/au/gov/nehta/vendorlibrary/hi/hpii/SearchForProviderIndividualBatchAsyncClientTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2011 NEHTA + * Copyright 2021-2026 ADHA (Australian Digital Health Agency) + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. A copy of the License is in the + * 'license.txt' file, which should be provided with this work. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package au.gov.nehta.vendorlibrary.hi.hpii; + +import au.net.electronichealth.ns.hi.svc.providerbatchasyncsearchforproviderindividual._5_1.RetrieveSearchForProviderIndividual; +import au.net.electronichealth.ns.hi.svc.providerbatchasyncsearchforproviderindividual._5_1.StandardErrorMsg; +import org.junit.Test; + +import static au.gov.nehta.vendorlibrary.hi.test.utils.TestConstants.*; + +public class SearchForProviderIndividualBatchAsyncClientTest { + + private final SearchForProviderIndividualBatchAsyncClient client = getMedicareTestClient(); + private final SearchForProviderIndividualBatchAsyncClient clientNoID = getMedicareTestClientNoId(); + + @Test(expected = IllegalArgumentException.class) + public void submitSearch_nullBatchRequest_clientUser() throws StandardErrorMsg { + client.submitSearch(null); + } + + @Test(expected = IllegalArgumentException.class) + public void submitSearch_nullBatchRequest_perRequestUser() throws StandardErrorMsg { + clientNoID.submitSearch(null, getWrappedUserQualifiedId()); + } + + @Test(expected = IllegalArgumentException.class) + public void submitSearch_nullIndividualId_throws() throws StandardErrorMsg { + ProviderIndividualBatchSearch batch = new ProviderIndividualBatchSearch(); + clientNoID.submitSearch(batch, null); + } + + @Test(expected = IllegalArgumentException.class) + public void retrieveSearch_nullRequest_clientUser() throws StandardErrorMsg { + client.retrieveSearch(null); + } + + @Test(expected = IllegalArgumentException.class) + public void retrieveSearch_nullRequest_perRequestUser() throws StandardErrorMsg { + clientNoID.retrieveSearch(null, getWrappedUserQualifiedId()); + } + + @Test(expected = IllegalArgumentException.class) + public void retrieveSearch_nullIndividualId_throws() throws StandardErrorMsg { + RetrieveSearchForProviderIndividual retrieve = new RetrieveSearchForProviderIndividual(); + retrieve.setBatchIdentifier("dummy"); + clientNoID.retrieveSearch(retrieve, null); + } + + private static SearchForProviderIndividualBatchAsyncClient getMedicareTestClient() { + try { + return new SearchForProviderIndividualBatchAsyncClient(MEDICARE_ENDPOINT_URL, getUserQualifiedId(), + getProductHeader(), getSigningPrivateKeyForMedicare(), + getSigningCertificateKeyForMedicare(), getSslSocketFactoryForMedicare()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static SearchForProviderIndividualBatchAsyncClient getMedicareTestClientNoId() { + try { + return new SearchForProviderIndividualBatchAsyncClient(MEDICARE_ENDPOINT_URL, getWrappedProductHeader(), + getSigningPrivateKeyForMedicare(), getSigningCertificateKeyForMedicare(), + getSslSocketFactoryForMedicare(), null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClientTest.java b/src/test/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClientTest.java new file mode 100644 index 0000000..d9231a7 --- /dev/null +++ b/src/test/java/au/gov/nehta/vendorlibrary/hi/hpio/SearchForProviderOrganisationBatchAsyncClientTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2011 NEHTA + * Copyright 2021-2026 ADHA (Australian Digital Health Agency) + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. A copy of the License is in the + * 'license.txt' file, which should be provided with this work. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package au.gov.nehta.vendorlibrary.hi.hpio; + +import au.net.electronichealth.ns.hi.svc.providerbatchasyncsearchforproviderorganisation._5_1.RetrieveSearchForProviderOrganisation; +import au.net.electronichealth.ns.hi.svc.providerbatchasyncsearchforproviderorganisation._5_1.StandardErrorMsg; +import org.junit.Test; + +import static au.gov.nehta.vendorlibrary.hi.test.utils.TestConstants.*; + +public class SearchForProviderOrganisationBatchAsyncClientTest { + + private final SearchForProviderOrganisationBatchAsyncClient client = getMedicareTestClient(); + private final SearchForProviderOrganisationBatchAsyncClient clientNoID = getMedicareTestClientNoId(); + + @Test(expected = IllegalArgumentException.class) + public void submitSearch_nullBatchRequest_clientUser() throws StandardErrorMsg { + client.submitSearch(null); + } + + @Test(expected = IllegalArgumentException.class) + public void submitSearch_nullBatchRequest_perRequestUser() throws StandardErrorMsg { + clientNoID.submitSearch(null, getWrappedUserQualifiedId()); + } + + @Test(expected = IllegalArgumentException.class) + public void submitSearch_nullIndividualId_throws() throws StandardErrorMsg { + ProviderOrganisationBatchSearch batch = new ProviderOrganisationBatchSearch(); + clientNoID.submitSearch(batch, null); + } + + @Test(expected = IllegalArgumentException.class) + public void retrieveSearch_nullRequest_clientUser() throws StandardErrorMsg { + client.retrieveSearch(null); + } + + @Test(expected = IllegalArgumentException.class) + public void retrieveSearch_nullRequest_perRequestUser() throws StandardErrorMsg { + clientNoID.retrieveSearch(null, getWrappedUserQualifiedId()); + } + + @Test(expected = IllegalArgumentException.class) + public void retrieveSearch_nullIndividualId_throws() throws StandardErrorMsg { + RetrieveSearchForProviderOrganisation retrieve = new RetrieveSearchForProviderOrganisation(); + retrieve.setBatchIdentifier("dummy"); + clientNoID.retrieveSearch(retrieve, null); + } + + private static SearchForProviderOrganisationBatchAsyncClient getMedicareTestClient() { + try { + return new SearchForProviderOrganisationBatchAsyncClient(MEDICARE_ENDPOINT_URL, getUserQualifiedId(), + getProductHeader(), getSigningPrivateKeyForMedicare(), + getSigningCertificateKeyForMedicare(), getSslSocketFactoryForMedicare()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static SearchForProviderOrganisationBatchAsyncClient getMedicareTestClientNoId() { + try { + return new SearchForProviderOrganisationBatchAsyncClient(MEDICARE_ENDPOINT_URL, getWrappedProductHeader(), + getSigningPrivateKeyForMedicare(), getSigningCertificateKeyForMedicare(), + getSslSocketFactoryForMedicare(), null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClientTest.java b/src/test/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClientTest.java index f63cb6d..e073218 100644 --- a/src/test/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClientTest.java +++ b/src/test/java/au/gov/nehta/vendorlibrary/hi/ihi/ConsumerSearchIHIBatchSyncClientTest.java @@ -38,6 +38,8 @@ import java.util.UUID; import static au.gov.nehta.vendorlibrary.hi.test.utils.IHITestConstants.*; +import static au.gov.nehta.vendorlibrary.hi.test.utils.TestConstants.getWrappedProductHeader; +import static au.gov.nehta.vendorlibrary.hi.test.utils.TestConstants.getWrappedUserQualifiedId; public class ConsumerSearchIHIBatchSyncClientTest { @@ -63,6 +65,21 @@ public void testNullLoggingHandler() throws Exception { Assert.assertEquals(lastSoapResponse, LoggingHandler.EMPTY); } + @Test(expected = IllegalArgumentException.class) + public void batchSearch_nullRequest_clientUser() throws Exception { + getMedicareTestClient().batchSearch(null); + } + + @Test(expected = IllegalArgumentException.class) + public void batchSearch_nullRequest_perRequestUser() throws Exception { + getMedicarePerRequestUserClient().batchSearch(null, getWrappedUserQualifiedId()); + } + + @Test(expected = IllegalArgumentException.class) + public void batchSearch_nullIndividualId_perRequestUser() throws Exception { + getMedicarePerRequestUserClient().batchSearch(new SearchBatch(), null); + } + @Test public void batchSearchAgainstMedicare() throws Exception { setSystemVariablesForTest(); @@ -318,6 +335,15 @@ private ConsumerSearchIHIBatchSyncClient getMedicareTestClient() throws GeneralS getSigningCertificateKeyForMedicare(), getSslSocketFactoryForMedicare()); } + private ConsumerSearchIHIBatchSyncClient getMedicarePerRequestUserClient() throws GeneralSecurityException, IOException { + return new ConsumerSearchIHIBatchSyncClient( + MEDICARE_ENDPOINT_URL, + getWrappedProductHeader(), + getSigningPrivateKeyForMedicare(), + getSigningCertificateKeyForMedicare(), + getSslSocketFactoryForMedicare()); + } + private SearchIHI getBasicSearchForMedicare() { SearchIHI searchIHI = new SearchIHI(); searchIHI.setIhiNumber(MEDICARE_GENERIC_TEST_INDIVIDUAL_IHI_NUMBER); diff --git a/src/test/java/au/gov/nehta/vendorlibrary/hi/wsdl/HiRequestElementOrderParityTest.java b/src/test/java/au/gov/nehta/vendorlibrary/hi/wsdl/HiRequestElementOrderParityTest.java new file mode 100644 index 0000000..e3b3f77 --- /dev/null +++ b/src/test/java/au/gov/nehta/vendorlibrary/hi/wsdl/HiRequestElementOrderParityTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 2011 NEHTA + * Copyright 2021-2026 ADHA (Australian Digital Health Agency) + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package au.gov.nehta.vendorlibrary.hi.wsdl; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import javax.xml.bind.annotation.XmlType; + +/** + * Asserts JAXB {@code @XmlType.propOrder} for selected HI request types used by + * Consumer Search IHI (Messages, Interface, and batch wrappers). + */ +public class HiRequestElementOrderParityTest { + + /** + * Messages {@code searchIHI}: {@code electronicCommunication} before {@code dateOfBirth}. + */ + @Test + public void searchIhiMessagesPropOrderForBatchSync() { + assertPropOrder( + "au.net.electronichealth.ns.hi.xsd.consumermessages.searchihi._3.SearchIHI", + Arrays.asList( + "ihiNumber", + "medicareCardNumber", + "medicareIRN", + "dvaFileNumber", + "electronicCommunication", + "dateOfBirth", + "sex", + "familyName", + "givenName", + "australianPostalAddress", + "australianStreetAddress", + "internationalAddress", + "australianUnstructuredStreetAddress", + "history" + ) + ); + } + + /** + * Interface {@code searchIHI} (IHI inquiry): {@code electronicCommunication} before {@code dateOfBirth}; + * unstructured street address before international address. + */ + @Test + public void searchIhiInterfacePropOrderForInquiry() { + assertPropOrder( + "au.net.electronichealth.ns.hi.svc.consumersearchihi._3.SearchIHI", + Arrays.asList( + "ihiNumber", + "medicareCardNumber", + "medicareIRN", + "dvaFileNumber", + "electronicCommunication", + "dateOfBirth", + "sex", + "familyName", + "givenName", + "australianPostalAddress", + "australianStreetAddress", + "australianUnstructuredStreetAddress", + "internationalAddress", + "history" + ) + ); + } + + /** + * Batch wrapper {@code SearchIHIRequestType}. + */ + @Test + public void searchIhiRequestTypePropOrder() { + assertPropOrder( + "au.net.electronichealth.ns.hi.xsd.consumermessages.searchihibatch._3.SearchIHIRequestType", + Arrays.asList("searchIHI", "requestIdentifier") + ); + } + + /** + * Loads {@code className}, reads {@link XmlType#propOrder()}, and asserts it equals {@code expected}. + * + * @param className fully qualified generated request type + * @param expected local element names in schema order + */ + private static void assertPropOrder(String className, List expected) { + Class type; + try { + type = Class.forName(className); + } catch (ClassNotFoundException ex) { + Assert.fail("Missing generated type on classpath: " + className); + return; + } + XmlType xmlType = type.getAnnotation(XmlType.class); + Assert.assertNotNull("@XmlType required on " + className, xmlType); + Assert.assertArrayEquals( + className + " propOrder", + expected.toArray(new String[0]), + xmlType.propOrder() + ); + } +} diff --git a/wsdls/readme.txt b/wsdls/readme.txt index 474e9b9..b6aaa04 100644 --- a/wsdls/readme.txt +++ b/wsdls/readme.txt @@ -8,8 +8,18 @@ are NOT shipped in this Git repository. Download them from: https://healthsoftware.humanservices.gov.au/claiming/ext-vnd/ Extract the bundle to a directory whose immediate children are lowercase wsdl/ and schema/. Some -hosts and CI runners are case-sensitive, so the casing matters. Optional JAX-WS / JAXB binding -fragments that this repository does ship live under wsdls/xml/binding/. +hosts and CI runners are case-sensitive, so the casing matters. + +For Consumer Search IHI (Messages schema SearchIHIMessages.xsd), request XML must place +electronicCommunication immediately after identity fields and before dateOfBirth. If a vendor +pack places that element after demographics or addresses, move it before regenerating types +(or before shipping matching hi-wsdl types); otherwise batch and related mobile/email search +requests can fail schema validation (badlyFormedMsg). On this Java 8 line (Maven **8.0.0**), +SOAP types come from au.gov.nehta:hi-wsdl at the same version (this artifact does not run +wsimport). The first number of both Maven versions is the targeted Java SE version. + +Optional JAX-WS / JAXB binding fragments that this repository does ship live under +wsdls/xml/binding/. See "Configuring the location" below to tell the build and/or the library where you put the tree. See CONTRIBUTING.md for building this repository and README.md for runtime use of the library.