This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 7fb9b0aa68 Marshall module improvements
7fb9b0aa68 is described below
commit 7fb9b0aa6879487d236fe9fc3839e109278d74b8
Author: James Bognar <[email protected]>
AuthorDate: Sat Dec 6 10:38:22 2025 -0500
Marshall module improvements
---
.../a/rttests/NameProperty_RoundTripTest.java | 105 ++++++++++++++++++---
.../a/rttests/ParentProperty_RoundTripTest.java | 100 ++++++++++++++++++--
.../annotation/NamePropertyAnnotation_Test.java | 26 +++++
.../annotation/ParentPropertyAnnotation_Test.java | 29 ++++++
4 files changed, 239 insertions(+), 21 deletions(-)
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
index e73c2c1608..fc844d2791 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/NameProperty_RoundTripTest.java
@@ -38,28 +38,28 @@ class NameProperty_RoundTripTest extends RoundTripTest_Base
{
@ParameterizedTest
@MethodSource("testers")
void a01_nameProperty(RoundTrip_Tester t) throws Exception {
- var x = new A().init();
+ var x = new NamePropertyMethodContainer().init();
x = t.roundTrip(x);
- assertBean(x, "a2{f2},m{k1{f2}}", "{2},{{2}}");
+ assertBean(x, "bean{f2},m{k1{f2}}", "{2},{{2}}");
if (t.isValidationOnly())
return;
- assertBean(x, "a2{name}", "{a2}");
+ assertBean(x, "bean{name}", "{bean}");
assertBean(x, "m{k1{name}}", "{{k1}}");
}
- public static class A {
- public A2 a2;
- public Map<String,A2> m;
+ public static class NamePropertyMethodContainer {
+ public NamePropertyMethodBean bean;
+ public Map<String,NamePropertyMethodBean> m;
- A init() {
- a2 = new A2().init();
+ NamePropertyMethodContainer init() {
+ bean = new NamePropertyMethodBean().init();
m = new LinkedHashMap<>();
- m.put("k1", new A2().init());
+ m.put("k1", new NamePropertyMethodBean().init());
return this;
}
}
- public static class A2 {
+ public static class NamePropertyMethodBean {
String name;
public int f2;
@@ -68,7 +68,90 @@ class NameProperty_RoundTripTest extends RoundTripTest_Base {
this.name = name;
}
- A2 init() {
+ NamePropertyMethodBean init() {
+ f2 = 2;
+ return this;
+ }
+ }
+
+
//====================================================================================================
+ // @NameProperty field.
+
//====================================================================================================
+
+ @ParameterizedTest
+ @MethodSource("testers")
+ void a02_namePropertyField(RoundTrip_Tester t) throws Exception {
+ var x = new NamePropertyFieldContainer().init();
+ x = t.roundTrip(x);
+ assertBean(x, "bean{f2},m{k1{f2}}", "{2},{{2}}");
+ if (t.isValidationOnly())
+ return;
+ assertBean(x, "bean{name}", "{bean}");
+ assertBean(x, "m{k1{name}}", "{{k1}}");
+ }
+
+ public static class NamePropertyFieldContainer {
+ public NamePropertyFieldBean bean;
+ public Map<String,NamePropertyFieldBean> m;
+
+ NamePropertyFieldContainer init() {
+ bean = new NamePropertyFieldBean().init();
+ m = new LinkedHashMap<>();
+ m.put("k1", new NamePropertyFieldBean().init());
+ return this;
+ }
+ }
+ public static class NamePropertyFieldBean {
+ @NameProperty
+ public String name;
+ public int f2;
+
+ NamePropertyFieldBean init() {
+ f2 = 2;
+ return this;
+ }
+ }
+
+
//====================================================================================================
+ // @NameProperty read-only (getter only, no setter).
+
//====================================================================================================
+
+ @ParameterizedTest
+ @MethodSource("testers")
+ void a03_readOnlyNameProperty(RoundTrip_Tester t) throws Exception {
+ var x = new ReadOnlyNamePropertyContainer().init();
+ var originalName = x.bean.getName(); // Should be "initialName"
+ x = t.roundTrip(x);
+ assertBean(x, "bean{f2},m{k1{f2}}", "{2},{{2}}");
+ if (t.isValidationOnly())
+ return;
+ // The name should NOT have changed because the property is
read-only
+ assertEquals(originalName, x.bean.getName(), "Read-only name
property should not be set by parser");
+ assertBean(x, "bean{name}", "{initialName}");
+ assertBean(x, "m{k1{name}}", "{{initialName}}");
+ }
+
+ public static class ReadOnlyNamePropertyContainer {
+ public ReadOnlyNamePropertyBean bean;
+ public Map<String,ReadOnlyNamePropertyBean> m;
+
+ ReadOnlyNamePropertyContainer init() {
+ bean = new ReadOnlyNamePropertyBean().init();
+ m = new LinkedHashMap<>();
+ m.put("k1", new ReadOnlyNamePropertyBean().init());
+ return this;
+ }
+ }
+ public static class ReadOnlyNamePropertyBean {
+ private String name = "initialName";
+ public int f2;
+
+ @NameProperty
+ public String getName() {
+ return name;
+ }
+
+ ReadOnlyNamePropertyBean init() {
f2 = 2;
return this;
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
index c460a87f03..1c34b97d35 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/ParentProperty_RoundTripTest.java
@@ -35,34 +35,114 @@ class ParentProperty_RoundTripTest extends
RoundTripTest_Base {
@ParameterizedTest
@MethodSource("testers")
void a01_parentProperty(RoundTrip_Tester t) throws Exception {
- var x = new B().init();
+ var x = new ParentPropertyMethodContainer().init();
x = t.roundTrip(x);
if (t.isValidationOnly())
return;
- assertEquals(x.f1, x.b2.parent.f1);
+ assertEquals(x.f1, x.bean.parent.f1);
}
- public static class B {
+ public static class ParentPropertyMethodContainer {
public int f1;
- public B2 b2;
+ public ParentPropertyMethodBean bean;
- B init() {
+ ParentPropertyMethodContainer init() {
f1 = 1;
- b2 = new B2().init();
+ bean = new ParentPropertyMethodBean().init();
return this;
}
}
- public static class B2 {
- B parent;
+ public static class ParentPropertyMethodBean {
+ ParentPropertyMethodContainer parent;
public int f2;
@ParentProperty
- protected void setParent(B v) {
+ protected void setParent(ParentPropertyMethodContainer v) {
parent = v;
}
- B2 init() {
+ ParentPropertyMethodBean init() {
+ f2 = 2;
+ return this;
+ }
+ }
+
+
//====================================================================================================
+ // @ParentProperty field.
+
//====================================================================================================
+
+ @ParameterizedTest
+ @MethodSource("testers")
+ void a02_parentPropertyField(RoundTrip_Tester t) throws Exception {
+ var x = new ParentPropertyFieldContainer().init();
+ x = t.roundTrip(x);
+ if (t.isValidationOnly())
+ return;
+ assertEquals(x.f1, x.bean.parent.f1);
+ }
+
+ public static class ParentPropertyFieldContainer {
+ public int f1;
+ public ParentPropertyFieldBean bean;
+
+ ParentPropertyFieldContainer init() {
+ f1 = 1;
+ bean = new ParentPropertyFieldBean().init();
+ return this;
+ }
+ }
+ public static class ParentPropertyFieldBean {
+ @ParentProperty
+ public ParentPropertyFieldContainer parent;
+ public int f2;
+
+ ParentPropertyFieldBean init() {
+ f2 = 2;
+ return this;
+ }
+ }
+
+
//====================================================================================================
+ // @ParentProperty read-only (getter only, no setter).
+
//====================================================================================================
+
+ @ParameterizedTest
+ @MethodSource("testers")
+ void a03_readOnlyParentProperty(RoundTrip_Tester t) throws Exception {
+ var x = new ReadOnlyParentPropertyContainer().init();
+ // Initially, parent should be null (read-only property, can't
be set)
+ assertNull(x.bean.getParent(), "Read-only parent property
should initially be null");
+ x = t.roundTrip(x);
+ if (t.isValidationOnly())
+ return;
+ // After round-trip, parent should still be null because parser
won't set read-only properties
+ assertNull(x.bean.getParent(), "Read-only parent property
should not be set by parser");
+ // Verify the object structure is still correct
+ assertEquals(1, x.f1);
+ assertEquals(2, x.bean.f2);
+ }
+
+ public static class ReadOnlyParentPropertyContainer {
+ public int f1;
+ public ReadOnlyParentPropertyBean bean;
+
+ ReadOnlyParentPropertyContainer init() {
+ f1 = 1;
+ bean = new ReadOnlyParentPropertyBean().init();
+ return this;
+ }
+ }
+ public static class ReadOnlyParentPropertyBean {
+ private ReadOnlyParentPropertyContainer parent;
+ public int f2;
+
+ @ParentProperty
+ public ReadOnlyParentPropertyContainer getParent() {
+ return parent;
+ }
+
+ ReadOnlyParentPropertyBean init() {
f2 = 2;
return this;
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
index f8455e4cd0..ed4a917751 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/annotation/NamePropertyAnnotation_Test.java
@@ -21,6 +21,7 @@ import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.juneau.*;
+import org.apache.juneau.commons.reflect.ExecutableException;
import org.junit.jupiter.api.*;
class NamePropertyAnnotation_Test extends TestBase {
@@ -210,4 +211,29 @@ class NamePropertyAnnotation_Test extends TestBase {
assertEquals(42, prop.get(bean));
assertEquals(Integer.valueOf(42), bean.getId());
}
+
+ public static class TestBeanWithReadOnlyNameProperty {
+ private String name = "defaultName";
+
+ @NameProperty
+ public String getName() {
+ return name;
+ }
+ }
+
+ @Test void e06_readOnlyNameProperty() throws Exception {
+ var bc = BeanContext.DEFAULT;
+ var cm =
bc.getClassMeta(TestBeanWithReadOnlyNameProperty.class);
+ var prop = cm.getNameProperty();
+ assertNotNull(prop, "NameProperty should be found even if
read-only");
+ assertFalse(prop.canWrite(), "Should not have setter");
+ assertTrue(prop.canRead(), "Should have getter");
+
+ var bean = new TestBeanWithReadOnlyNameProperty();
+ assertEquals("defaultName", prop.get(bean));
+
+ // Verify that set() throws an exception
+ var ex = assertThrows(ExecutableException.class, () ->
prop.set(bean, "newName"));
+ assertTrue(ex.getMessage().contains("No setter defined"),
"Should throw exception when trying to set read-only property");
+ }
}
\ No newline at end of file
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
index 51fd3565a2..cb7f675042 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/annotation/ParentPropertyAnnotation_Test.java
@@ -21,6 +21,7 @@ import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.juneau.*;
+import org.apache.juneau.commons.reflect.ExecutableException;
import org.junit.jupiter.api.*;
class ParentPropertyAnnotation_Test extends TestBase {
@@ -170,4 +171,32 @@ class ParentPropertyAnnotation_Test extends TestBase {
var prop = cm.getParentProperty();
assertNull(prop, "ParentProperty should not be found on String
class");
}
+
+ public static class TestBeanWithReadOnlyParentProperty {
+ private ParentBean parent = new ParentBean();
+
+ @ParentProperty
+ public ParentBean getParent() {
+ return parent;
+ }
+ }
+
+ @Test void e04_readOnlyParentProperty() throws Exception {
+ var bc = BeanContext.DEFAULT;
+ var cm =
bc.getClassMeta(TestBeanWithReadOnlyParentProperty.class);
+ var prop = cm.getParentProperty();
+ assertNotNull(prop, "ParentProperty should be found even if
read-only");
+ assertFalse(prop.canWrite(), "Should not have setter");
+ assertTrue(prop.canRead(), "Should have getter");
+
+ var bean = new TestBeanWithReadOnlyParentProperty();
+ var parent = (ParentBean)prop.get(bean);
+ assertNotNull(parent, "Should be able to get parent");
+ assertEquals(42, parent.value);
+
+ // Verify that set() throws an exception
+ var newParent = new ParentBean();
+ var ex = assertThrows(ExecutableException.class, () ->
prop.set(bean, newParent));
+ assertTrue(ex.getMessage().contains("No setter defined"),
"Should throw exception when trying to set read-only property");
+ }
}
\ No newline at end of file