Representing a static response in Swagger - swagger

For certain operations, our API responds with static bits of JSON, for example:
{"status":"ok"}
The closest I've come to making a model definition for this is:
definitions:
OKMessage:
type: object
properties:
status:
type: string
enum: ['ok']
but it feels like there should be a more straightforward way of representing a static string in a model (and results in clearer docs). Is there something in the spec I'm missing?

I think that's the correct way to define the response. You may consider using just string (not enum) to give you flexibility in adding different values (e.g. error, processing, etc) in the future.

Related

Swagger (hub) how to write certain type

I'm on the swaggerhub website and i need to do an API documentation.
I'm trying to define an object with multiple elements, most of which are basic, but one of the properties is another object, NOT ARRAY, but that child object can contain one or more properties (ALL OF SAME TYPE).
I need to make an object that looks like an array.
Lets say my big object is 'User', and the object that gives me problems is 'addresses':
User:
properties:
name:
type: string
adresses:
type: object
Example:
User:
name: Alex
addresses: {
address: {...}
address2: {....}
address3: {....}
}
I have the Address type defined, but 'addresses' must be an object (meaning that it should look like a json, and not with []). How do i make 'addresses' have variable length?? Maybe with 4 addresses, or only 2.
I want to write examples for this in the API documentation, and i want it to be of variable length, because that's how the API actually works, with a JSON, not an array.
Have you checked the OpenAPI Specification page for help on writing parts of your API definition? It's a great resource that goes into depth on how to write multiple aspects of your API.
Specification page is here: https://swagger.io/specification/
You can browse through topics on the left-hand side. What should be helpful here is the sections under Specification > Schema. There's a lot of information on how to write various types of objects.

Uri class throws error when queryParameters contains a key with a value: false?

I was working through some code, and noticed:
return new Uri(host: server, path: apiPath, query: query, queryParameters: queryParams);
This code is executed regularly throughout the application, and the only difference was queryParams. So i printed it out:
{Id:[1234], enabled:false}
shows it is a key:value set of: Id:List, enabled:boolean.
The stack trace i get is:
which shows the map and then the trace. #6 points to the above line.
It is looking at false... something with iterating false is what breaks this.
When dealing with the URI and query parameters, it is looking for numerics, lists, and strings but not booleans. In order to resolve this and allow it to function correctly, you will need to do:
{"enabled": false.toString()}
// or
{"enabled": "false"}
and the uri class will set the query parameter accordingly.
The Uri class is located in core library for Dart. When we are using it, we are passing in the created Uri object into an action for a client class,
Client client = new BrowserClient();
which accepts the url as a part of the parameters.
While looking at the errors above though, the Uri class ultimately is unable to properly parse a false value to an accepted value.
When looking at the Code Docs for Uri as per the Dart languages: https://api.dartlang.org/dev/1.25.0-dev.7.0/dart-core/Uri/Uri.html
The query component is set through either query or queryParameters. When query is used, the provided string should be a valid URI query, but invalid characters, other than general delimiters, will be escaped if necessary. When queryParameters is used the query is built from the provided map. Each key and value in the map is percent-encoded and joined using equal and ampersand characters. A value in the map must be either a string, or an Iterable of strings, where the latter corresponds to multiple values for the same key.
Which makes sense to say all values must be String or an Iterable of Strings. The only thing which I cant figure out is that in Dartpad, true and false have toString functions, and yet you can also pass numerics in there.
The only conclusion is that while it accepts Strings and Iterables of Strings, it will also parse ints and other numerics because they will explicitly check for that type as it is common to see in URI.
One would think that the URI would understand booleans since those are also common place, but that is yet to be seen since I cant take an explicit look at the source code for dartlang. I did however manage to look at the source code for it and narrowed it down. writeComponent points to _Uri._uriEncode but when looking at that function, there is no code as much as just a definition.
HTH.

Grails find existing record by criteria

I have (among others) two domain classes:
class Course {
String name
...
}
class Round {
Course course
String startweek // e.g. '201504'
String endweek // e.g. '201534'
String applcode // e.g. 'DA542133'
...
}
Application codes may be issued at several occasions and are then concatenated with 'applcode's separated by blanks. As I am streaming and parsing large amount of data (in XML format) from different sources, I might stumble on the same data from several sources, so I look up the records in the database to see if I may discard the rest of the stream or not. This is possible as the outermost tag contains data stating the above declared attributes. I search the database using:
def c = Course.findByName(name);
def found =
Round.findByCourseAndStartweekAndEndweekAndApplcodeLike(c, sw, ew,'%'+appc+'%')
where the parameters are fairly obvious and which works well but I find these 'findByBlaAndBlablaAnd...' very long and not very readable. My aim here is to find some more readable and thereby more comprehensible method. I have started to read about Criteria and HQL but I think one example or two would help me on the way.
Edit after reading the pages on the link provided by #injecteer:
It was fairly simple to make out the query above. I have worse thing to figure out but the query in my example became with criteria:
def found = Round.createCriteria().get {
eq ('course', c)
eq ('startweek', sw)
eq ('endweek', ew)
like ('applcode', '%'+appc+'%')
};
Much easier to read and understand than the original question.

Can I specify the response directly in Swagger 2.0?

I am defining my response as per:
responses:
200:
description: 'An authProvider object'
schema:
type: 'array'
items:
$ref: '#/definitions/AuthProvider'
Is it possible for me to directly attach another field or 2 in the response? I would like to add something that I don't want to put into AuthProvider
Whenever $ref is used, it's basically using JSON Reference. By definition (see linked spec), anything defined within the same object as the reference itself is ignored. As such, it is not possible to directly add additional properties alongside with the $ref definition.
That said, you can use composition to 'combine' two objects into one. This is done using the allOf JSON Schema directive. A simple example for such a definition would look like this:
allOf:
-
$ref: "..."
-
properties:
property1:
type: "string"
property2:
type: "boolean"
Note 1: The various Swagger tools out there may not fully support composition at the moment.
Note 2: As always, it's normally better to externalize the definition (even if used only once) rather than being defined inline.

Web Service Contributing ID Disambiguation

I work with a Web Service API that can pump through a generic type of Results that all offer certain basic information, most notably a unique ID. That unique ID tends to be--but is not required to be--a UUID defined by the sender, which is not always the same person (but IDs are unique across the system).
Fundamentally, the API results in something along the lines of this (written in Java, but the language should be irrelevant), where only the base interface represents common details:
interface Result
{
String getId();
}
class Result1 implements Result
{
public String getId() { return uniqueValueForInstance; }
public OtherType1 getField1() { /* ... */ }
public OtherType2 getField2() { /* ... */ }
}
class Result2 implements Result
{
public String getId() { return uniqueValueForInstance; }
public OtherType3 getField3() { /* ... */ }
}
It's important to note that each Result type may represent a completely different kind of information. Some of it cannot be correlated with other Results, and some of it can, whether or not they have identical types (e.g., Result1 may be able to be correlated with Result2, and therefore vice versa, but some ResultX may exist that cannot be correlated because it represents different information).
We are currently implementing a system that receives some of those Results and correlates them where possible, which generates a different Result object that is a container of what it correlated together:
class ContainerResult implements Result
{
public String getId() { return uniqueValueForInstance; }
public Collection<Result> getResults() { return containedResultsList; }
public OtherType4 getField4() { /* ... */ }
}
class IdContainerResult implements Result
{
public String getId() { return uniqueValueForInstance; }
public Collection<String> getIds() { return containedIdsList; }
public OtherType4 getField4() { /* ... */ }
}
These are two containers, which present different use cases. The first, ContainerResult, allows someone to receive the correlated details as well as the actual complete, correlated data. The second, IdContainerResult, sacrifices the complete listing in favor of bandwidth by only sending the associated IDs. The system doing the correlating is not necessarily the same as the client, and the client can receive Results that those IDs would represent, which is intended to allow them to show correlations on their system by simply receiving the IDs.
Now, my problem may be non-obvious to some, and it may be obvious to others: if I send only the ID as part of the IdContainerResult, then how does the client know how to match the Result on their end if they do not have a single ID-store? The types of data that are actually represented by each Result implementation lend themselves to being segregated when they cannot be correlated, which means that a single ID-store is unlikely in most situations without forcing a memory or storage burden.
The current solution that we have come up with entails creating a new type of ID, we'll call it TypedId, which combines the XML Namespace and XML Name from each Result with the Result's ID.
My main problem with that solution is that it requires either maintaining a mutable collection of types that is updated as they are discovered, or prior knowledge of all types so that the ID can be properly associated on any client's system. Unfortunately, I cannot come up with a better solution, but the current solution feels wrong.
Has anyone faced a similar situation where they want associate generic Results with its original type, particularly with the limitations of WSDLs in mind, and solved it in a cleaner way?
Here's my suggestion:
You want to have "the client know how to match the Result on their end". So include in your response an extra discriminator field called "RequestType", a String.
You want to avoid "maintaining a mutable collection of types that is updated as they are discovered, or prior knowledge of all types so that the ID can be properly associated on any client's system". Obviously, each client request call DOES know what area of processing the Result will relate to. So you can have the client pass the "RequestType" string in as part of the request. As long as the RequestType is a unique string for each different type of client request, your service can process and correlate it without hard-coding any knowledge.
Here's one possible example of java classes for request and response messages (i.e. not the actual service endpoint):
interface Request {
String getId();
String getRequestType();
// anything else ...
}
interface Result {
String getId();
String getRequestType();
}
class Result1 implements Result {
public String getId() { return uniqueValueForInstance; }
public OtherType1 getField1() { /* ... */ }
public OtherType2 getField2() { /* ... */ }
}
class Result2 implements Result {
public String getId() { return uniqueValueForInstance; }
public OtherType3 getField3() { /* ... */ }
}
Here's the gotcha. (2) and (3) above do not give a completely dynamic solution. You want your service to be able to return a flexible record structure relating to each different request. You have the following options:
4A) In XSD, declare Result as a singular strongly-typed variant record type, and in WSDL return Result from a single service endpoint and single operation. The XSD will still need to hardcode the values for the discriminator element when declaring variant record structure.
4B) In XSD, declare multiple strongly-typed unique types Result1, Result2, etc for each possible client request. In WSDL, have a multiple uniquely named operations to return each one of these. These operations can be across one or many service endpoints - or even across multiple WSDLs. While this avoids hard coding the request type as a specific field per se, it is not actually a generic client-independent solution because you are still explicitly hard-coding to discriminate each request type by creating a uniquely name for each result type and each operation. So any apparent dynamism is a mirage.
4C) In XSD, define a flexible generic data structure that is not variant, but has plenty of generally named fields that could be able to handle all possible results required. Example fields could be "stringField1", "stringField2", "integerField1", "dateField1058", etc. i.e. use extremely weak typing and put the burden on the client to magically know what data is in each field. This option may be very generic, but it is usually considered terrible practice. It is inelegant, pretty unreadable, error prone and has limitations/assumptions built in anyway - how do you know you have enough generic fields included? In your case, (4A) is probably the best option.
4D) Use flexible XSD schema design tactics - type substitutability and use of "any" element. See http://www.xfront.com/ExtensibleContentModels.html.
4E) Use the #Produces #SomeQualifier annotations against your own factory class method which creates a high level type. This tells CDI to always use this method to construct the specificied bean type & qualifier. Your factory method can have fancy logic to decide which specific low-level type to construct upon each call. #SomeQualifier can have additional parameters to give guidance towards selecting the type. This potentially reducing the number of qualifiers to just one.
If you use (4D) you will have a flexible service endpoint design that can deal with changing requirements quite effectively. BUT your service implementation still needs to implement the flexible behaviour to decide which results fields to return for each request. Fact is, if you have a logical requirement for varying data structures, your code must know how to process these data structures for each separate request, so must depend on some form of RequestType / unique operation names to discriminate. Any goal of completely dynamic processing (without adapting to each client's needs for results data) is over-ambitious.

Resources