Repository: incubator-juneau
Updated Branches:
  refs/heads/master 95ee1b536 -> 35cb8461b


Add @RemoteMethod(returns) annotation.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/35cb8461
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/35cb8461
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/35cb8461

Branch: refs/heads/master
Commit: 35cb8461bf0b4dab5214cb74843f28636827d809
Parents: 95ee1b5
Author: JamesBognar <[email protected]>
Authored: Mon Jun 19 21:29:23 2017 -0400
Committer: JamesBognar <[email protected]>
Committed: Mon Jun 19 21:29:23 2017 -0400

----------------------------------------------------------------------
 .../main/java/org/apache/juneau/ClassMeta.java  | 45 +---------
 .../org/apache/juneau/internal/ClassUtils.java  | 31 +++++++
 .../apache/juneau/remoteable/RemoteMethod.java  | 29 +++++-
 .../juneau/remoteable/RemoteableMethodMeta.java | 13 +++
 .../apache/juneau/remoteable/ReturnValue.java   | 25 ++++++
 .../java/org/apache/juneau/utils/PojoQuery.java |  1 +
 juneau-core/src/main/javadoc/overview.html      |  1 +
 .../apache/juneau/rest/client/RestClient.java   | 17 +++-
 .../rest/test/ThirdPartyProxyResource.java      | 14 +++
 .../juneau/rest/test/ThirdPartyProxyTest.java   | 75 ++++++++++++++++
 .../java/org/apache/juneau/rest/CallMethod.java |  2 +-
 .../apache/juneau/rest/widget/QueryWidget.html  | 92 ++++++++++++++------
 12 files changed, 271 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index 786d60a..1545511 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -111,15 +111,6 @@ public final class ClassMeta<T> implements Type {
        private final BeanRegistry beanRegistry;                // The bean 
registry of this class meta (if it has one).
        private final ClassMeta<?>[] args;                      // Arg types if 
this is an array of args.
 
-       private static final Boolean BOOLEAN_DEFAULT = false;
-       private static final Character CHARACTER_DEFAULT = (char)0;
-       private static final Short SHORT_DEFAULT = (short)0;
-       private static final Integer INTEGER_DEFAULT = 0;
-       private static final Long LONG_DEFAULT = 0l;
-       private static final Float FLOAT_DEFAULT = 0f;
-       private static final Double DOUBLE_DEFAULT = 0d;
-       private static final Byte BYTE_DEFAULT = (byte)0;
-
        private ReadWriteLock lock = new ReentrantReadWriteLock(false);
        private Lock rLock = lock.readLock(), wLock = lock.writeLock();
 
@@ -521,41 +512,7 @@ public final class ClassMeta<T> implements Type {
                                }
                        }
 
-                       if (c.isPrimitive()) {
-                               if (c == Boolean.TYPE)
-                                       primitiveDefault = BOOLEAN_DEFAULT;
-                               else if (c == Character.TYPE)
-                                       primitiveDefault = CHARACTER_DEFAULT;
-                               else if (c == Short.TYPE)
-                                       primitiveDefault = SHORT_DEFAULT;
-                               else if (c == Integer.TYPE)
-                                       primitiveDefault = INTEGER_DEFAULT;
-                               else if (c == Long.TYPE)
-                                       primitiveDefault = LONG_DEFAULT;
-                               else if (c == Float.TYPE)
-                                       primitiveDefault = FLOAT_DEFAULT;
-                               else if (c == Double.TYPE)
-                                       primitiveDefault = DOUBLE_DEFAULT;
-                               else if (c == Byte.TYPE)
-                                       primitiveDefault = BYTE_DEFAULT;
-                       } else {
-                               if (c == Boolean.class)
-                                       primitiveDefault = BOOLEAN_DEFAULT;
-                               else if (c == Character.class)
-                                       primitiveDefault = CHARACTER_DEFAULT;
-                               else if (c == Short.class)
-                                       primitiveDefault = SHORT_DEFAULT;
-                               else if (c == Integer.class)
-                                       primitiveDefault = INTEGER_DEFAULT;
-                               else if (c == Long.class)
-                                       primitiveDefault = LONG_DEFAULT;
-                               else if (c == Float.class)
-                                       primitiveDefault = FLOAT_DEFAULT;
-                               else if (c == Double.class)
-                                       primitiveDefault = DOUBLE_DEFAULT;
-                               else if (c == Byte.class)
-                                       primitiveDefault = BYTE_DEFAULT;
-                       }
+                       primitiveDefault = ClassUtils.getPrimitiveDefault(c);
 
                        for (Method m : c.getMethods())
                                if (isPublic(m) && isNotDeprecated(m))

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java 
b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 0f52ed5..6a3e812 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -18,6 +18,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Class-related utility methods.
@@ -923,4 +924,34 @@ public final class ClassUtils {
                }
                return l;
        }
+
+       /**
+        * Returns the default value for the specified primitive class.
+        *
+        * @param primitiveClass The primitive class to get the default value 
for.
+        * @return The default value, or <jk>null</jk> if the specified class 
is not a primitive class.
+        */
+       public static Object getPrimitiveDefault(Class<?> primitiveClass) {
+               return primitiveDefaultMap.get(primitiveClass);
+       }
+
+       private static final Map<Class<?>,Object> primitiveDefaultMap = 
Collections.unmodifiableMap(
+               new AMap<Class<?>,Object>()
+                       .append(Boolean.TYPE, false)
+                       .append(Character.TYPE, (char)0)
+                       .append(Short.TYPE, (short)0)
+                       .append(Integer.TYPE, 0)
+                       .append(Long.TYPE, 0l)
+                       .append(Float.TYPE, 0f)
+                       .append(Double.TYPE, 0d)
+                       .append(Byte.TYPE, (byte)0)
+                       .append(Boolean.class, false)
+                       .append(Character.class, (char)0)
+                       .append(Short.class, (short)0)
+                       .append(Integer.class, 0)
+                       .append(Long.class, 0l)
+                       .append(Float.class, 0f)
+                       .append(Double.class, 0d)
+                       .append(Byte.class, (byte)0)
+       );
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java 
b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java
index 97cd3be..0169033 100644
--- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java
+++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java
@@ -55,7 +55,7 @@ public @interface RemoteMethod {
        String path() default "";
 
        /**
-        * Defines whether to use <code>GET</code> or <code>POST</code> for 
REST calls.
+        * Defines the HTTP method to use for REST calls.
         * <p>
         * Possible values:
         * <ul>
@@ -66,4 +66,31 @@ public @interface RemoteMethod {
         * The default value is <js>"POST"</js>.
         */
        String httpMethod() default "POST";
+
+       /**
+        * The value the remoteable method returns.
+        * <p>
+        * Possible values:
+        * <ul>
+        *      <li>{@link ReturnValue#BODY} (default) - The body of the HTTP 
response converted to a POJO.
+        *              <br>The return type on the Java method can be any of 
the following:
+        *              <ul>
+        *                      <li><jk>void</jk> - Don't parse any response.  
Note that the method will still throw an exception if an
+        *                                      error HTTP status is returned.
+        *                      <li>Any parsable POJO - The body of the 
response will be converted to the POJO using the parser defined
+        *                                      on the <code>RestClient</code>.
+        *                      <li><code>HttpResponse</code> - Returns the raw 
<code>HttpResponse</code> returned by the inner
+        *                                      <code>HttpClient</code>.
+        *                      <li>{@link Reader} - Returns access to the raw 
reader of the response.
+        *                      <li>{@link InputStream} - Returns access to the 
raw input stream of the response.
+        *              </ul>
+        *      <li>{@link ReturnValue#HTTP_STATUS} - The HTTP status code on 
the response.
+        *              <br>The return type on the Java method can be any of 
the following:
+        *              <ul>
+        *                      <li><jk>int</jk>/<code>Integer</code> - The 
HTTP response code.
+        *                      <li><jk>boolean</jk>/<code>Boolean</code> - 
<jk>true</jk> if the response code is <code>&lt;400</code>
+        *              </ul>
+        * </ul>
+        */
+       ReturnValue returns() default ReturnValue.BODY;
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
 
b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
index 8430ae8..2db986e 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java
@@ -37,6 +37,7 @@ public class RemoteableMethodMeta {
        private final RemoteMethodArg[] pathArgs, queryArgs, headerArgs, 
formDataArgs, requestBeanArgs;
        private final Integer[] otherArgs;
        private final Integer bodyArg;
+       private final ReturnValue returnValue;
 
        /**
         * Constructor.
@@ -55,6 +56,7 @@ public class RemoteableMethodMeta {
                this.requestBeanArgs = b.requestBeanArgs.toArray(new 
RemoteMethodArg[b.requestBeanArgs.size()]);
                this.otherArgs = b.otherArgs.toArray(new 
Integer[b.otherArgs.size()]);
                this.bodyArg = b.bodyArg;
+               this.returnValue = b.returnValue;
        }
 
        private static class Builder {
@@ -68,6 +70,7 @@ public class RemoteableMethodMeta {
                private List<Integer>
                        otherArgs = new LinkedList<Integer>();
                private Integer bodyArg;
+               private ReturnValue returnValue;
 
                private Builder(String restUrl, Method m) {
                        Remoteable r = 
m.getDeclaringClass().getAnnotation(Remoteable.class);
@@ -83,6 +86,8 @@ public class RemoteableMethodMeta {
                        if (! isOneOf(methodPaths, "NAME", "SIGNATURE"))
                                throw new RemoteableMetadataException(m, 
"Invalid value specified for @Remoteable.methodPaths() annotation.  Valid 
values are [NAME,SIGNATURE].");
 
+                       returnValue = rm == null ? ReturnValue.BODY : 
rm.returns();
+
                        url =
                                trimSlashes(restUrl)
                                + '/'
@@ -206,4 +211,12 @@ public class RemoteableMethodMeta {
        public Integer getBodyArg() {
                return bodyArg;
        }
+
+       /**
+        * Returns whether the method returns the HTTP response body or status 
code.
+        * @return Whether the method returns the HTTP response body or status 
code.
+        */
+       public ReturnValue getReturns() {
+               return returnValue;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java 
b/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java
new file mode 100644
index 0000000..a6ebc3e
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java
@@ -0,0 +1,25 @@
+// 
***************************************************************************************************************************
+// * 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.remoteable;
+
+/**
+ * Possible values for the {@link RemoteMethod#returns()} annotation.
+ */
+public enum ReturnValue {
+
+       /** HTTP response body */
+       BODY, 
+       
+       /** HTTP status code */
+       HTTP_STATUS;
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java 
b/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java
index 737fb32..17292ef 100644
--- a/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java
+++ b/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java
@@ -238,6 +238,7 @@ public final class PojoQuery {
                int limit = args.getLimit();
                if (pos != 0 || limit != 0) {
                        int end = (limit == 0 || limit+pos >= l.size()) ? 
l.size() : limit + pos;
+                       pos = Math.min(pos, l.size());
                        ObjectList l2 = new 
DelegateList(((DelegateList)l).getClassMeta());
                        l2.addAll(l.subList(pos, end));
                        l = l2;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html 
b/juneau-core/src/main/javadoc/overview.html
index 12d6c29..15aa1eb 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -6183,6 +6183,7 @@
                        <li>{@link org.apache.juneau.utils.PojoQuery} 
improvements.
                                <br>Search columns containing lists and maps.
                                <br>Sort columns containing lists and maps.
+                       <li>New {@link 
org.apache.juneau.remoteable.RemoteMethod#returns()} annotation.
                </ul>
 
                <h6 class='topic'>org.apache.juneau.rest</h6>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
 
b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 484d934..6d06825 100644
--- 
a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ 
b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -30,6 +30,7 @@ import org.apache.http.client.utils.*;
 import org.apache.http.entity.*;
 import org.apache.http.impl.client.*;
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.remoteable.*;
@@ -642,7 +643,21 @@ public class RestClient extends CoreObject {
                                                                
rc.input(otherArgs);
                                                        }
 
-                                                       return 
rc.getResponse(method.getGenericReturnType());
+                                                       if (rmm.getReturns() == 
ReturnValue.HTTP_STATUS) {
+                                                               
rc.ignoreErrors();
+                                                               int returnCode 
= rc.run();
+                                                               Class<?> rt = 
method.getReturnType();
+                                                               if (rt == 
Integer.class || rt == int.class)
+                                                                       return 
returnCode;
+                                                               if (rt == 
Boolean.class || rt == boolean.class)
+                                                                       return 
returnCode < 400;
+                                                               throw new 
RestCallException("Invalid return type on method annotated with 
@RemoteableMethod(returns=HTTP_STATUS).  Only integer and booleans types are 
valid.");
+                                                       }
+
+                                                       Object v = 
rc.getResponse(method.getGenericReturnType());
+                                                       if (v == null && 
method.getReturnType().isPrimitive())
+                                                               v = 
ClassUtils.getPrimitiveDefault(method.getReturnType());
+                                                       return v;
 
                                                } catch (RestCallException e) {
                                                        // Try to throw 
original exception if possible.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java
 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java
index d613422..157e20d 100644
--- 
a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java
+++ 
b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java
@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
 import java.util.*;
 
 import org.apache.juneau.microservice.*;
+import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.test.pojos.*;
 import org.apache.juneau.utils.*;
@@ -1720,4 +1721,17 @@ public class ThirdPartyProxyResource extends 
ResourceJena {
                return "OK";
        }
 
+       
//--------------------------------------------------------------------------------
+       // @RemoteableMethod(returns=HTTP_STATUS)
+       
//--------------------------------------------------------------------------------
+
+       @RestMethod(name="GET", path="/httpStatusReturn200")
+       public void httpStatusReturn200(RestResponse res) {
+               res.setStatus(200);
+       }
+
+       @RestMethod(name="GET", path="/httpStatusReturn404")
+       public void httpStatusReturn404(RestResponse res) {
+               res.setStatus(404);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
index fe02c60..b6c0e5b 100644
--- 
a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
+++ 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
@@ -2147,6 +2147,55 @@ public class ThirdPartyProxyTest extends RestTestcase {
                assertEquals("OK", r);
        }
 
+       
//--------------------------------------------------------------------------------
+       // @RemoteableMethod(returns=HTTP_STATUS)
+       
//--------------------------------------------------------------------------------
+       @Test
+       public void i01a() throws Exception {
+               int r = proxy.httpStatusReturnInt200();
+               assertEquals(200, r);
+       }
+
+       @Test
+       public void i01b() throws Exception {
+               Integer r = proxy.httpStatusReturnInteger200();
+               assertEquals(200, r.intValue());
+       }
+
+       @Test
+       public void i01c() throws Exception {
+               int r = proxy.httpStatusReturnInt404();
+               assertEquals(404, r);
+       }
+
+       @Test
+       public void i01d() throws Exception {
+               Integer r = proxy.httpStatusReturnInteger404();
+               assertEquals(404, r.intValue());
+       }
+
+       @Test
+       public void i02a() throws Exception {
+               boolean r = proxy.httpStatusReturnBool200();
+               assertEquals(true, r);
+       }
+
+       @Test
+       public void i02b() throws Exception {
+               Boolean r = proxy.httpStatusReturnBoolean200();
+               assertEquals(true, r);
+       }
+
+       @Test
+       public void i02c() throws Exception {
+               boolean r = proxy.httpStatusReturnBool404();
+               assertEquals(false, r);
+       }
+
+       public void i02d() throws Exception {
+               Boolean r = proxy.httpStatusReturnBoolean404();
+               assertEquals(false, r);
+       }
 
        
//--------------------------------------------------------------------------------
        // Proxy class
@@ -3716,6 +3765,32 @@ public class ThirdPartyProxyTest extends RestTestcase {
 
                @RemoteMethod(httpMethod="POST", path="/setEnum1d3dListMap")
                void setEnum1d3dListMap(@Body 
Map<TestEnum,List<TestEnum[][][]>> x);
+
+               // Method returns status code
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", 
returns=ReturnValue.HTTP_STATUS)
+               int httpStatusReturnInt200();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", 
returns=ReturnValue.HTTP_STATUS)
+               Integer httpStatusReturnInteger200();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", 
returns=ReturnValue.HTTP_STATUS)
+               int httpStatusReturnInt404();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", 
returns=ReturnValue.HTTP_STATUS)
+               Integer httpStatusReturnInteger404();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", 
returns=ReturnValue.HTTP_STATUS)
+               boolean httpStatusReturnBool200();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", 
returns=ReturnValue.HTTP_STATUS)
+               Boolean httpStatusReturnBoolean200();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", 
returns=ReturnValue.HTTP_STATUS)
+               boolean httpStatusReturnBool404();
+
+               @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", 
returns=ReturnValue.HTTP_STATUS)
+               Boolean httpStatusReturnBoolean404();
        }
 
        // Bean for testing NE annotations.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
index 2563442..207e312 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -811,7 +811,7 @@ class CallMethod implements Comparable<CallMethod>  {
                        throw new RestException(SC_BAD_REQUEST,
                                "Invalid argument type passed to the following 
method: ''{0}''.\n\tArgument types: {1}",
                                method.toString(), getReadableClassNames(args)
-                       );
+                       ).initCause(e);
                } catch (InvocationTargetException e) {
                        Throwable e2 = e.getTargetException();          // Get 
the throwable thrown from the doX() method.
                        if (e2 instanceof RestException)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html 
b/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html
index 02c4adf..d89516f 100644
--- 
a/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html
+++ 
b/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html
@@ -63,71 +63,109 @@
        .tooltiptext {
                white-space: nowrap;
                float: left;
+               border: 1px solid black;
        }
 </style>
 <form id='queryForm' style='display:inline'>
        <table id='query' class='queryInput hidden'>
                <tr>
-                       <th>
+                       <th>Search:</th>
+                       <td>
+                               <input name="s" size="50" value='$R{query.s}'>
+                       </td>
+                       <td>
                                <div class="tooltip">
-                                       Search <small>(?)</small>:
+                                       <small>(?)</small>
                                        <span class="tooltiptext">
                                                Comma-delimited list of 
key/value pair search terms.
-                                               <br>Keys are column names.
-                                               <br>Values are search terms.
-                                               <br>Refer to the 
<code>Queryable</code> javadocs for a full explanation of possible search terms.
-                                               <br>Example: 
<code>column1=foo*, column2&lt;100, column3=2013-2016.06.30</code>
+                                               <br>
+                                               <br>Keys are column names.  
Values are search terms.
+                                               <br>
+                                               
<br><b>Example:</b>&nbsp;&nbsp;<code>[column1=foo*, column2&lt;100, 
column3=2013-2016.06.30]</code>
+                                               <br>
+                                               <br><b>String fields:</b>
+                                               <br> - <code>'*'</code> 
represents any character
+                                               <br> - <code>'?'</code> 
represents one character
+                                               <br> - Use single or double 
quotes for phrases
+                                               <br>&nbsp;&nbsp;&nbsp;e.g. 
<code>[column='foo bar']</code> - The term 'foo bar'
+                                               <br> - Multiple search terms 
are ORed 
+                                               <br>&nbsp;&nbsp;&nbsp;e.g. 
<code>[column=foo bar]</code> - 'foo' OR 'bar'
+                                               <br> - Prepend <code>'+'</code> 
on tokens that must match
+                                               <br>&nbsp;&nbsp;&nbsp;e.g. 
<code>[column=+foo* +*bar]</code> - Start with 'foo' AND end with 'bar'.
+                                               <br> - Prepend <code>'-'</code> 
on tokens that must not match 
+                                               <br>&nbsp;&nbsp;&nbsp;e.g. 
<code>[column=+foo* -*bar]</code> - Start with 'foo' AND does not end with 
'bar'.
+                                               <br>
+                                               <br><b>Numeric fields:</b>
+                                               <br><code>[column=123]</code> - 
A single number
+                                               <br><code>[column=1 2 3]</code> 
- Multiple numbers
+                                               <br><code>[column=1-100]</code> 
- Between two numbers
+                                               <br><code>[column=1-100 
200-300]</code> - Two ranges of numbers
+                                               
<br><code>[column&gt;100]</code> - Greater than a number
+                                               
<br><code>[column&gt;=100]</code> - Greater than or equal to a number
+                                               <br><code>[column=!123]</code> 
- Not a specific number
+                                               <br>
+                                               <br><b>Date/Calendar fields:</b>
+                                               <br><code>[column=2001]</code> 
- A specific year
+                                               
<br><code>[column=2001.01.01.10.50]</code> - A specific time
+                                               
<br><code>[column=&gt;2001]</code> - After a specific year
+                                               
<br><code>[column=&gt;=2001]</code> - During or after a specific year
+                                               
<br><code>[column=2001-2003.06.30]</code> - A date range
+                                               <br><code>[column=2001 2003 
2005]</code> - Multiple ORed dates
                                        </span>
                                </div>
-                       </th>
-                       <td>
-                               <input name="s" size="50" value='$R{query.s}'>
                        </td>
                </tr>
                <tr>
-                       <th>
+                       <th>View:</th>
+                       <td>
+                               <input name="v" size="50" value='$R{query.v}'>
+                       </td>
+                       <td>
                                <div class="tooltip">
-                                       View <small>(?)</small>:
+                                       <small>(?)</small>
                                        <span class="tooltiptext">
                                                Comma-delimited list of columns 
to display.
-                                               <br>Example: <code>column1, 
column2</code>
+                                               <br>
+                                               
<br><b>Example:</b>&nbsp;&nbsp;<code>[column1, column2]</code>
                                        </span>
                                </div>
-                       </th>
-                       <td>
-                               <input name="v" size="50" value='$R{query.v}'>
                        </td>
                </tr>
                <tr>
-                       <th>
+                       <th>Sort:</th>
+                       <td>
+                               <input name="o" size="50" value='$R{query.o}'>
+                       </td>
+                       <td>
                                <div class="tooltip">
-                                       Sort <small>(?)</small>:
+                                       <small>(?)</small>
                                        <span class="tooltiptext">
                                                Comma-delimited list of columns 
to sort by.
                                                <br>Columns can be suffixed 
with '-' to indicate descending order.
-                                               <br>Example: <code>column1, 
column2-</code>
+                                               <br>
+                                               
<br><b>Example:</b>&nbsp;&nbsp;<code>[column1, column2-]</code>
+                                               <br>
+                                               <br><b>Notes:</b>
+                                               <br> - Columns containing 
collections/arrays/lists are sorted by size.
                                        </span>
                                </div>
-                       </th>
-                       <td>
-                               <input name="o" size="50" value='$R{query.o}'>
                        </td>
                </tr>
                <tr>
-                       <th>
-                               Page:
-                       </th>
+                       <th>Page:</th>
                        <td>
                                Position: <input name='p' type='number' 
style='width:50px' step=20 min=0 value='$R{query.p}'>
                                Limit: <input name='l' type='number' 
style='width:50px' step=20 min=0 value='$R{query.l}'>
-                               Ignore-case: <input name='i' type='checkbox' 
value='true'>
+                               <span style='float:right'>Ignore-case: <input 
name='i' type='checkbox' value='true'></span>
                        </td>
-               </tr>
+                       <td>
+                       </td>
+               </tr> 
                <tr>
                        <th>
                                &nbsp;
                        </th>
-                       <td style='float:right'>
+                       <td colspan='2' style='text-align:right'>
                                <input type='reset' value='Reset'>
                                <input type='button' value='Cancel' 
onclick='getElementById("query").classList.add("hidden")'>
                                <input type="submit" value='Submit'>

Reply via email to