...
The main differnce in paths is based on the nesting pattern. There are multiple opinions on Nested Resources type of links. It helps with readability but it can lead to long URLs or redundant endpoints because of less flexibility in paths.
So and edpoint:
/policytypes/{policyTypeId}/policies/{policyId}
can become with policyTypeId in the body
/policies/{policyId}
Analysis Topics
1. Limitations of JSON Schema:
- JSON Schema Limitations:
- Pros:
- Standardized: JSON Schema provides a standardized way to define and validate the structure of JSON data.
- Widely Supported: Many tools and libraries support JSON Schema, making it easy to integrate with various technologies.
- Cons:
- Expressiveness: JSON Schema may lack the expressiveness needed for complex validation rules, such as interdependent fields.
- Readability: Large and complex schemas can become difficult to read and maintain.
...
2. Implement Adapter Pattern for Code Adaptation:
- Use the Adapter pattern to translate between different but similar objects, ensuring compliance with ORAN specifications without major code changes.
3. Use OpenAPI Tools for Code Generation:
- Leverage tools like OpenAPI Generator to generate client and server code, ensuring that implementations adhere to the defined contracts.
Pros and Cons of Java Patterns for Code Adaptation
All these solutions are viable, but will ad add complexity and abstraction to the code
...
1. Using `allOf`, `oneOf`, `anyOf`: https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/
- Combine multiple schemas using `allOf` to create a new schema that includes all properties.
- Use `oneOf` or `anyOf` to define schemas where only one or any combination of the listed schemas is valid, respectively.
...
2. Discriminator for Polymorphism: https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/
- Use the `discriminator` property to define inheritance and polymorphism in your schemas, allowing you to use a base schema with multiple derived schemas.
...
3. Extending and Overriding Schemas: (using 1)
- Create new schemas by extending existing ones to avoid duplication and ensure consistency.
...
4. Parameter and Response Reusability: (current)
- Define reusable parameters and responses in the components section and reference them in different paths.
Code Block | ||||
---|---|---|---|---|
| ||||
components: parameters: PolicyId: name: policyId in: path required: true schema: type: string paths: /policies/{policyId}: get: parameters: - $ref: '#/components/parameters/PolicyId' |
Schema Usage in Paths
Schema | Count | Paths |
---|---|---|
ErrorInformation | 4 | /policies/{policyId} , /policytypes/{policyTypeId}/policies , /policytypes/{policyTypeId}/policies/{policyId} , /policytypes/{policyTypeId}/policies/{policyId}/status |
JsonSchema | 2 | /policytypes/{policyTypeId}/policies , /policytypes/{policyTypeId}/policies/{policyId} |
NearRtRicId | 3 | /policies , /policies/{policyId} , /policytypes/{policyTypeId}/policies |
NotificationDestination | 1 | /policies/{policyId} |
PolicyId | 3 | /policies , /policies/{policyId} , /policytypes/{policyTypeId}/policies |
PolicyInformation | 2 | /policies/{policyId} , /policytypes/{policyTypeId}/policies/{policyId} |
PolicyObjectInformation | 1 | /policytypes/{policyTypeId}/policies/{policyId}/status |
PolicyStatusObject | 2 | /policies/{policyId} , /policytypes/{policyTypeId}/policies/{policyId}/status |
PolicyTypeId | 3 | /policytypes/{policyTypeId}/policies , /policytypes/{policyTypeId}/policies/{policyId} , /policytypes/{policyTypeId}/policies/{policyId}/status |
PolicyTypeInformation | 2 | /policytypes/{policyTypeId}/policies , /policytypes/{policyTypeId}/policies/{policyId} |
PolicyTypeObject | 1 |
|
Using allOf to Extend Objects
To avoid using the `required` flag directly and create more flexible schemas, we can use the allOf keyword to combine schemas. This allows you to create an extended schema from an original one without repeating required properties.
https://openapi-generator.tech/docs/generators/spring/#schema-support-feature | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
From the documentation of the openapi generator used in A1PMS, AllOf is not supported for spring server generator. But it still generated objects without the use of extending the parent class. For example: An extended object in the specification yaml:
|
OpenAPI Required Properties
In OpenAPI 3 by default, all object properties are optional. Required properties can be identified in the required list:
Code Block | ||||
---|---|---|---|---|
| ||||
components:
schemas:
Policy:
type: object
properties:
id:
type: string
name:
type: string
required:
- id |
Having required parameters has only one effect of genereted code, the tool generates only one construcotr with only default parameters. So the implementer can use the setters and getters.
Code Block | ||||
---|---|---|---|---|
| ||||
/**
* Constructor with only required parameters
*/
public Policy(String id, String name) {
this.id= id;
} |
Handling serviceId in Request Bodies and Bearer Tokens
Current Implementation
In the current implementation, the `serviceId` can be set in the body of a request and is defined as optional. The default value for `serviceId` in `PolicyObjectInformation` (PolicyApi) is a space, which accommodates cases where the `serviceId` might be missing. However, in the `ServiceApi`, the `serviceId` is required, for example, when creating a service.
Ideal Implementation
The use of a space as a default value for `serviceId` is a workaround to handle missing IDs. Ideally, the `serviceId` should be extracted from a bearer token. This can be done by decoding a JWT token using built-in Java functions.
Here’s a sample code snippet to decode a JWT token and extract the `serviceId`:
Code Block | ||||
---|---|---|---|---|
| ||||
String token = getAuthToken(receivedHttpHeaders);
String[] chunks = token.split("\\.");
Base64.Decoder decoder = Base64.getUrlDecoder();
String payload = new String(decoder.decode(chunks[1]));
JsonObject jsonObject = new JsonObject();
jsonObject.add("payload", JsonParser.parseString(payload));
String serviceId = jsonObject.getAsJsonObject("payload").get("serviceId").getAsString(); //if the json token has the field serviceId |
Integrating with Existing Code
In the codebase, there is already a function to get the token located in the class:
org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.AuthorizationCheck
String getAuthToken(Map<String, String> httpHeaders)
Bearer Token in Headers
The bearer token would be passed during the API call via headers as follows:
"Authorization: Bearer <bearer_token>"
By extracting the serviceId from the bearer token, we can ensure that the `serviceId` is always available and accurate, enhancing the security and reliability of the API.
TODO and topic to follow
- Evaluate the necessity of optional fields: Determine if certain optional fields can be removed or if their use can be better documented to avoid dead data.
- ** Consider adopting more specific schemas for critical operations: ** This can improve both the documentation and the generated code quality. Leverage OpenAPI Features: Use OpenAPI's advanced features like `allOf`,
- ** Prepare for code adaptations: ** Implement patterns like Adapter/Builder/Transformer to handle translations between similar objects, facilitating easier maintenance and adaptation to specification changes.
- ** Regular compliance checks:** Ensure regular checks against ORAN specifications to stay compliant and make necessary adjustments in a timely manner.
- **Adopt Specific Schemas:** Use specific schemas for different API operations to improve clarity and reduce the risk of errors.
- **Implement Adapter Pattern:** Use the Adapter pattern to manage differences between similar objects, ensuring compliance with ORAN specifications.
- **Leverage OpenAPI Features:** Use OpenAPI's advanced features like `allOf`, `oneOf`, `anyOf`, and discriminators to create flexible and reusable components.
- **Use OpenAPI Generator:** Automate code generation to ensure adherence to the defined contracts and reduce manual coding effort.
...
...