Skip to content

Commit 7cbc7dc

Browse files
committed
Add support for parameter descriptions.
1 parent 0359807 commit 7cbc7dc

File tree

9 files changed

+78
-70
lines changed

9 files changed

+78
-70
lines changed

README.md

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ API documentation can be viewed by appending "?api" to a service URL; for exampl
237237
GET /math?api
238238
```
239239

240-
Methods are grouped by resource path. Parameters and return values are encoded as follows:
240+
Methods are grouped by resource path. Parameter and return types are encoded as follows:
241241

242242
* `Object`: "any"
243243
* `Void` or `void`: "void"
@@ -259,38 +259,29 @@ Methods are grouped by resource path. Parameters and return values are encoded a
259259
* `java.util.Map`: "[<em>key type</em>: <em>value type</em>]"
260260
* Any other type: "{property1: <em>property1 type</em>, property2: <em>property2 type</em>, ...}"
261261

262-
For example, a description of the math service might look like this:
263-
264-
> ## /math/sum
265-
>
266-
> ```
267-
> GET (a: double, b: double) -> double
268-
> ```
269-
> ```
270-
> GET (values: [double]) -> double
271-
> ```
272-
273-
Implementations can provide additional details about service types and operations using the `Description` annotation. For example:
262+
Implementations can provide additional information about service types and operations using the `Description` annotation. For example:
274263

275264
```java
265+
@WebServlet(urlPatterns={"/math/*"})
276266
@Description("Math example service.")
277267
public class MathService extends WebService {
278268
private static final long serialVersionUID = 0;
279269

280270
@RequestMethod("GET")
281271
@ResourcePath("sum")
282272
@Description("Calculates the sum of two numbers.")
283-
public double getSum(double a, double b) {
273+
public double getSum(
274+
@Description("The first number.") double a,
275+
@Description("The second number.") double b
276+
) {
284277
return a + b;
285278
}
286279

287280
...
288281
}
289282
```
290283

291-
The provided values will appear immediately prior to their associated elements in the generated output.
292-
293-
Finally, if a method is tagged with the `Deprecated` annotation, it will be identified as such in the output.
284+
If a method is tagged with the `Deprecated` annotation, it will be identified as such in the output.
294285

295286
## WebServiceProxy
296287
The `WebServiceProxy` class is used to issue API requests to a server. This class provides a single constructor that accepts the following arguments:
@@ -923,6 +914,7 @@ In addition to Java, HTTP-RPC web services can be implemented using the [Kotlin]
923914

924915
```kotlin
925916
@WebServlet(urlPatterns = ["/system-info/*"], loadOnStartup = 1)
917+
@Description("System info service.")
926918
class SystemInfoService : WebService() {
927919
class SystemInfo(
928920
val hostName: String,
@@ -933,6 +925,7 @@ class SystemInfoService : WebService() {
933925
)
934926

935927
@RequestMethod("GET")
928+
@Description("Returns system info.")
936929
fun getSystemInfo(): SystemInfo {
937930
val localHost = InetAddress.getLocalHost()
938931
val runtime = Runtime.getRuntime()
@@ -948,27 +941,7 @@ class SystemInfoService : WebService() {
948941
}
949942
```
950943

951-
The API documentation for this service might look something like the following:
952-
953-
> ## /system-info
954-
>
955-
> ```
956-
> GET () -> SystemInfo
957-
> ```
958-
>
959-
> ## SystemInfo
960-
>
961-
> ```
962-
> {
963-
> hostAddress: string,
964-
> hostName: string,
965-
> availableProcessors: integer,
966-
> freeMemory: long,
967-
> totalMemory: long
968-
> }
969-
> ```
970-
971-
Data returned by the service might look like this:
944+
A response produced by the service might look like this:
972945

973946
```json
974947
{

httprpc-client/src/main/java/org/httprpc/io/CSVDecoder.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
/**
3030
* CSV decoder.
3131
*/
32+
@SuppressWarnings("unchecked")
3233
public class CSVDecoder extends Decoder {
3334
/**
3435
* CSV cursor.
@@ -187,13 +188,11 @@ public CSVDecoder(char delimiter) {
187188
}
188189

189190
@Override
190-
@SuppressWarnings("unchecked")
191191
public Cursor read(InputStream inputStream) throws IOException {
192192
return super.read(inputStream);
193193
}
194194

195195
@Override
196-
@SuppressWarnings("unchecked")
197196
public Cursor read(Reader reader) throws IOException {
198197
return new Cursor(new BufferedReader(reader), delimiter);
199198
}

httprpc-server/src/main/java/org/httprpc/Description.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
import java.lang.annotation.Target;
2121

2222
/**
23-
* Annotation that associates a description with a service class or method.
23+
* Annotation that associates a description with a service class, method, or
24+
* method parameter.
2425
*/
2526
@Retention(RetentionPolicy.RUNTIME)
26-
@Target({ElementType.TYPE, ElementType.METHOD})
27+
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
2728
public @interface Description {
2829
/**
2930
* @return
30-
* The description of the class or method.
31+
* The description of the class, method, or method parameter.
3132
*/
3233
String value();
3334
}

httprpc-server/src/main/java/org/httprpc/WebService.java

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,24 @@ private void describeResource(String path, Resource resource, TreeMap<Class<?>,
658658
handlers.sort(Comparator.comparing(handler -> handler.method.getName()));
659659

660660
for (Handler handler : handlers) {
661+
xmlStreamWriter.writeStartElement("pre");
662+
663+
Deprecated deprecated = handler.method.getAnnotation(Deprecated.class);
664+
665+
if (deprecated != null) {
666+
xmlStreamWriter.writeStartElement("del");
667+
}
668+
669+
xmlStreamWriter.writeCharacters(entry.getKey().toUpperCase());
670+
xmlStreamWriter.writeCharacters(" -> ");
671+
xmlStreamWriter.writeCharacters(BeanAdapter.describe(handler.method.getGenericReturnType(), structures));
672+
673+
if (deprecated != null) {
674+
xmlStreamWriter.writeEndElement();
675+
}
676+
677+
xmlStreamWriter.writeEndElement();
678+
661679
Description methodDescription = handler.method.getAnnotation(Description.class);
662680

663681
if (methodDescription != null) {
@@ -668,28 +686,16 @@ private void describeResource(String path, Resource resource, TreeMap<Class<?>,
668686

669687
Parameter[] parameters = handler.method.getParameters();
670688

671-
xmlStreamWriter.writeStartElement("pre");
672-
673-
String verb = entry.getKey().toUpperCase();
674-
675-
if (handler.method.getAnnotation(Deprecated.class) == null) {
676-
xmlStreamWriter.writeCharacters(verb);
677-
} else {
678-
xmlStreamWriter.writeStartElement("del");
679-
xmlStreamWriter.writeCharacters(verb);
680-
xmlStreamWriter.writeEndElement();
681-
}
682-
683-
xmlStreamWriter.writeCharacters(" (");
689+
xmlStreamWriter.writeStartElement("ul");
684690

685691
for (int i = 0; i < parameters.length; i++) {
686692
Parameter parameter = parameters[i];
687693

688-
if (i > 0) {
689-
xmlStreamWriter.writeCharacters(", ");
690-
}
694+
xmlStreamWriter.writeStartElement("li");
691695

692-
xmlStreamWriter.writeCharacters(parameter.getName() + ": ");
696+
xmlStreamWriter.writeStartElement("code");
697+
xmlStreamWriter.writeCharacters(parameter.getName());
698+
xmlStreamWriter.writeCharacters(": ");
693699

694700
Type type = parameter.getParameterizedType();
695701

@@ -702,10 +708,18 @@ private void describeResource(String path, Resource resource, TreeMap<Class<?>,
702708
} else {
703709
xmlStreamWriter.writeCharacters(BeanAdapter.describe(type, structures));
704710
}
705-
}
706711

707-
xmlStreamWriter.writeCharacters(") -> ");
708-
xmlStreamWriter.writeCharacters(BeanAdapter.describe(handler.method.getGenericReturnType(), structures));
712+
xmlStreamWriter.writeEndElement();
713+
714+
Description parameterDescription = parameter.getAnnotation(Description.class);
715+
716+
if (parameterDescription != null) {
717+
xmlStreamWriter.writeCharacters(" - ");
718+
xmlStreamWriter.writeCharacters(parameterDescription.value());
719+
}
720+
721+
xmlStreamWriter.writeEndElement();
722+
}
709723

710724
xmlStreamWriter.writeEndElement();
711725
}

httprpc-server/src/main/resources/org/httprpc/api.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ ul {
2121
pre {
2222
font-size: medium;
2323
}
24+
25+
code {
26+
font-size: medium;
27+
}

httprpc-test/src/main/java/org/httprpc/test/CatalogService.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ public List<Item> getItems() {
7676
@RequestMethod("POST")
7777
@ResourcePath("items")
7878
@Description("Adds a new item to the catalog.")
79-
public int addItem(String description, double price) {
79+
public int addItem(
80+
@Description("The item's description.") String description,
81+
@Description("The item's price.") double price
82+
) {
8083
items.add(new Item(description, price));
8184

8285
return items.size();
@@ -101,7 +104,10 @@ public Item getItem() {
101104
@RequestMethod("POST")
102105
@ResourcePath("items/?:itemID")
103106
@Description("Updates an item.")
104-
public void updateItem(String description, double price) {
107+
public void updateItem(
108+
@Description("The item's description.") String description,
109+
@Description("The item's price.") double price
110+
) {
105111
int itemID = Integer.parseInt(getKey("itemID"));
106112

107113
if (itemID > 0 && itemID <= items.size()) {

httprpc-test/src/main/java/org/httprpc/test/EchoService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ public class EchoService extends WebService {
3030

3131
@RequestMethod("GET")
3232
@Description("Echoes a string value to the servlet response stream.")
33-
public void echo(String value) throws IOException {
33+
public void echo(
34+
@Description("The value to echo.") String value
35+
) throws IOException {
3436
HttpServletResponse response = getResponse();
3537

3638
response.setContentType("text/plain");

httprpc-test/src/main/java/org/httprpc/test/FileUploadService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ public class FileUploadService extends WebService {
3636

3737
@RequestMethod("POST")
3838
@Description("Uploads a single file.")
39-
public long upload(URL file) throws IOException {
39+
public long upload(
40+
@Description("The file to upload.") URL file
41+
) throws IOException {
4042
long bytes = 0;
4143

4244
if (file != null) {
@@ -52,7 +54,9 @@ public long upload(URL file) throws IOException {
5254

5355
@RequestMethod("POST")
5456
@Description("Uploads a list of files.")
55-
public long upload(List<URL> files) throws IOException {
57+
public long upload(
58+
@Description("The files to upload.") List<URL> files
59+
) throws IOException {
5660
long bytes = 0;
5761

5862
for (URL file : files) {

httprpc-test/src/main/java/org/httprpc/test/MathService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,19 @@ public class MathService extends WebService {
3030
@RequestMethod("GET")
3131
@ResourcePath("sum")
3232
@Description("Calculates the sum of two numbers.")
33-
public double getSum(double a, double b) {
33+
public double getSum(
34+
@Description("The first number.") double a,
35+
@Description("The second number.") double b
36+
) {
3437
return a + b;
3538
}
3639

3740
@RequestMethod("GET")
3841
@ResourcePath("sum")
3942
@Description("Calculates the sum of a list of numbers.")
40-
public double getSum(List<Double> values) {
43+
public double getSum(
44+
@Description("The numbers to add.") List<Double> values
45+
) {
4146
double total = 0;
4247

4348
for (double value : values) {

0 commit comments

Comments
 (0)