Errors Building a library of web services is only worthwhile if you have a way to find those services. Like any library, a web service library needs a catalog. We build our catalog with a tool that scans our web services code and produces a set of JSON objects that describe the available services. These JSON objects, in turn, can then be displayed in a user interface that presents them as a catalog of services. This level of automation represents a real step forward, but we need to go a little further. We need to add a component to the process that will automatically analyze the catalog data and looking for gaps, services that developers may have neglected to document either in whole or in part. Building and plugging in that component is what we need you to do. As you proceed, lets make a point to meet briefly (15 minutes or so) each morning to review progress, issues and questions. Step 1 Read the background documentation on the tool http://dstconnect.dstcorp.net/display/ALLOY/USIRKS+API+Catalog Read the above page, take a look at the linked catalog, and peruse the linked documentation on the Swagger specification. Jot down questions and observations, and we can cover them in our morning standups. Step 2 Set up the Business Services Library (BSL) http://dstconnect.dstcorp.net/display/ALLOY/BSL+Developer+Setup The link above describes how to set up the Business Services Library (our framework for building web services). Youll just need to run the library import script described on the above page and the component script to import the AssetMgmtServices component (hint: component is the term we use to describe a project that has a bundle of related web services in it). Before you get started, be sure to check the prerequisites below. If youre missing any, we can chat about the best way to satisfy them. Prerequisites: Git ID and SCM Git Install 2
Basic knowledge of Git (enough to run a script to clone a workspace) Basic knowledge of Spring and Spring MVC (we have video training courses for this) Basic knowledge of Maven STS (Spring-optimized version of Eclipse) If you were going to develop web services, I would suggest you go through full training on the BSL. But your real focus is on the tool, and I can give you enough background on the BSL for your task in under half an hour, once you have the code on your machine. Step 3 Get the documentation tool running on your machine As the catalog page notes, the documentation tool is a Java doclet: BusinessServicesDoclet. You can retrieve it using the bsl_component script from the BSL set up page. After cloning the repository, just import it into your workspace as you would any Java project. The catalog documentation page describes how to run the tool. Your goal on this step is to get the tool running and producing documentation that displays through your local web server (see Prerequisite below). Prerequisite: Apache httpd 2.2 (web server) contact me for a configuration file once you have this set up Step 4 Review the documentation tool process and data From a process perspective, the doclet proceeds in three main steps: parsing the code and comments to build structured objects with the API documentation, organizing the raw documentation and rendering the documentation into distinct JSON files. Your validation process will not need to worry about the code scan. Instead it will be dealing with the structured objects that contain the API documentation after they have been organized. The documentation is broken into two main groups: APIs (information about the service operations) and Models (the request data sent to service and response data received from services). After the organization step, the APIs and the models related to them are grouped into ApiDeclaration objects, the complete collection of which is held by the ParsedResources object. 3
class businessservices parse::ParsedResources - l ogger: Logger = LoggerFactory ... {readOnl y} - model s: Map<Stri ng, Model > = new HashMap<Str... - opti ons: Servi cesDocl etOpti ons - resourceLi sti ng: ResourceLi sti ng - resourcePathMap: Map<Stri ng, Api Decl arati on> = new HashMap<Str... + addModel s(Li st<Model >) : voi d + addResource(Stri ng) : Api Decl arati on + bui l dResourceLi sti ng() : ResourceLi sti ng + di stri buteModel s() : voi d - fi ndRequestModel s(Api Decl arati on, Operati on) : voi d + fi ndResource(Stri ng) : Api Decl arati on - fi ndResponseModel s(Api Decl arati on, Operati on) : voi d - getModel Dependenci es(Stri ng) : Map<Stri ng, Model > + getModel s() : Map<Stri ng, Model > + getOpti ons() : Servi cesDocl etOpti ons + getResourceLi sti ng() : ResourceLi sti ng + getResourcePathMap() : Map<Stri ng, Api Decl arati on> - popul ateParameterFromRequestModel (Parameter, Map<Stri ng, Model >) : voi d + setModel s(Map<Stri ng, Model >) : voi d + setOpti ons(Servi cesDocl etOpti ons) : voi d + setResourceLi sti ng(ResourceLi sti ng) : voi d + setResourcePathMap(Map<Stri ng, Api Decl arati on>) : voi d model::ApiDeclaration - api Map: Map<Stri ng, Api > = new HashMap<Str... - api s: Li st<Api > - api Versi on: Stri ng - basePath: Stri ng - descri pti on: Stri ng - l ogger: Logger = LoggerFactory.g... {readOnl y} - model s: Map<Stri ng, Model > = new HashMap<Str... - resourcePath: Stri ng - swaggerVersi on: Stri ng + fi ndApi (Stri ng) : Api + getApi Map() : Map<Stri ng, Api > + getApi s() : Li st<Api > + getApi Versi on() : Stri ng + getBasePath() : Stri ng + getDescri pti on() : Stri ng + getModel s() : Map<Stri ng, Model > + getResourcePath() : Stri ng + getSwaggerVersi on() : Stri ng + setApi s(Li st<Api >) : voi d + setApi Versi on(Stri ng) : voi d + setBasePath(Stri ng) : voi d + setDescri pti on(Stri ng) : voi d + setModel s(Map<Stri ng, Model >) : voi d + setResourcePath(Stri ng) : voi d + setSwaggerVersi on(Stri ng) : voi d model::Api - descri pti on: Stri ng = "" - operati ons: Li st<Operati on> = new ArrayLi st<O... - path: Stri ng = "" + getDescri pti on() : Stri ng + getOperati ons() : Li st<Operati on> + getPath() : Stri ng + setDescri pti on(Stri ng) : voi d + setOperati ons(Li st<Operati on>) : voi d + setPath(Stri ng) : voi d model::Model - descri pti on: Stri ng - i d: Stri ng - i sAl i ased: bool ean = fal se - properti es: Map<Stri ng, Model Property> = new HashMap<Str... - requi red: Li st<Stri ng> + getDescri pti on() : Stri ng + getId() : Stri ng + getProperti es() : Map<Stri ng, Model Property> + getRequi red() : Li st<Stri ng> + i sAl i ased() : bool ean + setAl i ased(bool ean) : voi d + setDescri pti on(Stri ng) : voi d + setId(Stri ng) : voi d + setProperti es(Map<Stri ng, Model Property>) : voi d + setRequi red(Li st<Stri ng>) : voi d * 1 * 1 * 1 4
A closer look at the API object:
class API model::Api - descri pti on: Stri ng = "" - operati ons: Li st<Operati on> = new ArrayLi st<O... - path: Stri ng = "" + getDescri pti on() : Stri ng + getOperati ons() : Li st<Operati on> + getPath() : Stri ng + setDescri pti on(Stri ng) : voi d + setOperati ons(Li st<Operati on>) : voi d + setPath(Stri ng) : voi d model::Operation - dataAccessComponents: Li st<Stri ng> = new ArrayLi st<S... - dstServi ceRequest: Stri ng - method: Stri ng = "" - ni ckname: Stri ng = "" - notes: Stri ng - operati onType: Stri ng = "" - parameters: Li st<Parameter> = new ArrayLi st<P... - responseMessages: Li st<ResponseMessage> = new ArrayLi st<R... - summary: Stri ng = "" + getDataAccessComponents() : Li st<Stri ng> + getDstServi ceRequest() : Stri ng + getMethod() : Stri ng + getNi ckname() : Stri ng + getNotes() : Stri ng + getOperati onType() : Stri ng + getParameters() : Li st<Parameter> + getResponseMessages() : Li st<ResponseMessage> + getSummary() : Stri ng + setDataAccessComponents(Li st<Stri ng>) : voi d + setDstServi ceRequest(Stri ng) : voi d + setMethod(Stri ng) : voi d + setNi ckname(Stri ng) : voi d + setNotes(Stri ng) : voi d + setOperati onType(Stri ng) : voi d + setParameters(Li st<Parameter>) : voi d + setResponseMessages(Li st<ResponseMessage>) : voi d + setSummary(Stri ng) : voi d model::Parameter - dataType: Stri ng = "" - descri pti on: Stri ng = "" - format: Stri ng = "" - name: Stri ng = "" - paramType: Stri ng = "" - requi red: bool ean + getDataType() : Stri ng + getDescri pti on() : Stri ng + getFormat() : Stri ng + getName() : Stri ng + getParamType() : Stri ng + i sRequi red() : bool ean + setDataType(Stri ng) : voi d + setDescri pti on(Stri ng) : voi d + setFormat(Stri ng) : voi d + setName(Stri ng) : voi d + setParamType(Stri ng) : voi d + setRequi red(bool ean) : voi d * 1 * 1 5
A closer look at Models:
class Models model::Model - descri pti on: Stri ng - i d: Stri ng - i sAl i ased: bool ean = fal se - properti es: Map<Stri ng, Model Property> = new HashMap<Str... - requi red: Li st<Stri ng> + getDescri pti on() : Stri ng + getId() : Stri ng + getProperti es() : Map<Stri ng, Model Property> + getRequi red() : Li st<Stri ng> + i sAl i ased() : bool ean + setAl i ased(bool ean) : voi d + setDescri pti on(Stri ng) : voi d + setId(Stri ng) : voi d + setProperti es(Map<Stri ng, Model Property>) : voi d + setRequi red(Li st<Stri ng>) : voi d model::ModelProperty - descri pti on: Stri ng - format: Stri ng - i tems: Model Property - name: Stri ng - propertyType: Stri ng - ref: Stri ng + getDescri pti on() : Stri ng + getFormat() : Stri ng + getItems() : Model Property + getName() : Stri ng + getPropertyType() : Stri ng + getRef() : Stri ng + setDescri pti on(Stri ng) : voi d + setFormat(Stri ng) : voi d + setItems(Model Property) : voi d + setName(Stri ng) : voi d + setPropertyType(Stri ng) : voi d + setRef(Stri ng) : voi d * 1 6
Step 5 Review the error conditions Here are the error conditions that you will be checking for: Level Violation Locator Field Notes Api.Operation The operation has not been classified into a resource group. Api.path : Operation.method : Operation.nickname If ApiDeclaration.resourcePath is /uncategorized or blank This will be reported for all operations within all Apis in an /uncategorized ApiDeclaration. Thats the default grouping the parser applies to any services without a resource group assigned. Api.Operation The operation lacks a request model. Api.path : Operation.method : Operation.nickname If Operation.dstServiceRequest is blank
Api.Operation The operations request model cannot be found in the documentation. Api.path : Operation.method : Operation.nickname If Operation.dstServiceRequest (non-blank) cannot be found in the ApiDeclaration model map (ApiDeclaration.models)
Api.Operation The operation lacks a response model Api.path : Operation.method : Operation.nickname If Operation.type is blank Api.Operation The operations response model cannot be found in the documentation. Api.path : Operation.method : Operation.nickname If Operation.type (non-blank) cannot be found in the ApiDeclaration model map (ApiDeclaration.models)
Api.Operation The operation has no summary description. Api.path : Operation.method : Operation.nickname If Operation.summary is blank Api.Operation The parameter has no type. Api.path : Operation.method : Operation.nickname : Parameter.name If Parameter.paramType is blank
Model.Property The model property has no Model.property.description If Model.Property.description 7
description. is blank
Step 6 Review the error format Ultimately, we want the errors to be output to file. Weve played with a few different ideas in that regard, but as a practical matter have settled on simple XML. We see two files, one for operation errors and the other for model errors.
8
Operations
Models
Step 7 Propose a design
<?xml version="1.0" encoding="UTF-8"?> <documentationErrors> <documentationError> <type>Operation</type> <code>OP001</code> <message>The operation has not been classified into a resource group</message> <component>ServiceProvidersController.getServiceProviders</component> <path>/fund-sponsors/{fundSponsorId}/funds/{fundCode}/service-providers</path> <method>GET</method> <parameter></parameter> </documentationError> </documentationErrors> <?xml version="1.0" encoding="UTF-8"?> <documentationErrors> <documentationError> <type>Model</type> <code>M001</code> <message>The operation has not been classified into a resource group</message> <component>RedeemExceptionProcessRequestDTO</component> <property>idvTotalAccountValueAt</property> </documentationError> </documentationErrors> 9
Take some time to digest all of the above and then propose a design that we can discuss.