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>&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());
 	}
 
 	//------------------------------------------------------------------------------------------------------------------