001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.remoteable; 014 015import static java.lang.annotation.ElementType.*; 016import static java.lang.annotation.RetentionPolicy.*; 017 018import java.lang.annotation.*; 019 020import org.apache.juneau.httppart.*; 021import org.apache.juneau.urlencoding.*; 022 023/** 024 * Annotation applied to Java method arguments of interface proxies to denote that they are FORM post parameters on the 025 * request. 026 * 027 * <h5 class='section'>Example:</h5> 028 * <p class='bcode'> 029 * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) 030 * <jk>public interface</jk> MyProxy { 031 * 032 * <jc>// Explicit names specified for form data parameters.</jc> 033 * <jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc> 034 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1"</js>) 035 * String myProxyMethod1(<ja>@FormData</ja>(<js>"foo"</js>)</ja> String foo, 036 * <ja>@FormData</ja>(<js>"bar"</js>)</ja> MyPojo pojo); 037 * 038 * <jc>// Multiple values pulled from a NameValuePairs object.</jc> 039 * <jc>// Same as @FormData("*").</jc> 040 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod2"</js>) 041 * String myProxyMethod2(<ja>@FormData</ja> NameValuePairs nameValuePairs); 042 * 043 * <jc>// Multiple values pulled from a Map.</jc> 044 * <jc>// Same as @FormData("*").</jc> 045 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod3"</js>) 046 * String myProxyMethod3(<ja>@FormData</ja> Map<String,Object> map); 047 * 048 * <jc>// Multiple values pulled from a bean.</jc> 049 * <jc>// Same as @FormData("*").</jc> 050 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod4"</js>) 051 * String myProxyMethod4(<ja>@FormData</ja> MyBean myBean); 052 * 053 * <jc>// An entire form-data HTTP body as a String.</jc> 054 * <jc>// Same as @FormData("*").</jc> 055 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod5"</js>) 056 * String myProxyMethod5(<ja>@FormData</ja> String string); 057 * 058 * <jc>// An entire form-data HTTP body as a Reader.</jc> 059 * <jc>// Same as @FormData("*").</jc> 060 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod6"</js>) 061 * String myProxyMethod6(<ja>@FormData</ja> Reader reader); 062 * 063 * } 064 * </p> 065 * 066 * <p> 067 * The annotation can also be applied to a bean property field or getter when the argument is annotated with 068 * {@link RequestBean @RequestBean}: 069 * 070 * <h5 class='section'>Example:</h5> 071 * <p class='bcode'> 072 * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) 073 * <jk>public interface</jk> MyProxy { 074 * 075 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod"</js>) 076 * String myProxyMethod(<ja>@RequestBean</ja> MyRequestBean bean); 077 * } 078 * 079 * <jk>public interface</jk> MyRequestBean { 080 * 081 * <jc>// Name explicitly specified.</jc> 082 * <ja>@FormData</ja>(<js>"foo"</js>) 083 * String getX(); 084 * 085 * <jc>// Name inherited from bean property.</jc> 086 * <jc>// Same as @FormData("bar")</jc> 087 * <ja>@FormData</ja> 088 * String getBar(); 089 * 090 * <jc>// Name inherited from bean property.</jc> 091 * <jc>// Same as @FormData("baz")</jc> 092 * <ja>@FormData</ja> 093 * <ja>@BeanProperty</ja>(<js>"baz"</js>) 094 * String getY(); 095 * 096 * <jc>// Multiple values pulled from NameValuePairs object.</jc> 097 * <jc>// Same as @FormData("*")</jc> 098 * <ja>@FormData</ja> 099 * NameValuePairs getNameValuePairs(); 100 * 101 * <jc>// Multiple values pulled from Map.</jc> 102 * <jc>// Same as @FormData("*")</jc> 103 * <ja>@FormData</ja> 104 * Map<String,Object> getMap(); 105 * 106 * <jc>// Multiple values pulled from bean.</jc> 107 * <jc>// Same as @FormData("*")</jc> 108 * <ja>@FormData</ja> 109 * MyBean getMyBean(); 110 * 111 * <jc>// An entire form-data HTTP body as a Reader.</jc> 112 * <jc>// Same as @FormData("*")</jc> 113 * <ja>@FormData</ja> 114 * Reader getReader(); 115 * } 116 * </p> 117 * 118 * <p> 119 * The {@link #name()} and {@link #value()} elements are synonyms for specifying the parameter name. 120 * Only one should be used. 121 * <br>The following annotations are fully equivalent: 122 * <p class='bcode'> 123 * <ja>@FormData</ja>(name=<js>"foo"</js>) 124 * 125 * <ja>@FormData</ja>(<js>"foo"</js>) 126 * </p> 127 * 128 * <h5 class='section'>See Also:</h5> 129 * <ul class='doctree'> 130 * <li class='link'><a class='doclink' href='../../../../overview-summary.html#juneau-rest-client.3rdPartyProxies'>Overview > juneau-rest-client > Interface Proxies Against 3rd-party REST Interfaces</a> 131 * </ul> 132 */ 133@Documented 134@Target({PARAMETER,FIELD,METHOD}) 135@Retention(RUNTIME) 136@Inherited 137public @interface FormData { 138 139 /** 140 * The form post parameter name. 141 * 142 * <p> 143 * Note that {@link #name()} and {@link #value()} are synonyms. 144 * 145 * <p> 146 * The value should be either <js>"*"</js> to represent multiple name/value pairs, or a label that defines the 147 * form data parameter name. 148 * 149 * <p> 150 * A blank value (the default) has the following behavior: 151 * <ul class='spaced-list'> 152 * <li> 153 * If the data type is <code>NameValuePairs</code>, <code>Map</code>, or a bean, 154 * then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs. 155 * 156 * <h5 class='figure'>Example:</h5> 157 * <p class='bcode'> 158 * <jc>// When used on a remote method parameter</jc> 159 * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) 160 * <jk>public interface</jk> MyProxy { 161 * 162 * <jc>// Equivalent to @FormData("*")</jc> 163 * <ja>@RemoteMethod</ja>(path=<js>"/mymethod"</js>) 164 * String myProxyMethod1(<ja>@FormData</ja> Map<String,Object> formData); 165 * } 166 * 167 * <jc>// When used on a request bean method</jc> 168 * <jk>public interface</jk> MyRequestBean { 169 * 170 * <jc>// Equivalent to @FormData("*")</jc> 171 * <ja>@FormData</ja> 172 * Map<String,Object> getFoo(); 173 * } 174 * </p> 175 * </li> 176 * <li> 177 * If used on a request bean method, uses the bean property name. 178 * 179 * <h5 class='figure'>Example:</h5> 180 * <p class='bcode'> 181 * <jk>public interface</jk> MyRequestBean { 182 * 183 * <jc>// Equivalent to @FormData("foo")</jc> 184 * <ja>@FormData</ja> 185 * String getFoo(); 186 * } 187 * </p> 188 * </li> 189 * </ul> 190 */ 191 String name() default ""; 192 193 /** 194 * A synonym for {@link #name()}. 195 * 196 * <p> 197 * Allows you to use shortened notation if you're only specifying the name. 198 */ 199 String value() default ""; 200 201 /** 202 * Skips this value if it's an empty string or empty collection/array. 203 * 204 * <p> 205 * Note that <jk>null</jk> values are already ignored. 206 */ 207 boolean skipIfEmpty() default false; 208 209 /** 210 * Specifies the {@link HttpPartSerializer} class used for serializing values to strings. 211 * 212 * <p> 213 * The default value defaults to the using the part serializer defined on the {@link RequestBean @RequestBean} annotation, 214 * then on the client which by default is {@link UrlEncodingSerializer}. 215 * 216 * <p> 217 * This annotation is provided to allow values to be custom serialized. 218 */ 219 Class<? extends HttpPartSerializer> serializer() default HttpPartSerializer.Null.class; 220}