Quantcast
Channel: SCN : Blog List - ABAP Connectivity
Viewing all 68 articles
Browse latest View live

WebSocket Communication Using ABAP Push Channels

$
0
0

ABAP Push Channel (APC) is the ABAP framework for supporting WebSockets in ABAP engine. This framework is part of the ABAP Channles infrastructure, which is delivered with NW ABAP 740 support package 2 (SP2) for simple tests and prototyping and released with 740 support package 5 (SP5).

 

The basic idea of the ABAP Channels (see figure 1) is the native support of interactive and collaborative scenarios based on event-driven architecture. The scope of ABAP Channels consists of the following communication channels:


  • ABAP Push channel for bi-directional communication with user agents via WebSockets in ABAP. In figure 1 the documents tagged with letter "P" mark the ABAP Push Channel communication paths.


  • Publish/subscribe infrastructure for exchange of messages between either user sessions (Session C => Session A) or user session and user agents (Session C => User Agent B) residing on different servers via ABAP Messaging Channels. In figure 1 the documents tagged with letter "M" mark the ABAP Messaging Channels communication paths.

AC_Basic_Scenario.PNG

Figure 1: ABAP Channels supports eventing in ABAP

 

Most ABAP applications task use polling techniques to achieve an even-driven communication. For example for pushing an event from ABAP backend to a browser based user-agent, e.g. WebDynpro, Business Server Pages (BSP) or WebGUI, a pooling (in multi-seconds interval) against ICM cache is frequently used. This is a quit system resource consuming technique based on polling against a shared object area or database table, i.e. by checking the content of the shared area for the existence of an event. In SAPGUI usually the timer control is used to detect an event in the back-end. One of the the main goals of  ABAP Channel technology is- whenever possible -  to replace this type of inefficient eventing based on polling techniques.

 

The ABAP channels supports the following use-cases:

  1. ABAP Push Channel (APC): The WebSocket integration in ABAP.
  2. ABAP Messaging Channel (AMC): Eventing framework for messages exchange between different ABAP sessions based on publish/subscribe channels.
  3. Collaboration scenario: Using APC and AMC to push messages from ABAP sessions to WebSocket clients by binding publish/subscribe channels to the WebSocket connection.

 

In this article we focus on the WebSocket framework in ABAP called ABAP Push Channel.

 

 

Integration of WebSocket into ABAP engine

In order to pass an event from the ABAP engine to an HTML5 based user agent we decided to integrate the WebSocket protocol into the ABAP engine.WebSocket provides a bi-directional communication channel over a TCP/IP socket. It is designed to be implemented in web browsers and web servers, but in general it can be used by any client or server application. The WebSocket JavaScript APIis standardized by the W3C, whereas the WebSocket protocol (RFC 6455) is standardized by the IETF. The WebSocket protocol is supported by many new browsers, e.g.  Chrome 14, Firefox 7.0, IE 10 and Safari on iOS6 (and higher).


The implementation of the WebSocket protocol (RFC 6455) in ABAP is called ABAP Push Channel (APC).The APC communication is stateless per default, i.e. each WebSocket message leads to he creation of an individual ABAP session for execution of the respective method. After termination of the method the session will be released. In contrast to the existing request-response-based communication protocols, e.g. Remote Function Call (RFC) and HTTP(S), APC is a message-based protocol, i.e. per default the execution of a message does not lead to a response. However on top of the messaging protocols various communication patterns can be built, also a request-response-based communication. This is possible because the APC session has been implemented as a new session type..

 

It is important to have an understanding for the WebSocket events and methods before starting to explain how the WebSocket protocol has been integrated into the ABAP engine. The following simple sample code snippet shows how to use the JavaScript WebSockets interface (the essential events and methods are in bold format):

 

WebSocket JavaScript example code

   // open a WebSocket connection

     var ws = new WebSocket("ws[s]://host.domain:port/path?query_string");

 

     ws.onopen = function()

     {

        // WebSocket is connected, send data using send()

        ws.send("Sending Message ....");

        alert("Message is sent...");

     };

 

     ws.onmessage = function (msg)

     {

        // process received Message

        alert(msg.data);

 

        // optionally close connection
         ws.close();

     };

 

     ws.onclose = function()

     {

         // WebSocket is closed.

         alert("Connection is closed...");

     };


 

In APC framework the involved events and methods are very similar. A simple APC class handler would have the following events and methods.

 

APC example code

CLASS YCL_APC_WS_EXT_YEXAMPLE IMPLEMENTATION.


     METHOD if_apc_ws_extension~on_start( i_context type ref to  if_apc_ws_context ).

      " WebSocket connection has been established

     ENDMETHOD.

 

     METHOD if_apc_ws_extension~on_message( i_message type ref to  if_apc_ws_message ).

       " Message has been received

        TRY.

         " Echo the message on WebSocket connection

              data(lo_message_manager) = i_message->get_context( )->get_message_manager( ).

              lo_message = lo_message_manager->create_message( ).

              lo_message->set_text( i_message->get_text( ) )

 

              " Send message

              lo_message_manager->send( lo_message ).

           CATCH cx_apc_error INTO lx_apc_error.

              ...

          ENDTRY.

     ENDMETHOD.

 

     METHOD if_apc_ws_extension~on_close.

       " WebSocket is closed

     ENDMETHOD.


ENDCLASS.

 

The following diagram (figure 2.0) shows the interaction model of WebSocket client, e.g. HTML5-enabled browser, and APC framework in the ABAP engine of the NetWeaver application server.

 

APC_WebSocket_Interaction.jpg

Figure 2.0: WebSocket/APC interaction model in ABAP


 

The main advantage of the integration model is based on the fact that WebSocket connections are administrated by an ICM process, i.e. the end-point of a connection is the ICM process and not the ABAP session. This design helps to reduce resource consumption during inactivity phases of WebSocket communication. Furthermore APC applications are stateless per default.This means that each received message is handled in a dedicated session. The  application can preserve its state information either in shared object areas or database tables.


Creating an ABAP Push Channel (APC) application

This section contains a step by step description of the creation of an ABAP Push Channel application.

 

Before starting with development of an APC application we should check the prerequisites for the WebSocket environment in ABAP. From support package 5 upwards the WebSocket configuration is active per default. The WebSocket connection uses the same ports as the maintained HTTP and HTTPS ports and there is no explicit entry for "WEBSOCKET" and "WEBSOCKETS" services in service entries of transactionSMICM. This is different in lower releases. In NetWeaver 740 support package 2 up to support package 4, the WebSocket port parameters were maintained actively. This can be done in two different ways:

    • Manually and  temporarily in the transaction SMICM (via menu entry "Goto" -> "Service" and again in menu "Service" -> "Create") you can choose a proper port number for the field "New Service Port" , e.g. 50090 or 44390 for secure or non-secure WebSocket (WS), and then in the field "Protocol" enter "WEBSOCKET" (non-secure WebSocket) or "WEBSOCKETS" (secure WebSocket).
    • Alternatively, enabling ABAP to use WebSockets can be performed by setting ICM profile parameters. In the profile of the instances supporting WebSockets, some parameters must be added. Example:

icm/server_port_101 = PROT=WEBSOCKET,PORT=0,TIMEOUT=-1
icm/server_port_102 = PROT=WEBSOCKETS,PORT=0,TIMEOUT=-1

assuming that 101 and 102 are not yet used by other server_ports.

Port number is always 0. Timeout is always -1.

 

An ABAP Push Channel (APC) application can be created in two ways.

 

    • In transaction SE80 using the context menu entry ("Right-Click on top-level package object) "Create" -> "Connectivity" -> "ABAP Push Channel" (see figure 2.1):

APC_CREATE_SE80.png

Figure 2.1.



    • As of release 740 SP5: In the transaction SAPC using the context menu entry ("Right-Click") on the "ABAP Push Channel" entry and selecting "Create" (see figure 2.2):

       

      APC_CREATE_SAPC.png

      Figure 2.2.

       


      In the next step, the name of the APC application has to be enteredand the popup screens have to be confimed (press "Enter"). In this example "YAPC_WS_TEST" is used as application name(see figure 2.3):

      popup_1.pngFigure 2.3.


       

      Also choose an appropriate package entry, in this case as "Local Object"(see figure 2.4):

      popup_object_catalog.png

      Figure 2.4.


       

      Additionally, the field "Description" has to be maintained(see figure 2.5):

      apc_description.png

      Figure 2.5.



      Next step: save the application(see figure 2.6):

      apc_application_save.png

      Figure 2.6.



      Now the associated design time entities, i.e. in the transaction SICF service path /sap/bc/apc/<name space>/<application name> and the corresponding APC application class, have to be generated(see figure 2.7):

      apc_application_generation.png

      Figure 2.7.


      Confirm the generation step.

       

       

      In the next steps the basic implementation of the APC extension class will be initiated. To do so, double-click on the class name, here YCL_APC_WS_EXT_YAPC_WS_TEST (see figure 2.8):

      apc_class_impl.png

      Figure 2.8.


       

      The before-mentioned action leads to the display of the class YCL_APC_WS_EXT_YAPC_WS_TEST in the class builder environment(see figure 2.9):

      se24_class_display_mode.png

      Figure 2.9.


       

      Change the display mode to change, i.e.click "Display" <-> "Change"(see figure 2.10).

      se24_class_display_change_mode.png

      Figure 2.10.



      The required actions are the implementation of the methods ON_START and ON_MESSAGE. The ON_START method is executed as soon as the WebSocket connection setup phase is accomplished successfully. The ON_MESSAGE method is executed when receiving a message. As the extension class is inherited from an abstract class to implement the ON_START and ON_MESSAGE methods these methods have to be redefined. Optionally also the method ON_CLOSE and ON_ERROR can be redefined, i.e. implemented, as well. To do so, choose the respective method, i.e. ON_START, and press "Redefine" (see figure 2.11):

      se24_method_on_start_redefine.png

      Figure 2.11.



      In this example the only action which is processed during ON_STARTexecution is to send a text message to the WebSocket client, after inserting the following code in the method ON_START:


      METHOD if_apc_ws_extension~on_start.

        TRY.

      * send the message on WebSocket connection

            DATA(lo_message_manager) = i_context->get_message_manager( ).

            DATA(lo_message) = lo_message_manager->create_message( ).

            lo_message->set_text( |{ sy-mandt }/{ sy-uname }: ON_START has been successfully executed !| ).

            lo_message_manager->send( lo_message ).

          CATCH cx_apc_error INTO DATA(lx_apc_error).

            MESSAGE lx_apc_error->get_text( ) TYPE 'E'.

        ENDTRY.

      ENDMETHOD.

       

      the method contains the code below(see figure 2.12):

      ON_START_implementation.JPG

      Figure 2.12.


       

      Save the method (click "Save") in the "Class Builder"(see figure 2.13):

      se24_method_save.png

      Figure 2.13.


       

      and leavethe method(click "Back"), see figure 2.14:

       

      se24_leave_method.png

      Figure 2.14.

       

      In the ON_MESSAGE method both a message text and the received message are sent to the WebSocket client, after inserting the following code in the ON_MESSAGE method:


      METHOD if_apc_ws_extension~on_message.

        TRY.

      * retrieve the text message

            DATA(lv_text) = i_message->get_text( ).

       

      * create the message manager and message object

            DATA(lo_context) = i_message->get_context( ).

            DATA(lo_message_manager) = lo_context->get_message_manager( ).

            DATA(lo_message) = lo_message_manager->create_message( ).

       

      * send 1st message

            lo_message->set_text( |{ sy-mandt }/{ sy-uname }: ON_MESSAGE has been successfully executed !| ).

            lo_message_manager->send( lo_message )

       

      * send 2nd message, i.e. echo the incoming message

            lo_message->set_text( lv_text ).

            lo_message_manager->send( lo_message ).

          CATCH cx_apc_error INTO DATA(lx_apc_error).

            MESSAGE lx_apc_error->get_text( ) TYPE 'E'.

        ENDTRY.

      ENDMETHOD.

       

      The method contains the code below (see figure 2.15):

      ON_MESSAGE_implementation.JPG

      Figure 2.15.


       

      Additionally save the method (click "Save") in the "Class Builder" (transaction SE24), see figure 2.16:

      se24_method_save.png

      Figure 2.16.


      and leave the method (click "Back"), see figure 2.17:

      :

      se24_leave_method.png

      Figure 2.17.


       

      Finally, activate the class (click "Activate") in the "Class Builder", see figure 2.18:

      se24_class_activate.png

      Figure 2.18.


       

      and leave the "Class Builder" via Back(see figure 2.19):

      se24_class_builder_leave.png

      Figure 2.19.


       

      Optionally, you can maintain the virus/content scan IDs for incoming and outgoing messages at any time (see figure 2.20):

      virus_scan_ID.docx.png

      Figure 2.20.


      Now the APC application has to be activated as well, to do so press Activate apc_activate_icon.png(see figure 2.21):

      sapc_activate_application.png

      Figure 2.21.

       

      To test the application just press the Test iconapc_execute_icon.png(see figure 2.22):

      apc_application_test.png

      Figure 2.22.


       

      This action launches the Web Dynpro application WDR_TEST_APC in a browser (see figure 2.23) which supports the WebSocket protocol (RFC 6455) (e.g. Chrome version >= 16, Firefox version >= 11, Internet Explorer version >= 10 and Safari on iOS version >= 6). In case of any issue it should be double checked that the Web Dynpro service path "/sap/bc/webdynpro/sap/wdr_test_apc" in the transaction SICF is active.

      wdr_test_apc.png

      Figure 2.23.

 

 

Limitation: In the present version of APC framework is the size of WebSocket/APC messages exchanged between client and server limited to ~64 Kbytes.

 

APC Security

Each APC application has a path entry in the transaction SICF. With a new installation this entry is inactive per default. For an active usage of an APC application the associated APC path in SICF transaction has to be activated before. The path to an APC application is /sap/bc/apc/<name space>/<application name>. For each APC application you can maintain a dedicated virus/content scan ID for outgoing and incoming messages. Furthermore we recommend to use the existing escape methods in ABAP, e.g. the ESCAPE statement, to escape the WebSocket content that is exchanged between client and server. Finally we highly recommend to use the secure varaint of WebSocket, i.e. wss instead of ws, for the communication.

 

For cross-origin-access to an APC application the APC framework also supports some aspects of the "The Web Origin Concept", i.e. RFC 6454. In order to allow the access to APC application from an external server the white list maintenance via transaction SAPC_CROSS_ORIGIN has to be done accordingly.

 

 

APC Supportability

 

WIth external breakpoints you can debug the execution of the ON_START, ON_MESSAGE, ON_CLOSE and ON_ERROR methods similarily to HTTP handler i.e. by setting breakpoints in the respective methods.

 

In transaction SAPC you can activate/deactivate the following supportability tools for a specific APC application:

be initiated:

 

  • Debugging: choose menu bar the entry "Utilities" -> "Debugging" -> "Activate Debugging"/Deactivate Debugging"
  • Runtime Analysis: choose menu bar the entry "Utilities" -> "Runtime Analysis" -> "Activate"/Deactivate"
  • Kernel Trace: choose menu bar the entry "Utilities" -> "Trace" -> "Reset Trace"/"Display Trace"/"Activate Trace"/"Deactivate Trace"

 

The  runtime analysis records which start with the prefix "APC:<application path>", e.g. "APC:/sap/bc/apc/sap/ping" for a PING application, can be monitored in transaction SAT.

 

Furthermore, transaction SMWSshows the list of active WebSocket connections and their associated APC applicationon each application server.

 

 

Conclusion and outlook

As you can see from the lines above, the ABAP Push Channel provides the infrastructure for WebSocket communication in ABAP. The present implementation of APC supports only the server side of communication based on stateless sessions, i.e. stateless APC communication similar to stateless HTTP communication. A stateful APC communication and also an APC client library are under development.


Publish Subscribe Messaging Using ABAP Messaging Channels

$
0
0

ABAP Push Channel (APC) is the ABAP framework for supporting WebSockets in ABAP engine. This framework is part of the ABAP Channles infrastructure, which is delivered with NW ABAP 740 support package 2 (SP2) for simple tests and prototyping and released with 740 support package 5 (SP5).

 

The basic idea of the ABAP Channels (see figure 1) is the native support of interactive and collaborative scenarios based on event-driven architecture. The scope of ABAP Channels consists of the following communication channels:


  • ABAP Push channel for bi-directional communication with user agents via WebSockets in ABAP. In figure 1 the documents tagged with letter "P" mark the ABAP Push Channel communication paths.
  • Publish/subscribe infrastructure for exchange of messages between either user sessions (Session C => Session A) or user session and user agents (Session C => User Agent B) residing on different servers via ABAP Messaging Channels. In figure 1 the documents tagged with letter "M" mark the ABAP Messaging Channels communication paths.

AC_Basic_Scenario.PNGFigure 1: ABAP Channels supports eventing in ABAP


Most ABAP applications task use polling techniques to achieve an even-driven communication. For example for pushing an event from ABAP backend to a browser based user-agent, e.g. WebDynpro, Business Server Pages (BSP) or WebGUI, a pooling (in multi-seconds interval) against ICM cache is frequently used. This is a quit system resource consuming technique based on polling against a shared object area or database table, i.e. by checking the content of the shared area for the existence of an event. In SAPGUI usually the timer control is used to detect an event in the back-end. One of the the main goals of  ABAP Channel technology is- whenever possible -  to replace this type of inefficient eventing based on polling techniques.The ABAP channels supports the following use-cases:

  1. ABAP Push Channel (APC): The WebSocket integration in ABAP.
  2. ABAP Messaging Channel (AMC): Eventing framework for messages exchange between different ABAP sessions based on publish/subscribe channels.
  3. Collaboration scenario: Using APC and AMC to push messages from ABAP sessions to WebSocket clients by binding publish/subscribe channels to the WebSocket connection.

 

In this article we focus on the Publish/Subscribe messaging framework in ABAP called ABAP Messaging Channel.

 

 

Integration of ABAP Messaging Channel into ABAP engine

The Right Way to Create Web Services from Function Modules

$
0
0

The two main ways of developing Web services in the ABAP environment are often referred to as inside-out and outside-in. Inside-out refers to taking existing functions – for example, remote-enabled function modules and making Web services out of them. However, the recommended way of development is normally outside-in – that means modeling the service first and then implementing the methods.


The big advantage of the model-first approach is that you have complete control over the signature of the service. If you simply take an existing RFC function module and let the interface be generated, you have no influence over how it looks.


Since SAP NetWeaver 7.02 you can model in the ABAP environment and expose only what you want of your function module.


Metadata Repository (MDR)

 

The Metadata Repository is integrated in SE80 and is a local repository. This is in contrast to the Enterprise Services Repository (ESR), which is by its nature a central repository.


Some types of users who might be interested in MDR:

  • Customers who do not use SAP middleware, and have been creating Web services in ABAP using generation from remote-enabled function modules.
  • Customers who use SAP intensively, have a strong governance team, have SAP NW PI and the ESR but want to do a proof-of-concept development that requires minimal effort regarding governance, infrastructure, and so on.
  • Partners and consultants doing in-house development before moving objects to customer systems. For example, when the customer’s development system is not available for the start of the project.

 

Improvements in SAP NetWeaver 7.4


If you have been using the Metadata Repository in earlier releases, you may have noticed that displaying all the objects of large services can take a fairly long time. To make working with such services much smoother, only the higher level objects are now displayed by default and a sort of lazy loading has been introduced so that objects are loaded and displayed as required. Of course you can still choose to “Load All” (you can find this on the Objects tab) and wait a bit - then you have everything to hand as before.

 

Picture1.png


The search functionality for enterprise service objects in SE80 is also much improved. More detailed search criteria are possible and you can search for more object types. For example, you can now search for a service group without the need to know the relevant package. The backend Metadata Repository objects that are important for the new Integration and Connectivity in ABAP are also supported.

 

Picture2.png

Summary

 

For some scenarios it is over-the-top to install an ESR when all you need is some quick and simple modeling capability (perhaps a delivered service definition requires a minor modification). Or perhaps, you are just starting out in Web services and are not yet prepared to go the full way of SOA with all the governance and so on. Here the ability to create models directly in the ABAP system is useful.


Although SOAP-based Web services are no longer in fashion, support for them in the ABAP environment is getting better and better.

Step by step to download and configure JCO in your laptop

$
0
0

This blog can be used as a very simple tutorial for those guys who are new to JCO. It demonstrates how to download and configure the JCO in your laptop. A simple consumption from JAVA side to call a remote function module in ABAP side is done to verify the correctness of the configuration.


1. download SAP JCO3.0 from service marketplace

clipboard1.png

Choose the proper file according to your OS to download:

clipboard2.png

Unzip the downloaded file, create a new folder and put the dll and jar file into the folder.

clipboard3.png

add your local folder path to PATH environment variable:

clipboard4.png

maintain the absolute path for jar file as value for CLASSPATH:

clipboard5.png

Note: there is a folder javadoc after downloaded file is unzipped and it contains detailed information about JCO like installation guide, API documentation and sample code etc.


2. Create a new Java project. Right click on project and click "Property".

clipboard6.png

Add the JCO jar file to the project by clicking button "Add External JARs".

clipboard7.png

3. Create a simple remote function module in ABAP. The function module just accepts the product ID passed from JAVA side, and query against it in database table COMM_PRODUCT, and return the query result which will be fetched via JCO in JAVA side. Never forget to mark the "Remote enabled Function module" flag.

clipboard9.png

 

4. copy the attached JAVA source code to your project.

 

For demonstration purpose, the sample code just use a local file to store ABAP destination configuration which would lead to security issues and should not be used in productive code.

 

Just specify your own ABAP system information and your user credentials in the sample code:

 

clipboard9.png

in the test code, we hard code the product ID as ARNO_TEST004. Here below is the execution result, the detail information of this product is returned to JAVA side:

clipboard10.png


We can compare it with the information in SE16, and they are exactly the same:

clipboard11.png





ABAP Channels Part 2: Publish/Subscribe Messaging Using ABAP Messaging Channels

$
0
0

ABAP Messaging Channel (AMC) is the ABAP framework for supporting publish-subscribe messaging in the ABAP engine. This framework is part of the ABAP Channels infrastructure, which is delivered with SAP NetWeaver AS ABAP 7.40support package 2 (SP2) for simple tests and prototyping and released with 7.40 support package 5 (SP5).

 

The basic idea of the ABAP Channels (see figure 1.0) is the native support of interactive and collaborative scenarios based on event-driven architecture. The scope of ABAP Channels consists of the following communication channels:


  • ABAP Push channel for bi-directional communication with user agents via WebSockets in ABAP. In figure 1.0 the documents tagged with letter "P" mark the ABAP Push Channel communication paths.
  • Publish/subscribe infrastructure for exchange of messages between either user sessions (Session C => Session A) or user session and user agents (Session C => User Agent B) residing on different application servers via ABAP Messaging Channels. In figure 1.0 the documents tagged with letter "M" mark the ABAP Messaging Channels communication paths.

AC_Basic_Scenario.PNG

Figure 1.0: ABAP Channels supports eventing in ABAP

 

Most ABAP applications use polling techniques to achieve an even-driven communication. For pushing an event from an ABAP backend to a browser based user-agent like Web Dynpro, Business Server Pages (BSP) or WebGUI, a polling in multi-seconds interval against the ICM cache is frequently used. This is a quite system resource consuming technique. In SAPGUI usually the timer control is used to detect an event in the back-end. One of the the main goals of  the ABAP Channel technology is to replace such inefficient eventing based on polling techniques.

 

The ABAP Channels supports the following use-cases:

  1. ABAP Push Channel(APC): The WebSocket integration in ABAP.
  2. ABAP Messaging Channel (AMC): Eventing framework for messages exchange between different ABAP sessions based on publish/subscribe channels.
  3. Collaboration scenario: Using APC and AMC to push messages from ABAP sessions to WebSocket clients by binding publish/subscribe channels to a WebSocket connection.


In this article we focus on the ABAP’s publish-subscribe messaging framework called ABAP Messaging Channel (see figure 1.1).

amc_apc_collaboration_simple.gif

Figure 1.1: Message Flow in ABAP Channel Components


Integration of Messaging Channels into the ABAP Engine

In order to pass an event from an ABAP session to another session we decided to implement a publish/subscribe infrastructure in the ABAP engine. Any ABAP session can subscribe to channels and any ABAP session can publish messages to channels. The channels can be used to exchange messages between sessions in an ABAP system containing several application servers, no matter on which application server these sessions reside. The ABAP Messaging Channel (AMC) brokers take care of the exchange of messages between application servers (see figure 2.0).


AMC_simple_v1.gif

Figure 2.0: Simple interaction model of ABAP Messaging Channel

 

The following diagram (figure 2.1) shows the interaction model between AMC consumers and AMC producers in different ABAP sessions which are residing on different application servers. On top of the unidirectional communication also other communication patterns can be established, e.g. bidirectional communication. Furthermore a session can act simultaneously in both roles as AMC consumer and producer. The present ABAP Messaging Channels support only the best-effort quality of service of messaging but no reliable messaging such as exactly-once or exactly-once inorder.


AMC_v3.gif

Figure 2.1: Exchange of messages based on ABAP Messaging Channel

 

The ABAP Messaging Channels support also the exchange of messages between ABAP sessions and WebSocket clients. This kind of communication is called “Collaborative” scenario. In order to reach this goal the ABAP Push Channel applications (see my blog on the ABAP Push Channel) are able to bind their WebSocket connection to ABAP Channels in a way, that the WebSocket client acts as consumer of AMC messages. This scenario is described in the dedicated blog “Collaborative Scenario”. Figure 2.2 illustrates a simple scenario for publishing a message, which is consumed by a WebSocket client.

 

AMC_APC_v1.gif

Figure 2.2: Publishing AMC messages to a WebSocket client using ABAP Push Channel


Multicasting Granularity of ABAP Messaging Channels

The channels provide following possibilities to define/restrict the number of recipient of a message:

  • The channel attribute “activity scope” describes the area to which the message is provided. The attribute can have the following values (see also next section):
    • System: The producers and consumers reside in the same ABAP system. An example for such a channel is the system messages channel which is used to send messages from transaction SM02 to the active users in the system.
    • Client: The producers and consumers reside in same client of the ABAP system. I other words the messages published in a client 100 can only be consumed by the session in the client 100.
    • User: The producers and consumers running under the same user identity, i.e. same client and user id.
  • A channel consists of three sections “<application name><channel id>[<channel extension id>]”:
    • Application name: This section identifies the name space of the channel which contains the list of all channels that are maintained for this application.
    • Channel ID: This section is used to maintain the scope and security attributes. This is used to identify the consumers of a message.
    • Channel Extension ID (optional): This as extension to Channel ID is used to identify the consumers of a message. With this the application is able to restrict the number of recipients of a message at runtime.

            

Creating an ABAP Messaging Channel (AMC) Application

This section contains a step by step description of the creation of an ABAP Messaging Channel application.

An ABAP Messaging Channel (AMC) application can be created in two ways.

 

In transaction SE80 using the context menu entry ("Right-Click on top-level package object) "Create" -> "Connectivity" -> "ABAP Messaging Channel" (see figure 3.1):

SE80_AMC_CREATE_NEW.gif

Figure 3.1.


As of release 740 SP5: In the transaction SAMC using the context menu entry ("Right-Click") on the "ABAP Messaging Channel" entry and selecting "Create" (see figure 3.2):

samc_CREATE.gif

Figure 3.2.


In the next step, enter the name of the AMC application and confirm the popup screens (press "Enter").In this example "YAMC_TEST" is used as application name(see figure 3.3):

amc_application_yamc_text.gif

Figure 3.3.

Also choose an appropriate package entry, in this case as "Local Object"(see figure 3.4):

amc_yamc_test_package.jpg

Figure 3.4.

 

Additionally, maintain the field "Description"(see figure 3.5):

amc_yamc_test_create.jpg

Figure 3.5.

On the tab „Channels“ enter a channel name of your choice e.g.  „/ping“ and click on this field. The „Channel“ name must begin with slash(/) (see figure 3.6):

amc_yamc_test_ping_create.jpg

Figure 3.6.

 

 

Then, fill the next fields:

  • Message-Type ID: A dedicated message type is assigned to each channel. Only messages of the assigned message type can be transferred over the channel. Using message types, the access APIs are type safe and the ABAP compiler and ABAP runtime ensure the consistency. Currently, the following message types are provided with the corresponding ABAP types and the producer and receiver interfaces.
    • Message type "TEXT":
      • Corresponding ABAP type "STRING"
      • Producer interface: IF_AMC_MESSAGE_PRODUCER_TEXT
      • Receiver interface: IF_AMC_MESSAGE_RECEIVER_TEXT
    • Message type "BINARY":
      • Corresponding ABAP type "XSTRING"
      • Producer interface: IF_AMC_MESSAGE_PRODUCER_BINARY
      • Receiver interface: IF_AMC_MESSAGE_RECEIVER_BINARY
    • Message type "PCP" for Push Channel Protocol:
      • Corresponding ABAP interface "IF_AC_MESSAGE_TYPE_PCP"
      • Producer interface: IF_AMC_MESSAGE_PRODUCER_PCP
      • Receiver interface: IF_AMC_MESSAGE_RECEIVER_PCP


The construction of the Push Channel Protocol (PCP) is very similar to an HTTP message with (header) fields, i.e. field name/ field value pairs and a body with the exception that PCP does not contain any request/response line. Furthermore the field names are case-sensitive and in Unicode. The Body part is optional and can be either binary or text. A PCP object in ABAP  is created via the class factory method CL_AC_MESSAGE_TYPE_PCP=>CREATE( ).


The PCP message type is the preferred message type used in the ABAP basis technology. This is because with the PCP messages not only application is able to add additional meta-data as field to the message but also the AMC runtime inserts per default the name of the channel to the PCP message before it is sent. This information is often necessary for the consumers which subscribe to different AMC channels. Using the channel field, i.e. “pcp-channel”, consumers can identify the channel to which the message belongs.


For this basic example we choose the message type TEXT by clicking on input help Message Type ID (see figure 3.7):

amc_yamc_test_ping_attributes.jpg

Figure 3.7.

 

Choose entry TEXT (see figure 3.8):

amc_yamc_test_ping_text.jpg

Figure 3.8.

  • ActivityScope (System, Client or User):  The channel access scope defines whether a channel is system-specific, i.e. cross-client, client-specific or user-specific. With client- and user-specific channel access scopes, the exchange of messages between producer and consumer sessions can be limited to sessions residing in the same client or sessions of the same user.

For this example select the entry Client (see figure 3.9):

amc_yamc_test_ping_client.jpg

Figure 3.9.

  • Authorized Program:The access rights for the channels are realized via code based authorization. For each channel, and depending on the access role as consumer or producer, a white list of ABAP reports, function groups, classes has to be maintained otherwise the access will be rejected.

 

For the maintenance of the access rights of the AMC channels dedicated reports in the role of producer, i.e. sender, and consumer, i.e. receiver, of AMC messages is needed. In the next steps following example reports will be created:

    • Report YRS_AMC_RECEIVE_MESSAGE_TEXT will act as consumer for the AMC application “YAMC_TEST” and the channel “/ping”.
    • Report YRS_AMC_SEND_MESSAGE_TEXT will act as producer for the AMC application “YAMC_TEST” and channel “/ping”.

 

The programming model of ABAP Messaging Channels is simple. The class factory CL_AMC_CHANNEL_MANAGER provides AMC producer and consumer object. After creation of the AMC producer object for the respective channel, i.e. “<application name><channel id>[<channel extension id>]”, messages can be published with the provided interface method SEND. For the consumer receiving messages can be started with the interface method START_MESSAGE_DELIVERY. For this action an (call back) object has to be provided which implements the interface receiver method RECEIVE. Furthermore in order to receive the message the session has to be in an “interrupted” state. This can be achieved explicitly with the new ABAP statement WAIT FOR MESSAGING CHANNELS <expression> [UP TO <time> SECONDS].

 

Create the test report YRS_AMC_SEND_MESSAGE_TEXT in the transaction SE38 and copy-paste following ABAP code as context for the report (see figure 3.10):

YRS_AMC_RECEIVE_MESSAGE_TEXT_create.jpg

Figure 3.10.

 

Insert the title “Consumer test for ABAP Messaging Channel YAMC_TEST” for the report and choose following Attributes (see figure 3.11):

  • Type: “Executable program”
  • Status: “Test Program”

YRS_AMC_RECEIVE_MESSAGE_TEXT_attributes.jpg

Figure 3.11.

Additionally click Save and select Local Object (see figure 3.12):

YRS_AMC_RECEIVE_MESSAGE_TEXT_save.jpg

Figure 3.12.

Now insert the following ABAP code into the report and save the report (see figure 3.13):


AMC consumer example code

REPORT yrs_amc_receive_message_text.
PARAMETERS: msg_nr   TYPE i DEFAULT 1, "number of expected messages
                         wait_sec
TYPE i DEFAULT 20. "waiting time to

DATA: lo_consumer       TYPE REF TO if_amc_message_consumer.
DATA: gt_message_list TYPE TABLE OF string.
DATA: lv_message          TYPE string.
DATA: lx_amc_error         TYPE REF TO cx_amc_error.

* implemenation class for AMC receiver interface
CLASS lcl_amc_test_text DEFINITION
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
* interface for AMC messages of type TEXT
    INTERFACES if_amc_message_receiver_text .
ENDCLASS.

* Consumer test for ABAP Messaging Channel YAMC_TEST”
CLASS lcl_amc_test_text IMPLEMENTATION.
  METHOD if_amc_message_receiver_text~receive.
*
* remark: in this method should the message be received and  the main actions
* should be processed in the main program and  usually after WAIT statement.
* Any kind of communication, e.g. RFCs, HTTP and message hanlding,

* e.g. error message isnot supported and  will lead to ABAP dump.
*

* insert received messages into the global table
      APPEND i_message TO gt_message_list.
    ENDMETHOD.
  ENDCLASS.

START-OF-SELECTION.
DATA: lo_receiver_text TYPE REF TO lcl_amc_test_text.

TRY.
  lo_consumer
= cl_amc_channel_manager=>create_message_consumer( i_application_id = 'YAMC_TEST' i_channel_id = '/ping' ).
  CREATE OBJECT lo_receiver_text.

" start of message delivery
  lo_consumer
->start_message_delivery( i_receiver = lo_receiver_text ).
  CATCH cx_amc_error INTO lx_amc_error.
     MESSAGE lx_amc_error->get_text( ) TYPE 'E'.
  ENDTRY.

*
* wait until a message is received but not longer than waiting time in seconds
*
  WAIT FOR MESSAGING CHANNELS UNTIL lines( gt_message_list ) >= msg_nr UP TO wait_sec SECONDS.

  IF sy-subrc = 8 AND  lines( gt_message_list ) = 0.
     WRITE: ')-: Time out occured and no message received :-('.
  ELSE.
    LOOP AT gt_message_list INTO lv_message.
* print out the list of received AMC messages
      WRITE: / sy-tabix, lv_message.
    ENDLOOP.
  ENDIF
.

Figure 3.13.

Finally activate the report (see figure 3.14):

YRS_AMC_RECEIVE_MESSAGE_TEXT_activate.jpg

Figure 3.14.

 

Create the test report YRS_AMC_SEND_MESSAGE_TEXT in transaction SE38 and copy-paste the following ABAP code as context for the report (similar to figure 3.10-2.13)Insert the title“Producer test for ABAP Messaging Channel YAMC_TEST” for the report.


Now insert the following ABAP code into the report and save the report (see figure 3.15):

 

AMC produce example code

REPORT yrs_amc_send_message_text.
PARAMETERS: message TYPE string LOWER CASE DEFAULT 'Hi there !'.
DATA: lo_producer_text TYPE REF TO if_amc_message_producer_text.
DATA: lx_amc_error       TYPE REF TO cx_amc_error.

TRY.
   lo_producer_text ?= cl_amc_channel_manager
=>create_message_producer( i_application_id = 'YAMC_TEST' i_channel_id = '/ping' ).

 
" send message to the AMC channel
   lo_producer_text
->send( i_message = message ).

  
CATCH cx_amc_error INTO lx_amc_error.
    
MESSAGE lx_amc_error->get_text( ) TYPE 'E'.
ENDTRY
.

Figure 3.15.

Finally activate the report (see figure 3.14):

 

Choose Authorized Program and insert the report YRS_AMC_RECEIVE_MESSAGE_TEXT in the popup (see figure 3.16).

samc_insert_channel_report.jpg

Figure 3.16.


Insert the report name YRS_AMC_RECEIVE_MESSAGE_TEXT and click Accept (see figure 3.17).

samc_insert_channel_report_save.jpg

Figure 3.17.

Choose the activity Receive (see figure 3.18).

samc_insert_channel_report_rcv_save.jpg

Figure 3.19.


Similar to the previous steps insert the report name YRS_AMC_SEND_MESSAGE_TEXT with the activity Send (see figure 3.20).

samc_insert_channel_report_snd_save.jpg

Figure 3.20.


Finally Save (see figure 3.21) and Activate (see figure 3.22) the AMC application. To accomplish these steps just choose Continue (process Enter) in the next popup screens (see figure 3.23).

samc_application_save.jpg

Figure 3.21.

samc_application_activate.jpg

Figure 3.22

Click Continue (see figure 3.23).

samc_application_continue.jpg

Figure 3.23.


Now execute first the ABAP report YRS_AMC_RECEIVE_MESSAGE_TEXT (see figure 3.24) and then the report YRS_AMC_SEND_MESSAGE_TEXT (see figure 3.25)  in two parallel sessions.  While the report YRS_AMC_RECEIVE_MESSAGE_TEXT report subscribes to the application YAMC_TEST and channel /ping and waits for incoming messages, the report YRS_AMC_SEND_MESSAGE_TEXT sends messages to the same application and channel.

YRS_AMC_RECEIVE_MESSAGE_TEXT_execute.jpg

Figure 3.25.

YRS_AMC_SEND_MESSAGE_TEXT_execute.jpg

Figure 3.26.


Remark: If during of execution of an AMC program the AMC exception with the message

“No authority for program <program name> to access to ABAP Messaging Channel with application ID <application_id> and Channel <channel_id>”

is raised, this is because in the “Authorized Program” area (see figure 3.12) the reported program is not maintained appropriately.


 

Limitation: In the present version of AMC framework is the size of AMC messages limited to ~32 Kbytes.

Recommendation: The basic goal of AMC messages is the notification of subscribers about an event. If the subscribers should be informed about any changes to an entity in  this case is the transfer of the resource URL of the affected entity  to the subscribers recommended.The URL should refer to the persisted entity record, e.g. in the database.


AMC Security

The access rights for AMC channels are controlled via code based authorization and by maintenance of reports, i.e. classes, function groups or includes, which are permitted to apply an action, i.e. publish, subscribe, to the channel.


For the case, that  a channel is bound to a WebSocket connection and is used to push messages from a session to a WebSocket client (see figure 2.2) , can a dedicated virus/content scan ID for outgoing messages be maintained.


AMC Supportability

Since the AMC producers and consumers, besides the collaboration scenario, resides in an ABAP session, the existing ABAP supportability tools, e.g. debugger, ABAP runtime analysis or kernel trace can be used. Within the debugger the session breakpoints can be used to debug the session during send or receive phase of the messaging. Using transaction SAT the runtime analysis for the respective session and report can be activated. Via transaction SM04 you can activate and deactivate the user specific kernel trace for the respective session.

Furthermore with the following transactions you can manage the AMC logging (activate, deactivate and monitor recorded entries):

  • Transaction AMC_LOG_ADIM: Activate and deactivate logging for dedicated AMC channels.
  • Transaction AMC_LOG_PROCESSING: Monitoring transaction for the AMC log entries.

 

Note: For the reorganization of AMC log entries a dedicated batch job has to be planed. The pre-defined standard batch-job SAP_ABAP_CHANNELS_MANAGEMENT

          has to be scheduled in the transaction SM36. The batch-job requires the authorization for the authorization object S_AMC_LOG with the activity “Delete”.


The transaction „SMAMC“ (see figure 4.0) shows the list of the AMC channels (in our example the channel yamc_test/ping) which are registered in sessions (Type “Session”) or in case of “Collaboration scenario” the WebSocket connections (Type is “WebSocket”) in the system as AMC consumers.

smamc_tx.jpg

Figure 4.0.

Conclusion and outlook

The present implementation of AMC supports only the best-effort strategy without guarantee of delivery. We could think about providing also reliable messaging in future release.

Custom IDoc framework based on ABAP Objects (Part 1 - Intro)

$
0
0

Introduction

In this blog, I will introduce a custom IDoc framework that is based on Object Oriented Programming, implemented through ABAP Objects. The objective of this framework is to establish and enforce a consistent development approach for all IDoc based interfaces in a particular organization. In this first part of a two-part series blog, I will cover the design and architectural aspects of the framework. In part 2, I will cover the the development objects involved.

 

 

Background

Since Web AS 620, proxy has been available as an integration technology for SAP systems. In-line with SAP's SOA strategy, proxy enables development of interfaces with the outside-in approach. Introduction to Service Development details some differences between outside-in approach and inside-out approach. Many of SAP's newer "standard" interfaces (especially in newer products like SRM, IS-U, etc) are developed using the outside-in approach, and are delivered as Enterprise Services.

 

In recent years, SAP has introduced technologies like FEH/ECH and AIF to enhance the capabilities of proxy based interfaces. The following blog SXMB_MONI vs FEH/ECH vs AIF provides a comparison of the error-handling capability between these technologies.

 

 

Using IDocs

However, in spite of all the advancements in these newer technologies, IDoc remains a preferred and/or popular choice in many organizations for their integration development. This is especially true in the ERP system, where there is a wealth of standard IDocs available for integrating most of the common business documents like sales order, accounting document, customer master, etc. It is a mature and stable technology that has been around for decades, with an extensive coverage of tools in the various areas - development (WE30/31, WE80/81), configuration (WE20, WE21), documentation (WE60, WE64), testing (WE19), monitoring and error handling (WE02, BD87), content search (WE09). It is also a technology that the SAP business user community has become widely familiar with.

 

 

Customizing IDoc Interfaces

While it is ideal to be able to use the standard IDocs provided by SAP "as-is", we all know that more often that not, some level of customization is required to meet the specific needs of an organization. While it is fairly easy to achieve customization for a single IDoc interface, there are challenges to achieve a consistent customization approach when there are a multitude of IDoc interfaces to be developed. Below are some of the common challenges.

 

Not all IDocs are created the same

Some have extension segments, others do not. Some use call transaction, while others have BAPI-based processing.

 

Different code enhancement options

Different IDoc processing function modules are developed differently. Some can be enhanced by customer exits, some have BADIs, some do not have either.

 

Customized logging/validation

If a standard customized logging/validation is required, this logic has to be replicated across the various IDoc function module involved. This leads to a lot of reinventing the wheel every time a new interface is developed.

 

Overview of IDoc customization

There is no single place where we can get a high level overview of customizations for all the different IDoc interfaces developed.

 

Extensibility

Customizations are often done per a specific requirement for a specific interface, leaving little room for extension.

 

Locking of shared objects during development

If more than one interface is being developed that requires customization of the same IDoc, the developers might need to edit the same user exit/BADI, which leads to locking/contention issues.

 

 

Object Oriented Solution

The customized framework is designed with the following guiding principles, which is achieved by an object oriented approach using ABAP Objects.

  1. Promotes Generalization
    • Common logic and functionality pooled together to increase re-usability
  2. Allows Specialization
    • Capability to handle specific requirements that deviate from common scenarios
  3. Easily Extensible
    • Capability to extend to new business cases/scenarios

 

This approach also allows for a distinct separation of development objects, thereby preventing any locking/sharing/contention issues.

 

 

Class Inheritance Model

The following diagram displays the inheritance model of the classes in this custom framework. The customized logic that are common to all IDoc interfaces are implemented in the super classes. For each new type of IDoc, a new subclass is created inheriting from the super class. With this approach, the common framework logic (like validation, customized logging) need not be repeated again - only the type specific logic needs to be implemented at this level. Further down, there might be specific interfaces that require even further customization. This can be achieved again by inheriting from the appropriate IDoc type class.

 

inherit.png

 

 

Framework Processing Flow

With this framework, all inbound IDocs are processed by the same custom process code. This executes a custom Function Module, and it is a single point of entry into the framework processing.

flow1.png

 

During processing by the framework, the class responsible for processing the IDoc will be dynamically determined during runtime. Common logic like validation, customized logging, notification are implemented in super class which are always the same for all IDoc objects processed.

flow2.png

 

Meanwhile, each interface will implement it's own logic specific to the interface requirement. These specific logic are implemented in sub classes. These logic can be implemented in the preprocessing/postprocessing methods and establishes a consistent way of adding custom logic - reducing the need to find a suitable exit/BADI.

flow3.png

 

Continue to Part 2: Development Objects

Custom IDoc framework based on ABAP Objects (Part 2 - Development Objects)

$
0
0

8 April 2014: Updated section on ZCL_IDOC_INPUT and ZCL_IDOC_INPUT_SO, and added runtime flow diagram

 

In the first part of my article on custom IDoc framework, I have described the design and architectural aspects of the framework. In this part, I will elaborate more on the development objects involved.

 

The objects and source code described in this article are provided in the SAPLink nugget file attached at the end of this article. For more information on how to extract and install the objects, please refer to the SAPLink wiki. Please note that this article does not cover every aspect of the coding and design of objects and source code provided.

 

Customizing tables

The following customizing tables are used during runtime processing by the framework.

 

ZBC_IDOC_CFG determines which IDoc processing class is used for a particular interface (unique combination of IDoc direction, Message Type, Message Variant and Message Function)

ZBC_IDOC_CFG.png

 

ZBC_IDOC_OPTIONS determines if there are any other additional custom logic to be used during processing. This allows for configurable customization of the behavior of runtime processing, i.e. which logic to use for material conversion, whether interface should execute duplicate check or not.

ZBC_V_IDOC_CFG.png

 

 

Inbound Process Code and Inbound Function Module

The inbound partner profiles are configured using a single process code, ZBC_IDOC_FW. This process code is configured to link to the framework function module (with BD51, WE57 and WE42).

process_code.png

 

In the framework function module, Z_IDOC_INPUT_FW represents the single point of entry for all IDoc inbound processing. The IDoc processing class is dynamically determined during runtime by the factory method GET_INSTANCE. Subsequently, all further IDoc processing is passed on to the processing class through method EXECUTE_INBOUND.

func_module.png

 

 

IDoc Processing Classes

 

1. Base class - ZCL_IDOC_BASE

This abstract base class is the root superclass of the framework model. It provides the static factory method GET_INSTANCE to dynamically determine the runtime class to be used for processing. It also provides general functionality that can be used by all subclasses.

ZCL_IDOC_BASE.png

 

2. Buffer class - ZCL_IDOC_DB_BUFFER

This class is not part of the inheritance model, however it is a helper class that provides buffered database accesses to improve IDoc processing times.

ZCL_IDOC_DB_BUFFER.png

 

3. Inbound class - ZCL_IDOC_INPUT

This abstract class is a subclass of ZCL_IDOC_BASE. All the public/protected methods of the superclass are inherited here. Additionally, this class contains the methods that are common for all inbound processing, i.e. validation checks, customized logging.

ZCL_IDOC_INPUT.png

 

The public method EXECUTE_INBOUND is called by the Process Code function module. This controls the sequence of logic executed during inbound processing.

EXECUTE_INBOUND.png

 

This class also defines the following methods, which are abstract at this level. This enforces implementation at the subsequent subclasses level because different IDoc types require different IDoc processing function module, and/or preprocessing & postprocessing.

ZCL_IDOC_INPUT 2.png

 

4. Sales Order processing class - ZCL_IDOC_INPUT_SO

This class is a subclass of ZCL_IDOC_INPUT. It implements all the logic required for sales order processing, in this case, for IDoc message type SALESORDER_CREATEFROMDAT2. The abstract methods from the above superclass are implemented here.

ZCL_IDOC_INPUT_SO.png


Shown below is the implementation of abstract method PROCESS_IDOC_FM, whereby the standard SAP function module related to this IDoc type is executed.

PROCESS_IDOC_FM.png


Additionally, any of the superclass methods it inherited can be redefined here for more specific processing. The following approaches are available when redefining superclass methods:

  • Replace - Totally remove superclass logic and implement a new logic for this subclass
  • Modify - Copy existing superclass logic, and only modify portions of the logic
  • Extend - A mixture of both superclass logic and subclass logic. An example is shown below for method UPDATE_LOGS, where some additional subclass logic is added, and at the end, the superclass implementation is also executed (SUPER->UPDATE_LOGS)

UPDATE_LOGS.png

Lastly, this class can be further inherited by a different subclass if required. This will enable implementation of very specific logic for certain specific interfaces.

 

 

Program Flow During Runtime Execution

The diagram below displays the flow of execution during runtime. This is based on an example where ZCL_IDOC_INPUT_SO is configured in table ZBC_IDOC_CFG as the processing class for that particular interface. The flow displays that the common methods are executed from the superclass version, while the abstract and redefined methods are executed from the subclass version.

runtime.png

ABAP Channels Part 3: Collaboration Scenario Using ABAP Messaging and ABAP Push Channels

$
0
0

ABAP Push Channel (APC) is the ABAP framework for supporting WebSockets in the ABAP engine. This framework is part of the ABAP Channels infrastructure, which is delivered with SAP NetWeaver AS ABAP 7.40 support package 2 (SP2) for simple tests and prototyping and released with 7.40 support package 5 (SP5).

 

The basic idea of the ABAP Channels (see figure 1.0) is the native support of interactive and collaborative scenarios based on event-driven architecture. The scope of ABAP Channels consists of the following communication channels:

  • ABAP Push channel for bi-directional communication with user agents via WebSockets in ABAP. In figure 1.0 the documents tagged with letter "P" mark the ABAP Push Channel communication paths.
  • Publish/subscribe infrastructure for exchange of messages between either user sessions (Session C => Session A) or user session and user agents (Session C => User Agent B) residing on different application servers via ABAP Messaging Channels. In figure 1.0 the documents tagged with letter "M" mark the ABAP Messaging Channels communication paths.

AC_Basic_Scenario.PNG

Figure 1.0: ABAP Channels supports eventing in ABAP

 

Most ABAP applications use polling techniques to achieve an even-driven communication. For pushing an event from an ABAP backend to a browser based user-agent like Web Dynpro, Business Server Pages (BSP) or WebGUI, a polling in multi-seconds interval against the ICM cacheis frequentlyused.This is a quitesystem resource consuming technique. In SAPGUI usually the timer control is used to detect an event in the back-end. One of the the main goals of  the ABAP Channel technology is to replace such inefficient eventing based on polling techniques.

 

The ABAP Channels supports the following use-cases:

  1. ABAP Push Channel(APC): The WebSocket integration in ABAP.
  2. ABAP Messaging Channel(AMC): Eventing framework for messages exchange between different ABAP sessions based on publish/subscribe channels.
  3. Collaboration scenario: UsingAPCandAMCto push messages from ABAP sessions to WebSocket clients by binding publish/subscribe channels to a WebSocket connection.


In this article we focus on the exchange of messages between WebSocket clients and ABAP sessions called Collaboration scenario using AMC and APC (see figure1.1).

amc_apc_collaboration_simple.gifFigure1.1: Message Flow in ABAP Channel Components

 

Collaboration of ABAP Messaging and Push Channels

The collaboration scenario (see figure 2.0) provides the possibility on the basis of publish/subscribe pattern of ABAP Messaging Channels to push messages from an ABAP session or from a WebSocket client (using ABAP Push Channel) to from publisher to subscribers of channels.

amc_apc_simple_v2.gif

  Figure 2.0: Simple interaction model of collaboration scenario.

 

One of the goals for the collaboration scenario is to overcome the manual refresh for an object list in the user-interfaces by introducing an “auto-update” or alternatively by using a notification pattern. This goalcan easily be reached by notifying the user-agent having a WebSocket connection to the ABAP system about the changes on objects displayed in the user-agent.

AMC_APC_complex.gif

Figure 2.1 illustrates the technical interaction model for pushing messages between a WebSocket

 

In order to pass an event from an ABAP session to a WebSocket client and vice-versa the publish/subscribe infrastructure of the ABAP Messaging Channels is used. As in the figure 2.1 depicted the APC frame with the binding manager interface offers the possibility to bind an AMC channel to the underlying WebSocket connection to act as message consumer (receiver) for the corresponding channel. After a successful binding to an AMC channel, here <application>/<channel>, any messages published to the channel will
be forwarded by the AMC broker to the WebSocket client using corresponding WebSocket connection.


Creating an ABAP Push and Messaging Channel Application for Collaboration Scenario
This section outlines the additional steps required to extend the existing APC application (see ABAP Channels Part 1: WebSocket Communication Using ABAP Push Channels [1]) and AMC application (see ABAP Channels Part 2: Publish/Subscribe Messaging Using ABAP Messaging Channels[2]) to create the collaboration scenario.

 

First, the APC applicationwill be extended:

  • In the existing APC application YCL_APC_WS_EXT_YAPC_WS_TESTthe coding of methodON_START (Figure 2.12 in [1]) will be replaced with coding to bind the
    WebSocket connection to the AMC application
    YAMC_TESTand channel“/ping”.


METHOD if_apc_ws_extension~on_start.

  TRY.
* bind the WebSocket connection to the AMC channel
   
DATA(lo_binding) = i_context->get_binding_manager( ).
    lo_binding
->bind_amc_message_consumer( i_application_id = 'YAMC_TEST'
                                                                                         i_channel_id     
= '/ping' ).
 
CATCH cx_apc_error INTO DATA(lx_apc_error).
    D
ATA(lv_message) = lx_apc_error->get_text( ).
   
MESSAGE lx_apc_error->get_text( ) TYPE 'E'.
 
ENDTRY
.

ENDMETHOD.

 

  • Same for methodON_MESSAGE (figure 2.15 in [1]). Here the received messages from WebSocket client are forwarded to the AMC application YAMC_TESTand channel“/ping”.

 

METHOD if_apc_ws_extension~on_message.

  DATA: lo_producer TYPE REF TO if_amc_message_producer_text.
 
TRY.
* retrieve the text message
   
DATA(lv_text) = i_message->get_text( ).
    lo_producer ?= cl_amc_channel_manager
=>create_message_producer(

                                                                                                 i_application_id = 'YAMC_TEST'
                                                                                                 i_channel_id      
= '/ping' ).
    lo_producer
->send( i_message = lv_text ).
 
CATCH cx_amc_error INTO DATA(lx_amc_error).
   
MESSAGE lx_amc_error->get_text( ) TYPE 'E'.
 
CATCH cx_apc_error INTO DATA(lx_apc_error).
   
MESSAGE lx_apc_error->get_text( ) TYPE 'E'.
  ENDTRY
.

ENDMETHOD.


  • In the next step the access rights will be maintained. For the AMC application YAMC_TEST and channel “ping” the activities “Receive via APC WebSocket” and Send”are referencing the implementation class YCL_APC_WS_EXT_YAPC_WS_TEST of APC application YAPC_WS_TEST. This is done in the AMC design time, transaction SAMC (figure 3.20 in [2]).

 

Open the definition of application YAMC_TEST and click Insert line (see figure 3.1).

fig_3.1.jpg

  Figure 3.1


Open the value help in the Authorized Program field (see figure 3.2).

fig_3.2.jpg

Figure 3.2

 

Insert the class YCL_APC_WS_EXT_YAPC_WS_TESTand click Accept (see figure 3.3).

fig_3.3.jpg

Figure 3.3

 

Select the entry C Receive via APC WebSocket (see figure 3.4).

fig_3.4.jpg

Figure 3.4

 

Insert additional line as above and select the entry S Send (see figure 3.5).

fig_3.5.jpg

Figure 3.5


Optionally a Virus Scan ID (outgoing) can be specified (see figure 3.6).

fig_3.6.jpg

Figure 3.6

 

Click Save (see figure 3.7).

fig_3.7.jpg

Figure 3.7

And Activate. (see figure 3.8).

fig_3.8a.gif

Figure 3.8

Click Continue .(see figure 3.9)..

fig_3.9.jpg

Figure 3.9

 

To test the application just press the Test icon (see figure 3.10).

fig_3.10.jpg

Figure 3.10

 

This action launches the Web Dynpro application WDR_TEST_APCin a browser (see figure 3.11) which supports the WebSocket protocol (RFC 6455) (e.g. Chrome version >= 16, Firefox version >= 11, Internet Explorer version >= 10 and Safari on iOS version >= 6). If it does not launch, double check the Web Dynpro service path /sap/bc/webdynpro/sap/wdr_test_apc" in the transaction SICFis active.


  fig_3.11.jpg

Figure 3.11

 

Just starts a second time the Web Dynpro test application for APC application YAMC_TEST in browser (see figure 3.12).After a successful connection setup any messages send in a browser will be received also by the second browser.

fig_3.12.jpg

Figure 3.12

 

Furthermore any report which apply any actions on the AMC application YAMC_TESTand channel“/ping” will be involved in the collaboration interaction. In other words the execution of the AMC send report YRS_AMC_SEND_MESSAGE(refer [2] figure 3.15) will lead to receiving the send message by the browser(see figure 3.13) 

 

fig_3.13.jpg

Figure 3.13

 

And the execution of the AMC receive report YRS_AMC_RECEIVE_MESSAGE (refer blog [2]figure 3.25) will lead to receiving the send message by the browser(see figure 3.14).

fig_3.14.jpg

Figure 3.14


 

Collaboration Scenario Security

The security of collaboration scenario is handled by the underlying APC and ac frameworks.

 

 

Collaboration Scenario Supportability

Whereas for AMC channels with the transaction SMAMC(refer blog [2] figure 4.0) canthe subscribed channels be monitored also here a navigation to the bound WebSocket connection in SMWS(see [1] ) transaction. The transaction SMWS provides also the total number of bound AMC channels per WebSocket  connection (see figure 4.0).

fig_4.0.jpg

Figure 4.0


The transaction SMAMC (see figure 4.1) shows the list of the AMC channels which are registered in sessions (Type “Session”) or in case of “Collaboration scenario” the WebSocket connections (Type is “WebSocket”) in the system as AMC consumers.

fig_4.1.jpg

Figure 4.1


 

Conclusion and outlook

This article showed the collaboration scenario based on AMC and APC for exchange of messages between different WebSocket clients. Currently the message exchange based on best/effort strategy and no guaranteed delivery is available. In a future article best practices will be outlined.    


Enabling real-time bidirectional client-server communication using ABAP Push Channel

$
0
0

The client-server model is a typical architectural pattern in modern networks. But from an architect’s/developer’s point of view we are left with a full “zoo” of protocols and paradigms which can be used to enable communication between client and server. But a lot of commonly used techniques as polling are already prehistoric and their disadvantages outweigh their benefits.

 

Let’s assume a SAP UI5-based chart rendered in the browser which gets fed with data coming from an ERP backend. If the backend data changes often and irregularly (stock prices, sales orders), the chart can become outdated very quickly and therefore needs to adapt to these changes in order to show the correct values. A demo video of the example can be viewed here or in SAP’s media share at [1].

 

 

In the past we achieved this kind of client-server communication by polling techniques with multi-seconds intervals or just a refresh button to manually trigger an update. Usually we are using HTTP for the communication and open one connection for every update. The drawbacks of these approaches are lacks of built-in up-to-dateness, bad performance because of too many requests and a bad user experience because of unnecessary clicks.

 

Figure1.png

 

This picture shows both traditional polling and an improvement called long polling. Both are based on HTTP and therefore always send complete request-response pairs. The red stars in the graphic show where new data gets available or data changes (new sales order, updated stock price).

 

While using traditional polling e.g. with a time interval of 0.5 seconds, the frontend “asks” the backend in a frequent interval if new/updated data is available. The drawback of this approach is obviously that there is a lot of communication overhead since request-response-pairs are sent even if no data is available. Decreasing the overhead via reducing the polling interval leads to more misses and more outdated data on the frontend. While using long polling, the server only “answers” the requests when new data is available. While this approach performs better, especially when updates are non-frequent, there is still an unnecessary big overhead because plain old request-response-pairs are used.

 

Figure2.png

 

HTML 5 WebSockets introduce a new way the client and the server communicate. WebSockets build a persistent connection between client and server by using only two HTTP messages; one handshake to establish and another to close the connection. The main difference to the polling approaches is that WebSocket messages are based directly on TCP (OSI Layer 4) while polling messages are based on HTTP (Layer 5-7). This eliminates the need to use HTTP request-response-pairs and opens the door to real-time communication from server to the client and from the client to the server.

 

The WebSocket protocol was standardized in 2011 by the IETF as RFC 6455 [2] and the WebSocket API is defined in a W3C specification [3]. WebSockets can use TCP port 80 which is usually used for HTTP connections. Because of that it can also be used with firewalls which block non-web Internet connections. The secure version of WebSockets (wss://) is supported by several modern browsers as Chrome 14 (released in 2011), Firefox 6 (2011), Safari 6 (2012) and IE 10 (2012).

 

But WebSockets also have some drawbacks: The application of the Same Origin Policy which restricts browser-side programming scripts in accessing content - e.g. the DOM - of pages with different origin is not required by the protocol (neither in [2] nor in [3]). However, developers and security consultants should always implement or try to make it a requirement to check the “Origin” header at the server to secure web applications from Cross-Site Hijacking attacks. Another disadvantage of WebSockets is that you are restricted to the basic datatypes BINARY and STRING, which means you have to care yourself about data conversion. Apart from that, it has to be kept in mind that older browsers don’t support WebSockets and proxys have to support WebSockets as well.

 

Figure3.png

 

SAP’s ABAP framework of WebSockets is called ABAP Push Channel (APC). APC is available as of SAP Netweaver AS ABAP 7.40 support package 5 (SP5) as part of the ABAP Channels infrastructure. Together with ABAP Messaging Channel (AMC), APC enables the development of interactive scenarios. The basic architecture as shown in picture 3 consists of several WebSocket clients which communicate via APCs - the ABAP implementation of the actual WebSocket messages - through AMC, which acts as an underlying communication channel. If you want to learn more about ABAP Channels architectures, please refer to Masouds [4] SCN article.

 

Let’s assume we want to refresh an UI5 chart as soon as data updates on an ERP backend system.

 

Having that in mind, we can follow two different patterns to use APC. The first one is to send trigger messages from the backend, transporting only the information that something has changed without sending actual data. At frontend side we can react to that trigger message with a full update of the OData entity set. This first pattern has the advantage that it is very easy to implement and that the trigger messages are lean. The clear drawback is that full updates might not be needed in every scenario and there is an additional roundtrip (e.g. an OData refresh).

 

Apart from that we can send actual data within the messages for partial updates or recalculations. While this second pattern is more difficult to implement and it has to be kept in mind that only BINARY and STRING datatypes can be send through APCs and therefore a data conversion / serialization might be needed, it improves the overall performance and the latency.

 

Figure4.png

 

The exemplary architecture enhances the general ABAP Channel architecture basically at two points. The first one is the additional oData call from the UI5 frontend back to the ABAP backend (first pattern was used) and the second one is a tiny modification in the backend. Without going into detailed specifics, we need to set up the backend in that way that the APC message is sent automatically when data is saved / persisted. This could be achieved by adding the APC call into the V2 update task which is always executed after the DB commit. There exist some other ways to initiate the APC call but this highly depends on the scenario.

An exemplary code example for the UI5 frontend which reacts to APC message coming from the backend could look like as follows:


// Open connection to WebSocket "demo_apc" on system "xyz"

ws = new WebSocket("wss://xyz.wdf.sap.corp:44322/sap/bc/apc/sap/demo_apc");

 

// React to incoming APC message (second pattern)

  1. ws.onmessage = function (evt) { 

  var oModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/YOUR_DEMO_UI5_APPLICATION/");

sap.ui.getCore().setModel(oModel);

oChart.bindRows("/Values");

};

 

For further hands-on-tutorials and more code examples (both Javascript on the client side and ABAP on the server side) please refer to the following SCN article [5].

 

As a conclusion, it has been shown that there is a possibility to enable real-time bidirectional client-server communication via APC, the ABAP implementation of WebSockets. But as discussed please keep also in mind that APC is no magic bullet for all client-server scenarios.

 

[1] https://mediashare.wdf.sap.corp/public/id/0_1f1wupq3 (only SAP internally)

[2] http://tools.ietf.org/html/rfc6455

[3] http://dev.w3.org/html5/WebSockets/

[4] http://scn.sap.com/community/abap/connectivity/blog/2013/11/18/websocket-communication-using-abap-push-channels

[5] http://scn.sap.com/docs/DOC-53598

How to use RFC-SDK with FreeBASIC - Part 4: CGI Apps (FreeBASIC uses SAP)

$
0
0

Hello community,

 

I presented here and here the possibility to code FreeBASIC programs as SAP client applications via SAP RFC SDK. Now in the 4th part I will show, how easy it is to code Common Gateway Interface (CGI) programs with FreeBASIC and to embed an SAP client application inside this CGI program. This CGI program can be implemented on any web server - Attention, it is platform dependent - and on this way you can integrate SAP NW RFC library functions seamlessly.

 

We start with the FreeBASIC code. For this example I use cgi-util from New Breed Software. Hint: Also you can use FastCGI  from here, FreeBASIC offers for both an interface. For a little bit more information look here.

 

'-Begin-----------------------------------------------------------------  '-Includes------------------------------------------------------------    #Include Once "cgi-util.bi"    #Include Once "sapnwrfc.inc"  '-Variables-----------------------------------------------------------    Dim RfcErrorInfo As RFC_ERROR_INFO    Dim connParams(6) AS RFC_CONNECTION_PARAMETER    Dim As Integer hRFC, hFuncDesc, hFunc, hStruct, res    Dim As ZString Ptr pASHost, pSysNr, pClient, pUser, pPassWd, pLang    Dim As WString * 16 nASHost, nSysNr, nClient, nUser, nPassWd, nLang    Dim As WString * 16 vASHost, vSysNr, vClient, vUser, vPassWd, vLang    Dim As WString * 9 SAPHost, SAPSysID    Dim As WString * 11 SAPDBSys    Dim As WString * 33 SAPDBHost  '-Macros--------------------------------------------------------------    #Macro RfcErrorHandlerCGI()      If RfcErrorInfo.code <> RFC_OK Then        Print "<h1>RFC Error Message</h1><br>"        Print RfcErrorInfo.message      End If    #EndMacro  '-Main----------------------------------------------------------------    res = cgi_init()    Print !"Content-type: text/html\n\n"    If res <> CGIERR_NONE Then      Print "Error " & Str(res) & " " & Str(cgi_strerror(res)) & "<p>"    Else      pASHost = cgi_getentrystr("ASHOST") : nASHost = "ASHOST" : vASHost = *pASHost      pSysNr  = cgi_getentrystr("SYSNR")  : nSysNr  = "SYSNR"  : vSysNr  = *pSysNr      pClient = cgi_getentrystr("CLIENT") : nClient = "CLIENT" : vClient = *pClient      pUser   = cgi_getentrystr("USER")   : nUser   = "USER"   : vUser   = *pUser      pPassWd = cgi_getentrystr("PASSWD") : nPassWd = "PASSWD" : vPassWd = *pPassWd      pLang   = cgi_getentrystr("LANG")   : nLang   = "LANG"   : vLang   = *pLang      connParams(0).name = @nASHost : connParams(0).value = @vASHost      connParams(1).name = @nSysNr  : connParams(1).value = @vSysNr      connParams(2).name = @nClient : connParams(2).value = @vClient      connParams(3).name = @nUser   : connParams(3).value = @vUser      connParams(4).name = @nPassWd : connParams(4).value = @vPassWd      connParams(5).name = @nLang   : connParams(5).value = @vLang      hRFC = RfcOpenConnection(@connParams(0), 8, RfcErrorInfo)      RfcErrorHandlerCGI()      If hRFC <> 0 And RfcErrorInfo.code = RFC_OK Then        hFuncDesc = RfcGetFunctionDesc(hRFC, "RFC_SYSTEM_INFO", _          RfcErrorInfo)        RfcErrorHandlerCGI()        If hFuncDesc <> 0 And RfcErrorInfo.code = RFC_OK Then          hFunc = RfcCreateFunction(hFuncDesc, RfcErrorInfo)          RfcErrorHandlerCGI()          If hFunc <> 0 And RfcErrorInfo.code = RFC_OK Then            RfcInvoke hRFC, hFunc, RfcErrorInfo            RfcErrorHandlerCGI()            If RfcErrorInfo.code = RFC_OK Then              RfcGetStructure hFunc, "RFCSI_EXPORT", @hStruct, _                RfcErrorInfo              RfcErrorHandlerCGI()              If RfcErrorInfo.code = RFC_OK Then                RfcGetChars hStruct, "RFCHOST", @SAPHost, 8, _                  RfcErrorInfo                RfcGetChars hStruct, "RFCSYSID", @SAPSysID, 8, _                  RfcErrorInfo                RfcGetChars hStruct, "RFCDBHOST", @SAPDBHost, 32, _                  RfcErrorInfo                RfcGetChars hStruct, "RFCDBSYS", @SAPDBSys, 10, _                  RfcErrorInfo                Print "<h1>FM RFC_SYSTEM_INFO</h1>"                Print "Host: " & SAPHost                Print "<br />"                Print "SysID: " & SAPSysID                Print "<br />"                Print "DBHost: " & SAPDBHost                Print "<br />"                Print "DBSys: " & SAPDBSys                Print "<p>"              End If            End If            RfcDestroyFunction hFunc, RfcErrorInfo            RfcErrorHandlerCGI()          End If        End If        RfcCloseConnection hRFC, RfcErrorInfo        RfcErrorHandlerCGI()      End If      cgi_quit()    End If

'-End-------------------------------------------------------------------

 

As you can see, is there no big difference between this code and that code. Only the CGI initialization, the input from the HTML page and the output via console print command.

 

Now we take a look at the HTML code

 

<html>  <head>    <title>Test form for SAP RFC call via CGI</title>  </head>  <body>    <form action="0104_SysInfo_CGI.exe" method="post">      ASHost: <input type="text" name="ASHOST"><br />      SysNr: <input type="text" name="SYSNR"><br />      Client: <input type="text" name="CLIENT"><br />      User: <input type="text" name="USER"><br />      Password: <input type="password" name="PASSWD"><br />      Language:<select name="LANG">                 <option>EN</option>                 <option>DE</option>               </select>      <br />      <input type="submit" name="sub" value="Ok">    </form>  </body></html> 

 

Only one form, the different input fields and a button to submit the request.

 

001.JPG

 

If I press the button I get the following expected result.

 

002.JPG

 

As you can see is it with CGI and FreeBASIC very easy to implement SAP RFC library in a context of a web server.

 

Cheers

Stefan

 

 

P.S. You can find Part 1 here, Part 2 here and Part 3 here.

Idoc View and its use in sending PO Condition Data(PO Outbound)

$
0
0

Overview

 

During testing of PO outbound interface, a defect has been raised which says “PO Conditions are not appearing in IDoc”, which leads me to write a blog on Idoc View and use of IDoc view for sending PO condition data.

 

IDoc types can be used for more than one message, that is, for more than one business process. As a result, the IDoc types usually contain more segments than necessary for the individual application cases. To improve performance when generating IDocs, we can use views to ensure that only the segments relevant to the current business process are filled with data. Views are therefore only important for IDoc outbound processing.

This document explains how to use IDoc view to send PO conditions data.

 

Background

 

Check below snapshot from function module IDOC_OUTPUT_ORDERS/IDOC_OUTPUT_ORDCHG

1.jpg

As we can see highlighted comment which says “Do not Send Conditions without View”, we have to create a view for IDoc type/IDoc extension to send PO condition data.

In this document, we are going to create IDoc view for Idoc extension.

 

Configuration & Design in SAP

 

Create Idoc View:

For some of IDoc type/message type, views are already available.

Go to WE32 and press F4

2.jpg

As we can see from above IDoc view is already there for PO create/change.

Select any one of them and click display

 

3.jpg

As we can see above it is available for Basic type ORDERS05. Look at Color Legend in  below screen shot, the Greens are included in Idoc view.


4.jpg

 

Here we have created an Idoc extension so we have to create view for IDoc extension.

Go to WE32 and enter a name for View and click on Create icon.

 

Check below snapshot for view created for Idoc extension

5.jpg

As we can condition data are included in extension.



Assign IDoc View to Partner Profile


           Go to WE20 and assign Idoc view in partner profile.

6.jpg

 

Comparison with Idoc Reduction

 

As we know SAP has also provided Idoc Reduction tool (BD53) to remove segments which are not required.

Key differences between Idoc Reduction and Idoc View are:

 

  • Idoc Reduction works at segment field level. It means we can remove fields from segments which are not required instead of removing entire segment.In case of IDoc view, entire segment is rejected. No control at field level.


  • In case of Idoc reduction a new message has to be created and assigned in Partner Profile while in Idoc view no need to create new message type just maintain an Idoc View using WE32 for Idoc type/Message Type/Extension combination and assign the View in Partner Profile.

 

Scenario Execution

 

Without IDoc View:

 

First test without Idoc view assigned in partner profile

Go to ME21N and create PO.

 

7.jpg

 

Check generated Idoc in WE02.

8.jpg

 

As we can see above there are no condition segments appearing in Idoc.

 

With IDoc View:

Now test with Idoc view assigned in partner profile

Go to ME21N and create PO.

9.jpg

 

Check generated Idoc in WE02.

10.jpg

As we can see above there are condition segments appearing in Idoc.

 

References

 

     http://help.sap.com

     http://scn.sap.com

       SAP Note: 185445

Process Synchronisation Between ABAP and the Presentation Server

$
0
0

Hello community,

 

the overview of this forum offers a lot of connection technologies from and to ABAP, e.g. HTTP, XML and SOAP, RFC/BAPI etc. etc. etc. I am the opinion, that the COM interface (Component Object Model) is also a connection technology of ABAP. Sure, it works only with dialog processes with the SAP GUI for Windows, on this point it is limited in comparison with other connectivity methods. Last but not least combines the ABAP COM interface an easy coding with powerful possibilities.

 

Here now an example of process synchronisation between ABAP and the Microsoft Office suite, e.g. Excel with VBA (Visual Basic for Applications), via a COM library. For the process synchronization and communication offers Windows the IPC interface (Interprocess Communication).

 

There are different technics to synchronize and to communicate between processes on Windows, like

  • Events,
  • Semaphores,
  • FileMaps and
  • the ClipBoard
  • etc.

 

To use this possibilities I programmed a COM library which offers this technics. You find it here.

 

At first the ABAP program which creates an event, with the name TestEvent, and then it waits until the event is set.

 

"-Begin-----------------------------------------------------------------

  Report  zCOMIPC.

 

  "-Includes------------------------------------------------------------

    Include OLE2INCL.

 

  "-Constants-----------------------------------------------------------

    Constants Infinite Type i Value -1.

 

  "-Variables-----------------------------------------------------------

    Data oIPC Type Ole2_Object.

    Data rc Type i.

    Data hEvent Type i.

 

  "-Main----------------------------------------------------------------

    Create Object oIPC 'COMIPC'.

 

    If sy-subrc = 0 And oIPC-HANDLE <> 0 And oIPC-TYPE = 'OLE2'.

 

      "-Event-----------------------------------------------------------

        Call Method Of oIPC 'EventCreate' = hEvent

          Exporting #1 = 'TestEvent' #2 = 1 #3 = 0.

        Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.

       

        If hEvent <> 0.

 

          Call Method Of oIPC 'EventWait' = rc

            Exporting #1 = 'TestEvent' #2 = Infinite.

          "-------------------------------------------------------------

          "-

          "- At this point the ABAP program waits until the VBA routine

          "- was executed

          "-

          "-------------------------------------------------------------

          Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.

 

          Call Method Of oIPC 'EventClose' = rc

            Exporting #1 = hEvent.

          Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.

         

        EndIf.

 

      Free Object oIPC.

 

    EndIf.

 

"-End-------------------------------------------------------------------

 

Here now the VBA routine, to set the event.

 

'-Begin-----------------------------------------------------------------

 

  Public oIPC As COMIPC.COMIPC

 

  '-Sub TestEvent-------------------------------------------------------

    Sub TestEvent()

   

      Set oIPC = CreateObject("COMIPC")

     

      oIPC.EVENTSET "TestEvent"

     

      Set oIPC = Nothing

     

    End Sub

 

'-End-------------------------------------------------------------------

 

After the event is set, the ABAP program continues running and closes the event.

 

This simple example should demonstrate, on the one hand, that with little effort very interesting solutions can be created and, on the other hand, how powerful these solutions can be. On this way you can synchronize now different processes on the application and presentation server, in a context of dialog processes. The example above could be used to get data from ABAP to the Office suite, the data could be processed, in a longer running process, and after this the data comes back to the same ABAP process, which continues its work. Certainly there are many ways to realize this, and this is one of them.

 

The COM library itself is nothing more than an easy wrapper around the Windows API functions of IPC. Here as example the EventSet method:

 

'-EventSet--------------------------------------------------------------

'-

'- Sets the specified event object to the signaled state

'-

'- Param: EventName As String

'- Return: Zero if fails

'-

'-----------------------------------------------------------------------

  Method EventSet(ByVal EventName As String) As Long

 

    '-Variables---------------------------------------------------------

      Local NameOfEvent As AsciiZ * %Max_Path

      Local hEvent As Dword

      Local resSet As Long

      Local resClose As Long

 

    NameOfEvent = ACode$(EventName)

    hEvent = OpenEvent(%EVENT_ALL_ACCESS, 0, NameOfEvent)

    If hEvent Then

      '-Set event-------------------------------------------------------

        resSet = SetEvent(hEvent)

      '-Close handle----------------------------------------------------

        resClose = CloseHandle(hEvent)

      '-Return----------------------------------------------------------

        If resSet And resClose Then

          Method = resSet

        Else

          Method = 0

        End If

    Else

      Method = 0

    End If

 

  End Method

 

You can realize it in any programming language which supports COM library creation.

 

Hope you enjoy the perspective.

 

Cheers

Stefan

Tip: Easy Way of ABAP ActiveX Connectivity

$
0
0

Hello community,

 

a long time ago Thomas Jung published his very good blog about "Using Classic ActiveX Controls in the ABAP Control Framework" here.

I asked myself, is there an easier way to realize a connectivity between an ActiveX control and an ABAP program, e.g. for prototyping.

Here now my result: I use a selection screen with a docking container, and the docking container is linked to the ActiveX control. That's all

 

At first the program:

001.jpg

 

"-Begin-----------------------------------------------------------------

  Program Z_TEST.

 

    "-Variables---------------------------------------------------------

      Data Ref_Dock Type Ref To CL_GUI_DOCKING_CONTAINER.

      Data Ref_Media Type Ref To Z_CL_MEDIA.

 

    "-GUI---------------------------------------------------------------

      Selection-Screen Begin Of Block Media.

        Parameters pa_Dummy(1).

      Selection-Screen End Of Block Media.

 

    "-Main--------------------------------------------------------------

      At Selection-Screen.

 

        Create Object Ref_Dock

          Exporting

            REPID = sy-repid

            DYNNR = sy-dynnr

            SIDE = CL_GUI_DOCKING_CONTAINER=>dock_at_right

            RATIO = 50

          Exceptions

            Others = 1.

 

        Create Object Ref_Media

          Exporting

            PARENT = Ref_Dock

          Exceptions

            Others = 1.

 

        Call Method Ref_Media->setdatasource

          Exporting

            FileName = 'MyMovie.mp4'.

 

        Call Screen 1000.

 

"-End-------------------------------------------------------------------

 

As you can see, only a selection screen with a dummy parameter, the docking container, the media class and a method call to set the file name property.

 

Now the class for the ActiveX control, in my case the Windows Media Player:

002.JPG

 

"-Begin-----------------------------------------------------------------

 

  Class Z_CL_MEDIA Definition Public Inheriting From CL_GUI_CONTROL

    Final Create Public .

    Public Section.

      Type-Pools CNTL .

      Methods Constructor Importing Parent Type Ref To CL_GUI_CONTAINER.

      Methods Dispatch Redefinition.

      Methods SetDataSource Importing FileName Type String.

  EndClass.

 

  Class Z_CL_MEDIA Implementation.

 

    Method Constructor.

      Call Method Super->constructor

        Exporting

          CLSID = 'MediaPlayer.MediaPlayer'

          PARENT = Parent

          LIFETIME = 2

        Exceptions

          Others = 1.

    EndMethod.

 

    Method Dispatch.

      Call Method CL_GUI_CFW=>Flush.

    EndMethod.

 

    Method SetDataSource.

      Call Method Set_Property

        Exporting

          PROPERTY = 'FileName'

          VALUE = FileName.

      Call Method CL_GUI_CFW=>FLUSH.

    EndMethod.

 

  EndClass.

 

"-End-------------------------------------------------------------------

 

As you can see, also nothing special. In the constructor method is the name of the ActiveX control (ClassID) defined and the method SetDataSource sets the property FileName of the control.

 

Here now an example result:

003.JPG

With only 53 lines code you can implement the Windows MediaPlayer ActiveX control inside a selection screen.

 

Hint: To analyze the control you can use also COMView, a phantastic tool for viewing Windows COM things.

 

Cheers

Stefan

Tip: Easy Way of ABAP ActiveX Connectivity (Addendum)

$
0
0

Hello community,

 

I presented here an approach for an easy way to use ActiveX controls inside ABAP. I got a few e-mails with questions about the possibility to use different ActiveX control. Here now other examples to show that it isn't only easy, it is also very flexible.

 

Here now two little modifications to use the Acrobat PDF control and the Internet Explorer control - changes are marked in red.

 

"-Begin-----------------------------------------------------------------

  Program Z_TEST.

 

    "-Variables---------------------------------------------------------

      Data Ref_Dock Type Ref To CL_GUI_DOCKING_CONTAINER.

      Data Ref_Media Type Ref To Z_CL_MEDIA.

 

    "-GUI---------------------------------------------------------------

      Selection-Screen Begin Of Block Media.

        Parameters pa_Dummy(1).

      Selection-Screen End Of Block Media.

 

    "-Main--------------------------------------------------------------

      At Selection-Screen.

 

        Create Object Ref_Dock

          Exporting

            REPID = sy-repid

            DYNNR = sy-dynnr

            SIDE = CL_GUI_DOCKING_CONTAINER=>dock_at_right

            RATIO = 50

          Exceptions

            Others = 1.

 

        Create Object Ref_Media

          Exporting

            PARENT = Ref_Dock

          Exceptions

            Others = 1.

 

        Call Method Ref_Media->setdatasource

          Exporting

            FileName = 'file://MyHTML.html'.       "InternetExplorer

            "FileName = 'MyPDF.pdf'.               "Acrobat

            "FileName = 'MyMovie.mp4'.             "Mediaplayer

 

        Call Screen 1000.

 

"-End-------------------------------------------------------------------

 

0032.jpg

 

"-Begin-----------------------------------------------------------------

 

  Class Z_CL_MEDIA Definition Public Inheriting From CL_GUI_CONTROL

    Final Create Public .

    Public Section.

      Type-Pools CNTL .

      Methods Constructor Importing Parent Type Ref To CL_GUI_CONTAINER.

      Methods Dispatch Redefinition.

      Methods SetDataSource Importing FileName Type String.

  EndClass.

 

  Class Z_CL_MEDIA Implementation.

 

    Method Constructor.

      Call Method Super->constructor

        Exporting

          CLSID = 'Shell.Explorer'                     "InternetExplorer

          "CLSID = 'AcroPDF.PDF'                       "Acrobat

          "CLSID = 'MediaPlayer.MediaPlayer'           "MediaPlayer

          PARENT = Parent

          LIFETIME = 2

        Exceptions

          Others = 1.

    EndMethod.

 

    Method Dispatch.

      Call Method CL_GUI_CFW=>Flush.

    EndMethod.

 

    Method SetDataSource.

      "Call Method Set_Property

      "  Exporting

          "PROPERTY = 'Src'                            "Acrobat

          "PROPERTY = 'FileName'                       "MediaPlayer

      "    VALUE = FileName.

      Call Method Call_Method                          "InternetExplorer

        Exporting

          METHOD = 'Navigate'

          P_COUNT = 1

          P1 = FileName.

      Call Method CL_GUI_CFW=>FLUSH.

    EndMethod.

 

  EndClass.

 

"-End-------------------------------------------------------------------

 

As you can see you must change of course the ClassID of the control and also the property resp. method to open the document. Acrobat uses the property Src and Internet Explorer uses the method Navigate.

 

0033.jpg

 

With a little bit more than 50 lines of ABAP code you can create interesting applications.

 

Cheers

Stefan

IDOC as Web Service

$
0
0

We had a requirement to convert IDOC’s in web service without PI (PO). We tried to find out whether SAP provides such solutions. SAP replied to our OSS message saying NO. So we developed our own solution that can convert any IDOC into a web service within minutes. Here I will explain the steps.

 

Once you set up the system then all programs are reusable to convert any IDOC into web service.

 

Step 1. Create WSDL for the IDOC basic type or extension type

Step 2. Create server proxy for the WSDL to host the IDOC

 

Step 1. Create WSDL for the IDOC basic type or extension type. You don’t need to transport step 1 to subsequent systems.

 

      1) Copy class CL_PROXY_TEST_UTILS to ZCL_PROXY_UTILS

            I) Edit method XSD2WSDL. Paste the source code attached below.

            II) Create method GET_WSDL.  Paste the source code attached below.

      2) Copy program SAPMSEDIDOCU to ZSAPMSEDIDOCU

            I) Copy all include programs with prefix Z

            II) Edit ZMSEDIDOCUF01 and paste source code below

      3) Activate all programs

      4) Assign a TCODE to program ZSAPMSEDIDOCU. In my case I have assigned ZIDOCWSDL

 

 

 

Run the transaction to download the WSDL of the IDOC. If you are using standard IDOC type then use parameter Basic Type or else if you have IDOC extension use Enhancement to download the WSDL.

 

Here I am downloading standard basic type ORDERS05

1.png

 

Save the file in your local drive. I have saved the file into my desktop.

 

2.png

3.png

 

Step 2. Create server proxy for the WSDL to host the IDOC

Create a class ZCL_CA_IDOC_SERVICE with 3 methods as below and copy paste the source code attached below and activate the class.

4.png

5.png

6.png

7.png

    Now create the server proxy from the WSDL you downloaded in step 1. Go to SE80 and crate a service

 

8.png

9.png

10.png

11.png

12.png

13.png

I have used $tmp. Please use your package and transport here.

14.png

15.png

16.png

Activate the service

 

Go to the implementing class by double clicking, Insert this code and activate the class.

17.png

output-tid = zcl_ca_idoc_service=>trigger_idoc( input = input queueid = space ).

18.png

 

Go to SOAMANAGER and create an endpoint for the service.

19.png

Now test the service from SOAPUI to post an IDOC into the system

 

20.png

 

TID 0A6A381E48FE541C4FFF0304 create with IDOC 881704

21.png

IDOC posted in SAP

 

22.png

Similarly you can convert any IDOC into a web service. With ABAP 7.40, SP05 you can further fine tune the code.


File Upload/Download through NetWeaver Gateway

$
0
0

Here I will explain file handing in NW Gateway in few simple steps.

 

1) Create a NetWeaver Gateway project in SEGW.

1.jpg

 

2) Create an Entity type “File” (you can choose any name)

2.jpg

 

Create an Entity Set for the Entity Type by checking the check  box.

2.1.jpg

 

Mark Entity Type “File” as Media

2.2.jpg

 

3) Create one property “FileName” mark it as key and type as String

3.jpg

 

4) Generate run-time objects (or artifacts)

4.jpg

4.1.jpg

 

5) Go to data provider extension class in edit mode and redefine method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM and

/IWBEP/IF_MGW_APPL_SRV_RUNTIME~UPDATE_STREAM. Then add below code.

5.jpg

 

/IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM for download file

5.1.jpg

 

DATA: ls_stream  TYPE ty_s_media_resource,

              ls_upld    TYPE zzupld.

 

READ TABLE it_key_tab ASSIGNING FIELD-SYMBOL(<fs_key>) INDEX 1.

 

DATA: lv_filename TYPE char30.

lv_filename = <fs_key>-value.

 

SELECT SINGLE * FROM zzupld INTO ls_upld WHERE filename = lv_filename.

  IF ls_upld IS NOT INITIAL.

ls_stream-value = ls_upld-value.

ls_stream-mime_type = ls_upld-mimetype.

 

copy_data_to_ref( EXPORTING is_data = ls_stream

                    CHANGING  cr_data = er_stream ).

ENDIF.

 

/IWBEP/IF_MGW_APPL_SRV_RUNTIME~UPDATE_STREAM for upload file

5.2.jpg

 

DATA: lw_file TYPE zzupld.

 

READ TABLE it_key_tab ASSIGNING FIELD-SYMBOL(<fs_key>) INDEX 1.

 

lw_file-filename = <fs_key>-value.

lw_file-value    = is_media_resource-value.

lw_file-mimetype = is_media_resource-mime_type.

lw_file-sydate  = sy-datum.

lw_file-sytime  = sy-uzeit.

MODIFY zzupld FROM lw_file.

 

I have created a Z table ZZUPLD to store/extract the file

5.3.jpg

 

6) Register the service & service is ready for use

6.1.jpg

 

7) Test the service from GW client. Upload the file into the Z table and extract it.

      /sap/opu/odata/sap/ZDEMO_FILE_SRV/FileSet(lor.jpg)/$value

7.jpg

 

8) Browse your local file system and select your file. Once you upload the file SAP with automatically change the HTTP method as PUT . Execute the method. lor.jpg file got uploaded with ~status_code = 204.

8.jpg

 

File got updated in Z table

8.1.jpg

 

9) To download the file, just change the HTTP method to GET and execute. Program will read the existing file from the Z table as per FileName.

      Here we are passing lor.jpg so GET operation will download the file we uploaded in Z table.

8.2.jpg

 

Similarly you can upload any file type to the Z table and can download them.  In my next blog I will upload files from my UI5 application.

ScriptX NEON - Library To Use Any Script Language Inside ABAP

$
0
0

Hello community,

 

one year ago I presented here a way how to use Freestyle BASIC Script Language (FBSL) inside ABAP. Also I presented here a way how to use native C with FBSL inside ABAP. Here is now the Next stEp Of evolutioN (NEON) of FBSLX, ScriptX. You can find ScriptX here and FBSL here.


ScriptX is a COM library to control scripting languages. Therefor it offers a set of different functions which supports the pre and post activities to use any scripting language, and also the communication to the running script. ScriptX contains FBSL, a powerful scripting language which extends the possibilities of ScriptX to a maximum.


zjuliarings2.jpg

Lord of the Julia Rings 2 inside ABAP in eclipse


ScriptX builds a bridge to integrate your presentation server environment on Windows platform in the SAP application server environment. You can communicate between these two worlds on the application server side with ABAP and on the presentation server side with FBSL. FBSL offers phantastic possibilities to be the base on the presentation server side.


ScriptX1.jpg

 

zufo.jpgUFO inside ABAP in eclipse

 

 

Python inside ABAP

 

With ScriptX you can use e.g. Python inside ABAP. Here an example how to use a simple Python 3.4.1 script inside ABAP

 

"-Begin-----------------------------------------------------------------

  Program ZSCRIPTX.

 

    "-Constants---------------------------------------------------------

      Constants SW_SHOWNORMAL Type i Value 1.

 

    "-Variables---------------------------------------------------------

      Data oScriptX Type OLE2_OBJECT.

      Data Buffer Type String Value ''.

      Data WorkDir Type String Value ''.

      Data PathName Type String Value ''.

      Data FileName Type String Value ''.

      Data rc Type i Value 0.

      Data hFileMap Type i Value 0.

      Data RetCode Type String Value ''.

 

    "-Macros------------------------------------------------------------

      Define _.

        Concatenate Buffer &1 cl_abap_char_utilities=>cr_lf Into Buffer.

      End-Of-Definition.

 

      Define Flush.

        Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.

      End-Of-Definition.

 

    "-Main--------------------------------------------------------------

      Create Object oScriptX 'ScriptX'.

      If sy-subrc <> 0 Or  oScriptX-Handle = 0 Or oScriptX-Type <> 'OLE2'.

        Call Function 'ZSCRIPTXDLL'.

        Create Object oScriptX 'ScriptX'.

      EndIf.

 

      If sy-subrc = 0 And oScriptX-Handle > 0 And oScriptX-Type = 'OLE2'.

 

        "-Show messages in system debugger, e.g. DebugView--------------

          Set Property Of oScriptX 'DebugOutput' = 1.

 

        "-Get SAP GUIs work directory-----------------------------------

          Call Method cl_gui_frontend_services=>get_sapgui_workdir

            Changing SAPWORKDIR = WorkDir Exceptions Others = 1.

          Set Property Of oScriptX 'CurrentDirectory' = WorkDir.

 

        Call Method Of oScriptX 'About'.

        Flush.

 

        "-Create archive file-------------------------------------------

          Call Function 'ZPYTHONRAR'.

 

        "-Unpack archive------------------------------------------------

          Call Method Of oScriptX 'Unrar' Exporting

            #1 = 'Python.rar' #2 = ''.

          Flush.

 

        "-Delete archive file-------------------------------------------

          Call Method Of oScriptX 'DeleteFileA' Exporting

            #1 = 'Python.rar'.

          Flush.

 

        Call Method Of oScriptX 'FileMapCreate' = hFileMap

          Exporting #1 = 'SAP001' #2 = 64.

        Flush.

 

        If hFileMap <> 0.

 

"-Python Script begin---------------------------------------------------

 

  "-Coding--------------------------------------------------------------

_ '# -*- coding: iso-8859-15 -*-'.

 

  "-Packages------------------------------------------------------------

_ 'import ctypes'.

_ 'import sys'.

 

  "-Constants-----------------------------------------------------------

_ 'FILE_MAP_ALL_ACCESS = 30'.

 

  "-Main----------------------------------------------------------------

_ 'print("Python version ", sys.version)'.

_ 'print("Hello World from Python")'.

_ 'var_inp = input("Enter something: ")'.

_ 'print("You entered: ", var_inp)'.

 

  "-Transfer the input to the memory map file---------------------------

_ 'hMMF = ctypes.windll.kernel32.OpenFileMappingW(FILE_MAP_ALL_ACCESS, \'.

_ '  0, "SAP001")'.

 

_ 'if hMMF != 0:'.

_ '  buffer = ctypes.windll.kernel32.MapViewOfFile(hMMF, \'.

_ '    FILE_MAP_ALL_ACCESS, 0, 0, 0)'.

 

_ '  if buffer != 0:'.

_ '    ctypes.cdll.msvcrt.strcpy(buffer, var_inp.encode("ascii"))'.

_ '    rc = ctypes.windll.kernel32.UnmapViewOfFile(buffer)'.

_ '  rc = ctypes.windll.kernel32.CloseHandle(hMMF)'.

 

_ 'input("Press any key...")'.

 

"-Python Script end-----------------------------------------------------

 

          "-Create Python script file-----------------------------------

            Concatenate WorkDir '\Test.py' Into FileName.

            Call Method Of oScriptX 'WriteFile' Exporting #1 = FileName

              #2 = Buffer.

            Flush.

 

          "-Add Python path---------------------------------------------

            Concatenate WorkDir '\Python' Into PathName.

            Call Method Of oScriptX 'AddPath' Exporting #1 = PathName.

            Flush.

 

          "-Execute Python script---------------------------------------

            Call Method Of oScriptX 'Shell' = rc

              Exporting #1 = 'python.exe' #2 = 'Test.py'

              #3 = SW_SHOWNORMAL #4 = 1.

            Flush.

 

          "-Read the input from the memory map file---------------------

            Call Method Of oScriptX 'FileMapRead' = RetCode

              Exporting #1 = 'SAP001' #2 = 64.

            Flush.

 

          "-Destroy memory map file-------------------------------------

            Call Method Of oScriptX 'FileMapClose' = rc

              Exporting #1 = hFileMap.

            Flush.

 

          "-Delete Python script file-----------------------------------

            Call Method Of oScriptX 'DeleteFileA'

              Exporting #1 = FileName.

 

          "-Delete Python environment-----------------------------------

            Call Method Of oScriptX 'DeleteDirectory'

              Exporting #1 = 'Python'.

            Flush.

 

          "-Write the content of the memory map file--------------------

            Write: / RetCode.

 

        EndIf.

 

        Free Object oScriptX.

      EndIf.

 

"-End-------------------------------------------------------------------

 

001.jpg

 

002.JPG

 

Comments are welcome.

 

Enjoy it.

 

Cheers
Stefan

File attachment in ABAP Web Service - Service Consumer(Consumer Proxy)

$
0
0

During one of our requirement I found ABAP Consumer proxy class doesn't create the attachment method like Java consumer proxy. We need to insert the attachment at runtime using WS protocol. Here I am going to explain the steps and code.

Assumption:

  1. Web service you are going to consume has the attachment enabled

        <sapattahnd:Enabledxmlns:sapattahnd="http://www.sap.com/710/features/attachment/">true</sapattahnd:Enabled>


  2.  Web service is consumed and proxy class is activated

  3.  Create a Z class, method and use the code below

 

METHOD set_proposal.
* Author: Amaresh Pani  DATA: lcl_obj TYPE REF TO zca_co_customerproposal,        ls_request  TYPE  zca_send_customer_proposal_re4,        ls_response TYPE  zca_send_customer_proposal_re3.  TRY.      CREATE OBJECT lcl_obj.      CATCH cx_ai_system_fault INTO lx_fault.      gv_msg = lx_fault->get_text( ).  ENDTRY.
*----------------------------------------------------------------------------------------**
DATA: lo_attachments                TYPE REF TO if_wsprotocol_attachments.
DATA: g_attachment    TYPE REF TO  if_ai_attachment,      g_attachments    TYPE          prx_attach,      "Internal table for attachment      g_attach_xstring TYPE          xstring.          "variable of xstring type.
* binary xstring file stored in Z table
SELECT SINGLE value FROM zzupld INTO g_attach_xstring WHERE filename = 'CUST'.
TRY.    lo_attachments ?= lcl_obj->get_protocol( if_wsprotocol=>attachments ).    g_attachment = lo_attachments->get_attachment_from_binary(          data = g_attach_xstring                " File content          type = if_ai_attachment=>c_mimetype_pdf " MIME type          name = 'CustomerProposal' ).            " Name of PDF to be uploaded    APPEND g_attachment TO g_attachments.    lo_attachments->set_attachments( g_attachments ).    CATCH cx_ai_system_fault INTO lx_fault.    gv_msg = lx_fault->get_text( ).
ENDTRY.
*----------------------------------------------------------------------------------------**
ls_request-send_customer_proposal_request-document-opprotunity_id-content = '7117941'. " Defaulted content of proxy  TRY.      lcl_obj->send_customer_proposal(        EXPORTING          send_customer_proposal_request  = ls_request        IMPORTING          send_customer_proposal_respons = ls_response ).    CATCH cx_ai_system_fault INTO lx_fault.      gv_msg = lx_fault->get_text( ).    CATCH cx_ai_application_fault INTO lx_fault1.      gv_msg = lx_fault->get_text( ).  ENDTRY.
ENDMETHOD.

Content in Z table zzupld

Capture.JPG

Remember to set attachment "YES" while creating the endpoint.

 

Capture1.JPG

Execute the method to trigger the web service with attachment. Enable payload trace in SRT_UTIL to see the file attachment.

Capture5.JPG

SOAP creates tag MULTIPART. PART_1 contains the general SOAP xml content. PART_2 contains the attachment as above.

How to Store and Use Any Code with ABAP

$
0
0

Hello community,

 

I presented here the possibility to use FBSL via ScriptX inside ABAP. FBSL offers JIT compiler layers for Intel-style assembly and ANSI C. Therewith you can use Assembler and C inside your ABAP program. Here now a tiny trick to store and use your Assembler and C code in the ABAP environment.

 

You can store your code as include and read the include at the execution time of your ABAP program. To do that you can use the following function module. It reads the content of the include and delivers it as string.

 

"-Begin-----------------------------------------------------------------

  Function ZREADINCLASSTRING

    Importing

      Value(I_INCLNAME) Type SOBJ_NAME

    Exporting

      Value(E_STRINCL) Type String.

 

    "-Variables---------------------------------------------------------

      Data resTADIR Type TADIR.

      Data tabIncl Type Table Of String.

      Data lineIncl Type String Value ''.

      Data strIncl Type String Value ''.

 

    "-Main--------------------------------------------------------------

      Select Single * From TADIR Into resTADIR

        Where OBJ_NAME = I_InclName.

      If sy-subrc = 0.

 

        Read Report I_InclName Into tabIncl.

        If sy-subrc = 0.

          Loop At tabIncl Into lineIncl.

            Concatenate strIncl lineIncl cl_abap_char_utilities=>cr_lf

              Into strIncl.

            lineIncl = ''.

          EndLoop.

        EndIf.

 

      EndIf.

      E_strIncl = strIncl.

 

  EndFunction.

 

"-End-------------------------------------------------------------------

 

 

Now you can create an include with the following ANSI C content:

 

//-Begin----------------------------------------------------------------

 

  #include <windows.h>

 

  int main() {

 

    int rc = MessageBox(0, "Hello World from FBSL Dynamic C Layer",

      "FBSL Dynamic C Layer", 0);

 

  }

 

//-End------------------------------------------------------------------

 

 

And you can use the C code with the following report:

 

"-Begin-----------------------------------------------------------------

  Program ZTESTDYNC2.

 

    "-Constants---------------------------------------------------------

      Constants SW_SHOWNORMAL Type i Value 1.

 

    "-Variables---------------------------------------------------------

      Data oFBSL Type OLE2_OBJECT.

      Data Buffer Type String Value ''.

      Data WorkDir Type String Value ''.

      Data WinInc Type String Value ''.

      Data FileName Type String Value ''.

      Data ProcID Type i Value 0.

      Data InclCode Type String Value ''.

 

    "-Macros------------------------------------------------------------

      Define _.

        Concatenate Buffer &1 cl_abap_char_utilities=>cr_lf Into Buffer.

      End-Of-Definition.

 

      Define Flush.

        Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.

      End-Of-Definition.

 

    "-Main--------------------------------------------------------------

      Create Object oFBSL 'ScriptX'.

      If sy-subrc <> 0 Or  oFBSL-Handle = 0 Or oFBSL-Type <> 'OLE2'.

        Call Function 'ZSCRIPTXDLL'.

        Create Object oFBSL 'ScriptX'.

      EndIf.

 

      If sy-subrc = 0 And oFBSL-Handle > 0 And oFBSL-Type = 'OLE2'.

 

        "-Show messages in system debugger, e.g. DebugView--------------

          Set Property Of oFBSL 'DebugOutput' = 1.

 

        "-Get SAP GUIs work directory-----------------------------------

          Call Method cl_gui_frontend_services=>get_sapgui_workdir

            Changing SAPWORKDIR = WorkDir Exceptions Others = 1.

          Set Property Of oFBSL 'CurrentDirectory' = WorkDir.

 

        Concatenate '#Include "' WorkDir '\Include\Windows.inc"'

          Into WinInc.

 

        Call Method Of oFBSL 'ExtractFbslExe'.

        Call Method Of oFBSL 'ExtractFbslWinInc'.

        Call Method Of oFBSL 'ExtractFbslCInc'.

 

"-FBSL script begin-----------------------------------------------------

_ '#AppType GUI'.

_ '#Option Strict'.

_ WinInc.

 

  "-Dynamic C routine begin---------------------------------------------

    _ 'DynC Test()'.

 

    "-Read C code from include file-------------------------------------

      Call Function 'ZREADINCLASSTRING'

        Exporting I_InclName = 'ZTESTDYNCINC'

        Importing E_strIncl = InclCode.

      _ InclCode.

   

    _ 'End DynC'.

  "-Dynamic C routine end-----------------------------------------------

 

_ 'Sub Main()'.

_ '  Test()'.

_ 'End Sub'.

"-FBSL script end-------------------------------------------------------

 

        Concatenate WorkDir '\TestDynC2.fbs' Into FileName.

        Call Method Of oFBSL 'WriteFile' Exporting #1 = FileName

          #2 = Buffer.

        Flush.

 

        Call Method Of oFBSL 'Shell' = ProcID Exporting

          #1 = 'Fbsl.exe' #2 = 'TestDynC2.fbs'

          #3 = SW_SHOWNORMAL #4 = 1.

        Flush.

 

        Call Method Of oFBSL 'DeleteFileA'

          Exporting #1 = 'TestDynC2.fbs'.

        Call Method Of oFBSL 'DeleteFileA' Exporting #1 = 'Fbsl.exe'.

        Call Method Of oFBSL 'DeleteDirectory'

          Exporting #1 = 'CInclude'.

        Call Method Of oFBSL 'DeleteDirectory' Exporting #1 = 'Include'.

 

        Free Object oFBSL.

      EndIf.

 

"-End-------------------------------------------------------------------

 

With ABAP in eclipse you have an excellent environment to develop polyglot, look here, here, here and here.

Now you can use also Assembler and C in your ABAP code and with ABAP in eclipse you have the possibility to do it in one IDE.

 

Comments are welcome.

 

Cheers

Stefan

How to use Assembler Inside ABAP - Example CPUID and RDRAND instructions

$
0
0

Hello community,

 

with the random number generator offers Intel a powerful possibility to use a secure way to create random numbers on a hardware base. You can find more information here. Unfortunately it is not direct possible to use this kind of code inside of ABAP. I presented here an example how to use ANSI C inside ABAP. On the same way it is possible to use assembler code inside ABAP. Here an example how to use the RDRAND instruction inside ABAP via FBSLs assembler layer.

At first we check the availability via CPUID instruction. If it is successful, we call the instruction via the opcodes. To receive the text of OutputDebugString use DebugView.

 

 

We begin with the assembler include:

 

;-Begin-----------------------------------------------------------------

 

  .data

    @FeatureFlagsECX dd 0

    @RandomNumber dd 0

    @NumberFormat db "%ld",0

    @strNumber db 20 dup 0

    @msgRDRAND db "Random number generator on-chip",0

 

  .code

    enter 0, 0

 

    ;-Checks the availability of CPUID instruction----------------------

      pushfd

      pop eax

      mov ebx, eax

      xor eax, &H00200000

      push eax

      popfd

      pushfd

      pop eax

 

    ;-If CPUID is available---------------------------------------------

      .if eax <> ebx

 

       ;-Feature information-------------------------------------------

          mov eax, 1

          cpuid

          mov [FeatureFlagsECX], ecx

 

          clc

          bt [FeatureFlagsECX], 30

          jnc Next

            invoke OutputDebugString, msgRDRAND

 

            ;-rdrand eax as opcodes-------------------------------------

              db &H0F, &HC7, &HF0

            jnc Next

              mov [RandomNumber], eax

              ;-Convert number to string--------------------------------

                invoke wsprintf, strNumber, NumberFormat, [RandomNumber]

              invoke OutputDebugString, strNumber

 

          @Next

 

      .endif

 

    mov eax, [RandomNumber]

    leave

    ret

 

;-End-------------------------------------------------------------------

 

 

Here the ABAP report:

 

"-Begin-----------------------------------------------------------------

  Program ZASSEMBLER.

 

    "-Constants---------------------------------------------------------

      Constants SW_SHOWNORMAL Type i Value 1.

 

    "-Variables---------------------------------------------------------

      Data oScriptX Type OLE2_OBJECT.

      Data Buffer Type String Value ''.

      Data WorkDir Type String Value ''.

      Data WinInc Type String Value ''.

      Data FileName Type String Value ''.

      Data rc Type i Value 0.

      Data hFileMap Type i Value 0.

      Data ProcID Type i Value 0.

      Data InclCode Type String Value ''.

      Data FBSLFileName Type String Value 'RandomNumber.fbs'.

      Data rcRandomNumber Type String Value ''.

      Data RandomNumber Type i Value 0.

 

    "-Macros------------------------------------------------------------

      Define _.

        Concatenate Buffer &1 cl_abap_char_utilities=>cr_lf Into Buffer.

      End-Of-Definition.

 

      Define Flush.

        Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.

      End-Of-Definition.

 

    "-Main--------------------------------------------------------------

      Create Object oScriptX 'ScriptX'.

      If sy-subrc <> 0 Or  oScriptX-Handle = 0 Or oScriptX-Type <> 'OLE2'.

        Call Function 'ZSCRIPTXDLL'.

        Create Object oScriptX 'ScriptX'.

      EndIf.

 

      If sy-subrc = 0 And oScriptX-Handle > 0 And oScriptX-Type = 'OLE2'.

 

        "-Show messages in system debugger, e.g. DebugView--------------

          Set Property Of oScriptX 'DebugOutput' = 1.

 

        "-Get SAP GUIs work directory-----------------------------------

          Call Method cl_gui_frontend_services=>get_sapgui_workdir

            Changing SAPWORKDIR = WorkDir Exceptions Others = 1.

          Set Property Of oScriptX 'CurrentDirectory' = WorkDir.

 

        Concatenate '#Include "' WorkDir '\Include\Windows.inc"'

          Into WinInc.

 

        Call Method Of oScriptX 'ExtractFbslExe'.

        Call Method Of oScriptX 'ExtractFbslWinInc'.

 

        Call Method Of oScriptX 'FileMapCreate' = hFileMap

          Exporting #1 = 'SAP001' #2 = 32.

 

        If hFileMap <> 0.

 

"-FBSL script begin-----------------------------------------------------

 

  "-Directives----------------------------------------------------------

  _ '#AppType GUI'.

  _ '#Option Strict'.

  _ WinInc.

 

  "-Function Assembler--------------------------------------------------

  _ 'DynAsm RandomNumber() As Long'.

 

    "-Read Assembler code from include file-----------------------------

      Call Function 'ZREADINCLASSTRING'

        Exporting I_InclName = 'ZASM_INC'

        Importing E_strIncl = InclCode.

      _ InclCode.

 

  _ 'End DynAsm'.

 

  "-Sub RC--------------------------------------------------------------

  _ 'Sub RC(ByVal FileMapName As String, ByVal RetCode As String)'.

  _ '  Dim hMMF As Long'.

  _ '  Dim Buffer As Long'.

  _ '  Dim Temp As String'.

  _ '  hMMF = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, FileMapName)'.

  _ '  If hMMF Then'.

  _ '    Buffer = MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0)'.

  _ '    If Buffer Then'.

  _ '      Poke(Buffer, RetCode)'.

  _ '      UnmapViewOffile(Buffer)'.

  _ '    End If'.

  _ '    CloseHandle(hMMF)'.

  _ '  End If'.

  _ 'End Sub'.

 

  "-Main----------------------------------------------------------------

  _ 'Sub Main()'.

  _ '  RC("SAP001", RandomNumber())'.

  _ 'End Sub'.

 

"-FBSL script end-------------------------------------------------------

 

          Concatenate WorkDir '\' FBSLFileName Into FileName.

          Call Method Of oScriptX 'WriteFile' Exporting #1 = FileName

            #2 = Buffer.

          Flush.

 

          Concatenate '"' FileName '"' Into FileName.

          Call Method Of oScriptX 'Shell' = ProcID Exporting

            #1 = 'Fbsl.exe' #2 = FileName

            #3 = SW_SHOWNORMAL #4 = 1.

          Flush.

          Replace All Occurrences Of '"' In FileName With ''.

 

          Call Method Of oScriptX 'FileMapRead' = rcRandomNumber

            Exporting #1 = 'SAP001' #2 = 32.

          Flush.

 

          "-Delete files------------------------------------------------

            Call Method Of oScriptX 'DeleteFileA'

              Exporting #1 = FileName.

            Call Method Of oScriptX 'DeleteFileA'

              Exporting #1 = 'Fbsl.exe'.

            Call Method Of oScriptX 'DeleteDirectory'

              Exporting #1 = 'Include'.

            Flush.

 

         RandomNumber = rcRandomNumber.

         Write: / RandomNumber.

 

         Call Method Of oScriptX 'FileMapClose' = rc

            Exporting #1 = hFileMap.

          Flush.

 

        EndIf.

 

        Free Object oScriptX.

      EndIf.

 

"-End-------------------------------------------------------------------

 

To execute this code you need ScriptX, which I introduced here.

 

As you can see it is possible to use Intel-style assembler code inside ABAP. In my case I need the CPU functions for doument management, here for creating (security) keys, AES chiffres and CRC checks,

 

Enjoy the code.

 

Cheers

Stefan

Viewing all 68 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>