Skip to content

Commit 81e06f2

Browse files
authored
Add support for parameterized host in annotation-processor (#45099)
1 parent 11ac9cf commit 81e06f2

File tree

17 files changed

+464
-295
lines changed

17 files changed

+464
-295
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package io.clientcore.annotation.processor.test;
4+
5+
import io.clientcore.core.http.models.HttpHeaderName;
6+
import io.clientcore.core.http.models.HttpMethod;
7+
import io.clientcore.core.http.models.HttpRequest;
8+
import io.clientcore.core.http.models.Response;
9+
import io.clientcore.core.http.pipeline.HttpPipeline;
10+
import io.clientcore.core.models.binarydata.BinaryData;
11+
import io.clientcore.annotation.processor.test.implementation.ParameterizedHostService;
12+
import io.clientcore.core.instrumentation.logging.ClientLogger;
13+
import io.clientcore.core.serialization.json.JsonSerializer;
14+
import io.clientcore.core.serialization.xml.XmlSerializer;
15+
16+
/**
17+
* Initializes a new instance of the ParameterizedHostServiceImpl type.
18+
*/
19+
public class ParameterizedHostServiceImpl implements ParameterizedHostService {
20+
21+
private static final ClientLogger LOGGER = new ClientLogger(ParameterizedHostService.class);
22+
23+
private final HttpPipeline httpPipeline;
24+
25+
private final JsonSerializer jsonSerializer;
26+
27+
private final XmlSerializer xmlSerializer;
28+
29+
private ParameterizedHostServiceImpl(HttpPipeline httpPipeline) {
30+
this.httpPipeline = httpPipeline;
31+
this.jsonSerializer = JsonSerializer.getInstance();
32+
this.xmlSerializer = XmlSerializer.getInstance();
33+
}
34+
35+
/**
36+
* Creates an instance of ParameterizedHostService that is capable of sending requests to the service.
37+
* @param httpPipeline The HTTP pipeline to use for sending requests.
38+
* @return An instance of `ParameterizedHostService`;
39+
*/
40+
public static ParameterizedHostService getNewInstance(HttpPipeline httpPipeline) {
41+
return new ParameterizedHostServiceImpl(httpPipeline);
42+
}
43+
44+
@SuppressWarnings({ "unchecked", "cast" })
45+
@Override
46+
public byte[] getByteArray(String scheme, String host, int numberOfBytes) {
47+
String url = scheme + "://" + host + "/bytes/" + numberOfBytes;
48+
// Create the HTTP request
49+
HttpRequest httpRequest = new HttpRequest().setMethod(HttpMethod.GET).setUri(url);
50+
// Send the request through the httpPipeline
51+
Response<BinaryData> networkResponse = this.httpPipeline.send(httpRequest);
52+
int responseCode = networkResponse.getStatusCode();
53+
boolean expectedResponse = responseCode == 200;
54+
if (!expectedResponse) {
55+
throw new RuntimeException("Unexpected response code: " + responseCode);
56+
}
57+
BinaryData responseBody = networkResponse.getValue();
58+
byte[] responseBodyBytes = responseBody != null ? responseBody.toBytes() : null;
59+
return responseBodyBytes != null ? (responseBodyBytes.length == 0 ? null : responseBodyBytes) : null;
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package io.clientcore.annotation.processor.test;
4+
5+
import io.clientcore.annotation.processor.test.implementation.models.HttpBinJSON;
6+
import io.clientcore.core.http.models.HttpHeaderName;
7+
import io.clientcore.core.http.models.HttpMethod;
8+
import io.clientcore.core.http.models.HttpRequest;
9+
import io.clientcore.core.http.models.Response;
10+
import io.clientcore.core.http.pipeline.HttpPipeline;
11+
import io.clientcore.core.models.binarydata.BinaryData;
12+
import io.clientcore.annotation.processor.test.implementation.ParameterizedMultipleHostService;
13+
import io.clientcore.core.instrumentation.logging.ClientLogger;
14+
import io.clientcore.core.serialization.json.JsonSerializer;
15+
import io.clientcore.core.serialization.xml.XmlSerializer;
16+
import io.clientcore.core.utils.CoreUtils;
17+
import java.lang.reflect.ParameterizedType;
18+
import io.clientcore.core.serialization.SerializationFormat;
19+
20+
/**
21+
* Initializes a new instance of the ParameterizedMultipleHostServiceImpl type.
22+
*/
23+
public class ParameterizedMultipleHostServiceImpl implements ParameterizedMultipleHostService {
24+
25+
private static final ClientLogger LOGGER = new ClientLogger(ParameterizedMultipleHostService.class);
26+
27+
private final HttpPipeline httpPipeline;
28+
29+
private final JsonSerializer jsonSerializer;
30+
31+
private final XmlSerializer xmlSerializer;
32+
33+
private ParameterizedMultipleHostServiceImpl(HttpPipeline httpPipeline) {
34+
this.httpPipeline = httpPipeline;
35+
this.jsonSerializer = JsonSerializer.getInstance();
36+
this.xmlSerializer = XmlSerializer.getInstance();
37+
}
38+
39+
/**
40+
* Creates an instance of ParameterizedMultipleHostService that is capable of sending requests to the service.
41+
* @param httpPipeline The HTTP pipeline to use for sending requests.
42+
* @return An instance of `ParameterizedMultipleHostService`;
43+
*/
44+
public static ParameterizedMultipleHostService getNewInstance(HttpPipeline httpPipeline) {
45+
return new ParameterizedMultipleHostServiceImpl(httpPipeline);
46+
}
47+
48+
@SuppressWarnings({ "unchecked", "cast" })
49+
@Override
50+
public HttpBinJSON get(String scheme, String hostPart1, String hostPart2) {
51+
String url = scheme + "://" + hostPart1 + hostPart2 + "/get";
52+
// Create the HTTP request
53+
HttpRequest httpRequest = new HttpRequest().setMethod(HttpMethod.GET).setUri(url);
54+
// Send the request through the httpPipeline
55+
Response<BinaryData> networkResponse = this.httpPipeline.send(httpRequest);
56+
int responseCode = networkResponse.getStatusCode();
57+
boolean expectedResponse = responseCode == 200;
58+
if (!expectedResponse) {
59+
throw new RuntimeException("Unexpected response code: " + responseCode);
60+
}
61+
Object result = null;
62+
ParameterizedType returnType = CoreUtils.createParameterizedType(io.clientcore.annotation.processor.test.implementation.models.HttpBinJSON.class);
63+
SerializationFormat serializationFormat = CoreUtils.serializationFormatFromContentType(httpRequest.getHeaders());
64+
if (jsonSerializer.supportsFormat(serializationFormat)) {
65+
result = CoreUtils.decodeNetworkResponse(networkResponse.getValue(), jsonSerializer, returnType);
66+
} else if (xmlSerializer.supportsFormat(serializationFormat)) {
67+
result = CoreUtils.decodeNetworkResponse(networkResponse.getValue(), xmlSerializer, returnType);
68+
} else {
69+
throw new RuntimeException(new UnsupportedOperationException("None of the provided serializers support the format: " + serializationFormat + "."));
70+
}
71+
networkResponse.close();
72+
return (io.clientcore.annotation.processor.test.implementation.models.HttpBinJSON) result;
73+
}
74+
}

sdk/clientcore/annotation-processor-test/src/main/java/io/clientcore/annotation/processor/test/SimpleXmlSerializableServiceImpl.java

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,9 @@
1313
import io.clientcore.core.instrumentation.logging.ClientLogger;
1414
import io.clientcore.core.serialization.json.JsonSerializer;
1515
import io.clientcore.core.serialization.xml.XmlSerializer;
16-
import java.io.IOException;
17-
import io.clientcore.core.models.CoreException;
1816
import io.clientcore.core.utils.CoreUtils;
19-
import io.clientcore.core.serialization.SerializationFormat;
20-
import io.clientcore.core.serialization.ObjectSerializer;
2117
import java.lang.reflect.ParameterizedType;
22-
import java.lang.reflect.Type;
23-
import java.util.List;
18+
import io.clientcore.core.serialization.SerializationFormat;
2419

2520
/**
2621
* Initializes a new instance of the SimpleXmlSerializableServiceImpl type.
@@ -118,9 +113,9 @@ public SimpleXmlSerializable getXml(String contentType) {
118113
ParameterizedType returnType = CoreUtils.createParameterizedType(io.clientcore.annotation.processor.test.implementation.models.SimpleXmlSerializable.class);
119114
SerializationFormat serializationFormat = CoreUtils.serializationFormatFromContentType(httpRequest.getHeaders());
120115
if (jsonSerializer.supportsFormat(serializationFormat)) {
121-
result = decodeNetworkResponse(networkResponse.getValue(), jsonSerializer, returnType);
116+
result = CoreUtils.decodeNetworkResponse(networkResponse.getValue(), jsonSerializer, returnType);
122117
} else if (xmlSerializer.supportsFormat(serializationFormat)) {
123-
result = decodeNetworkResponse(networkResponse.getValue(), xmlSerializer, returnType);
118+
result = CoreUtils.decodeNetworkResponse(networkResponse.getValue(), xmlSerializer, returnType);
124119
} else {
125120
throw new RuntimeException(new UnsupportedOperationException("None of the provided serializers support the format: " + serializationFormat + "."));
126121
}
@@ -146,39 +141,13 @@ public SimpleXmlSerializable getInvalidXml(String contentType) {
146141
ParameterizedType returnType = CoreUtils.createParameterizedType(io.clientcore.annotation.processor.test.implementation.models.SimpleXmlSerializable.class);
147142
SerializationFormat serializationFormat = CoreUtils.serializationFormatFromContentType(httpRequest.getHeaders());
148143
if (jsonSerializer.supportsFormat(serializationFormat)) {
149-
result = decodeNetworkResponse(networkResponse.getValue(), jsonSerializer, returnType);
144+
result = CoreUtils.decodeNetworkResponse(networkResponse.getValue(), jsonSerializer, returnType);
150145
} else if (xmlSerializer.supportsFormat(serializationFormat)) {
151-
result = decodeNetworkResponse(networkResponse.getValue(), xmlSerializer, returnType);
146+
result = CoreUtils.decodeNetworkResponse(networkResponse.getValue(), xmlSerializer, returnType);
152147
} else {
153148
throw new RuntimeException(new UnsupportedOperationException("None of the provided serializers support the format: " + serializationFormat + "."));
154149
}
155150
networkResponse.close();
156151
return (io.clientcore.annotation.processor.test.implementation.models.SimpleXmlSerializable) result;
157152
}
158-
159-
/**
160-
* Decodes the body of an {@link Response} into the type returned by the called API.
161-
* @param data The BinaryData to decode.
162-
* @param serializer The serializer to use.
163-
* @param returnType The type of the ParameterizedType return value.
164-
* @return The decoded value.
165-
* @throws CoreException If the deserialization fails.
166-
*/
167-
private static Object decodeNetworkResponse(BinaryData data, ObjectSerializer serializer, ParameterizedType returnType) {
168-
if (data == null) {
169-
return null;
170-
}
171-
try {
172-
if (List.class.isAssignableFrom((Class<?>) returnType.getRawType())) {
173-
return serializer.deserializeFromBytes(data.toBytes(), returnType);
174-
}
175-
Type token = returnType.getRawType();
176-
if (Response.class.isAssignableFrom((Class<?>) token)) {
177-
token = returnType.getActualTypeArguments()[0];
178-
}
179-
return serializer.deserializeFromBytes(data.toBytes(), token);
180-
} catch (IOException e) {
181-
throw LOGGER.logThrowableAsError(CoreException.from(e));
182-
}
183-
}
184153
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package io.clientcore.annotation.processor.test.implementation;
5+
6+
import io.clientcore.core.annotations.ServiceInterface;
7+
import io.clientcore.core.http.annotations.HostParam;
8+
import io.clientcore.core.http.annotations.HttpRequestInformation;
9+
import io.clientcore.core.http.annotations.PathParam;
10+
import io.clientcore.core.http.models.HttpMethod;
11+
import io.clientcore.core.http.pipeline.HttpPipeline;
12+
import java.lang.reflect.InvocationTargetException;
13+
14+
@ServiceInterface(name = "ParameterizedHostService", host = "{scheme}://{hostName}")
15+
public interface ParameterizedHostService {
16+
/**
17+
* Creates a new instance of {@link ParameterizedHostService}.
18+
*
19+
* @param pipeline The HTTP pipeline to use.
20+
* @return A new instance of ParameterizedHostService.
21+
*/
22+
static ParameterizedHostService getNewInstance(HttpPipeline pipeline) {
23+
if (pipeline == null) {
24+
throw new IllegalArgumentException("pipeline cannot be null");
25+
}
26+
try {
27+
Class<?> clazz = Class
28+
.forName("io.clientcore.annotation.processor.test.ParameterizedHostServiceImpl");
29+
return (ParameterizedHostService) clazz.getMethod("getNewInstance", HttpPipeline.class)
30+
.invoke(null, pipeline);
31+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
32+
| InvocationTargetException e) {
33+
throw new RuntimeException(e);
34+
}
35+
}
36+
37+
/**
38+
* Gets the byte array from the specified host and scheme.
39+
*
40+
* @param scheme The URI scheme (e.g., "https").
41+
* @param host The host name.
42+
* @param numberOfBytes The number of bytes to retrieve.
43+
* @return The byte array result.
44+
*/
45+
@HttpRequestInformation(method = HttpMethod.GET, path = "bytes/{numberOfBytes}", expectedStatusCodes = { 200 })
46+
byte[] getByteArray(@HostParam("scheme") String scheme, @HostParam("hostName") String host,
47+
@PathParam("numberOfBytes") int numberOfBytes);
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package io.clientcore.annotation.processor.test.implementation;
5+
6+
import io.clientcore.annotation.processor.test.implementation.models.HttpBinJSON;
7+
import io.clientcore.core.annotations.ServiceInterface;
8+
import io.clientcore.core.http.annotations.HostParam;
9+
import io.clientcore.core.http.annotations.HttpRequestInformation;
10+
import io.clientcore.core.http.models.HttpMethod;
11+
import io.clientcore.core.http.pipeline.HttpPipeline;
12+
import java.lang.reflect.InvocationTargetException;
13+
14+
@ServiceInterface(name = "ParameterizedMultipleHostService", host = "{scheme}://{hostPart1}{hostPart2}")
15+
public interface ParameterizedMultipleHostService {
16+
17+
/**
18+
* Creates a new instance of {@link ParameterizedMultipleHostService}.
19+
*
20+
* @param pipeline The HTTP pipeline to use.
21+
* @return A new instance of ParameterizedMultipleHostService.
22+
*/ static ParameterizedMultipleHostService getNewInstance(HttpPipeline pipeline) {
23+
if (pipeline == null) {
24+
throw new IllegalArgumentException("pipeline cannot be null");
25+
}
26+
try {
27+
Class<?> clazz = Class
28+
.forName("io.clientcore.annotation.processor.test.ParameterizedMultipleHostServiceImpl");
29+
return (ParameterizedMultipleHostService) clazz.getMethod("getNewInstance", HttpPipeline.class)
30+
.invoke(null, pipeline);
31+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
32+
| InvocationTargetException e) {
33+
throw new RuntimeException(e);
34+
}
35+
}
36+
37+
/**
38+
* Retrieves a JSON object from the specified URL.
39+
* @param scheme The scheme to use (e.g., "http" or "https").
40+
* @param hostPart1 The first part of the host (e.g., "localhost").
41+
* @param hostPart2 The second part of the host (e.g., ":8000").
42+
* @return The JSON object retrieved from the URL.
43+
*/
44+
@HttpRequestInformation(method = HttpMethod.GET, path = "get", expectedStatusCodes = { 200 })
45+
HttpBinJSON get(@HostParam("scheme") String scheme, @HostParam("hostPart1") String hostPart1,
46+
@HostParam("hostPart2") String hostPart2);
47+
}

sdk/clientcore/annotation-processor-test/src/main/java/io/clientcore/annotation/processor/test/implementation/SimpleXmlSerializableService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static SimpleXmlSerializableService getNewInstance(HttpPipeline pipeline) {
6666

6767
/**
6868
* Retrieves an invalid XML payload.
69+
* @param contentType The content type of the invalid XML payload.
6970
*
7071
* @param contentType The content type of the XML payload.
7172
* @return The retrieved invalid XML payload.

sdk/clientcore/annotation-processor-test/src/main/java/io/clientcore/annotation/processor/test/implementation/TestInterfaceClientImpl.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,6 @@ Response<HttpBinJSON> postStreamResponse(@HostParam("uri") String uri,
111111
@HttpRequestInformation(method = HttpMethod.GET, path = "bytes/100", expectedStatusCodes = { 200 })
112112
byte[] getByteArray(@HostParam("uri") String uri);
113113

114-
// Service 2
115-
@HttpRequestInformation(method = HttpMethod.GET, path = "bytes/{numberOfBytes}", expectedStatusCodes = { 200 })
116-
byte[] getByteArray(@HostParam("scheme") String scheme, @HostParam("hostName") String hostName,
117-
@PathParam(value = "numberOfBytes", encoded = true) int numberOfBytes);
118-
119114
// Service 3
120115
@HttpRequestInformation(method = HttpMethod.GET, path = "bytes/100", expectedStatusCodes = { 200 })
121116
void getNothing(@HostParam("uri") String uri);
@@ -350,10 +345,6 @@ HttpBinJSON patch(@HostParam("uri") String uri,
350345
HttpBinJSON putByteArray(@HostParam("uri") String uri,
351346
@BodyParam(ContentType.APPLICATION_OCTET_STREAM) byte[] bytes);
352347

353-
@HttpRequestInformation(method = HttpMethod.GET, path = "get", expectedStatusCodes = { 200 })
354-
HttpBinJSON get(@HostParam("scheme") String scheme, @HostParam("hostPart1") String hostPart1,
355-
@HostParam("hostPart2") String hostPart2);
356-
357348
@HttpRequestInformation(method = HttpMethod.GET, path = "status/200")
358349
void getStatus200(@HostParam("uri") String uri);
359350

0 commit comments

Comments
 (0)