This is the second blog post in this series. Here is the previous blog post: reCAP 2023 – CAP Advanced Programming model #1.
In the previous blog post Wouter Lemaire explains our approach and gives a sneak peek of how the project is structured.
In this blog post you will learn how the approach makes it easier to create and maintain different
services, entities and operations.
Let’s start with where Wouter left off and explain how our “EntityFactory” works.
EntityFactory
As we can see with this one line of code, we first call the getInstance method which should already give a good idea what it does as it uses the singleton pattern.
We chose to use a singleton as the entityfactory will dynamically pick up all the handler files and load them in. We only want to do this once so within the contructor of the factory, a build method is being executed which does this for us.
A getAllFiles method is being called which uses a relative path (defined in the startDir constant) and recursively searches for all files within the project.
As we are only interested in files within our handler directory, we do a small check at line 39 with another constant which contains the name of the handler directory.
After that the code uses the require function from node and the path modules to load in the actual files we are interested in.
The rest of the build method will use the project structure and namespace to define if the required file is a handler, an unbound or a bound operation and saves it locally in the above attributes for further use hence the reasoning behind using the singleton pattern.
BaseHandler
Before we can continue with the applyhandlers method, we will take a look at another important part of the approach.
How can the entityfactory know what method of the handler, belongs to what event?
Here we can see that the event and types have been defined in specific types that can be passed along in the constructor of the handler.
By extending from the BaseHandler and passing along the event and type of the method that you would like to implement, the entityfactory will correctly bind the method to the service.
Important: The implementation needs to have the same name as the event and type as seen above (onRead).
There is 1 more additional feature of the BaseHandler that hasn’t been shown yet, but the EntityFactory will not directly apply the handler methods to the service. Instead it will us a wrapper method (namespace event+type+base) which allows us to have some additional functionality as seen in above snippet. In the onRead we could for example already pass the skip & top parameters and we could already split up single and multiple selects.
Next to that the wrapper method allows for generic error handling.
BaseService
Next to the BaseHandler, we also have a BaseService which can be retrieved directly from the handler by using the above method in the handler.
The BaseService also uses a singleton pattern so that we only connect once to the service and reuse the connection as seen in the connect and getInstance methods.
The only thing left for our actual service files is to pass along the destination in the constructor to our BaseService and the service file can then make use of this.cdsService to retrieve its data as seen in above snippet.
ApplyHandlers
Now that all the files are loaded in and saved within the “EntityFactory”, we can continue with the last step which will bind the correct method to the service.
We take the example here of the unbound operations, but the logic is very similar for bound operations and the handlers themselves.
Within the apply function we have the service passed via parameter so we can loop over the operations within the service itself as it is provided in the service object.
We can then use the name of the service and name of the operation to look into the array of the BaseHandler if a file has been loaded in or not.
If an implementation has been found, we can bind it on the service.
Important: If you would like to use the standard functionality of CAP (Going directly to the service/db without custom handler), this still works by not passing along the required type and event in the constructor of the handler.
This means that only methods that correspond to the passed event/type combination in the constructor, will be bound to the service.
This brings us to the end of this post and Dries Van Vaerenbergh will further explain how to actually use it in an example.
- What is it by Wouter: reCAP 2023 – CAP Advanced Programming model #1 | SAP Blogs
- How to use it by Dries: reCAP 2023 – CAP Advanced Programming model #3 | SAP Blogs