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 db31683 RestClient tests.
db31683 is described below
commit db316836b999775f94bd56e307a1a10341978f5d
Author: JamesBognar <[email protected]>
AuthorDate: Mon Jun 15 20:11:18 2020 -0400
RestClient tests.
---
.../remote/RrpcInterfaceMeta.java} | 38 +-
.../remote/RrpcInterfaceMethodMeta.java} | 8 +-
.../org/apache/juneau/remote/RemoteInterface.java | 5 +
.../apache/juneau/rest/client2/RemotesTest.java | 512 ++++++++++++++++++---
...erfaceProxyTest.java => RrpcInterfaceTest.java} | 6 +-
.../org/apache/juneau/rest/client/RestClient.java | 6 +-
.../org/apache/juneau/rest/client2/RestClient.java | 259 +++++------
.../java/org/apache/juneau/rest/RestContext.java | 7 +-
.../org/apache/juneau/rest/RestMethodContext.java | 18 +-
.../juneau/rest/RestMethodContextBuilder.java | 12 +
.../apache/juneau/rest/annotation/RestMethod.java | 4 +-
.../org/apache/juneau/rest/remote/RrpcServlet.java | 18 +-
12 files changed, 652 insertions(+), 241 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/RrpcInterfaceMeta.java
similarity index 77%
rename from
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java
rename to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/RrpcInterfaceMeta.java
index f2d0f4e..de5fa05 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/RrpcInterfaceMeta.java
@@ -10,7 +10,7 @@
// * "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.remote;
+package org.apache.juneau.http.remote;
import static org.apache.juneau.internal.StringUtils.*;
import java.lang.reflect.*;
@@ -18,21 +18,22 @@ import java.util.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.reflect.*;
+import org.apache.juneau.remote.*;
/**
* Contains the meta-data about a remote proxy REST interface.
*
* <p>
- * Captures the information in {@link RemoteInterface @RemoteInterface}
annotations for caching and reuse.
+ * Captures the information in {@link Remote @Remote} annotations for caching
and reuse.
*
* <ul class='seealso'>
* <li class='link'>{@doc juneau-rest-server.restRPC}
* </ul>
*/
-public class RemoteInterfaceMeta {
+public class RrpcInterfaceMeta {
- private final Map<Method,RemoteInterfaceMethod> methods;
- private final Map<String,RemoteInterfaceMethod> methodsByPath;
+ private final Map<Method,RrpcInterfaceMethodMeta> methods;
+ private final Map<String,RrpcInterfaceMethodMeta> methodsByPath;
private final String path;
private final Class<?> c;
@@ -40,28 +41,33 @@ public class RemoteInterfaceMeta {
* Constructor.
*
* @param c
- * The interface class annotated with a {@link RemoteInterface
@RemoteInterface} annotation.
+ * The interface class annotated with a {@link Remote @Remote}
annotation.
* <br>Note that the annotations are optional.
* @param uri
* The absolute URL of the remote REST interface that implements
this proxy interface.
* <br>This is only used on the client side.
*/
- public RemoteInterfaceMeta(Class<?> c, String uri) {
+ @SuppressWarnings("deprecation")
+ public RrpcInterfaceMeta(Class<?> c, String uri) {
this.c = c;
String path = "";
ClassInfo ci = ClassInfo.of(c);
- List<RemoteInterface> rr =
ci.getAnnotations(RemoteInterface.class);
- for (RemoteInterface r : rr)
+
+ for (RemoteInterface r :
ci.getAnnotations(RemoteInterface.class))
+ if (! r.path().isEmpty())
+ path = trimSlashes(r.path());
+
+ for (Remote r : ci.getAnnotations(Remote.class))
if (! r.path().isEmpty())
path = trimSlashes(r.path());
- AMap<Method,RemoteInterfaceMethod> methods = AMap.of();
+ AMap<Method,RrpcInterfaceMethodMeta> methods = AMap.of();
for (MethodInfo m : ci.getPublicMethods())
if (m.isPublic())
- methods.put(m.inner(), new
RemoteInterfaceMethod(uri, m.inner()));
+ methods.put(m.inner(), new
RrpcInterfaceMethodMeta(uri, m.inner()));
- AMap<String,RemoteInterfaceMethod> methodsByPath = AMap.of();
- for (RemoteInterfaceMethod rmm : methods.values())
+ AMap<String,RrpcInterfaceMethodMeta> methodsByPath = AMap.of();
+ for (RrpcInterfaceMethodMeta rmm : methods.values())
methodsByPath.put(rmm.getPath(), rmm);
this.methods = methods.unmodifiable();
@@ -77,7 +83,7 @@ public class RemoteInterfaceMeta {
* <br>The keys never have leading slashes.
* <br>The map is never <jk>null</jk>.
*/
- public Map<String,RemoteInterfaceMethod> getMethodsByPath() {
+ public Map<String,RrpcInterfaceMethodMeta> getMethodsByPath() {
return methodsByPath;
}
@@ -87,7 +93,7 @@ public class RemoteInterfaceMeta {
* @param m The method to look up.
* @return Metadata about the method or <jk>null</jk> if no metadata
was found.
*/
- public RemoteInterfaceMethod getMethodMeta(Method m) {
+ public RrpcInterfaceMethodMeta getMethodMeta(Method m) {
return methods.get(m);
}
@@ -97,7 +103,7 @@ public class RemoteInterfaceMeta {
* @param p The HTTP path to look for.
* @return Metadata about the method or <jk>null</jk> if no metadata
was found.
*/
- public RemoteInterfaceMethod getMethodMetaByPath(String p) {
+ public RrpcInterfaceMethodMeta getMethodMetaByPath(String p) {
return methodsByPath.get(p);
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMethod.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/RrpcInterfaceMethodMeta.java
similarity index 92%
rename from
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMethod.java
rename to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/RrpcInterfaceMethodMeta.java
index b609e6a..112d0be 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMethod.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/RrpcInterfaceMethodMeta.java
@@ -10,7 +10,7 @@
// * "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.remote;
+package org.apache.juneau.http.remote;
import static org.apache.juneau.internal.StringUtils.*;
@@ -22,13 +22,13 @@ import org.apache.juneau.internal.*;
* Contains the meta-data about a Java method on a remote class.
*
* <p>
- * Captures the information in {@link RemoteInterface @RemoteInterface}
annotations for caching and reuse.
+ * Captures the information in {@link Remote @Remote} annotations for caching
and reuse.
*
* <ul class='seealso'>
* <li class='link'>{@doc juneau-rest-server.restRPC}
* </ul>
*/
-public class RemoteInterfaceMethod {
+public class RrpcInterfaceMethodMeta {
private final String url, path;
private final Method method;
@@ -39,7 +39,7 @@ public class RemoteInterfaceMethod {
* @param restUrl The absolute URL of the REST interface backing the
interface proxy.
* @param m The Java method.
*/
- public RemoteInterfaceMethod(final String restUrl, Method m) {
+ public RrpcInterfaceMethodMeta(final String restUrl, Method m) {
this.method = m;
this.path = m.getName() + '/' +
HttpUtils.getMethodArgsSignature(m, true);
this.url = trimSlashes(restUrl) + '/' + urlEncode(path);
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterface.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterface.java
index 72ff094..26600ea 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterface.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterface.java
@@ -17,17 +17,22 @@ import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
+import org.apache.juneau.http.remote.*;
+
/**
* Identifies a remote proxy REST interface.
*
* <ul class='seealso'>
* <li class='link'>{@doc juneau-rest-server.restRPC}
* </ul>
+ *
+ * @deprecated Use {@link Remote}
*/
@Documented
@Target({TYPE})
@Retention(RUNTIME)
@Inherited
+@Deprecated
public @interface RemoteInterface {
/**
diff --git
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RemotesTest.java
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RemotesTest.java
index a66548a..0b8a215 100644
---
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RemotesTest.java
+++
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RemotesTest.java
@@ -15,11 +15,15 @@ package org.apache.juneau.rest.client2;
import static org.junit.Assert.*;
import static org.junit.runners.MethodSorters.*;
+import java.util.concurrent.*;
+
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.client.remote.*;
import org.apache.juneau.rest.config.*;
+import org.apache.juneau.http.*;
import org.apache.juneau.http.remote.*;
import org.apache.juneau.http.remote.RemoteMethod;
+import org.apache.juneau.http.remote.RemoteReturn;
import org.apache.juneau.rest.mock2.*;
import org.junit.*;
@@ -281,129 +285,521 @@ public class RemotesTest {
// Other tests
//=================================================================================================================
+ @SuppressWarnings("serial")
+ public static class CException extends Exception {
+ public CException(String msg) {
+ super(msg);
+ }
+ }
+
@Rest(path="/C01")
public static class C01 implements BasicSimpleJsonRest {
-
@RestMethod
- public String c01() {
+ public String a() {
return "foo";
}
+ }
+
+ @Remote(path="/")
+ public static interface C01i {
+ @RemoteMethod
+ public String a();
+ }
+
+ @Test
+ public void c01_overriddenRootUrl() throws Exception {
+ C01i x = MockRestClient
+ .create(C01.class)
+ .json()
+ .build()
+ .getRemote(C01i.class, "http://localhost/C01");
+
+ assertEquals("foo", x.a());
+ }
+
+ @Test
+ public void c02_rootUriNotSpecified() throws Exception {
+ C01i x = MockRestClient
+ .create(C01.class)
+ .json()
+ .rootUrl("")
+ .build()
+ .getRemote(C01i.class);
+
+ try {
+ x.a();
+ fail();
+ } catch (RemoteMetadataException e) {
+ assertEquals("Invalid remote definition found on class
org.apache.juneau.rest.client2.RemotesTest$C01i. Root URI has not been
specified. Cannot construct absolute path to remote resource.",
e.getLocalizedMessage());
+ }
+ }
+
+ @Rest(path="/C03")
+ public static class C03 implements BasicSimpleJsonRest {
@RestMethod
- public String c02() {
+ public String a() {
return "bar";
}
-
@RestMethod
- public String c03() {
+ public String getB() {
return "baz";
}
+ }
+
+ @Remote(path="/")
+ public static interface C03i {
+ public String a();
+ public String getB();
+ }
+ @Test
+ public void c03_methodNotAnnotated() throws Exception {
+ C03i x = MockRestClient
+ .create(C03.class)
+ .json()
+ .build()
+ .getRemote(C03i.class);
+
+ assertEquals("bar", x.a());
+ assertEquals("baz", x.getB());
+ }
+
+ @Rest(path="/C04")
+ public static class C04 implements BasicSimpleJsonRest {
@RestMethod
- public String c04() throws C01Exception {
- throw new C01Exception("foo");
+ public String a() throws CException {
+ throw new CException("foo");
+ }
+ }
+
+ @Remote
+ public static interface C04i {
+ public String a() throws CException;
+ }
+
+ @Test
+ public void c04_rethrownException() throws Exception {
+ C04i x = MockRestClient
+ .create(C04.class)
+ .json()
+ .build()
+ .getRemote(C04i.class);
+
+ try {
+ x.a();
+ fail();
+ } catch (CException e) {
+ assertEquals("foo", e.getLocalizedMessage());
}
+ }
+ @Rest
+ public static class C05 implements BasicSimpleJsonRest {
@RestMethod
- public String c05() throws C02Exception {
- throw new C02Exception("foo");
+ public String a() throws CException {
+ throw new RuntimeException("foo");
}
}
- @Remote(path="/")
- public static interface C01i {
- @RemoteMethod
- public String c01();
- public String c02();
- public String getC03();
- public String c04() throws C01Exception;
- public String c05();
+ @Remote
+ public static interface C05i {
+ public String a() throws CException;
}
- @SuppressWarnings("serial")
- public static class C01Exception extends Exception {
- public C01Exception(String msg) {
- super(msg);
+ @Test
+ public void c05_rethrownUndefinedException() throws Exception {
+ C05i x = MockRestClient
+ .create(C05.class)
+ .json()
+ .build()
+ .getRemote(C05i.class);
+
+ try {
+ x.a();
+ fail();
+ } catch (RuntimeException e) {
+ assertTrue(e.getLocalizedMessage().contains("foo"));
}
}
- @SuppressWarnings("serial")
- public static class C02Exception extends Exception {
- public C02Exception(String msg) {
- super(msg);
+ public static class C06 implements BasicSimpleJsonRest {
+ @RestMethod
+ public String a() throws CException {
+ throw new CException("foo");
}
}
+ @Remote
+ public static interface C06i {
+ public Future<String> a() throws CException;
+ }
+
@Test
- public void c01_overriddenRootUrl() throws Exception {
- C01i x = MockRestClient
- .create(C01.class)
+ public void c06_rethrownExceptionOnFuture() throws Exception {
+ C06i x = MockRestClient
+ .create(C06.class)
.json()
.build()
- .getRemote(C01i.class, "http://localhost/C01");
+ .getRemote(C06i.class);
+
+ try {
+ x.a().get();
+ fail();
+ } catch (ExecutionException e) {
+ assertEquals("foo", e.getCause().getLocalizedMessage());
+ }
+ }
- assertEquals("foo", x.c01());
+ @Remote
+ public static interface C07i {
+ public CompletableFuture<String> a() throws CException;
}
@Test
- public void c02_methodNotAnnotated() throws Exception {
- C01i x = MockRestClient
- .create(C01.class)
+ public void c07_rethrownExceptionOnCompletableFuture() throws Exception
{
+ C07i x = MockRestClient
+ .create(C06.class)
.json()
.build()
- .getRemote(C01i.class, "http://localhost/C01");
+ .getRemote(C07i.class);
+
+ try {
+ x.a().get();
+ fail();
+ } catch (ExecutionException e) {
+ assertEquals("foo", e.getCause().getLocalizedMessage());
+ }
+ }
- assertEquals("bar", x.c02());
- assertEquals("baz", x.getC03());
+ @Rest
+ public static class C08 implements BasicSimpleJsonRest {
+ @RestMethod
+ public String a() {
+ throw new AssertionError("foo");
+ }
+ }
+
+ @Remote
+ public static interface C08i {
+ public Future<String> a() throws AssertionError;
}
@Test
- public void c03_rootUriNotSpecified() throws Exception {
- C01i x = MockRestClient
- .create(C01.class)
+ public void c08_rethrownThrowableOnFuture() throws Exception {
+ C08i x = MockRestClient
+ .create(C08.class)
.json()
- .rootUrl("")
.build()
- .getRemote(C01i.class);
+ .getRemote(C08i.class);
try {
- x.c01();
+ x.a().get();
fail();
- } catch (RemoteMetadataException e) {
- assertEquals("Invalid remote definition found on class
org.apache.juneau.rest.client2.RemotesTest$C01i. Root URI has not been
specified. Cannot construct absolute path to remote resource.",
e.getLocalizedMessage());
+ } catch (ExecutionException e) {
+ assertEquals("foo",
e.getCause().getCause().getLocalizedMessage());
}
}
+
//=================================================================================================================
+ // Status return type
+
//=================================================================================================================
+
+ @Rest
+ public static class DA implements BasicSimpleJsonRest {
+ @RestMethod
+ public void getR202(org.apache.juneau.rest.RestResponse res) {
+ res.setStatus(202);
+ }
+ @RestMethod
+ public void getR400(org.apache.juneau.rest.RestResponse res) {
+ res.setStatus(400);
+ }
+ }
+
+ @Remote
+ public static interface DAi {
+ @RemoteMethod(path="/r202", returns=RemoteReturn.STATUS)
+ public int a() throws AssertionError;
+ @RemoteMethod(path="/r202", returns=RemoteReturn.STATUS)
+ public Integer b() throws AssertionError;
+ @RemoteMethod(path="/r202", returns=RemoteReturn.STATUS)
+ public boolean c() throws AssertionError;
+ @RemoteMethod(path="/r202", returns=RemoteReturn.STATUS)
+ public Boolean d() throws AssertionError;
+ @RemoteMethod(path="/r202", returns=RemoteReturn.STATUS)
+ public String e() throws AssertionError;
+
+ @RemoteMethod(path="/r400", returns=RemoteReturn.STATUS)
+ public int f() throws AssertionError;
+ @RemoteMethod(path="/r400", returns=RemoteReturn.STATUS)
+ public Integer g() throws AssertionError;
+ @RemoteMethod(path="/r400", returns=RemoteReturn.STATUS)
+ public boolean h() throws AssertionError;
+ @RemoteMethod(path="/r400", returns=RemoteReturn.STATUS)
+ public Boolean i() throws AssertionError;
+ @RemoteMethod(path="/r400", returns=RemoteReturn.STATUS)
+ public String j() throws AssertionError;
+ }
+
@Test
- public void c04_rethrownException() throws Exception {
- C01i x = MockRestClient
- .create(C01.class)
+ public void d01_statusReturnType() throws Exception {
+ DAi x = MockRestClient
+ .create(DA.class)
.json()
+ .ignoreErrors()
.build()
- .getRemote(C01i.class);
+ .getRemote(DAi.class);
+
+ assertEquals(202, x.a());
+ assertEquals(202, x.b().intValue());
+ assertEquals(true, x.c());
+ assertEquals(true, x.d());
+ assertEquals(400, x.f());
+ assertEquals(400, x.g().intValue());
+ assertEquals(false, x.h());
+ assertEquals(false, x.i());
try {
- x.c04();
+ x.e();
fail();
- } catch (C01Exception e) {
- assertEquals("foo", e.getLocalizedMessage());
+ } catch (Exception e) {
+ assertEquals("Invalid return type on method annotated
with @RemoteMethod(returns=RemoteReturn.STATUS). Only integer and booleans
types are valid.", e.getCause().getLocalizedMessage());
+ }
+
+ try {
+ x.j();
+ fail();
+ } catch (Exception e) {
+ assertEquals("Invalid return type on method annotated
with @RemoteMethod(returns=RemoteReturn.STATUS). Only integer and booleans
types are valid.", e.getCause().getLocalizedMessage());
}
}
+ @Rest
+ public static class DB implements BasicSimpleJsonRest {
+ @RestMethod
+ public Integer getA() {
+ return null;
+ }
+ }
+
+ @Remote
+ public static interface DBi {
+ @RemoteMethod
+ public int a() throws AssertionError;
+ }
@Test
- public void c05_rethrownUndefinedException() throws Exception {
- C01i x = MockRestClient
- .create(C01.class)
+ public void d02_nullPrimitiveReturn() throws Exception {
+ DBi x = MockRestClient
+ .create(DB.class)
.json()
+ .ignoreErrors()
.build()
- .getRemote(C01i.class);
+ .getRemote(DBi.class);
+
+ assertEquals(0, x.a());
+ }
+
+ @Rest
+ public static class DC implements BasicSimpleJsonRest {
+ @RestMethod
+ public Integer getA() {
+ return 1;
+ }
+ }
+
+ @Remote
+ public static interface DCi {
+ @RemoteMethod
+ public int a() throws AssertionError;
+ }
+ @Test
+ public void d03_primitiveReturn() throws Exception {
+ DCi x = MockRestClient
+ .create(DC.class)
+ .json()
+ .ignoreErrors()
+ .build()
+ .getRemote(DCi.class);
+
+ assertEquals(1, x.a());
+ }
+
+ @Rest
+ public static class DD implements BasicSimpleJsonRest {
+ @RestMethod
+ public Integer getA() {
+ return null;
+ }
+ }
+
+ @Remote
+ public static interface DDi {
+ @RemoteMethod
+ public Integer a() throws AssertionError;
+ }
+
+ @Test
+ public void d04_nullNonPrimitive() throws Exception {
+ DDi x = MockRestClient
+ .create(DD.class)
+ .json()
+ .ignoreErrors()
+ .build()
+ .getRemote(DDi.class);
+
+ assertNull(x.a());
+ }
+
+
//=================================================================================================================
+ // RRPC interfaces
+
//=================================================================================================================
+
+ public interface E1i {
+ String echo(String body);
+ }
+
+ @Rest
+ public static class E1 implements BasicSimpleJsonRest {
+ @RestMethod(name=HttpMethodName.RRPC)
+ public E1i getProxy() {
+ return new E1i() {
+ @Override
+ public String echo(String body) {
+ return body;
+ }
+ };
+ }
+ }
+
+ @Test
+ public void e01_rrpcBasic() throws Exception {
+ E1i x = MockRestClient
+ .create(E1.class)
+ .rootUrl("http://localhost/proxy")
+ .json()
+ .build()
+ .getRrpcInterface(E1i.class);
+
+ assertEquals("foo", x.echo("foo"));
+ }
+
+ @Test
+ public void e02_rrpc_noRootPath() throws Exception {
try {
- x.c05();
- fail();
+ MockRestClient
+ .create(E1.class)
+ .rootUrl("")
+ .json()
+ .build()
+ .getRrpcInterface(E1i.class);
+ } catch (RemoteMetadataException e) {
+ assertEquals("Invalid remote definition found on class
org.apache.juneau.rest.client2.RemotesTest$E1i. Root URI has not been
specified. Cannot construct absolute path to remote interface.",
e.getMessage());
+ }
+ }
+
+ @Remote(path="/proxy")
+ public interface E3i {
+ String echo(String body);
+ }
+
+ @Test
+ public void e03_rrpc_noRestUrl() throws Exception {
+ E3i x = MockRestClient
+ .create(E1.class)
+ .rootUrl("http://localhost")
+ .json()
+ .build()
+ .getRrpcInterface(E3i.class);
+
+ assertEquals("foo", x.echo("foo"));
+ }
+
+ @Remote(path="http://localhost/proxy")
+ public interface E4i {
+ String echo(String body);
+ }
+
+ @Test
+ public void e04_rrpc_fullPathOnRemotePath() throws Exception {
+ E4i x = MockRestClient
+ .create(E1.class)
+ .rootUrl("")
+ .json()
+ .build()
+ .getRrpcInterface(E4i.class);
+
+ assertEquals("foo", x.echo("foo"));
+ }
+
+ public interface E5i {
+ String echo(String body) throws EException;
+ }
+
+ @SuppressWarnings("serial")
+ public static class EException extends Exception {
+ public EException(String msg) {
+ super(msg);
+ }
+ }
+
+ @Rest
+ public static class E5 implements BasicSimpleJsonRest {
+ @RestMethod(name=HttpMethodName.RRPC)
+ public E5i getProxy() {
+ return new E5i() {
+ @Override
+ public String echo(String body) throws
EException {
+ throw new EException("foobar");
+ }
+ };
+ }
+ }
+
+ @Test
+ public void e05_rrpc_rethrownCheckedException() throws Exception {
+ try {
+ E5i x = MockRestClient
+ .create(E5.class)
+ .json()
+ .build()
+ .getRrpcInterface(E5i.class, "/proxy");
+
+ x.echo("foo");
+ } catch (EException e) {
+ assertEquals("foobar", e.getMessage());
+ }
+ }
+
+ @Rest
+ public static class E6 implements BasicSimpleJsonRest {
+ @RestMethod(name=HttpMethodName.RRPC)
+ public E5i getProxy() {
+ return new E5i() {
+ @Override
+ public String echo(String body) throws
EException {
+ throw new AssertionError("foobar");
+ }
+ };
+ }
+ }
+
+ @Test
+ public void e06_rrpc_rethrownUncheckedException() throws Exception {
+ try {
+ E5i x = MockRestClient
+ .create(E6.class)
+ .json()
+ .build()
+ .getRrpcInterface(E5i.class, "/proxy");
+
+ x.echo("foo");
} catch (RuntimeException e) {
- assertTrue(e.getLocalizedMessage().contains("foo"));
+ assertEquals(RestCallException.class,
e.getCause().getClass());
+
assertTrue(e.getCause().getMessage().contains("foobar"));
}
}
+
}
diff --git
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/InterfaceProxyTest.java
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RrpcInterfaceTest.java
similarity index 96%
rename from
juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/InterfaceProxyTest.java
rename to
juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RrpcInterfaceTest.java
index 1e4b734..065dac1 100644
---
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/InterfaceProxyTest.java
+++
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RrpcInterfaceTest.java
@@ -28,7 +28,6 @@ import org.apache.juneau.jena.*;
import org.apache.juneau.json.*;
import org.apache.juneau.msgpack.*;
import org.apache.juneau.parser.*;
-import org.apache.juneau.remote.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.mock2.*;
@@ -44,7 +43,7 @@ import org.junit.runners.*;
@FixMethodOrder(NAME_ASCENDING)
@RunWith(Parameterized.class)
-public class InterfaceProxyTest {
+public class RrpcInterfaceTest {
@Parameterized.Parameters
public static Collection<Object[]> getParameters() {
@@ -60,7 +59,6 @@ public class InterfaceProxyTest {
});
}
- @RemoteInterface
public interface InterfaceProxy {
public static final String SWAP =
"swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/";
@@ -927,7 +925,7 @@ public class InterfaceProxyTest {
private InterfaceProxy proxy;
- public InterfaceProxyTest(String label, Serializer serializer, Parser
parser) {
+ public RrpcInterfaceTest(String label, Serializer serializer, Parser
parser) {
proxy = cache.get(label);
if (proxy == null) {
proxy =
MockRestClient.create(InterfaceProxyResource.class).serializer(serializer).parser(parser).ignoreErrors(false).build().getRrpcInterface(InterfaceProxy.class,
"/proxy");
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 5eed9a6..4b1ba6e 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -1383,7 +1383,7 @@ public class RestClient extends BeanContext implements
Closeable {
public <T> T getRrpcInterface(final Class<T> interfaceClass, Object
restUrl, final Serializer serializer, final Parser parser) {
if (restUrl == null) {
- RemoteInterfaceMeta rm = new
RemoteInterfaceMeta(interfaceClass, stringify(restUrl));
+ RrpcInterfaceMeta rm = new
RrpcInterfaceMeta(interfaceClass, stringify(restUrl));
String path = rm.getPath();
if (path.indexOf("://") == -1) {
if (rootUrl == null)
@@ -1401,11 +1401,11 @@ public class RestClient extends BeanContext implements
Closeable {
new Class[] { interfaceClass },
new InvocationHandler() {
- final RemoteInterfaceMeta rm = new
RemoteInterfaceMeta(interfaceClass, restUrl2);
+ final RrpcInterfaceMeta rm = new
RrpcInterfaceMeta(interfaceClass, restUrl2);
@Override /* InvocationHandler */
public Object invoke(Object proxy,
Method method, Object[] args) throws Throwable {
- RemoteInterfaceMethod rim =
rm.getMethodMeta(method);
+ RrpcInterfaceMethodMeta rim =
rm.getMethodMeta(method);
if (rim == null)
throw new
RuntimeException("Method is not exposed as a remote method.");
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
index e74a59c..2b2d7ae 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
@@ -65,7 +65,6 @@ import org.apache.juneau.oapi.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.parser.ParseException;
import org.apache.juneau.reflect.*;
-import org.apache.juneau.remote.*;
import org.apache.juneau.rest.client.remote.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.urlencoding.*;
@@ -2948,115 +2947,109 @@ public class RestClient extends BeanContext
implements HttpClient, Closeable, Re
final String restUrl2 = trimSlashes(emptyIfNull(rootUrl));
- try {
- return (T)Proxy.newProxyInstance(
- interfaceClass.getClassLoader(),
- new Class[] { interfaceClass },
- new InvocationHandler() {
-
- final RemoteMeta rm = new
RemoteMeta(interfaceClass);
-
- @Override /* InvocationHandler */
- public Object invoke(Object proxy,
Method method, Object[] args) throws Throwable {
- RemoteMethodMeta rmm =
rm.getMethodMeta(method);
-
- String url = rmm.getFullPath();
- if (url.indexOf("://") == -1)
- url = restUrl2 + '/' +
url;
- if (url.indexOf("://") == -1)
- throw new
RemoteMetadataException(interfaceClass, "Root URI has not been specified.
Cannot construct absolute path to remote resource.");
-
- String httpMethod =
rmm.getHttpMethod();
- HttpPartSerializerSession s =
getPartSerializerSession();
-
- RestRequest rc =
request(httpMethod, url, hasContent(httpMethod));
-
- rc.serializer(serializer);
- rc.parser(parser);
-
- for (RemoteMethodArg a :
rmm.getPathArgs())
- rc.path(a.getName(),
args[a.getIndex()], a.getSchema(), a.getSerializer(s));
-
- for (RemoteMethodArg a :
rmm.getQueryArgs())
-
rc.query(a.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(),
args[a.getIndex()], a.getSchema(), a.getSerializer(s));
-
- for (RemoteMethodArg a :
rmm.getFormDataArgs())
-
rc.formData(a.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS,
a.getName(), args[a.getIndex()], a.getSchema(), a.getSerializer(s));
-
- for (RemoteMethodArg a :
rmm.getHeaderArgs())
-
rc.header(a.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(),
args[a.getIndex()], a.getSchema(), a.getSerializer(s));
-
- RemoteMethodArg ba =
rmm.getBodyArg();
- if (ba != null)
-
rc.body(args[ba.getIndex()], ba.getSchema());
-
- if (rmm.getRequestArgs().length
> 0) {
- for
(RemoteMethodBeanArg rmba : rmm.getRequestArgs()) {
- RequestBeanMeta
rbm = rmba.getMeta();
- Object bean =
args[rmba.getIndex()];
- if (bean !=
null) {
- for
(RequestBeanPropertyMeta p : rbm.getProperties()) {
-
Object val = p.getGetter().invoke(bean);
-
HttpPartType pt = p.getPartType();
-
HttpPartSerializerSession ps = p.getSerializer(s);
-
String pn = p.getPartName();
-
HttpPartSchema schema = p.getSchema();
-
EnumSet<AddFlag> flags = schema.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS :
DEFAULT_FLAGS;
-
if (pt == PATH)
-
rc.path(pn, val, schema, p.getSerializer(s));
-
else if (val != null) {
-
if (pt == QUERY)
-
rc.query(flags, pn, val, schema, ps);
-
else if (pt == FORMDATA)
-
rc.formData(flags, pn, val, schema, ps);
-
else if (pt == HEADER)
-
rc.header(flags, pn, val, schema, ps);
-
else /* (pt == HttpPartType.BODY) */
-
rc.body(val, schema);
-
}
+ return (T)Proxy.newProxyInstance(
+ interfaceClass.getClassLoader(),
+ new Class[] { interfaceClass },
+ new InvocationHandler() {
+
+ final RemoteMeta rm = new
RemoteMeta(interfaceClass);
+
+ @Override /* InvocationHandler */
+ public Object invoke(Object proxy, Method
method, Object[] args) throws Throwable {
+ RemoteMethodMeta rmm =
rm.getMethodMeta(method);
+
+ String url = rmm.getFullPath();
+ if (url.indexOf("://") == -1)
+ url = restUrl2 + '/' + url;
+ if (url.indexOf("://") == -1)
+ throw new
RemoteMetadataException(interfaceClass, "Root URI has not been specified.
Cannot construct absolute path to remote resource.");
+
+ String httpMethod = rmm.getHttpMethod();
+ HttpPartSerializerSession s =
getPartSerializerSession();
+
+ RestRequest rc = request(httpMethod,
url, hasContent(httpMethod));
+
+ rc.serializer(serializer);
+ rc.parser(parser);
+
+ for (RemoteMethodArg a :
rmm.getPathArgs())
+ rc.path(a.getName(),
args[a.getIndex()], a.getSchema(), a.getSerializer(s));
+
+ for (RemoteMethodArg a :
rmm.getQueryArgs())
+ rc.query(a.isSkipIfEmpty() ?
SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(), args[a.getIndex()],
a.getSchema(), a.getSerializer(s));
+
+ for (RemoteMethodArg a :
rmm.getFormDataArgs())
+ rc.formData(a.isSkipIfEmpty() ?
SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(), args[a.getIndex()],
a.getSchema(), a.getSerializer(s));
+
+ for (RemoteMethodArg a :
rmm.getHeaderArgs())
+ rc.header(a.isSkipIfEmpty() ?
SKIP_IF_EMPTY_FLAGS : DEFAULT_FLAGS, a.getName(), args[a.getIndex()],
a.getSchema(), a.getSerializer(s));
+
+ RemoteMethodArg ba = rmm.getBodyArg();
+ if (ba != null)
+ rc.body(args[ba.getIndex()],
ba.getSchema());
+
+ if (rmm.getRequestArgs().length > 0) {
+ for (RemoteMethodBeanArg rmba :
rmm.getRequestArgs()) {
+ RequestBeanMeta rbm =
rmba.getMeta();
+ Object bean =
args[rmba.getIndex()];
+ if (bean != null) {
+ for
(RequestBeanPropertyMeta p : rbm.getProperties()) {
+ Object
val = p.getGetter().invoke(bean);
+
HttpPartType pt = p.getPartType();
+
HttpPartSerializerSession ps = p.getSerializer(s);
+ String
pn = p.getPartName();
+
HttpPartSchema schema = p.getSchema();
+
EnumSet<AddFlag> flags = schema.isSkipIfEmpty() ? SKIP_IF_EMPTY_FLAGS :
DEFAULT_FLAGS;
+ if (pt
== PATH)
+
rc.path(pn, val, schema, p.getSerializer(s));
+ else if
(val != null) {
+
if (pt == QUERY)
+
rc.query(flags, pn, val, schema, ps);
+
else if (pt == FORMDATA)
+
rc.formData(flags, pn, val, schema, ps);
+
else if (pt == HEADER)
+
rc.header(flags, pn, val, schema, ps);
+
else /* (pt == HttpPartType.BODY) */
+
rc.body(val, schema);
}
}
}
}
+ }
- RemoteMethodReturn rmr =
rmm.getReturns();
- if (rmr.isFuture()) {
- return
getExecutorService(true).submit(new Callable<Object>() {
- @Override
- public Object
call() throws Exception {
- try {
-
return executeRemote(interfaceClass, rc, method, rmm);
- } catch
(Exception e) {
-
throw e;
- } catch
(Throwable e) {
-
throw new RuntimeException(e);
- }
+ RemoteMethodReturn rmr =
rmm.getReturns();
+ if (rmr.isFuture()) {
+ return
getExecutorService(true).submit(new Callable<Object>() {
+ @Override
+ public Object call()
throws Exception {
+ try {
+ return
executeRemote(interfaceClass, rc, method, rmm);
+ } catch
(Exception e) {
+ throw e;
+ } catch
(Throwable e) {
+ throw
new RuntimeException(e);
}
- });
- } else if
(rmr.isCompletableFuture()) {
-
CompletableFuture<Object> cf = new CompletableFuture<>();
-
getExecutorService(true).submit(new Callable<Object>() {
- @Override
- public Object
call() throws Exception {
- try {
-
cf.complete(executeRemote(interfaceClass, rc, method, rmm));
-
return null;
- } catch
(Exception e) {
-
throw e;
- } catch
(Throwable e) {
-
throw new RuntimeException(e);
- }
+ }
+ });
+ } else if (rmr.isCompletableFuture()) {
+ CompletableFuture<Object> cf =
new CompletableFuture<>();
+
getExecutorService(true).submit(new Callable<Object>() {
+ @Override
+ public Object call()
throws Exception {
+ try {
+
cf.complete(executeRemote(interfaceClass, rc, method, rmm));
+ } catch
(Throwable e) {
+
cf.completeExceptionally(e);
}
- });
- return cf;
- }
-
- return
executeRemote(interfaceClass, rc, method, rmm);
+ return null;
+ }
+ });
+ return cf;
}
- });
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+
+ return executeRemote(interfaceClass,
rc, method, rmm);
+ }
+ });
}
Object executeRemote(Class<?> interfaceClass, RestRequest rc, Method
method, RemoteMethodMeta rmm) throws Throwable {
@@ -3076,7 +3069,7 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
else if (rt == Boolean.class || rt ==
boolean.class)
ret = returnCode < 400;
else
- throw new RestCallException("Invalid
return type on method annotated with @RemoteMethod(returns=HTTP_STATUS). Only
integer and booleans types are valid.");
+ throw new RestCallException("Invalid
return type on method annotated with
@RemoteMethod(returns=RemoteReturn.STATUS). Only integer and booleans types
are valid.");
} else if (rmr.getReturnValue() == RemoteReturn.BEAN) {
rc.ignoreErrors();
res = rc.run();
@@ -3103,7 +3096,7 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
}
/**
- * Create a new Remote Interface against a {@link RemoteInterface
@RemoteInterface}-annotated class.
+ * Create a new proxy interface against an RRPC-style service.
*
* <p>
* Remote interfaces are interfaces exposed on the server side using
either the <c>RrpcServlet</c>
@@ -3178,10 +3171,10 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
public <T> T getRrpcInterface(final Class<T> interfaceClass, Object
restUrl, final Serializer serializer, final Parser parser) {
if (restUrl == null) {
- RemoteInterfaceMeta rm = new
RemoteInterfaceMeta(interfaceClass, stringify(restUrl));
+ RrpcInterfaceMeta rm = new
RrpcInterfaceMeta(interfaceClass, "");
String path = rm.getPath();
if (path.indexOf("://") == -1) {
- if (rootUrl == null)
+ if (isEmpty(rootUrl))
throw new
RemoteMetadataException(interfaceClass, "Root URI has not been specified.
Cannot construct absolute path to remote interface.");
path = trimSlashes(rootUrl) + '/' + path;
}
@@ -3190,43 +3183,34 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
final String restUrl2 = stringify(restUrl);
- try {
- return (T)Proxy.newProxyInstance(
- interfaceClass.getClassLoader(),
- new Class[] { interfaceClass },
- new InvocationHandler() {
-
- final RemoteInterfaceMeta rm = new
RemoteInterfaceMeta(interfaceClass, restUrl2);
+ return (T)Proxy.newProxyInstance(
+ interfaceClass.getClassLoader(),
+ new Class[] { interfaceClass },
+ new InvocationHandler() {
- @Override /* InvocationHandler */
- public Object invoke(Object proxy,
Method method, Object[] args) throws Throwable {
- RemoteInterfaceMethod rim =
rm.getMethodMeta(method);
+ final RrpcInterfaceMeta rm = new
RrpcInterfaceMeta(interfaceClass, restUrl2);
- if (rim == null)
- throw new
RuntimeException("Method is not exposed as a remote method.");
+ @Override /* InvocationHandler */
+ public Object invoke(Object proxy, Method
method, Object[] args) throws Throwable {
+ RrpcInterfaceMethodMeta rim =
rm.getMethodMeta(method);
- String url = rim.getUrl();
+ String url = rim.getUrl();
- try {
- RestRequest rc =
request("POST", url, true).serializer(serializer).body(args);
+ try {
+ RestRequest rc =
request("POST", url, true).serializer(serializer).body(args);
- Object v =
rc.run().getBody().as(method.getGenericReturnType());
- if (v == null &&
method.getReturnType().isPrimitive())
- v =
ClassInfo.of(method.getReturnType()).getPrimitiveDefault();
- return v;
+ Object v =
rc.run().getBody().as(method.getGenericReturnType());
+ if (v == null &&
method.getReturnType().isPrimitive())
+ v =
ClassInfo.of(method.getReturnType()).getPrimitiveDefault();
+ return v;
- } catch (RestCallException e) {
- // Try to throw
original exception if possible.
-
ThrowableUtils.throwException(e.getServerExceptionName(),
e.getServerExceptionMessage(), method.getExceptionTypes());
- throw new
RuntimeException(e);
- } catch (Exception e) {
- throw new
RuntimeException(e);
- }
+ } catch (RestCallException e) {
+ // Try to throw original
exception if possible.
+
ThrowableUtils.throwException(e.getServerExceptionName(),
e.getServerExceptionMessage(), method.getExceptionTypes());
+ throw new RuntimeException(e);
}
- });
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ }
+ });
}
@Override
@@ -3254,7 +3238,8 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
logger.log(level, t, msg(msg, args));
if (logToConsole) {
System.err.println(msg(msg, args).get());
- t.printStackTrace();
+ if (t != null)
+ t.printStackTrace();
}
}
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 5c1780d..eb6aefc 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
@@ -60,10 +60,10 @@ import org.apache.juneau.oapi.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.plaintext.*;
import org.apache.juneau.reflect.*;
-import org.apache.juneau.remote.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.converters.*;
import org.apache.juneau.http.exception.*;
+import org.apache.juneau.http.remote.*;
import org.apache.juneau.rest.reshandlers.*;
import org.apache.juneau.rest.util.*;
import org.apache.juneau.rest.vars.*;
@@ -3908,11 +3908,12 @@ public final class RestContext extends BeanContext {
if ("RRPC".equals(httpMethod)) {
final ClassMeta<?>
interfaceClass = getClassMeta(mi.inner().getGenericReturnType());
- final
RemoteInterfaceMeta rim = new
RemoteInterfaceMeta(interfaceClass.getInnerClass(), null);
+ final RrpcInterfaceMeta
rim = new RrpcInterfaceMeta(interfaceClass.getInnerClass(), null);
if
(rim.getMethodsByPath().isEmpty())
throw new
RestException(SC_INTERNAL_SERVER_ERROR, "Method {0} returns an interface {1}
that doesn't define any remote methods.", mi.getSignature(),
interfaceClass.getFullName());
RestMethodContextBuilder smb = new RestMethodContextBuilder(resource,
mi.inner(), this);
+ smb.dotAll();
sm = new
RestMethodContext(smb) {
@Override
@@ -3933,7 +3934,7 @@ public final class RestContext extends BeanContext {
if (pip.indexOf('/') != -1)
pip = pip.substring(pip.lastIndexOf('/')+1);
pip = urlDecode(pip);
-
RemoteInterfaceMethod rmm = rim.getMethodMetaByPath(pip);
+
RrpcInterfaceMethodMeta rmm = rim.getMethodMetaByPath(pip);
if (rmm != null) {
Method m = rmm.getJavaMethod();
try {
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
index 91b28bf..b24497b 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
@@ -45,10 +45,10 @@ import org.apache.juneau.internal.HttpUtils;
import org.apache.juneau.jsonschema.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.reflect.*;
-import org.apache.juneau.remote.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.annotation.Method;
import org.apache.juneau.http.exception.*;
+import org.apache.juneau.http.remote.*;
import org.apache.juneau.rest.guards.*;
import org.apache.juneau.rest.util.*;
import org.apache.juneau.rest.widget.*;
@@ -318,7 +318,7 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
* <js>"RRPC"</js>
* - Remote-proxy interface.
* <br>This denotes a Java method that returns an object
(usually an interface, often annotated with the
- * {@link RemoteInterface @RemoteInterface} annotation) to
be used as a remote proxy using
+ * {@link Remote @Remote} annotation) to be used as a
remote proxy using
* <c>RestClient.getRemoteInterface(Class<T>
interfaceClass, String url)</c>.
* <br>This allows you to construct client-side interface
proxies using REST as a transport medium.
* <br>Conceptually, this is simply a fancy <c>POST</c>
against the url <js>"/{path}/{javaMethodName}"</js>
@@ -692,11 +692,19 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
this.responseMeta = ResponseBeanMeta.create(mi, ps);
+ boolean dotAll = b.dotAll;
List<UrlPathPattern> pathPatterns = new ArrayList<>();
- for (String p : getArrayProperty(RESTMETHOD_paths,
String.class))
+ for (String p : getArrayProperty(RESTMETHOD_paths,
String.class)) {
+ if (dotAll && ! p.endsWith("/*"))
+ p += "/*";
pathPatterns.add(new UrlPathPattern(p));
- if (pathPatterns.isEmpty())
- pathPatterns.add(new
UrlPathPattern(HttpUtils.detectHttpPath(method, true)));
+ }
+ if (pathPatterns.isEmpty()) {
+ String p = HttpUtils.detectHttpPath(method, true);
+ if (dotAll && ! p.endsWith("/*"))
+ p += "/*";
+ pathPatterns.add(new UrlPathPattern(p));
+ }
this.pathPatterns = pathPatterns.toArray(new
UrlPathPattern[pathPatterns.size()]);
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
index 859897c..b839454 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContextBuilder.java
@@ -31,6 +31,8 @@ public class RestMethodContextBuilder extends
BeanContextBuilder {
RestContext context;
java.lang.reflect.Method method;
+ boolean dotAll;
+
RestMethodProperties properties;
RestMethodContextBuilder(Object servlet, java.lang.reflect.Method
method, RestContext context) throws RestServletException {
@@ -68,6 +70,16 @@ public class RestMethodContextBuilder extends
BeanContextBuilder {
}
}
+ /**
+ * When enabled, append <js>"/*"</js> to path patterns if not already
present.
+ *
+ * @return This object (for method chaining).
+ */
+ public RestMethodContextBuilder dotAll() {
+ this.dotAll = true;
+ return this;
+ }
+
// <FluentSetters>
@Override /* GENERATED - ContextBuilder */
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
index 8fb8f57..ab3d479 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
@@ -20,9 +20,9 @@ import java.lang.annotation.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
-import org.apache.juneau.remote.*;
import org.apache.juneau.html.annotation.*;
import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.http.remote.*;
/**
* Identifies a REST Java method on a {@link RestServlet} implementation class.
@@ -470,7 +470,7 @@ public @interface RestMethod {
* <js>"RRPC"</js>
* - Remote-proxy interface.
* <br>This denotes a Java method that returns an object
(usually an interface, often annotated with the
- * {@link RemoteInterface @RemoteInterface} annotation) to
be used as a remote proxy using
+ * {@link Remote @Remote} annotation) to be used as a
remote proxy using
* <c>RestClient.getRemoteInterface(Class<T>
interfaceClass, String url)</c>.
* <br>This allows you to construct client-side interface
proxies using REST as a transport medium.
* <br>Conceptually, this is simply a fancy <c>POST</c>
against the url <js>"/{path}/{javaMethodName}"</js>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RrpcServlet.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RrpcServlet.java
index 7d57ec2..548be81 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RrpcServlet.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/remote/RrpcServlet.java
@@ -29,11 +29,11 @@ import org.apache.juneau.http.annotation.Header;
import org.apache.juneau.http.annotation.Path;
import org.apache.juneau.internal.*;
import org.apache.juneau.parser.*;
-import org.apache.juneau.remote.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.http.exception.*;
import org.apache.juneau.http.header.*;
+import org.apache.juneau.http.remote.*;
/**
* Abstract class for defining Remote Interface Services.
@@ -52,7 +52,7 @@ import org.apache.juneau.http.header.*;
@SuppressWarnings({"serial","javadoc"})
public abstract class RrpcServlet extends BasicRestServlet {
- private final Map<String,RemoteInterfaceMeta> serviceMap = new
ConcurrentHashMap<>();
+ private final Map<String,RrpcInterfaceMeta> serviceMap = new
ConcurrentHashMap<>();
//-----------------------------------------------------------------------------------------------------------------
// Abstract methods
@@ -123,7 +123,7 @@ public abstract class RrpcServlet extends BasicRestServlet {
) throws NotFound, Exception {
// Find the method.
- RemoteInterfaceMethod rmm =
getMethods(javaInterface).get(javaMethod);
+ RrpcInterfaceMethodMeta rmm =
getMethods(javaInterface).get(javaMethod);
if (rmm == null)
throw new NotFound("Method not found");
@@ -193,7 +193,7 @@ public abstract class RrpcServlet extends BasicRestServlet {
// Find the parser.
if (p == null)
throw new UnsupportedMediaType("Could not find parser
for media type ''{0}''", contentType);
- RemoteInterfaceMeta rim = getInterfaceClass(javaInterface);
+ RrpcInterfaceMeta rim = getInterfaceClass(javaInterface);
// Find the service.
Object service = getServiceMap().get(rim.getJavaClass());
@@ -201,7 +201,7 @@ public abstract class RrpcServlet extends BasicRestServlet {
throw new NotFound("Service not found");
// Find the method.
- RemoteInterfaceMethod rmm =
getMethods(javaInterface).get(javaMethod);
+ RrpcInterfaceMethodMeta rmm =
getMethods(javaInterface).get(javaMethod);
if (rmm == null)
throw new NotFound("Method not found");
@@ -216,19 +216,19 @@ public abstract class RrpcServlet extends
BasicRestServlet {
// Other methods
//-----------------------------------------------------------------------------------------------------------------
- private Map<String,RemoteInterfaceMethod> getMethods(String
javaInterface) throws Exception {
+ private Map<String,RrpcInterfaceMethodMeta> getMethods(String
javaInterface) throws Exception {
return getInterfaceClass(javaInterface).getMethodsByPath();
}
/**
* Return the <c>Class</c> given it's name if it exists in the services
map.
*/
- private RemoteInterfaceMeta getInterfaceClass(String javaInterface)
throws NotFound, Exception {
- RemoteInterfaceMeta rm = serviceMap.get(javaInterface);
+ private RrpcInterfaceMeta getInterfaceClass(String javaInterface)
throws NotFound, Exception {
+ RrpcInterfaceMeta rm = serviceMap.get(javaInterface);
if (rm == null) {
for (Class<?> c : getServiceMap().keySet()) {
if (c.getName().equals(javaInterface)) {
- rm = new RemoteInterfaceMeta(c, null);
+ rm = new RrpcInterfaceMeta(c, null);
serviceMap.put(javaInterface, rm);
return rm;
}