View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.http.remote;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.apache.juneau.common.utils.IOUtils.*;
21  import static org.apache.juneau.http.HttpParts.*;
22  import static org.junit.jupiter.api.Assertions.*;
23  
24  import java.io.*;
25  import java.util.*;
26  
27  import org.apache.http.*;
28  import org.apache.http.entity.*;
29  import org.apache.juneau.*;
30  import org.apache.juneau.http.annotation.*;
31  import org.apache.juneau.http.annotation.Header;
32  import org.apache.juneau.http.part.*;
33  import org.apache.juneau.json.*;
34  import org.apache.juneau.marshaller.*;
35  import org.apache.juneau.rest.annotation.*;
36  import org.apache.juneau.rest.config.*;
37  import org.apache.juneau.rest.mock.*;
38  import org.junit.jupiter.api.*;
39  
40  /**
41   * Tests the @Body annotation.
42   */
43  class Remote_ContentAnnotation_Test extends TestBase {
44  
45  	//------------------------------------------------------------------------------------------------------------------
46  	// Helpers
47  	//------------------------------------------------------------------------------------------------------------------
48  
49  	public static class Bean {
50  		public int f;
51  
52  		public static Bean create() {
53  			var b = new Bean();
54  			b.f = 1;
55  			return b;
56  		}
57  
58  		@Override
59  		public String toString() {
60  			return Json5.of(this);
61  		}
62  	}
63  
64  	//-----------------------------------------------------------------------------------------------------------------
65  	// Basic tests - JSON
66  	//-----------------------------------------------------------------------------------------------------------------
67  
68  	@Rest(parsers=JsonParser.class)
69  	public static class A {
70  		@RestPost
71  		public String x1(@Content int b, @Header("Content-Type") String ct) {
72  			assertEquals("application/json",ct);
73  			return String.valueOf(b);
74  		}
75  
76  		@RestPost
77  		public String x2(@Content float b, @Header("Content-Type") String ct) {
78  			assertEquals("application/json",ct);
79  			return String.valueOf(b);
80  		}
81  
82  		@RestPost
83  		public String x3(@Content Bean b, @Header("Content-Type") String ct) {
84  			assertEquals("application/json",ct);
85  			return Json5Serializer.DEFAULT.toString(b);
86  		}
87  
88  		@RestPost
89  		public String x4(@Content Bean[] b, @Header("Content-Type") String ct) {
90  			assertEquals("application/json",ct);
91  			return Json5Serializer.DEFAULT.toString(b);
92  		}
93  
94  		@RestPost
95  		public String x5(@Content List<Bean> b, @Header("Content-Type") String ct) {
96  			assertEquals("application/json",ct);
97  			return Json5Serializer.DEFAULT.toString(b);
98  		}
99  
100 		@RestPost
101 		public String x6(@Content Map<String,Bean> b, @Header("Content-Type") String ct) {
102 			assertEquals("application/json",ct);
103 			return Json5Serializer.DEFAULT.toString(b);
104 		}
105 
106 		@RestPost
107 		public String x7(@Content Reader b, @Header("Content-Type") String ct) throws Exception {
108 			assertEquals("text/plain",ct);
109 			return read(b);
110 		}
111 
112 		@RestPost
113 		public String x8(@Content InputStream b, @Header("Content-Type") String ct) throws Exception {
114 			assertEquals("application/octet-stream",ct);
115 			return read(b);
116 		}
117 
118 		@RestPost
119 		public String x9(@Content Reader b, @Header("Content-Type") String ct) throws Exception {
120 			assertTrue(ct.startsWith("text/plain"));
121 			return read(b);
122 		}
123 
124 		@RestPost
125 		public String x10(@Content Reader b, @Header("Content-Type") String ct) throws IOException {
126 			assertEquals("application/x-www-form-urlencoded",ct);
127 			return read(b);
128 		}
129 	}
130 
131 	@Remote
132 	public interface A1 {
133 		String postX1(@Content int b);
134 		String postX2(@Content float b);
135 		String postX3(@Content Bean b);
136 		String postX4(@Content Bean[] b);
137 		String postX5(@Content List<Bean> b);
138 		String postX6(@Content Map<String,Bean> b);
139 		String postX7(@Content Reader b);
140 		String postX8(@Content InputStream b);
141 		String postX9(@Content HttpEntity b);
142 		String postX10(@Content PartList b);
143 	}
144 
145 	@Test void a01_objectTypes_json() throws Exception {
146 		var x = MockRestClient.create(A.class).serializer(JsonSerializer.class).build().getRemote(A1.class);
147 		assertEquals("1",x.postX1(1));
148 		assertEquals("1.0",x.postX2(1f));
149 		assertEquals("{f:1}",x.postX3(Bean.create()));
150 		assertEquals("[{f:1}]",x.postX4(new Bean[]{Bean.create()}));
151 		assertEquals("[{f:1}]",x.postX5(alist(Bean.create())));
152 		assertEquals("{k1:{f:1}}",x.postX6(map("k1",Bean.create())));
153 		assertEquals("xxx",x.postX7(reader("xxx")));
154 		assertEquals("xxx",x.postX8(inputStream("xxx")));
155 		assertEquals("xxx",x.postX9(new StringEntity("xxx")));
156 		assertEquals("foo=bar",x.postX10(partList("foo","bar")));
157 	}
158 
159 	//-----------------------------------------------------------------------------------------------------------------
160 	// Basic tests - OpenAPI
161 	//-----------------------------------------------------------------------------------------------------------------
162 
163 	@Rest
164 	public static class B implements BasicOpenApiConfig {
165 		@RestPost
166 		public Object x1(@Content int b, @Header("Content-Type") String ct) {
167 			assertEquals("text/openapi",ct);
168 			return b;
169 		}
170 
171 		@RestPost
172 		public Object x2(@Content float b, @Header("Content-Type") String ct) {
173 			assertEquals("text/openapi",ct);
174 			return b;
175 		}
176 
177 		@RestPost
178 		public String x3(@Content Bean b, @Header("Content-Type") String ct) {
179 			assertEquals("text/openapi",ct);
180 			return Json5.of(b);
181 		}
182 
183 		@RestPost
184 		public Object x4(@Content Bean[] b, @Header("Content-Type") String ct) {
185 			assertEquals("text/openapi",ct);
186 			return Json5.of(b);
187 		}
188 
189 		@RestPost
190 		public Object x5(@Content List<Bean> b, @Header("Content-Type") String ct) {
191 			assertEquals("text/openapi",ct);
192 			return Json5.of(b);
193 		}
194 
195 		@RestPost
196 		public Object x6(@Content Map<String,Bean> b, @Header("Content-Type") String ct) {
197 			assertEquals("text/openapi",ct);
198 			return Json5.of(b);
199 		}
200 
201 		@RestPost
202 		public Object x7(@Content Reader b, @Header("Content-Type") String ct) {
203 			assertEquals("text/plain",ct);
204 			return b;
205 		}
206 
207 		@RestPost
208 		public Object x8(@Content InputStream b, @Header("Content-Type") String ct) {
209 			assertEquals("application/octet-stream",ct);
210 			return b;
211 		}
212 
213 		@RestPost
214 		public Object x9(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
215 			assertEquals("text/plain",ct);
216 			return b;
217 		}
218 
219 		@RestPost
220 		public Object x10(@Content Reader b, @Header("Content-Type") String ct) {
221 			assertEquals("application/x-www-form-urlencoded",ct);
222 			return b;
223 		}
224 	}
225 	@Remote
226 	public interface B1 {
227 		String postX1(@Content int b);
228 		String postX2(@Content float b);
229 		String postX3(@Content Bean b);
230 		String postX4(@Content Bean[] b);
231 		String postX5(@Content List<Bean> b);
232 		String postX6(@Content Map<String,Bean> b);
233 		String postX7(@Content Reader b);
234 		String postX8(@Content InputStream b);
235 		String postX9(@Content HttpEntity b);
236 		String postX10(@Content PartList b);
237 	}
238 
239 	@Test void b01_objectTypes_openApi() throws Exception {
240 		var x = MockRestClient.create(B.class).openApi().contentType(null).build().getRemote(B1.class);
241 		assertEquals("1",x.postX1(1));
242 		assertEquals("1.0",x.postX2(1f));
243 		assertEquals("{f:1}",x.postX3(Bean.create()));
244 		assertEquals("[{f:1}]",x.postX4(new Bean[]{Bean.create()}));
245 		assertEquals("[{f:1}]",x.postX5(alist(Bean.create())));
246 		assertEquals("{k1:{f:1}}",x.postX6(map("k1",Bean.create())));
247 		assertEquals("xxx",x.postX7(reader("xxx")));
248 		assertEquals("xxx",x.postX8(inputStream("xxx")));
249 		assertEquals("xxx",x.postX9(new StringEntity("xxx",org.apache.http.entity.ContentType.create("text/plain"))));
250 		assertEquals("foo=bar",x.postX10(partList("foo","bar")));
251 	}
252 
253 	//-----------------------------------------------------------------------------------------------------------------
254 	// Basic tests - OpenAPI, overridden Content-Type
255 	//-----------------------------------------------------------------------------------------------------------------
256 
257 	@Rest
258 	public static class C {
259 		@RestPost
260 		public Reader x1(@Content Reader b, @Header("Content-Type") String ct) {
261 			assertEquals("text/foo",ct);
262 			return b;
263 		}
264 		@RestPost
265 		public Reader x2(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
266 			assertEquals("text/foo",ct);
267 			return b;
268 		}
269 		@RestPost
270 		public Reader x3(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
271 			assertEquals("text/foo",ct);
272 			return b;
273 		}
274 		@RestPost
275 		public Reader x5(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
276 			assertEquals("text/foo",ct);
277 			return b;
278 		}
279 		@RestPost
280 		public Reader x6(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
281 			assertEquals("text/foo",ct);
282 			return b;
283 		}
284 		@RestPost
285 		public Reader x7(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
286 			assertEquals("text/foo",ct);
287 			return b;
288 		}
289 		@RestPost
290 		public Reader x8(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
291 			assertEquals("text/foo",ct);
292 			return b;
293 		}
294 		@RestPost
295 		public Reader x9(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
296 			assertEquals("text/foo",ct);
297 			return b;
298 		}
299 		@RestPost
300 		public Reader x10(@Content Reader b, @Header("Content-Type") String ct) {  // NOSONAR
301 			assertEquals("text/foo",ct);
302 			return b;
303 		}
304 	}
305 	@Remote
306 	public interface C1 {
307 		String postX1(@Content int b);
308 		String postX2(@Content float b);
309 		String postX3(@Content Bean b);
310 		String postX4(@Content Bean[] b);
311 		String postX5(@Content List<Bean> b);
312 		String postX6(@Content Map<String,Bean> b);
313 		String postX7(@Content Reader b);
314 		String postX8(@Content InputStream b);
315 		String postX9(@Content HttpEntity b);
316 		String postX10(@Content PartList b);
317 	}
318 
319 	@Test void c01_openApi_overriddenContentType() throws Exception {
320 		var x = MockRestClient.create(C.class).parser(JsonParser.class).contentType("text/foo").build().getRemote(C1.class);
321 		assertEquals("1",x.postX1(1));
322 		assertEquals("1.0",x.postX2(1f));
323 		assertEquals("{f:1}",x.postX3(Bean.create()));
324 		assertEquals("[{f:1}]",x.postX5(alist(Bean.create())));
325 		assertEquals("{k1={f:1}}",x.postX6(map("k1",Bean.create())));
326 		assertEquals("xxx",x.postX7(reader("xxx")));
327 		assertEquals("xxx",x.postX8(inputStream("xxx")));
328 		assertEquals("xxx",x.postX9(new StringEntity("xxx",org.apache.http.entity.ContentType.create("text/plain"))));
329 		assertEquals("foo=bar",x.postX10(partList("foo","bar")));
330 	}
331 }