Springfox class Parameter is deprecated - swagger

In Springfox 3.0, springfox.documentation.service.Parameter is deprecated.
Is there a newer way of providing the parameter and its builder?
And how to provide its default value?

Firstly, use the RequestParameter for specify the Parameter in your Docket bean.
for its builder use RequestParameterBuilder class
RequestParameter can be look like this.
private RequestParameter authorizationParameter() {
RequestParameterBuilder tokenBuilder = new RequestParameterBuilder();
tokenBuilder
.name("Authorization")
.description("access_token")
.required(false)
.in("header")
.accepts(Collections.singleton(MediaType.APPLICATION_JSON))
.build();
return tokenBuilder.build();

#Bean
public Docket api() {
// Adding Header
RequestParameterBuilder aParameterBuilder = new RequestParameterBuilder();
aParameterBuilder.name("Cache-Control")
.query(q -> q.defaultValue("no-cache, no-store")
.model(modelSpecificationBuilder -> modelSpecificationBuilder.scalarModel(ScalarType.STRING)))
.in(ParameterType.HEADER).required(true).build();
List<RequestParameter> aParameters = new ArrayList<>();
aParameters.add(aParameterBuilder.build());
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("(?!/error.*).*")).build().apiInfo(metadata())
.globalRequestParameters(aParameters);
}

The swagger ui does not seem to work when you set required=true. If you leave the fields empty and click submit instead of the fields blinking red, the page goes busy and the spinner just spins forever without ever sending anything

Related

Deprecated APIs should be marked accordingly in the Swagger UI

Feature Request
Today it is possible to version APIs and most things around that work perfectly fine with Swagger. What I am really missing here is the possibility to make it transparent for any Swagger UI users that an API version has been marked as deprecated.
API deprecation in aspnetcore is described here.
My expectation would be to have an icon or a tag which says "OBSOLETE" or "DEPRECATED" next to the API group name.
On a side note:
The Swashbuckle Swagger ASPNET.Core github project issue tracker advised to open feature requests on SO.
Edit:
The whole Controller is marked as deprecated using the ApiVersion attribute. If you mark the controller as [Obsolete] all the methods are grey and text is striked through. However this is not what I am looking for. I don't want mark my codebase [Obsolete]. I want to mark a specific API version as deprecated so people know they should switch to a newer version.
[ApiVersion("1", Deprecated = true)]
[Route("v{version:apiVersion}/[controller]")]
[Authorize("my.auth.policy")]
[ApiController]
public class MyApiController
{
// do stuff
}
My current workaround is this:
In my Startup I add the swaggerUI and do a custom formatting on the swagger endpoint dropdown display.
app.UseSwagger();
app.UseSwaggerUI(options =>
{
foreach (ApiVersionDescription apiVersionDescription in apiVersionDescriptionProvider.ApiVersionDescriptions.OrderByDescending(a => a.ApiVersion))
{
string isDeprecated = apiVersionDescription.IsDeprecated ? " (DEPRECATED)" : string.Empty;
options.SwaggerEndpoint($"{Configuration["PathBase"]}/swagger/{apiVersionDescription.GroupName}/swagger.json",
$"{apiVersionDescription.GroupName.ToUpperInvariant()}{isDeprecated}");
}
});
#helen
Definition
public class CustomHeaderFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
var apiDescription = context.ApiDescription;
if (apiDescription.IsDeprecated())
{
operation.Deprecated = true;
}
}
}
Use
builder.Services.AddSwaggerGen(g =>
{
g.OperationFilter<CustomHeaderFilter>();
}).AddSwaggerGenNewtonsoftSupport();
The interface must have the following
[ApiVersion("1.0", Deprecated = true)]
public class WeatherForecastController : ControllerBase
result

How can I document objects that I don't have ownership over?

I'm returning a Page<SomeObject> In my method endpoints. In my OpenAPI UI, how can I generate a description of the fields that come from org.springframework.data.domain.Page type.
Normally what I do is go to the Object that I want to document and annotate its fields with #Schema(description = "some description"). But I don't have access to the Page class. How can I document its fields?
I'm probably missing something simple here, but any help would be appreciated.
PS: I am using OpenAPI v3 and springdoc
You can use OpenApiCustomiser.
Let's say for example you have this controller:
#RestController
public class HelloController {
#GetMapping("/hello")
Page<PersonDTO> getPage() {
return null;
}
}
Let's suppose you want add the description the Pageable element:
#Bean
public OpenApiCustomiser pageableOpenApiCustomiser() {
return openApi -> {
Schema pageableSchema = openApi.getComponents().getSchemas().get("Pageable");
pageableSchema.setDescription("my description");
};
}
The same logic applies for any other attribute you nned to customize.

Add Authorize Attribute Filter in Swashbuckler Implementation of Swagger

Looking to add the AuthorizeFilterAttribute or AnonymousFilterAttribute to an endpoint in Swashbuckle's implementation of Swagger so I can see which attribute is used on each endpoint in the generated documentation file in a running webapi that ends in /swagger. Is this currenlty possible?
I specifically would like to add a big bold label that says this endpoint is [Anonymous] or that endpoint is using [Authorize] and have them look differently that the summary or remark text.
Also I would like to be able to filter out all the different types of these restriction filter attributes for each endpoint including [NonAction], [Authorize], and [Anonymous] where one of these might be at the top of each controller endpoint. Maybe even eventually add other types of FilterAttributes besides these on each endpoint.
Currently it looks like only the HTTP Methods, the request and response objects can be retrieved in the current implementation so I was not able to find definitive information on this.
Since this is a Swagger implementation do these .NET specific attribute filters not translate to Swashbuckle b/c they only implement what's in the Swagger specification and nothing else?
Finally are their .NET specific extensions to Swashbuckle's implementation that do this?
Thanks!
For the part adding the label to unprotected methods/actions you could use an operation filter like this
public class UnprotectedOperationFilter : IOperationFilter
{
private bool HasAttribute(MethodInfo methodInfo, Type type, bool inherit)
{
// inhertit = true also checks inherited attributes
var actionAttributes = methodInfo.GetCustomAttributes(inherit);
var controllerAttributes = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(inherit);
var actionAndControllerAttributes = actionAttributes.Union(controllerAttributes);
return actionAndControllerAttributes.Any(attr => attr.GetType() == type);
}
public void Apply(Operation operation, OperationFilterContext context)
{
bool hasAuthorizeAttribute = HasAttribute(context.MethodInfo, typeof(AuthorizeAttribute), true);
bool hasAnonymousAttribute = HasAttribute(context.MethodInfo, typeof(AllowAnonymousAttribute), true);
// so far as I understood the action/operation is public/unprotected
// if there is no authorize or an allow anonymous (allow anonymous overrides all authorize)
bool isAuthorized = hasAuthorizeAttribute && !hasAnonymousAttribute;
if (!isAuthorized)
{
operation.Description =
"<p><bold>BIG BOLD LABEL indicating an UPROTECTED PUBLIC method</bold></p>"
+ operation.Description;
}
}
}
and add it with
services.AddSwaggerGen(c => { c.OperationFilter<UnprotectedOperationFilter>();} );
I didn't understand what you mean with filter out different attributes but I hope the code above helps you to check if the attribute is present and do what you desire to do.

mvc4 webapi custom json serializer for specific type

I know MVC4 uses NewtonSoft Json de/serialization. I was wondering how I can exclude a property on serialization to client, without using any of the data annotations like JsonIgnore/DataMemberIngore etc (the assembly is used elsewhere and can't be changed. Can I implement a custom formatter/JsonSerializerSettings/Dynamic ContractResolver etc for a specific object type and then filter out a specific property name?
Any help much appreciated.
Edit. Came up with the following as a first attempt. If anyone has a more elegant solution please let me know...
public class DynamicContractResolver : DefaultContractResolver
{
public DynamicContractResolver()
{
}
protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, Newtonsoft.Json.MemberSerialization.Fields);
if (type == typeof(SomeType))
{
var matchedProp = properties.Where(v=> v.PropertyName=="SomeProperty").FirstOrDefault();
if (matchedProp!=null)
{
properties.Remove(matchedProp);
}
}
return properties;
}
}
Plumbed into global.asax:
HttpConfiguration config = GlobalConfiguration.Configuration;
JsonSerializerSettings serializerSetting = new JsonSerializerSettings
{
ContractResolver = new DynamicContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};
config.Formatters.JsonFormatter.SerializerSettings = serializerSetting;
Regards
Phil
This is solvable with a proper overriding
Override a Json function(s) that is in the MVC Controller class.
In this class you can customize the data. (with another mapping,
with reflection, ...)
Create a custom JsonResult class, just override the default one. You
are also able to override there the default serialization which is
going on there.
Now:
You can exclude this data when you already have a JSON
serialized string ... This would be the easiest option. Basically just string operations.
On the other hand you will also be able to call a custom NewtonSoft
serialization and you can do there whatever you want ... Even use custom serializations.

how to programmatically handle navigation from backing bean in jsf2

I want to be able to do semething in the likes of:
#ManagedBean
class MyBackingBean {
public void processRequest() {
String viewName;
if (condition1)
viewName = "page1";
else if (condition2)
viewName = "pagexx";
invokeAndRenderXHTML(viewName);
}
}
thanks
Just in case anyone stumbles upon this old question:
you can programatically invoke navigation handler like this
FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null, "YOUR_NAVIGATION_CASE_DEFINED_IN_FACES_CONFIG");
JSF provides programmatic navigation by default. You do NOT need a third party library to effect navigation. To use JSF navigation, your method should simply return the name of the view you're trying to access and it'll navigate to that page. You could also include an optional redirect parameter to the return value to instruct the JSF context to redirect the response in full to the destination view. For your needs, just change processRequest to
public String processRequest() {
// String viewName unnecessary
if (condition1) {
return "page1";
}
else if (condition2) {
return = "pagexx";
}
return null;
// invokeAndRenderXHTML(viewName) becomes unnecessary
}
If you choose to have the redirect option like I indicated above just change the return String to
return "page1?faces-redirect=true"
the faces-redirect=true is the parameter that does the redirect magic
as you need a request to trigger a response i think there are two ways to go. either polling or push.
www.primefaces.org/showcase/ui/poll.jsf
www.primefaces.org/showcase/push/index.jsf
Check out primefaces showcase of both to get an understanding on which suits your need best. Even if you dont use the library you can look at the sources to get a better understanding of how to do this in jsf2

Resources