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.http.annotation; 014 015import static java.lang.annotation.ElementType.*; 016import static java.lang.annotation.RetentionPolicy.*; 017 018import java.lang.annotation.*; 019 020import org.apache.juneau.annotation.*; 021import org.apache.juneau.httppart.*; 022import org.apache.juneau.oapi.*; 023 024/** 025 * REST request form-data annotation. 026 * 027 * <p> 028 * Identifies a POJO to be used as a form-data entry on an HTTP request. 029 * 030 * <p> 031 * Can be used in the following locations: 032 * <ul> 033 * <li>Arguments and argument-types of server-side <ja>@RestOp</ja>-annotated methods. 034 * <li>Arguments and argument-types of client-side <ja>@RemoteResource</ja>-annotated interfaces. 035 * <li>Methods and return types of server-side and client-side <ja>@Request</ja>-annotated interfaces. 036 * </ul> 037 * 038 * <h5 class='topic'>Arguments and argument-types of server-side @RestOp-annotated methods</h5> 039 * <p> 040 * Annotation that can be applied to a parameter of a <ja>@RestOp</ja>-annotated method to identify it as a form-data parameter. 041 * 042 * <h5 class='section'>Example:</h5> 043 * <p class='bjava'> 044 * <ja>@RestPost</ja> 045 * <jk>public void</jk> doPost( 046 * <ja>@FormData</ja>(<js>"p1"</js>) <jk>int</jk> <jv>p1</jv>, 047 * <ja>@FormData</ja>(<js>"p2"</js>) String <jv>p2</jv>, 048 * <ja>@FormData</ja>(<js>"p3"</js>) UUID <jv>p3</jv> 049 * ) {...} 050 * </p> 051 * 052 * <p> 053 * This is functionally equivalent to the following code... 054 * <p class='bjava'> 055 * <ja>@RestPost</ja> 056 * <jk>public void</jk> doPost(RestRequest <jv>req</jv>) { 057 * <jk>int</jk> <jv>p1</jv> = <jv>req</jv>.getFormParam(<js>"p1"</js>).as(<jk>int</jk>.<jk>class</jk>).orElse(0); 058 * String <jv>p2</jv> = <jv>req</jv>.getFormParam(<js>"p2"</js>).asString().orElse(<jk>null</jk>); 059 * UUID <jv>p3</jv> = <jv>req</jv>.getFormParam(<js>"p3"</js>).as(UUID.<jk>class</jk>).orElse(<jk>null</jk>); 060 * ... 061 * } 062 * </p> 063 * 064 * <h5 class='section'>See Also:</h5><ul> 065 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.Swagger">Swagger</a> 066 * <li class='extlink'><a class='doclink' href='https://swagger.io/specification/v2#parameterObject'>Swagger Parameter Object</a> 067 * </ul> 068 * 069 * <h5 class='topic'>Important note concerning FORM posts</h5> 070 * <p> 071 * This annotation should not be combined with the {@link Content @Content} annotation or <c>RestRequest.getContent()</c> method 072 * for <c>application/x-www-form-urlencoded POST</c> posts, since it will trigger the underlying servlet 073 * API to parse the body content as key-value pairs resulting in empty content. 074 * 075 * <p> 076 * The {@link Query @Query} annotation can be used to retrieve a URL parameter in the URL string without triggering the 077 * servlet to drain the body content. 078 * 079 * <h5 class='topic'>Arguments and argument-types of client-side @RemoteResource-annotated interfaces</h5> 080 * <p> 081 * Annotation applied to Java method arguments of interface proxies to denote that they are FORM post parameters on the 082 * request. 083 * 084 * <h5 class='section'>See Also:</h5><ul> 085 * <li class='link'><a class="doclink" href="../../../../../index.html#jrc.FormData">@FormData</a> 086 * <li class='link'><a class="doclink" href="../../../../../index.html#jrc.Request">@Request</a> 087 * </ul> 088 * 089 * <h5 class='topic'>Methods and return types of server-side and client-side @Request-annotated interfaces</h5> 090 * <p> 091 * <h5 class='section'>See Also:</h5><ul> 092 * <li class='link'><a class="doclink" href="../../../../../index.html#jrc.Request">@Request</a> 093 * </ul> 094 * 095 * <div class='warn'> 096 * This annotation should not be combined with the {@link Content @Content} annotation or <c>RestRequest#getContent()</c> method 097 * for <c>application/x-www-form-urlencoded POST</c> posts, since it will trigger the underlying servlet 098 * API to parse the body content as key-value pairs resulting in empty content. 099 * <br>The {@link Query @Query} annotation can be used to retrieve a URL parameter in the URL string without triggering the 100 * servlet to drain the body content. 101 * </div> 102 * <div class='warn'> 103 * If using this annotation on a Spring bean, note that you are likely to encounter issues when using on parameterized 104 * types such as <code>List<MyBean></code>. This is due to the fact that Spring uses CGLIB to recompile classes 105 * at runtime, and CGLIB was written before generics were introduced into Java and is a virtually-unsupported library. 106 * Therefore, parameterized types will often be stripped from class definitions and replaced with unparameterized types 107 * (e.g. <code>List</code>). Under these circumstances, you are likely to get <code>ClassCastExceptions</code> 108 * when trying to access generalized <code>JsonMaps</code> as beans. The best solution to this issue is to either 109 * specify the parameter as a bean array (e.g. <code>MyBean[]</code>) or declare the method as final so that CGLIB 110 * will not try to recompile it. 111 * </div> 112 * 113 * <h5 class='section'>See Also:</h5><ul> 114 115 * </ul> 116 */ 117@Documented 118@Target({PARAMETER,METHOD,TYPE,FIELD}) 119@Retention(RUNTIME) 120@Inherited 121@Repeatable(FormDataAnnotation.Array.class) 122@ContextApply(FormDataAnnotation.Applier.class) 123public @interface FormData { 124 125 /** 126 * Default value for this parameter. 127 * 128 * @return The annotation value. 129 */ 130 String def() default ""; 131 132 /** 133 * FORM parameter name. 134 * 135 * <p> 136 * The name of the parameter (required). 137 * 138 * <p> 139 * The value should be either a valid form parameter name, or <js>"*"</js> to represent multiple name/value pairs 140 * 141 * <p> 142 * A blank value (the default) has the following behavior: 143 * <ul class='spaced-list'> 144 * <li> 145 * If the data type is <c>NameValuePairs</c>, <c>Map</c>, or a bean, 146 * then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs. 147 * 148 * <h5 class='figure'>Examples:</h5> 149 * <p class='bjava'> 150 * <jc>// When used on a REST method</jc> 151 * <ja>@RestPost</ja>(<js>"/addPet"</js>) 152 * <jk>public void</jk> addPet(<ja>@FormData</ja> JsonMap <jv>allFormDataParameters</jv>) {...} 153 * </p> 154 * <p class='bjava'> 155 * <jc>// When used on a remote method parameter</jc> 156 * <ja>@RemoteResource</ja>(path=<js>"/myproxy"</js>) 157 * <jk>public interface</jk> MyProxy { 158 * 159 * <jc>// Equivalent to @FormData("*")</jc> 160 * <ja>@RemotePost</ja>(<js>"/mymethod"</js>) 161 * String myProxyMethod1(<ja>@FormData</ja> Map<String,Object> <jv>allFormDataParameters</jv>); 162 * } 163 * </p> 164 * <p class='bjava'> 165 * <jc>// When used on a request bean method</jc> 166 * <jk>public interface</jk> MyRequest { 167 * 168 * <jc>// Equivalent to @FormData("*")</jc> 169 * <ja>@FormData</ja> 170 * Map<String,Object> getFoo(); 171 * } 172 * </p> 173 * </li> 174 * <li> 175 * If used on a request bean method, uses the bean property name. 176 * 177 * <h5 class='figure'>Example:</h5> 178 * <p class='bjava'> 179 * <jk>public interface</jk> MyRequest { 180 * 181 * <jc>// Equivalent to @FormData("foo")</jc> 182 * <ja>@FormData</ja> 183 * String getFoo(); 184 * } 185 * </p> 186 * </li> 187 * </ul> 188 * 189 * <h5 class='section'>Notes:</h5><ul> 190 * <li class='note'> 191 * The format is plain-text. 192 * </ul> 193 * 194 * @return The annotation value. 195 */ 196 String name() default ""; 197 198 /** 199 * Dynamically apply this annotation to the specified classes. 200 * 201 * <h5 class='section'>See Also:</h5><ul> 202 * <li class='link'><a class="doclink" href="../../../../../index.html#jm.DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a> 203 * </ul> 204 * 205 * @return The annotation value. 206 */ 207 String[] on() default {}; 208 209 /** 210 * Dynamically apply this annotation to the specified classes. 211 * 212 * <p> 213 * Identical to {@link #on()} except allows you to specify class objects instead of a strings. 214 * 215 * <h5 class='section'>See Also:</h5><ul> 216 * <li class='link'><a class="doclink" href="../../../../../index.html#jm.DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a> 217 * </ul> 218 * 219 * @return The annotation value. 220 */ 221 Class<?>[] onClass() default {}; 222 223 /** 224 * Specifies the {@link HttpPartParser} class used for parsing strings to values. 225 * 226 * <p> 227 * Overrides for this part the part parser defined on the REST resource which by default is {@link OpenApiParser}. 228 * 229 * @return The annotation value. 230 */ 231 Class<? extends HttpPartParser> parser() default HttpPartParser.Void.class; 232 233 /** 234 * <mk>schema</mk> field of the <a class='doclink' href='https://swagger.io/specification/v2#parameterObject'>Swagger Parameter Object</a>. 235 * 236 * <p> 237 * The schema defining the type used for parameter. 238 * 239 * <p> 240 * The {@link Schema @Schema} annotation can also be used standalone on the parameter or type. 241 * Values specified on this field override values specified on the type, and values specified on child types override values 242 * specified on parent types. 243 * 244 * <h5 class='section'>Used for:</h5> 245 * <ul class='spaced-list'> 246 * <li> 247 * Server-side schema-based parsing and parsing validation. 248 * <li> 249 * Server-side generated Swagger documentation. 250 * <li> 251 * Client-side schema-based serializing and serializing validation. 252 * </ul> 253 * 254 * @return The annotation value. 255 */ 256 Schema schema() default @Schema; 257 258 /** 259 * Specifies the {@link HttpPartSerializer} class used for serializing values to strings. 260 * 261 * <p> 262 * Overrides for this part the part serializer defined on the REST client which by default is {@link OpenApiSerializer}. 263 * 264 * @return The annotation value. 265 */ 266 Class<? extends HttpPartSerializer> serializer() default HttpPartSerializer.Void.class; 267 268 /** 269 * A synonym for {@link #name()}. 270 * 271 * <p> 272 * Allows you to use shortened notation if you're only specifying the name. 273 * 274 * <p> 275 * The following are completely equivalent ways of defining a form post entry: 276 * <p class='bjava'> 277 * <jk>public</jk> Order placeOrder(<ja>@FormData</ja>(name=<js>"petId"</js>) <jk>long</jk> <jv>petId</jv>) {...} 278 * </p> 279 * <p class='bjava'> 280 * <jk>public</jk> Order placeOrder(<ja>@FormData</ja>(<js>"petId"</js>) <jk>long</jk> <jv>petId</jv>) {...} 281 * </p> 282 * 283 * @return The annotation value. 284 */ 285 String value() default ""; 286}