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 <[email protected]>
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>&lt;args&gt;</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>&lt;args&gt;</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());
        }
 
        
//------------------------------------------------------------------------------------------------------------------

Reply via email to