So you have started your gateway project from the scratch. You have an app to build which will parse many OData calls, churn a huge amount of business logic and seamlessly pass the information back and forth through the gateway. It can prove to be daunting. Especially while following Agile methodology where we have little time to plan our technical design and must remain open to a shifting scope throughout the breadth of the project.
I am a SAP Gateway developer. This is where we need to be able to use a little bit of organization skills and foresight so that our programs are efficient, re-usable and time saving. Here is a collection of wisdom that I have accumulated through my journey as a SAP Gateway developer. Now, this will not fit all your apps or scenarios but they will help shift your focus more towards the business logic and away from the data transmission mechanism.
- Always keep business logic in a separate class – It may be tempting to write the entire application in the DPC_EXT class and the corresponding methods that are conveniently generated for us, but keeping the business logic in a separate class has some advantages:
- Decluttered code – Once we start using the DPC_EXT class, it can quickly become unmanageable as our app begins to grow and we keep adding newer entities into the project. So from the get go, keep things separate. Allowing a mentality of compartmentalizing the code to foster from the beginning will let you create more artifacts if required and let you use the complete toolset of object-oriented programming methodology.
- Reusability – When you keep the app logic in its own class, you decouple the business logic from the presentation technology so that you can use the same application logic no matter which application is requesting it. It could be an ABAP report or a workflow and you can supply a consistent behavior to all of them.
- Use the INIT method – /IWBEP/IF_MGW_CORE_SRV_RUNTIME~INIT is a public method that is implemented in /IWBEP/CL_MGW_ABS_DATA from which our DPC_EXT class is eventually inherited. Redefine this method to initialize a lot of things that you’d want to get triggered every time an OData request is invoked. I use it to initialize the object of the application logic class that I had mentioned in point 1, pass the message container object to the constructor of the application logic class, generate and store the current timestamp in an attribute of the app logic class, obtain user profile information, check user roles etc.
In the example below, I am initializing my application logic class object O_APP_MAIN after redefining the INIT method.
- Parsing the input – Now no matter how big your project gets, we will mostly play with a limited set of input parameters that comes to the backend in forms of filter parameters or entity keys or http headers. But we keep writing the same code in different methods to be able to parse and use those parameters. Why not create a re-usable piece of code for this as well? Just plug it in and play! Here are the steps I like to follow:
a. Create the range structure and keep adding a new range field to the structure based on what your entity sets look like. Remember to name them so that their ABAP name in the entity property is same as their name in the structure.
Range Type and Structure:
b. Receive the technical context in each DPC_EXT method. Each Redefined method should have this exact call.
c. Dynamically parse the data so that your range gets filled up with filter/key values.
d. Create exceptions for parameters that have different names or need to be converted.
e. Now your app logic class method will have all your inputs in a range structure attribute for you to use in your queries.
Range structure getting filled up in runtime:
You can use the request context to extract information from the http headers or entity keys and fill up the same range tables.
- Handling Exceptions – In the app logic class I create a static attribute of type BAPIRET2 which I can use whenever required. It mostly acts as a dummy placeholder. Combination of these attributes and the message container object that we have passed to our class earlier, we can efficiently handle all kinds of exceptions.
- Quite blindly add the exception class /IWBEP/CX_MGW_BUSI_EXCEPTION to the exception section of every method interface of your app logic class. Don’t think much about whether they’d actually be used or not. They only result in a warning.
- Write a static method (say RAISE_EXCEPTION) with the following code in it.
- Whenever you have to raise an error message write them in this format – MESSAGE e<msgno>(<msgid>) WITH <msgv1> .. <msgv4> INTO <bapiret2 static attribute-message>. This will ensure that the message can be found in the ‘where-used’ list and also set the SYST variables for messages. Call the RAISE_EXCEPTION method right after.
- For any other kind of messages, use the message container object which has methods for different exception scenarios.
Raising message from another exception class:
- You’d still have to meticulously design your entities and their relationships. Spare no expenses when it comes to properly setting up the gateway project.
- You’d still have to redefine the entity methods as you create new entities.
- Can lead to some superfluous code in the name of dynamism. They may throw warning when sent through code inspector for some organizations depending on their development standards.
Set all these up in the beginning of the project and you can single-mindedly focus on the business logic.
If you are interested in viewing similar articles, visit our blog, here.
View our LinkedIn, here.