Skip to content

Commit e1341ce

Browse files
Merge pull request #266 from contentstack/development
DX | 16-02-2026 | Release dev -> stage
2 parents 055fe38 + ad23a11 commit e1341ce

File tree

14 files changed

+539
-19
lines changed

14 files changed

+539
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,4 @@ src/main/resources/
274274
/.vscode/
275275
/docs/
276276
INTEGRATION-TESTS-GUIDE.md
277+
src/main/java/com/demo/*

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## v2.5.0
4+
5+
### Feb 12, 2026
6+
- Enhancement: assetFields method added
7+
38
## v2.4.0
49

510
### Feb 02, 2026

pom.xml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>com.contentstack.sdk</groupId>
77
<artifactId>java</artifactId>
8-
<version>2.4.0</version>
8+
<version>2.5.0</version>
99
<packaging>jar</packaging>
1010
<name>contentstack-java</name>
1111
<description>Java SDK for Contentstack Content Delivery API</description>
@@ -20,11 +20,11 @@
2020
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
2121
<maven-javadoc-plugin.version>3.4.1</maven-javadoc-plugin.version>
2222
<dotenv-source.version>3.0.0</dotenv-source.version>
23-
<rxjava-source.version>3.1.11</rxjava-source.version>
23+
<rxjava-source.version>3.1.12</rxjava-source.version>
2424
<retrofit-source.version>3.0.0</retrofit-source.version>
25-
<loggin.version>5.1.0</loggin.version>
25+
<loggin.version>5.3.2</loggin.version>
2626
<jococo-plugin.version>0.8.5</jococo-plugin.version>
27-
<lombok-source.version>1.18.36</lombok-source.version>
27+
<lombok-source.version>1.18.42</lombok-source.version>
2828
<junit-jupiter.version>5.11.4</junit-jupiter.version>
2929
<junit-jupiter-engine.version>5.8.0-M1</junit-jupiter-engine.version>
3030
<gson.version>2.8.8</gson.version>
@@ -33,17 +33,14 @@
3333
<maven-gpg-plugin.version>1.5</maven-gpg-plugin.version>
3434
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
3535
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
36-
<json-version>20250107</json-version>
36+
<json-version>20250517</json-version>
3737
<jacoco-maven-plugin-version>0.8.11</jacoco-maven-plugin-version>
3838
<maven-release-plugin-version>2.5.3</maven-release-plugin-version>
3939
<contentstack-utils-version>1.2.15</contentstack-utils-version>
4040
</properties>
4141

42-
<parent>
43-
<groupId>org.sonatype.oss</groupId>
44-
<artifactId>oss-parent</artifactId>
45-
<version>7</version>
46-
</parent>
42+
<!-- Parent POM removed to avoid 403 from Maven Central in CI (Snyk, etc.). -->
43+
<!-- Plugin versions and config are defined explicitly in this POM. -->
4744

4845
<scm>
4946
<url>https://github.com/contentstack/contentstack-java</url>
@@ -184,12 +181,12 @@
184181
<dependency>
185182
<groupId>com.fasterxml.jackson.core</groupId>
186183
<artifactId>jackson-databind</artifactId>
187-
<version>2.19.2</version>
184+
<version>2.21.0</version>
188185
</dependency>
189186
<dependency>
190187
<groupId>com.slack.api</groupId>
191188
<artifactId>bolt</artifactId>
192-
<version>1.45.3</version>
189+
<version>1.46.0</version>
193190
</dependency>
194191
<dependency>
195192
<groupId>org.jetbrains</groupId>
@@ -199,7 +196,7 @@
199196
<dependency>
200197
<groupId>com.squareup.okhttp3</groupId>
201198
<artifactId>okhttp</artifactId>
202-
<version>5.1.0</version>
199+
<version>5.3.2</version>
203200
</dependency>
204201
<dependency>
205202
<groupId>org.slf4j</groupId>

src/main/java/com/contentstack/sdk/Asset.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.contentstack.sdk;
22

33
import org.jetbrains.annotations.NotNull;
4+
import org.json.JSONArray;
45
import org.json.JSONObject;
56
import retrofit2.Retrofit;
67
import lombok.Getter;
@@ -544,6 +545,19 @@ public Asset includeMetadata() {
544545
return this;
545546
}
546547

548+
public Asset assetFields(String... fields) {
549+
if (fields != null && fields.length > 0) {
550+
JSONArray array = new JSONArray();
551+
for (String field : fields) {
552+
array.put(field);
553+
}
554+
if (!array.isEmpty()) {
555+
urlQueries.put("asset_fields[]", array);
556+
}
557+
}
558+
return this;
559+
}
560+
547561
/**
548562
* Fetch.
549563
*

src/main/java/com/contentstack/sdk/AssetLibrary.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.jetbrains.annotations.NotNull;
44
import org.json.JSONObject;
5+
import org.json.JSONArray;
56

67
import java.util.*;
78
import java.util.logging.Logger;
@@ -33,7 +34,8 @@ protected void setStackInstance(@NotNull Stack stack) {
3334

3435
//Sanitization of keys
3536
private boolean isValidKey(String key) {
36-
return key.matches("^[a-zA-Z0-9_.]+$");
37+
// Fixed regex: allow alphanumeric, underscore, dot, and square brackets at the end, escaped properly
38+
return key.matches("^[a-zA-Z0-9_.]+(\\[\\])?$");
3739
}
3840

3941
//Sanitization of values
@@ -265,6 +267,19 @@ public AssetLibrary limit (@NotNull int number) {
265267
return this;
266268
}
267269

270+
public AssetLibrary assetFields(String... fields) {
271+
if (fields != null && fields.length > 0) {
272+
JSONArray array = new JSONArray();
273+
for (String field : fields) {
274+
array.put(field);
275+
}
276+
if (!array.isEmpty()) {
277+
urlQueries.put("asset_fields[]", array);
278+
}
279+
}
280+
return this;
281+
}
282+
268283
/**
269284
* Fetch all.
270285
*

src/main/java/com/contentstack/sdk/CSHttpConnection.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ public String setFormParamsGET(HashMap<String, Object> params) {
102102
if (params != null && params.size() > 0) {
103103
String urlParams = null;
104104
urlParams = info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.QUERY.name())
105-
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ENTRY.name()) ? getParams(params) : null;
105+
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ENTRY.name())
106+
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ASSET.name())
107+
|| info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ASSETLIBRARY.name()) ? getParams(params) : null;
106108
if (urlParams == null) {
107109
for (Map.Entry<String, Object> e : params.entrySet()) {
108110
if (urlParams == null) {
@@ -124,7 +126,7 @@ private String getParams(HashMap<String, Object> params) {
124126
Object value = e.getValue();
125127
try {
126128
if (key.equalsIgnoreCase("include[]") || key.equalsIgnoreCase("only[BASE][]")
127-
|| key.equalsIgnoreCase("except[BASE][]")) {
129+
|| key.equalsIgnoreCase("except[BASE][]") || key.equalsIgnoreCase("asset_fields[]")) {
128130
urlParams = convertUrlParam(urlParams, value, key);
129131
} else if (key.equalsIgnoreCase("only")) {
130132
JSONObject onlyJSON = (JSONObject) value;

src/main/java/com/contentstack/sdk/Entry.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,19 @@ public Entry exceptWithReferenceUid(@NotNull List<String> fieldUid, @NotNull Str
904904
return this;
905905
}
906906

907+
908+
public Entry assetFields(String... fields) {
909+
if (fields != null && fields.length > 0) {
910+
JSONArray array = new JSONArray();
911+
for (String field : fields) {
912+
array.put(field);
913+
}
914+
if (!array.isEmpty()) {
915+
params.put("asset_fields[]", array);
916+
}
917+
}
918+
return this;
919+
}
907920
/**
908921
* Fetches the latest version of the entries from Contentstack.com content stack
909922
*

src/main/java/com/contentstack/sdk/Query.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,19 @@ public Query search(@NotNull String value) {
11461146
return this;
11471147
}
11481148

1149+
public Query assetFields(String... fields) {
1150+
if (fields != null && fields.length > 0) {
1151+
JSONArray array = new JSONArray();
1152+
for (String field : fields) {
1153+
array.put(field);
1154+
}
1155+
if (!array.isEmpty()) {
1156+
urlQueries.put("asset_fields[]", array);
1157+
}
1158+
}
1159+
return this;
1160+
}
1161+
11491162
/**
11501163
* Execute a Query and Caches its result (Optional)
11511164
*

src/test/java/com/contentstack/sdk/TestAsset.java

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,133 @@ void testIncludeMetadata() {
182182
assertEquals(true, asset.urlQueries.get("include_metadata"));
183183
}
184184

185+
// ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ==========
186+
187+
@Test
188+
void testAssetFieldsWithSupportedValues() {
189+
Asset result = asset.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups");
190+
assertSame(asset, result);
191+
assertTrue(asset.urlQueries.has("asset_fields[]"));
192+
Object val = asset.urlQueries.get("asset_fields[]");
193+
assertTrue(val instanceof JSONArray);
194+
JSONArray arr = (JSONArray) val;
195+
assertEquals(4, arr.length());
196+
assertEquals("user_defined_fields", arr.get(0));
197+
assertEquals("embedded", arr.get(1));
198+
assertEquals("ai_suggested", arr.get(2));
199+
assertEquals("visual_markups", arr.get(3));
200+
}
201+
202+
@Test
203+
void testAssetFieldsReturnsThis() {
204+
Asset result = asset.assetFields("user_defined_fields");
205+
assertSame(asset, result);
206+
}
207+
208+
@Test
209+
void testAssetFieldsWithNoArgsDoesNotSetParam() {
210+
asset.assetFields();
211+
assertFalse(asset.urlQueries.has("asset_fields[]"));
212+
}
213+
214+
@Test
215+
void testAssetFieldsWithNullDoesNotSetParam() {
216+
asset.assetFields((String[]) null);
217+
assertFalse(asset.urlQueries.has("asset_fields[]"));
218+
}
219+
220+
@Test
221+
void testAssetFieldsChainingWithOtherMethods() {
222+
Asset result = asset.assetFields("embedded", "visual_markups")
223+
.includeMetadata()
224+
.includeDimension();
225+
assertSame(asset, result);
226+
assertTrue(asset.urlQueries.has("asset_fields[]"));
227+
assertTrue(asset.urlQueries.has("include_metadata"));
228+
assertTrue(asset.urlQueries.has("include_dimension"));
229+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
230+
assertEquals(2, arr.length());
231+
assertEquals("embedded", arr.get(0));
232+
assertEquals("visual_markups", arr.get(1));
233+
}
234+
235+
/**
236+
* Usage: stack.asset(assetUid).assetFields(...).fetch()
237+
* Verifies the full chain sets asset_fields[] on the asset before fetch.
238+
*/
239+
@Test
240+
void testUsageSingleAssetFetchWithAssetFields() throws IllegalAccessException {
241+
Stack stack = Contentstack.stack("api_key", "delivery_token", "env");
242+
Asset asset = stack.asset("asset_uid_123")
243+
.assetFields("embedded", "visual_markups");
244+
assertTrue(asset.urlQueries.has("asset_fields[]"));
245+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
246+
assertEquals(2, arr.length());
247+
assertEquals("embedded", arr.get(0));
248+
assertEquals("visual_markups", arr.get(1));
249+
}
250+
251+
252+
@Test
253+
void testAssetFieldsSingleField() {
254+
asset.assetFields("embedded");
255+
assertTrue(asset.urlQueries.has("asset_fields[]"));
256+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
257+
assertEquals(1, arr.length());
258+
assertEquals("embedded", arr.get(0));
259+
}
260+
261+
@Test
262+
void testAssetFieldsEmptyVarargsArrayDoesNotSetParam() {
263+
asset.assetFields(new String[0]);
264+
assertFalse(asset.urlQueries.has("asset_fields[]"));
265+
}
266+
267+
@Test
268+
void testAssetFieldsDuplicateValuesAllowed() {
269+
asset.assetFields("embedded", "embedded");
270+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
271+
assertEquals(2, arr.length());
272+
assertEquals("embedded", arr.get(0));
273+
assertEquals("embedded", arr.get(1));
274+
}
275+
276+
@Test
277+
void testAssetFieldsSecondCallOverwrites() {
278+
asset.assetFields("user_defined_fields", "embedded");
279+
asset.assetFields("ai_suggested");
280+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
281+
assertEquals(1, arr.length());
282+
assertEquals("ai_suggested", arr.get(0));
283+
}
284+
285+
@Test
286+
void testAssetFieldsWithEmptyStringInArray() {
287+
asset.assetFields("valid", "", "embedded");
288+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
289+
assertEquals(3, arr.length());
290+
assertEquals("valid", arr.get(0));
291+
assertEquals("", arr.get(1));
292+
assertEquals("embedded", arr.get(2));
293+
}
294+
295+
@Test
296+
void testAssetFieldsWithNullInArray() {
297+
asset.assetFields("valid", null, "embedded");
298+
JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]");
299+
assertEquals(3, arr.length());
300+
assertEquals("valid", arr.get(0));
301+
assertEquals("embedded", arr.get(2));
302+
}
303+
304+
@Test
305+
void testAssetFieldsSingleEmptyStringSetsParam() {
306+
asset.assetFields("");
307+
assertTrue(asset.urlQueries.has("asset_fields[]"));
308+
assertEquals(1, asset.urlQueries.getJSONArray("asset_fields[]").length());
309+
assertEquals("", asset.urlQueries.getJSONArray("asset_fields[]").get(0));
310+
}
311+
185312
// ========== CHAINING TESTS ==========
186313

187314
@Test

0 commit comments

Comments
 (0)