You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2022/07/23 18:08:21 UTC
[juneau] branch jbFixRestNpe updated: Unit tests.
This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch jbFixRestNpe
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/jbFixRestNpe by this push:
new c41cff071 Unit tests.
c41cff071 is described below
commit c41cff0713439bcb4e23710e9a898c993af01b29
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Sat Jul 23 14:07:53 2022 -0400
Unit tests.
---
.../java/org/apache/juneau/cp/BeanStoreEntry.java | 1 +
.../java/org/apache/juneau/reflect/FieldInfo.java | 30 ++++++--
.../java/org/apache/juneau/rest/RestContext.java | 28 ++++---
.../apache/juneau/rest/annotation/RestBean.java | 2 +-
.../juneau/rest/RestContext_Builder_Test.java | 89 ++++++++++++++++++++++
.../apache/juneau/rest/client/RestClient_Test.java | 6 +-
6 files changed, 136 insertions(+), 20 deletions(-)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreEntry.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreEntry.java
index 4c4b593e6..cab377a22 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreEntry.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreEntry.java
@@ -93,6 +93,7 @@ public class BeanStoreEntry<T> {
* @return <jk>true</jk> if this bean is exactly of the specified type and has the specified name.
*/
public boolean matches(Class<?> type, String name) {
+ name = nullIfEmpty(name);
return matches(type) && StringUtils.eq(this.name, name);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
index ad8f7cebe..f747c386f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
@@ -482,14 +482,34 @@ public final class FieldInfo implements Comparable<FieldInfo> {
}
/**
- * Invokes this field on the specified object.
+ * Returns the field value on the specified object.
*
* @param o The object containing the field.
* @return The field value.
- * @throws IllegalAccessException Field was not accessible.
- * @throws IllegalArgumentException Field does not belong to object.
+ * @throws BeanRuntimeException Field was not accessible or field does not belong to object.
*/
- public Object invoke(Object o) throws IllegalArgumentException, IllegalAccessException {
- return f.get(o);
+ public Object get(Object o) throws BeanRuntimeException {
+ try {
+ f.setAccessible(true);
+ return f.get(o);
+ } catch (Exception e) {
+ throw new BeanRuntimeException(e);
+ }
+ }
+
+ /**
+ * Sets the field value on the specified object.
+ *
+ * @param o The object containing the field.
+ * @param value The new field value.
+ * @throws BeanRuntimeException Field was not accessible or field does not belong to object.
+ */
+ public void set(Object o, Object value) throws BeanRuntimeException {
+ try {
+ f.setAccessible(true);
+ f.set(o, value);
+ } catch (Exception e) {
+ throw new BeanRuntimeException(e);
+ }
}
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index bab38267a..d1743adab 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -389,7 +389,7 @@ public class RestContext extends Context {
Supplier<?> r = this.resource;
Class<?> rc = resourceClass;
- beanStore = createBeanStore(rc, r)
+ beanStore = createBeanStore()
.build()
.addBean(Builder.class, this)
.addBean(ResourceSupplier.class, this.resource)
@@ -402,6 +402,7 @@ public class RestContext extends Context {
}
BeanStore bs = beanStore;
+ beanStore.add(BeanStore.class, bs);
varResolver = createVarResolver(bs, rc);
beanStore.add(VarResolver.class, varResolver.build());
config = beanStore.add(Config.class, createConfig(bs, rc));
@@ -431,6 +432,10 @@ public class RestContext extends Context {
runInitHooks(bs, resource());
+ // Set @RestBean fields.
+ // Note that these only get set on the first resource bean.
+ rci.forEachAllField(x -> x.hasAnnotation(RestBean.class), x -> x.set(resource.get(), beanStore.getBean(x.getType().inner(), x.getAnnotation(RestBean.class).name()).orElse(null)));
+
return this;
}
@@ -577,7 +582,7 @@ public class RestContext extends Context {
* Can be used to add more beans to the bean store.
*
* <p>
- * The bean store is created by the constructor using the {@link #createBeanStore(Class,Supplier)} method and is initialized with the following beans:
+ * The bean store is created by the constructor using the {@link #createBeanStore()} method and is initialized with the following beans:
* <ul>
* <li>{@link RestContext.Builder}
* <li>{@link ServletConfig}
@@ -633,17 +638,18 @@ public class RestContext extends Context {
* The bean store is created with the parent root bean store as the parent, allowing any beans in the root bean store to be available
* in this builder. The root bean store typically pulls from an injection framework such as Spring to allow injected beans to be used.
*
- * The resource class can optionally define a <c><jk>public static</jk> BeanStore <jsm>createBeanStore</jk>(...);</c> method to override
- * the default bean store created by this method. The parameters can be any beans available in the root bean store (such as any available
- * Spring beans if the top level resource is an instance of SpringRestServlet).
+ * The default bean store can be overridden via any of the following methods:
+ * <ul>
+ * <li>Annotation: {@link Rest#beanStore()}
+ * <li>Method: <c><ja>@RestBean</ja> <jk>public</jk> [<jk>static</jk>] BeanStore.Builder myMethod(<i><args></i>)</c>
+ * <br>Args can be any injectable bean including {@link org.apache.juneau.cp.BeanStore.Builder}, the default builder.
+ * <li>Method: <c><ja>@RestBean</ja> <jk>public</jk> [<jk>static</jk>] BeanStore myMethod(<i><args></i>)</c>
+ * <br>Args can be any injectable bean including {@link org.apache.juneau.cp.BeanStore.Builder}, the default builder.
+ * </ul>
*
- * @param resourceClass
- * The REST servlet/bean type that this context is defined against.
- * @param resource
- * The REST servlet/bean instance that this context is defined against.
- * @return A new bean store.
+ * @return A new bean store builder.
*/
- protected BeanStore.Builder createBeanStore(Class<?> resourceClass, Supplier<?> resource) {
+ protected BeanStore.Builder createBeanStore() {
// Default value.
Value<BeanStore.Builder> v = Value.of(
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestBean.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestBean.java
index 620942abf..d068e60ce 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestBean.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestBean.java
@@ -117,7 +117,7 @@ import org.apache.juneau.svl.*;
* <tr><td>{@link VarResolver}<br>{@link org.apache.juneau.svl.VarResolver.Builder}</td><td></td><td>class</td></tr>
* </table>
*/
-@Target({METHOD})
+@Target({METHOD,FIELD})
@Retention(RUNTIME)
@Inherited
public @interface RestBean {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/RestContext_Builder_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/RestContext_Builder_Test.java
new file mode 100644
index 000000000..3589dbdb7
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/RestContext_Builder_Test.java
@@ -0,0 +1,89 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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 *
+// * *
+// * http://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 org.apache.juneau.rest;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.cp.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.mock.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class RestContext_Builder_Test {
+
+ //-----------------------------------------------------------------------------------------------------------------
+ // beanStore
+ //-----------------------------------------------------------------------------------------------------------------
+
+ public static class Foo {}
+
+ @Rest
+ public static class A1 {
+ @RestBean static BeanStore beanStore;
+ }
+
+ @Test
+ public void a01_createBeanStore_default() {
+ MockRestClient.buildLax(A1.class);
+ assertString(A1.beanStore.getClass().getSimpleName()).is("BeanStore");
+ }
+
+ public static class MyBeanStore extends BeanStore {
+ protected MyBeanStore(Builder builder) {
+ super(builder.parent(BeanStore.create().build().addBean(Foo.class, new Foo())));
+ }
+ }
+
+ @Rest(beanStore=MyBeanStore.class)
+ public static class A2 {
+ @RestBean static BeanStore beanStore;
+ }
+
+ @Test
+ public void a02_createBeanStore_annotation() {
+ MockRestClient.buildLax(A2.class);
+ assertObject(A2.beanStore.getBean(Foo.class)).isNotNull();
+ }
+
+ @Rest
+ public static class A3 {
+ @RestBean static BeanStore beanStore;
+
+ @RestBean BeanStore.Builder beanStore(BeanStore.Builder b) {
+ return b.type(MyBeanStore.class);
+ }
+ }
+
+ @Test
+ public void a03_createBeanStore_restBean1() {
+ MockRestClient.buildLax(A3.class);
+ assertObject(A3.beanStore.getBean(Foo.class)).isNotNull();
+ }
+
+ @Rest
+ public static class A4 {
+ @RestBean static BeanStore beanStore;
+
+ @RestBean BeanStore beanStore() {
+ return BeanStore.create().type(MyBeanStore.class).build();
+ }
+ }
+
+ @Test
+ public void a04_createBeanStore_restBean2() {
+ MockRestClient.buildLax(A4.class);
+ assertObject(A4.beanStore.getBean(Foo.class)).isNotNull();
+ }
+}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
index af0dfd51b..994d19b22 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
@@ -314,9 +314,9 @@ public class RestClient_Test {
RestClient x1 = RestClient.create().simpleJson().pooled().build();
RestClient x2 = RestClient.create().simpleJson().build();
RestClient x3 = client().pooled().build();
- assertEquals("PoolingHttpClientConnectionManager",ClassInfo.of(x1.httpClient).getDeclaredField(x -> x.hasName("connManager")).accessible().invoke(x1.httpClient).getClass().getSimpleName());
- assertEquals("BasicHttpClientConnectionManager",ClassInfo.of(x2.httpClient).getDeclaredField(x -> x.hasName("connManager")).accessible().invoke(x2.httpClient).getClass().getSimpleName());
- assertEquals("MockHttpClientConnectionManager",ClassInfo.of(x3.httpClient).getDeclaredField(x -> x.hasName("connManager")).accessible().invoke(x3.httpClient).getClass().getSimpleName());
+ assertEquals("PoolingHttpClientConnectionManager",ClassInfo.of(x1.httpClient).getDeclaredField(x -> x.hasName("connManager")).accessible().get(x1.httpClient).getClass().getSimpleName());
+ assertEquals("BasicHttpClientConnectionManager",ClassInfo.of(x2.httpClient).getDeclaredField(x -> x.hasName("connManager")).accessible().get(x2.httpClient).getClass().getSimpleName());
+ assertEquals("MockHttpClientConnectionManager",ClassInfo.of(x3.httpClient).getDeclaredField(x -> x.hasName("connManager")).accessible().get(x3.httpClient).getClass().getSimpleName());
}
//------------------------------------------------------------------------------------------------------------------