Angular and Swagger: Experiences Learned

RJ Dela-Cruz Angular, JavaScript, Technology Snapshot Leave a Comment

Recently I was fortunate enough to be a part of a project where we were building an application from scratch into an Angular front-end application with Microservices in the back end. Swagger was used as the contract between the UI and Microservices.

In this blog, I talk about the things I learned from this project experience, like how to use Swagger to define the endpoints of the Microservices, integrating Swagger-Generated code into Angular, and working with configuration including oAuth2 tokens, among other “gotchas.”

Learning More About Angular

If you read my previous blog about PWAs, I was teaching myself Angular 4+ during that time. I knew this project would give me the experience I needed. There weren’t as many “gotchas” going into the project as the Angular tutorials and documentation I read were very easy to pick up; I mean seriously, go through the Angular Tour of Heroes tutorial you will learn a lot. The part that took some time for me to grasp was the concepts of React Observables.

Enter the Swagger

Swagger is a tool used for designing and building APIs. This tool is extremely convenient.

The project was going to use Swagger to define the endpoints of the Microservices.

First, we designed the endpoints in a Swagger Document (YAML or JSON format). Then we used it to not only generate code for the API server, but also for the API client. So we had the luxury of defining what endpoints we need and then generating the code from it, which was valuable for get-together development sessions (such as agile mob programming).

Integrating Swagger-Generated Code into Angular

For my case, I was able to generate Angular TypeScript code from the Swagger documents we had defined. There were a couple of things that the code Swagger generated that had me scratching my head. It generated the domain models and the API services, however, it had other things it generated that I didn’t think we needed… but ended up using later.

I started referencing the API service code (this is the code used to talk to the API) into our application module, ignoring the API module that Swagger generated. In case the Swagger document changed, I imported the API module into our application module. This would make it easier to copy over the generated API module instead of changing the application module.

See Also:  Release: Hyperledger Blockchain Analytics Tool

Speaking of when the Swagger document changes, one approach I went forward with was to make sure we didn’t modify the Swagger-generated code. It would be a total nightmare if we started coding business logic or changing things around within the Swagger-generated code. This would cause the Swagger document to change, which means we would have to regenerate the code and merge it with the existing one. Instead, we decided to apply a wrapper pattern here and injected the Swagger generated service code into another service class that had business logic. This way, if we ever needed to regen the Swagger code, we simply copy it over without worrying about changes to the business logic.

The Configuration Conundrum

Now that we had the code to talk to the API, it was time to actually talk to the API. First, we needed to have the code point to the API URL. First instinct would be just to hardcode the URL into the API service (again, the code that was generated by Swagger to talk to the API). Remember we’re trying not to change the generated code if possible.

One of the things I found and didn’t take into consideration until later on in the project, is the configuration.ts file that Swagger generated. Here is an example one. The configuration class is injected into the API service code and used to set up a connection to the API. For instance, the basePath property in the configuration class contains the URL to the API used by the API service to make the API call.

We had to figure out a way to create a Configuration instance with the proper values populated for the API service code to use. Adding to the mix was the OAuth2 token we needed to pass to the APIs. We already had a service that talked to an IDP server and got us an OAuth2 token.

See Also:  Creating A Simple Library Using Angular CLI 6

However, we needed to figure out a way to use that token in our Configuration class. The API service code already does the work of including the token for us in the header whenever it makes the call to the API (super convenient by the way!), we just needed to provide the token through the Configuration class.

After a long search, I found a way by using the Provide Factory of Angular. In the application module when you define what to provide, you can specify how it is created. See the following code example:

function getConfig(myAuthService: MyAuthService) {
    return new Configuration({
        basePath: https: //someApi.org, 
            accessToken: myAuthService.getToken.bind(myAuthService)
    });
}

providers: [
    MyAuthService,
    {
        provide: Configuration,
        useFactory: getConfig,
        deps: MyAuthService,
        multi: false
    }
]

As you can see above, you tell Angular that whenever it tries to inject a Configuration instance to use the getConfig function to create one. The deps attribute tells it that the getConfig depends on the MyAuthService, while the multiset to false means it is only going to create one instance. It takes the token from the auth service and populates the accessToken property of the Configuration instance.

Overall

Looking back at my experience with Swagger and Angular, it was hard to imagine what it would’ve been like without Swagger.

There were many times we had to make changes to the Swagger document because of a business requirement change or a “technical gotcha,” but it didn’t slow down development because we could easily regenerate the code from the changes. It was dead scary how easy it was.

Out of all the projects I have worked on, this has been the most fun.

What Do You Think?