Skip to content

feat: bump to 1.100.0 — new models, breaking cleanups, and Jackson fixes#14

Merged
nebay-abraha merged 6 commits into
mainfrom
improvments
Jun 11, 2026
Merged

feat: bump to 1.100.0 — new models, breaking cleanups, and Jackson fixes#14
nebay-abraha merged 6 commits into
mainfrom
improvments

Conversation

@nebay-abraha

Copy link
Copy Markdown
Contributor

Breaking changes:

  • AbstractExportPost: rename scope()/format() to getScopeString()/getFormatString()
  • ApiShareInfo.sharedItemName: corrected type from Long to String
  • FieldPut: remove shadowed content field; now inherits from FieldPost
  • ActivitySearchResult, DocumentSearchResult, FileSearchResult, FormSearchResult, ShareSearchResult: change from @value to @DaTa @NoArgsConstructor for correct Jackson deserialisation

Added:

  • UserInfo model (sysadmin user-listing endpoint)
  • UserSearchResult model (paginated UserInfo wrapper)
  • GroupSearchResult model (paginated GroupInfo wrapper)
  • AGENTS.md: single source of truth for contributors and AI agents

Fixed:

  • @JsonIgnoreProperties(ignoreUnknown = true) on all response POJOs via IdentifiableNameable and individually on non-hierarchy classes
  • User.java: replace @value @NoArgsConstructor with @DaTa @NoArgsConstructor
  • ISO8601DateSerialiser: replace per-call SimpleDateFormat with thread-safe static DateTimeFormatter
  • ApiShareInfo: split multi-field Long declaration; sharedItemName is now a separate String field
  • Removed stale swagger-codegen DO NOT EDIT headers from source files

Breaking changes:
- AbstractExportPost: rename scope()/format() to getScopeString()/getFormatString()
- ApiShareInfo.sharedItemName: corrected type from Long to String
- FieldPut: remove shadowed content field; now inherits from FieldPost
- ActivitySearchResult, DocumentSearchResult, FileSearchResult,
  FormSearchResult, ShareSearchResult: change from @value to
  @DaTa @NoArgsConstructor for correct Jackson deserialisation

Added:
- UserInfo model (sysadmin user-listing endpoint)
- UserSearchResult model (paginated UserInfo wrapper)
- GroupSearchResult model (paginated GroupInfo wrapper)
- AGENTS.md: single source of truth for contributors and AI agents

Fixed:
- @JsonIgnoreProperties(ignoreUnknown = true) on all response POJOs
  via IdentifiableNameable and individually on non-hierarchy classes
- User.java: replace @value @NoArgsConstructor with @DaTa @NoArgsConstructor
- ISO8601DateSerialiser: replace per-call SimpleDateFormat with
  thread-safe static DateTimeFormatter
- ApiShareInfo: split multi-field Long declaration; sharedItemName
  is now a separate String field
- Removed stale swagger-codegen DO NOT EDIT headers from source files

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Bumps the library to 1.100.0 and performs a broad cleanup of the response/request POJO layer: it fixes Jackson deserialisation issues by replacing @Value with @Data @NoArgsConstructor on several models, sprinkles @JsonIgnoreProperties(ignoreUnknown = true) across response types, fixes a thread-unsafe SimpleDateFormat, splits a malformed multi-field declaration in ApiShareInfo, removes dead shadowed state from FieldPut, renames scope()/format() on AbstractExportPost, adds new UserInfo/UserSearchResult/GroupSearchResult models, and introduces an AGENTS.md contributor guide.

Changes:

  • Breaking API cleanups: AbstractExportPost method renames, ApiShareInfo.sharedItemName type fix, FieldPut removes shadowed content, search-result classes converted from @Value to @Data @NoArgsConstructor.
  • Deserialisation hardening: @JsonIgnoreProperties added widely, User switched to @Data, ISO8601DateSerialiser rewritten with a static thread-safe DateTimeFormatter, PaginatedResultList gains pageSize.
  • New models + docs: UserInfo, UserSearchResult, GroupSearchResult; new AGENTS.md; new tests/JSON fixtures; cleanup of stale swagger-codegen headers.

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
pom.xml Version bump to 1.100.0.
CHANGELOG.md Documents 1.100.0 breaking changes/additions/fixes.
AGENTS.md New contributor & AI-agent guide (partly stale vs. the PR's own changes).
src/main/java/.../AbstractExportPost.java Rename scope()/format()getScopeString()/getFormatString().
src/main/java/.../Activity.java, ExportJob.java, ExportJobResult.java, LinkItem.java, Status.java, ApiSharingResult.java, ApiShareInfo.java, UserGroupInfo.java Add @JsonIgnoreProperties(ignoreUnknown = true) (and split ApiShareInfo Long/String fields).
src/main/java/.../IdentifiableNameable.java Add @JsonIgnoreProperties; drop unused import.
src/main/java/.../PaginatedResultList.java Strip stale codegen header; add pageSize.
src/main/java/.../ActivitySearchResult.java, DocumentSearchResult.java, FileSearchResult.java, FormSearchResult.java, ShareSearchResult.java Convert @Value@Data @NoArgsConstructor + @JsonIgnoreProperties.
src/main/java/.../Document*.java, Folder.java, FolderTreeItemInfo.java, FolderTreeItemListing.java, Field.java, ApiFile.java Remove stale codegen headers; FolderTreeItemListing gains @NoArgsConstructor + @JsonIgnoreProperties.
src/main/java/.../FieldPut.java Remove shadowed content field; add explicit constructors.
src/main/java/.../MoveRequest.java @JsonProperty("docId") on recordId; Javadoc cleanup.
src/main/java/.../User.java Replace @Value @NoArgsConstructor with @Data @NoArgsConstructor.
src/main/java/.../UserInfo.java New POJO for sysadmin user listing (missing username field).
src/main/java/.../UserSearchResult.java, GroupSearchResult.java New paginated wrappers.
src/main/java/.../UserPost.java Inline comment about server constraint on apiKey.
src/main/java/.../jackson/ISO8601DateSerialiser.java Replace per-call SimpleDateFormat with static DateTimeFormatter.
src/test/.../*Test.java Replace System.err.println debug with proper assertions; add UserTest, GroupInfoTest, FolderTreeItemListingTest, MoveRequestTest, OID serialisation test.
src/test/resources/User.json, FolderTreeItemListing.json New JSON fixtures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +25
public class UserInfo extends IdentifiableNameable {

private String email;
private String firstName;
private String lastName;
private UserRole role;
private String affiliation;
private boolean enabled;
private Long homeFolderId;

Comment thread AGENTS.md Outdated
Comment on lines +126 to +143
**Immutable search results** use: `@Value @EqualsAndHashCode(callSuper=true)` — see note below

### `@Value` vs `@Data` — know the difference

`@Value` generates an immutable class: all fields `final`, no setters, all-args constructor.
Jackson cannot deserialise into a `@Value` class without a custom deserialiser because
there are no setters and the all-args constructor requires every field by position.

**Only use `@Value` for classes where you are certain Jackson will never try to deserialise them.**

Current `@Value` classes: `ActivitySearchResult`, `DocumentSearchResult`,
`FileSearchResult`, `FormSearchResult`, `ShareSearchResult`.
These work because `AbstractModelTest.readFileToClass()` disables `FAIL_ON_UNKNOWN_PROPERTIES`
and the fields are initialised to `new ArrayList<>()` which Jackson appends to.
This is fragile — see IMPROVEMENT.md item 1.1 for the correct fix.

**`User.java` uses `@Value @NoArgsConstructor` which is a bug — see IMPROVEMENT.md item 1.3.**

Comment on lines +19 to +20
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault());
Comment thread CHANGELOG.md Outdated

- **`AbstractExportPost`**: renamed `scope()` → `getScopeString()` and `format()` → `getFormatString()` to avoid confusion with Lombok-generated getters. Update any callers of the old method names.
- **`ApiShareInfo.sharedItemName`**: field type corrected from `Long` to `String`. Any code storing or passing `getSharedItemName()` as a `Long` must be updated.
- **`FieldPut`**: removed the shadowed `content` field; `FieldPut` now inherits `content` from `FieldPost`. The `@AllArgsConstructor`-generated constructor signature changes from `FieldPut(String content, Long id)` to `FieldPut(Long id)`. Replace any positional constructor calls with the no-args constructor + `setContent()`.
Comment on lines +20 to +22
public class UserSearchResult extends PaginatedResultList {
private List<User> users = new ArrayList<>();

Comment on lines +12 to +15
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
Comment on lines 37 to 38
// Server accepts 16–32 alphanumeric characters; verify exact constraint in com.researchspace.api.v1.model.ApiUserPost
@Size(min = 16, max = 32)
private Long totalHits = null;
private Long totalHits = null;
private Integer pageNumber = null;
private Integer pageSize = null;
Comment on lines 8 to 16
@Data
@EqualsAndHashCode(callSuper=false)
@AllArgsConstructor
@NoArgsConstructor
/**
* Extends FieldPost with a field Id property to specify the Field whose content is to be updated.
* Extends FieldPost with a field Id property to specify the Field, whose content is to be updated.
* @author rspace
*
*/
public class FieldPut extends FieldPost {
Comment on lines +54 to +55
MoveRequest deserialized = om.readValue(json, MoveRequest.class);
assertEquals(original, deserialized);
- UserInfo: add missing username field + @tostring(callSuper=true)
- UserInfoTest, UserSearchResultTest, GroupSearchResultTest: new
  deserialisation tests with JSON fixtures (UserInfo.json,
  UserSearchResult.json, GroupSearchResult.json)
- ISO8601DateSerialiser: pin timezone to UTC (was systemDefault);
  add Javadoc explaining the UTC behaviour
- FieldPut: move class Javadoc before annotations (was misplaced)
- CHANGELOG: reword FieldPut breaking change — constructor preserved,
  describe actual shadow-removal semantics
- DocumentSearchResult.json: add pageSize field; assert on it in test
- AGENTS.md: update taxonomy table (search results -> @DaTa, User fixed,
  add UserInfo/UserSearchResult/GroupSearchResult); update Lombok rules
  section to remove stale @value guidance; add pageSize to
  PaginatedResultList inheritance note
- UserPost: remove unverified 'alphanumeric' claim from apiKey comment
- MoveRequestTest: fix British spelling (deserialized -> deserialised)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 53 out of 53 changed files in this pull request and generated 10 comments.

@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserSearchResult extends PaginatedResultList {
private List<User> users = new ArrayList<>();
Comment on lines +23 to +37
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneOffset.UTC);

public ISO8601DateSerialiser() {
this(null);
}

public ISO8601DateSerialiser(Class<Date> t) {
super(t);
}

@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
gen.writeString(FORMATTER.format(value.toInstant()));
Comment on lines +17 to +19
public class UserInfo extends IdentifiableNameable {

private String username;
Comment on lines +30 to +34
void testUserInfoIgnoresUnknownFields() throws IOException {
UserInfo user = readFileToClass(fixture, UserInfo.class);
// fixture has unknown fields if added in future — @JsonIgnoreProperties ensures no exception
assertEquals("jsmith", user.getUsername());
}
Comment on lines +35 to +38
public void serialize(Date value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
gen.writeString(FORMATTER.format(value.toInstant()));
}

private Long id;
private Long sharedItemId;
private String sharedItemName;
Comment on lines +21 to +30
/** Constructor for updating a specific field by ID only (content left as default). */
public FieldPut(Long id) {
this.id = id;
}

/** Constructor for updating the content of a specific field by ID. */
public FieldPut(String content, Long id) {
super(content);
this.id = id;
}
Comment on lines +5 to +14
"users": [
{
"id": 1,
"username": "admin",
"email": "admin@example.com",
"firstName": "Admin",
"lastName": "User",
"homeFolderId": 5
}
],
Comment on lines 15 to 21
public String getScopeString() {
return scope.name().toLowerCase();
}
public String format () {

public String getFormatString() {
return format.name().toLowerCase();
}
private String email;
private String firstName;
private String lastName;
private UserRole role;
nebay-abraha and others added 2 commits May 14, 2026 17:08
- AbstractExportPost: add @JsonIgnore to getScopeString()/getFormatString()
  so Jackson does not serialise them as unintended scopeString/formatString
  properties in export request payloads
- UserSearchResult: change List<User> to List<UserInfo> to match the
  sysadmin endpoint response; update fixture and test accordingly
- DocumentSearchResult.documents: add missing private modifier
- FormSearchResult.forms: add missing private modifier
- FieldPut: fix @EqualsAndHashCode(callSuper=false) → callSuper=true
  so inherited content field participates in equality checks
- ShareSearchResult, FileSearchResult, FolderTreeItemListing: add
  @tostring(callSuper=true) for consistency with other PaginatedResultList
  subclasses
- UserInfo.json: add role field (ROLE_USER) to exercise enum deserialisation
- UserInfoTest: replace duplicate fixture-read test with a genuine unknown-
  fields test using inline JSON; add role assertion; add null-role test
- UserSearchResult.json: update to UserInfo-shaped objects with all fields
- UserSearchResultTest: assert UserInfo-specific fields including role
- CHANGELOG: move User.java @value@DaTa to Breaking Changes section;
  add ISO8601DateSerialiser UTC timezone change as a breaking change;
  remove User.java entry from Fixed section
- AGENTS.md: remove stale IMPROVEMENT.md cross-repo references

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- UserInfo: clarify getName() vs getUsername() in Javadoc — name is the
  display name (from IdentifiableNameable), username is the login identifier
- UserPost: remove unverifiable cross-repo reference from apiKey comment

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nebay-abraha nebay-abraha marked this pull request as draft June 8, 2026 16:51
@nebay-abraha nebay-abraha marked this pull request as ready for review June 11, 2026 18:35
@nebay-abraha nebay-abraha merged commit 5800fae into main Jun 11, 2026
1 check passed
@nebay-abraha nebay-abraha deleted the improvments branch June 11, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants