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.common.utils.IOUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.io.*;
23  
24  import org.apache.juneau.*;
25  import org.apache.juneau.collections.*;
26  import org.apache.juneau.http.annotation.*;
27  import org.apache.juneau.rest.annotation.*;
28  import org.apache.juneau.rest.mock.*;
29  import org.apache.juneau.utest.utils.*;
30  import org.junit.jupiter.api.*;
31  
32  class Remote_RequestAnnotation_Test  extends TestBase{
33  
34  	//-----------------------------------------------------------------------------------------------------------------
35  	// Basic tests
36  	//-----------------------------------------------------------------------------------------------------------------
37  
38  	@Rest
39  	public static class A {
40  		@RestOp(path="/{x}")
41  		public String post(@Content Reader r, @Header("X") String h, @Query("x") String q, @Path("x") String p) throws Exception {
42  			return JsonMap.of(
43  				"body",read(r),
44  				"header",h,
45  				"query",q,
46  				"path",p
47  			).toString();
48  		}
49  	}
50  
51  	@Request
52  	public static class A1 {
53  		@Content
54  		public String getBody() {
55  			return "foo";
56  		}
57  		@Header("X")
58  		public String getHeader() {
59  			return "x";
60  		}
61  		@Query("x")
62  		public String getQuery() {
63  			return "x";
64  		}
65  		@Path("x")
66  		public String getPath() {
67  			return "x";
68  		}
69  	}
70  
71  	@Remote
72  	public interface A2 {
73  		@RemoteOp(path="/{x}") String post(A1 req);
74  	}
75  
76  	@Test void a01_basic() {
77  		var x = remote(A.class,A2.class);
78  		assertEquals("{body:'foo',header:'x',query:'x',path:'x'}",x.post(new A1()));
79  		assertEquals("{body:'',header:null,query:null,path:'{x}'}",x.post(null));
80  	}
81  
82  	//-----------------------------------------------------------------------------------------------------------------
83  	// Annotation on parent
84  	//-----------------------------------------------------------------------------------------------------------------
85  
86  	@Rest
87  	public static class B {
88  		@RestOp(path="/{x}")
89  		public String post(@Content Reader r, @Header("X") String h, @Query("x") String q, @Path("x") String p) throws Exception {
90  			return JsonMap.of(
91  				"body",read(r),
92  				"header",h,
93  				"query",q,
94  				"path",p
95  			).toString();
96  		}
97  	}
98  
99  	@Request
100 	public abstract static class B1 {
101 		@Content public abstract String getBody();
102 		@Header("X") public abstract String getHeader();
103 		@Query("x") public abstract String getQuery();
104 		@Path("x") public abstract String getPath();
105 	}
106 
107 	public static class B2 extends B1 {
108 		@Override
109 		public String getBody() {
110 			return "foo";
111 		}
112 		@Override
113 		public String getHeader() {
114 			return "x";
115 		}
116 		@Override
117 		public String getQuery() {
118 			return "x";
119 		}
120 		@Override
121 		public String getPath() {
122 			return "x";
123 		}
124 	}
125 
126 	@Remote
127 	public interface B3 {
128 		@RemoteOp(path="/{x}") String post(B1 req);
129 	}
130 
131 	@Test void b01_annotationOnParent() {
132 		var x = remote(B.class,B3.class);
133 		assertEquals("{body:'foo',header:'x',query:'x',path:'x'}",x.post(new B2()));
134 		assertEquals("{body:'',header:null,query:null,path:'{x}'}",x.post(null));
135 	}
136 
137 	//-----------------------------------------------------------------------------------------------------------------
138 	// Annotation on interface
139 	//-----------------------------------------------------------------------------------------------------------------
140 
141 	@Rest
142 	public static class C {
143 		@RestOp(path="/{x}")
144 		public String post(@Content Reader r, @Header("X") String h, @Query("x") String q, @Path("x") String p) throws Exception {
145 			return JsonMap.of(
146 				"body",read(r),
147 				"header",h,
148 				"query",q,
149 				"path",p
150 			).toString();
151 		}
152 	}
153 
154 	@Request
155 	public interface C1 {
156 		@Content String getBody();
157 		@Header("X") String getHeader();
158 		@Query("x") String getQuery();
159 		@Path("x") String getPath();
160 	}
161 
162 	public static class C2 implements C1 {
163 		@Override
164 		public String getBody() {
165 			return "foo";
166 		}
167 		@Override
168 		public String getHeader() {
169 			return "x";
170 		}
171 		@Override
172 		public String getQuery() {
173 			return "x";
174 		}
175 		@Override
176 		public String getPath() {
177 			return "x";
178 		}
179 	}
180 
181 	@Remote
182 	public interface C3 {
183 		@RemoteOp(path="/{x}") String post(C1 req);
184 	}
185 
186 	@Test void c01_annotationOnInterface() {
187 		var x = remote(C.class,C3.class);
188 		assertEquals("{body:'foo',header:'x',query:'x',path:'x'}",x.post(new C2()));
189 		assertEquals("{body:'',header:null,query:null,path:'{x}'}",x.post(null));
190 	}
191 
192 	//-----------------------------------------------------------------------------------------------------------------
193 	// Annotation on parameter
194 	//-----------------------------------------------------------------------------------------------------------------
195 
196 	@Rest
197 	public static class D {
198 		@RestOp(path="/{x}")
199 		public String post(@Content Reader r, @Header("X") String h, @Query("x") String q, @Path("x") String p) throws Exception {
200 			return JsonMap.of(
201 				"body",read(r),
202 				"header",h,
203 				"query",q,
204 				"path",p
205 			).toString();
206 		}
207 	}
208 
209 	public static class D1 {
210 		@Content
211 		public String getBody() {
212 			return "foo";
213 		}
214 		@Header("X")
215 		public String getHeader() {
216 			return "x";
217 		}
218 		@Query("x")
219 		public String getQuery() {
220 			return "x";
221 		}
222 		@Path("x")
223 		public String getPath() {
224 			return "x";
225 		}
226 	}
227 
228 	@Remote
229 	public interface D2 {
230 		@RemoteOp(path="/{x}") String post(@Request D1 req);
231 	}
232 
233 	@Test void d01_annotationOnParameter() {
234 		var x = remote(D.class,D2.class);
235 		assertEquals("{body:'foo',header:'x',query:'x',path:'x'}",x.post(new D1()));
236 		assertEquals("{body:'',header:null,query:null,path:'{x}'}",x.post(null));
237 	}
238 
239 	//-----------------------------------------------------------------------------------------------------------------
240 	// @Request(partSerializer)
241 	//-----------------------------------------------------------------------------------------------------------------
242 
243 	@Rest
244 	public static class E {
245 		@RestOp(path="/{x}")
246 		public String post(@Content Reader r, @Header("X") String h, @Query("x") String q, @Path("x") String p) throws Exception {
247 			return JsonMap.of(
248 				"body",read(r),
249 				"header",h,
250 				"query",q,
251 				"path",p
252 			).toString();
253 		}
254 	}
255 
256 	@Request(serializer=FakeWriterSerializer.X.class)
257 	public static class E1 {
258 		@Content
259 		public String getBody() {
260 			return "foo";
261 		}
262 		@Header("X")
263 		public String getHeader() {
264 			return "x";
265 		}
266 		@Query("x")
267 		public String getQuery() {
268 			return "x";
269 		}
270 		@Path("x")
271 		public String getPath() {
272 			return "x";
273 		}
274 	}
275 
276 	@Remote
277 	public interface E2 {
278 		@RemoteOp(path="/{x}") String post(E1 req);
279 	}
280 
281 	@Test void e01_partSerializer() {
282 		var x = remote(E.class,E2.class);
283 		assertEquals("{body:'foo',header:'xxx',query:'xxx',path:'xxx'}",x.post(new E1()));
284 		assertEquals("{body:'',header:null,query:null,path:'{x}'}",x.post(null));
285 	}
286 
287 	//------------------------------------------------------------------------------------------------------------------
288 	// Helper methods.
289 	//------------------------------------------------------------------------------------------------------------------
290 
291 	private static <T> T remote(Class<?> rest, Class<T> t) {
292 		return MockRestClient.build(rest).getRemote(t);
293 	}
294 }