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.rest.client;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import org.apache.juneau.*;
23  import org.apache.juneau.http.annotation.*;
24  import org.apache.juneau.http.header.*;
25  import org.apache.juneau.marshaller.*;
26  import org.apache.juneau.rest.annotation.*;
27  import org.apache.juneau.rest.mock.*;
28  import org.apache.juneau.rest.servlet.*;
29  import org.junit.jupiter.api.*;
30  
31  public class RestClient_Marshalls_Test extends TestBase {
32  
33  	public static class Bean {
34  		public int f;
35  
36  		public static Bean create() {
37  			var b = new Bean();
38  			b.f = 1;
39  			return b;
40  		}
41  
42  		public void check() {
43  			assertEquals(1, f);
44  		}
45  
46  		@Override
47  		public String toString() {
48  			return Json5.of(this);
49  		}
50  	}
51  
52  	public static Bean bean = Bean.create();
53  
54  	@Rest
55  	public static class A extends BasicRestObject {
56  		@RestPost
57  		public Bean a01(@Content Bean b, @Header("Accept") String accept, @Header("Content-Type") String ct, @Header("X-Accept") String xaccept, @Header("X-Content-Type") String xct) {
58  			assertEquals(nn(xaccept), nn(accept), "Accept doesn't match");
59  			assertEquals(nn(xct), nn(ct), "Content-Type doesn't match");
60  			return b;
61  		}
62  	}
63  
64  	private static String nn(String s) {
65  		return s == null ? "nil" : s;
66  	}
67  
68  	//------------------------------------------------------------------------------------------------------------------
69  	// Basic tests - Single language support
70  	//------------------------------------------------------------------------------------------------------------------
71  
72  	@Test void a01_singleLanguages() throws Exception {
73  		var x1 = client().json5().build();
74  		var x2 = client().json().build();
75  		var x3 = client().xml().build();
76  		var x4 = client().html().build();
77  		var x5 = client().plainText().build();
78  		var x6 = client().msgPack().build();
79  		var x7 = client().uon().build();
80  		var x8 = client().urlEnc().build();
81  		var x9 = client().openApi().build();
82  		var x10 = client().htmlDoc().build();
83  		var x11 = client().htmlStrippedDoc().build();
84  		x1.post("/a01",bean).header("X-Accept","application/json5").header("X-Content-Type","application/json5").run().assertStatus(200).getContent().as(Bean.class).check();
85  		x2.post("/a01",bean).header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
86  		x3.post("/a01",bean).header("X-Accept","text/xml").header("X-Content-Type","text/xml").run().assertStatus(200).getContent().as(Bean.class).check();
87  		x4.post("/a01",bean).header("X-Accept","text/html").header("X-Content-Type","text/html").run().assertStatus(200).getContent().as(Bean.class).check();
88  		x5.post("/a01",bean).header("X-Accept","text/plain").header("X-Content-Type","text/plain").run().assertStatus(200).getContent().as(Bean.class).check();
89  		x6.post("/a01",bean).header("X-Accept","octal/msgpack").header("X-Content-Type","octal/msgpack").run().assertStatus(200).getContent().as(Bean.class).check();
90  		x7.post("/a01",bean).header("X-Accept","text/uon").header("X-Content-Type","text/uon").run().assertStatus(200).getContent().as(Bean.class).check();
91  		x8.post("/a01",bean).header("X-Accept","application/x-www-form-urlencoded").header("X-Content-Type","application/x-www-form-urlencoded").run().assertStatus(200).getContent().as(Bean.class).check();
92  		x9.post("/a01",bean).header("X-Accept","text/openapi").header("X-Content-Type","text/openapi").run().assertStatus(200).getContent().as(Bean.class).check();
93  		x10.post("/a01",bean).header("X-Accept","text/html").header("X-Content-Type","text/html").run().assertStatus(200).getContent().as(Bean.class).check();
94  		x11.post("/a01",bean).header("X-Accept","text/html").header("X-Content-Type","text/html+stripped").run().assertStatus(200).getContent().as(Bean.class).check();
95  
96  		// With override
97  		x1.post("/a01",bean).header("Accept","application/json").header("Content-Type","application/json").header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
98  	}
99  
100 	@Test void a02_singleLanguages_perRequest() throws Exception {
101 		var x = client().build();
102 		x.post("/a01",bean).header("X-Accept","application/json5").header("X-Content-Type","application/json5").json5().run().assertStatus(200).getContent().as(Bean.class).check();
103 		x.post("/a01",bean).header("X-Accept","application/json").header("X-Content-Type","application/json").json().run().assertStatus(200).getContent().as(Bean.class).check();
104 		x.post("/a01",bean).header("X-Accept","text/xml").header("X-Content-Type","text/xml").xml().run().assertStatus(200).getContent().as(Bean.class).check();
105 		x.post("/a01",bean).header("X-Accept","text/html").header("X-Content-Type","text/html").html().run().assertStatus(200).getContent().as(Bean.class).check();
106 		x.post("/a01",bean).header("X-Accept","text/plain").header("X-Content-Type","text/plain").plainText().run().assertStatus(200).getContent().as(Bean.class).check();
107 		x.post("/a01",bean).header("X-Accept","octal/msgpack").header("X-Content-Type","octal/msgpack").msgPack().run().assertStatus(200).getContent().as(Bean.class).check();
108 		x.post("/a01",bean).header("X-Accept","text/uon").header("X-Content-Type","text/uon").uon().run().assertStatus(200).getContent().as(Bean.class).check();
109 		x.post("/a01",bean).header("X-Accept","application/x-www-form-urlencoded").header("X-Content-Type","application/x-www-form-urlencoded").urlEnc().run().assertStatus(200).getContent().as(Bean.class).check();
110 		x.post("/a01",bean).header("X-Accept","text/openapi").header("X-Content-Type","text/openapi").openApi().run().assertStatus(200).getContent().as(Bean.class).check();
111 		x.post("/a01",bean).header("X-Accept","text/html").header("X-Content-Type","text/html").htmlDoc().run().assertStatus(200).getContent().as(Bean.class).check();
112 		x.post("/a01",bean).header("X-Accept","text/html").header("X-Content-Type","text/html+stripped").htmlStrippedDoc().run().assertStatus(200).getContent().as(Bean.class).check();
113 	}
114 
115 	@Test void a03_noLanguages() throws Exception {
116 		var x = client().build();
117 		x.post("/a01",bean).header("Accept","application/json").header("Content-Type","application/json").header("X-Accept","application/json").header("X-Content-Type","application/json").content("{f:1}").run().assertStatus(200).assertContent("{\"f\":1}");
118 	}
119 
120 	//------------------------------------------------------------------------------------------------------------------
121 	// Basic tests - Multiple language support
122 	//------------------------------------------------------------------------------------------------------------------
123 
124 	@Test void b01_multiLanguages() throws Exception {
125 		var x = client().json5().json().xml().html().plainText().msgPack().uon().urlEnc().openApi().build();
126 		x.post("/a01",bean).header("Accept","application/json").header("Content-Type","application/json").header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
127 		x.post("/a01",bean).header("Accept","text/xml").header("Content-Type","text/xml").header("X-Accept","text/xml").header("X-Content-Type","text/xml").run().assertStatus(200).getContent().as(Bean.class).check();
128 		x.post("/a01",bean).header("Accept","text/html").header("Content-Type","text/html").header("X-Accept","text/html").header("X-Content-Type","text/html").run().assertStatus(200).getContent().as(Bean.class).check();
129 		x.post("/a01",bean).header("Accept","text/plain").header("Content-Type","text/plain").header("X-Accept","text/plain").header("X-Content-Type","text/plain").run().assertStatus(200).getContent().as(Bean.class).check();
130 		x.post("/a01",bean).header("Accept","octal/msgpack").header("Content-Type","octal/msgpack").header("X-Accept","octal/msgpack").header("X-Content-Type","octal/msgpack").run().assertStatus(200).getContent().as(Bean.class).check();
131 		x.post("/a01",bean).header("Accept","text/uon").header("Content-Type","text/uon").header("X-Accept","text/uon").header("X-Content-Type","text/uon").run().assertStatus(200).getContent().as(Bean.class).check();
132 		x.post("/a01",bean).header("Accept","application/x-www-form-urlencoded").header("Content-Type","application/x-www-form-urlencoded").header("X-Accept","application/x-www-form-urlencoded").header("X-Content-Type","application/x-www-form-urlencoded").run().assertStatus(200).getContent().as(Bean.class).check();
133 		x.post("/a01",bean).header("Accept","text/openapi").header("Content-Type","text/openapi").header("X-Accept","text/openapi").header("X-Content-Type","text/openapi").run().assertStatus(200).getContent().as(Bean.class).check();
134 
135 		assertThrowsWithMessage(RestCallException.class, "Content-Type not specified on request.  Cannot match correct serializer.  Use contentType(String) or mediaType(String) to specify transport language.", ()->x.post("/a01",bean).run());
136 	}
137 
138 	//------------------------------------------------------------------------------------------------------------------
139 	// Basic tests - Universal language support
140 	//------------------------------------------------------------------------------------------------------------------
141 
142 	@Test void c01_universal() throws Exception {
143 		var x = client().universal().build();
144 		x.post("/a01",bean).header("Accept","application/json").header("Content-Type","application/json").header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
145 		x.post("/a01",bean).header("Accept","text/xml").header("Content-Type","text/xml").header("X-Accept","text/xml").header("X-Content-Type","text/xml").run().assertStatus(200).getContent().as(Bean.class).check();
146 		x.post("/a01",bean).header("Accept","text/html").header("Content-Type","text/html").header("X-Accept","text/html").header("X-Content-Type","text/html").run().assertStatus(200).getContent().as(Bean.class).check();
147 		x.post("/a01",bean).header("Accept","text/plain").header("Content-Type","text/plain").header("X-Accept","text/plain").header("X-Content-Type","text/plain").run().assertStatus(200).getContent().as(Bean.class).check();
148 		x.post("/a01",bean).header("Accept","octal/msgpack").header("Content-Type","octal/msgpack").header("X-Accept","octal/msgpack").header("X-Content-Type","octal/msgpack").run().assertStatus(200).getContent().as(Bean.class).check();
149 		x.post("/a01",bean).header("Accept","text/uon").header("Content-Type","text/uon").header("X-Accept","text/uon").header("X-Content-Type","text/uon").run().assertStatus(200).getContent().as(Bean.class).check();
150 		x.post("/a01",bean).header("Accept","application/x-www-form-urlencoded").header("Content-Type","application/x-www-form-urlencoded").header("X-Accept","application/x-www-form-urlencoded").header("X-Content-Type","application/x-www-form-urlencoded").run().assertStatus(200).getContent().as(Bean.class).check();
151 		x.post("/a01",bean).header("Accept","text/openapi").header("Content-Type","text/openapi").header("X-Accept","text/openapi").header("X-Content-Type","text/openapi").run().assertStatus(200).getContent().as(Bean.class).check();
152 
153 		assertThrowsWithMessage(RestCallException.class, "Content-Type not specified on request.  Cannot match correct serializer.  Use contentType(String) or mediaType(String) to specify transport language.", ()->x.post("/a01",bean).run());
154 	}
155 
156 	//------------------------------------------------------------------------------------------------------------------
157 	// Basic tests - Universal language support with default headers
158 	//------------------------------------------------------------------------------------------------------------------
159 
160 
161 	@Test void d01_universal() throws Exception {
162 		var x = client().universal().headersDefault(Accept.APPLICATION_JSON, ContentType.APPLICATION_JSON).build();
163 		x.post("/a01",bean).header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
164 		x.post("/a01",bean).header("Accept","application/json").header("Content-Type","application/json").header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
165 		x.post("/a01",bean).header("Accept","text/xml").header("Content-Type","text/xml").header("X-Accept","text/xml").header("X-Content-Type","text/xml").run().assertStatus(200).getContent().as(Bean.class).check();
166 		x.post("/a01",bean).header("Accept","text/html").header("Content-Type","text/html").header("X-Accept","text/html").header("X-Content-Type","text/html").run().assertStatus(200).getContent().as(Bean.class).check();
167 		x.post("/a01",bean).header("Accept","text/plain").header("Content-Type","text/plain").header("X-Accept","text/plain").header("X-Content-Type","text/plain").run().assertStatus(200).getContent().as(Bean.class).check();
168 		x.post("/a01",bean).header("Accept","octal/msgpack").header("Content-Type","octal/msgpack").header("X-Accept","octal/msgpack").header("X-Content-Type","octal/msgpack").run().assertStatus(200).getContent().as(Bean.class).check();
169 		x.post("/a01",bean).header("Accept","text/uon").header("Content-Type","text/uon").header("X-Accept","text/uon").header("X-Content-Type","text/uon").run().assertStatus(200).getContent().as(Bean.class).check();
170 		x.post("/a01",bean).header("Accept","application/x-www-form-urlencoded").header("Content-Type","application/x-www-form-urlencoded").header("X-Accept","application/x-www-form-urlencoded").header("X-Content-Type","application/x-www-form-urlencoded").run().assertStatus(200).getContent().as(Bean.class).check();
171 		x.post("/a01",bean).header("Accept","text/openapi").header("Content-Type","text/openapi").header("X-Accept","text/openapi").header("X-Content-Type","text/openapi").run().assertStatus(200).getContent().as(Bean.class).check();
172 
173 		// Default
174 		x.post("/a01",bean).header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
175 	}
176 
177 	@Test void d03_nullMarshalls() throws Exception {
178 		var x = client().marshaller(null).marshallers(Json.DEFAULT,null).build();
179 		x.post("/a01",bean).header("X-Accept","application/json").header("X-Content-Type","application/json").run().assertStatus(200).getContent().as(Bean.class).check();
180 	}
181 
182 	//------------------------------------------------------------------------------------------------------------------
183 	// Helper methods.
184 	//------------------------------------------------------------------------------------------------------------------
185 
186 	private static RestClient.Builder client() {
187 		return MockRestClient.create(A.class);
188 	}
189 }