blob: 91a32d4c36fb91f92d0c42a6055434b6c5e18eff [file] [log] [blame]
<!--
/***************************************************************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
***************************************************************************************************************************/
-->
@Response
<p>
The {@link oaj.http.annotation.Response @Response} annotation is used to identify schema information about an HTTP response.
</p>
<ul class='javatree'>
<li class='ja'>{@link oaj.http.annotation.Response}
<ul>
<li class='jf'>{@link oaj.http.annotation.Response#api() api} - Free-form Swagger JSON.
<li class='jf'>{@link oaj.http.annotation.Response#code() code} - HTTP status code.
<li class='jf'>{@link oaj.http.annotation.Response#description() description} - Description.
<li class='jf'>{@link oaj.http.annotation.Response#example() example} - Serialized example.
<li class='jf'>{@link oaj.http.annotation.Response#examples() examples} - Serialized examples per media type.
<li class='jf'>{@link oaj.http.annotation.Response#headers() headers} - Swagger about headers added to response.
<li class='jf'>{@link oaj.http.annotation.Response#partSerializer() partSerializer} - Override the part serializer.
<li class='jf'>{@link oaj.http.annotation.Response#schema() schema} - Swagger schema.
<li class='jf'>{@link oaj.http.annotation.Response#value() value} - Free-form Swagger JSON.
</ul>
</ul>
<p>
It can be used in the following locations:
</p>
<ul>
<li>Exception classes thrown from <ja>@RestMethod</ja>-annotated methods.
<li>Return type classes of <ja>@RestMethod</ja>-annotated methods.
<li><ja>@RestMethod</ja>-annotated methods themselves.
<li>Arguments and argument-types of <ja>@RestMethod</ja>-annotated methods.
</ul>
<p>
When the <ja>@Response</ja> annotation is applied to classes, the following annotations can be used on
public non-static methods of the class to identify parts of a response:
</p>
<ul class='javatree'>
<li class='ja'>{@link oaj.http.annotation.ResponseStatus}
<li class='ja'>{@link oaj.http.annotation.ResponseHeader}
<li class='ja'>{@link oaj.http.annotation.ResponseBody}
</ul>
<h5 class='topic'>@Resource on exception classes</h5>
<p>
When applied to an exception class, this annotation defines Swagger schema and information on non-200 return types.
</p>
<p>
The following example shows the <ja>@Response</ja> annotation used to define an exception for an invalid login attempt:
</p>
<p class='bpcode w800'>
<jc>// Our annotated exception.</jc>
<ja>@Response</ja>(
code=401,
description=<js>"Invalid username or password provided"</js> <jc>// Description show in Swagger</jc>
)
<jk>public class</jk> InvalidLogin <jk>extends</jk> Exception {
<jk>public</jk> InvalidLogin() {
<jk>super</jk>(<js>"Invalid username or password."</js>); <jc>// Message sent in response</jc>
}
}
<jc>// Our REST method that throws an annotated exception.</jc>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
<jk>public</jk> Ok login(
<ja>@FormData</ja>(<js>"username"</js>) String username,
<ja>@FormData</ja>(<js>"password"</js>) String password
) <jk>throws</jk> InvalidLogin
{
checkCredentials(username, password);
<jk>return new</jk> Ok();
}
</p>
<p>
Custom exceptions can also extend from one of the predefined HTTP exceptions such as the {@link oajr.exception.Unauthorized} exception:
</p>
<p class='bpcode w800'>
<jc>// Our annotated exception.</jc>
<ja>@Response</ja>(
description=<js>"Invalid username or password provided"</js> <jc>// Overridden from parent class</jc>
)
<jk>public class</jk> InvalidLogin <jk>extends</jk> Unauthorized {
<jk>public</jk> InvalidLogin() {
<jk>super</jk>(<js>"Invalid username or password."</js>);
}
}
<jc>// Parent predefined exception class.</jc>
<ja>@Response</ja>(
code=401,
description=<js>"Unauthorized"</js>
)
<jk>public class</jk> Unauthorized <jk>extends</jk> RestException {...}
</p>
<h5 class='topic'>@Resource on return type classes</h5>
<p>
When applied type classes returned by a Java method, this annotation defines schema and Swagger information on the body of responses.
</p>
<p>
In the example above, we're using the <c>Ok</c> class which is defined like so:
</p>
<p class='bpcode w800'>
<ja>@Response</ja>(
code=200,
description=<js>"OK"</js>
)
<jk>public class</jk> Ok {
<ja>@ResponseBody</ja>
<jk>public</jk> String toString() {
<jk>return</jk> <js>"OK"</js>;
}
}
</p>
<p>
Another example showing how a redirect can be defined:
</p>
<p class='bpcode w800'>
<ja>@Response</ja>(
code=307,
description=<js>"Temporary Redirect"</js>
)
<jk>public class</jk> Redirect {
<jk>private final</jk> URI <jf>location</jf>;
<jk>public</jk> Redirect(URI location) {
<jk>this</jk>.<jf>location</jf> = location;
}
<ja>@ResponseHeader</ja>(
name=<js>"Location"</js>,
format=<js>"uri"</js>
)
<jk>public</jk> URI getLocation() {
<jk>return</jk> location;
}
<ja>@ResponseBody</ja>
<jk>public</jk> String toString() {
<jk>return</jk> <js>"Temporary Redirect"</js>;
}
}
</p>
<p class='bpcode w800'>
<jc>// Usage</jc>
<ja>@RestMethod</ja>(method=<jsf>POST</jsf>)
<jk>public</jk> Redirect addPet(Pet pet) {
<jc>// Redirect to servlet root</jc>
<jk>return new</jk> Redirect(URI.<jsm>create</jsm>(<js>"servlet:/"</js>));
}
</p>
<h5 class='topic'>@Resource on @RestMethod-annotated methods</h5>
<p>
The <ja>@Response</ja> annotation can also be applied to the Java method itself which is effectively
the same as applying it to the return type (albeit for this method only).
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
<ja>@Response</ja>(code=200, description=<js>"OK"</js>)
<jk>public</jk> Ok login(
<ja>@FormData</ja>(<js>"username"</js>) String username,
<ja>@FormData</ja>(<js>"password"</js>) String password
) <jk>throws</jk> InvalidLogin
{
checkCredentials(username, password);
<jk>return new</jk> Ok();
}
</p>
<p>
The <ja>@Response</ja> annotation can be simultaneously on both the Java method and return type.
When used in both locations, the annotation values are combined, but values defined on the
method return annotation take precedence over the values defined on the type.
</p>
<h5 class='topic'>@Resource on @RestMethod-annotated method parameters</h5>
<p>
The <ja>@Response</ja> annotation can also be applied to the Java method parameters when the parameter type
is {@link oaj.Value} (a placeholder for objects).
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
<jk>public void</jk> login(
<ja>@FormData</ja>(<js>"username"</js>) String username,
<ja>@FormData</ja>(<js>"password"</js>) String password,
<ja>@Response</ja>(code=200, description=<js>"Login succeeded"</js>) Value&lt;String&gt; body
) <jk>throws</jk> InvalidLogin
{
checkCredentials(username, password);
body.set(<js>"OK"</js>);
}
</p>
<p>
<ja>@Response</ja>-annotated types can also be used as value parameters:
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(...)
<jk>public void</jk> login(
...
<ja>@Response</ja> Value&lt;Ok&gt; res
) <jk>throws</jk> InvalidLogin
{
...
res.set(<jk>new</jk> Ok());
}
</p>
<p>
In the above example, the <ja>@Response</ja> annotation is optional since it is inferred from the class
that it's a <ja>@Response</ja> bean.
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/user/login"</js>)
<jk>public void</jk> login(
...
Value&lt;Ok&gt; res <jc>// @Response annotation not needed.</jc>
) <jk>throws</jk> InvalidLogin
{
...
res.set(<jk>new</jk> Ok());
}
</p>
<h5 class='topic'>@ResponseStatus on methods of @Response-annotated types</h5>
<p>
The {@link oaj.http.annotation.ResponseStatus @ResponseStatus} annotation can be used on
the method of a <ja>@Response</ja>-annotated class to identify HTTP response
statuses other than <c>200</c> (the default).
</p>
<h5 class='figure'>Example:</h5>
<p class='bpcode w800'>
<ja>@Response</ja>
<jk>public class</jk> AddPetSuccess {
<ja>@ResponseStatus</ja>
<jk>public int</jk> getStatus() {
<jk>return</jk> 201;
}
<ja>@Override</ja>
<jk>public</jk> String toString() {
<jk>return</jk> <js>"Pet was successfully added"</js>;
}
}
</p>
<h5 class='topic'>@ResponseHeader on methods of @Response-annotated types</h5>
<p>
The {@link oaj.http.annotation.ResponseHeader @ResponseHeader} annotation can be used on
the method of a <ja>@Response</ja>-annotated class to identify a header
to add to the response.
</p>
<h5 class='figure'>Example:</h5>
<p class='bpcode w800'>
<ja>@Response</ja>
<jk>public class</jk> AddPetSuccess {
<ja>@ResponseHeader</ja>(
name=<js>"X-PetId"</js>,
type=<js>"integer"</js>,
format=<js>"int32"</js>,
description=<js>"ID of added pet."</js>,
example=<js>"123"</js>
)
<jk>public int</jk> getPetId() {...}
}
</p>
<h5 class='topic'>@ResponseBody on methods of @Response-annotated types</h5>
<p>
The {@link oaj.http.annotation.ResponseBody @ResponseBody} annotation can be used on
the method of a <ja>@Response</ja>-annotated class to identify a POJO
as the body of the HTTP response.
</p>
<h5 class='figure'>Example:</h5>
<p class='bpcode w800'>
<ja>@Response</ja>
<jk>public class</jk> AddPetSuccess {
<ja>@ResponseBody</ja>
<jk>public</jk> Pet getPet() {...}
}
</p>
<p>
If a <ja>@Response</ja> class does not have a <ja>@ResponseBody</ja>-annotated method, then the response
object itself is serialized in the response (typically using <c>toString()</c>).
</p>
<h5 class='topic'>Notes about OpenAPI part serialization</h5>
<p>
By default, POJOs representing the body of the request are serialized using the Juneau serializer
matching the requesting <c>Accept</c> header.
The {@link oaj.oapi.OpenApiSerializer} class can be used to serialize response bodies using OpenAPI rules.
</p>
<p>
The following examples show part-schema-based serialization of response bodies:
</p>
<p class='bpcode w800'>
<ja>@RestResource</ja>
<jk>public class</jk> ExampleResource {
<jc>// Example 1 - String[] should be serialized using part serializer.</jc>
<ja>@Response</ja>(
serializers=OpenApiSerializer.<jk>class</jk>,
defaultAccept=<js>"text/openapi"</js>
)
<ja>@RestMethod</ja>
<jk>public</jk> String[] example1() {
<jk>return new</jk> String[]{<js>"foo"</js>,<js>"bar"</js>};
}
<jc>// Example 2 - Same as above. Annotation on parameter.</jc>
<ja>@RestMethod</ja>
<jk>public void</jk> example2(
<ja>@Response</ja>(
serializers=OpenApiSerializer.<jk>class</jk>,
defaultAccept=<js>"text/openapi"</js>
)
Value&lt;String[]&gt; body
)
{
body.set(<jk>new</jk> String[]{<js>"foo"</js>,<js>"bar"</js>});
}
}
</p>
<p>
The <c><ja>@Response</ja>(schema)</c> annotation can be used to define the format of the output using OpenAPI-based rules.
</p>
<p class='bpcode w800'>
<ja>@RestResource</ja>
<jk>public class</jk> ExampleResource {
<ja>@Response</ja>(
serializers=OpenApiSerializer.<jk>class</jk>,
defaultAccept=<js>"text/openapi"</js>,
schema=<ja>@Schema</ja>(collectionFormat=<js>"pipes"</js>)
)
<ja>@RestMethod</ja>
<jk>public</jk> String[] example1() {
<jk>return new</jk> String[]{<js>"foo"</js>,<js>"bar"</js>};
}
}
</p>
<h5 class='topic'>Swagger documentation</h5>
<p>
The attributes on this annotation are also used to populate the generated Swagger for the method.
For example, in the case of the <c>InvalidLogin</c> example above, the following Swagger is generated:
</p>
<p class='bpcode w800'>
<jok>'/user/login'</jok>: {
<jok>get</jok>: {
<jok>responses</jok>: {
<jok>401</jok>: {
<jok>description</jok>: <jov>'Invalid username or password provided'</jov>
}
}
}
}
</p>
<h5 class='topic'>Automatic HTTP status</h5>
<p>
When the {@link oaj.http.annotation.Response#code() @Response(code)} value is specified,
the HTTP status is automatically set to that value on the response regardless of how it's used.
</p>
<p>
The following two examples are equivalent:
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/ok"</js>)
<jk>public void</jk> sendContinue(
<ja>@Response</ja>(code=100) Value&lt;String&gt; body
)
{
body.set(<js>"OK"</js>);
}
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/ok"</js>)
<jk>public void</jk> sendContinue(RestResponse res) {
res.setStatus(100);
res.setOutput(<js>"OK"</js>);
}
</p>
<ul class='seealso'>
<li class='link'>{@doc juneau-rest-server.OpenApiSchemaPartSerializing}
</ul>