Are you the publisher? Claim or contact us about this channel


Embed this content in your HTML

Search

Report adult content:

click to rate:

Account: (login)

More Channels


Channel Catalog


Channel Description:

SAP NetWeaver Gateway (formerly called "Project Gateway") is a technology that provides a simple way to connect devices, environments and platforms to SAP software based on market standards. The framework enables development of innovative people centric solutions bringing the power of SAP business software into new experiences such as social and collaboration environments, mobile and tablet devices and rich internet applications. It offers connectivity to SAP applications using any programming language or model without the need for SAP knowledge by leveraging REST services and OData/ATOM protocols '

older | 1 | .... | 3 | 4 | (Page 5) | 6 | 7 | .... | 13 | newer

    0 0
  • 12/12/13--21:18: Day two at TechEd Bangalore
  • http://scn.sap.com/community/events/teched/blog/2013/12/13/day-2-sap-netweaver-gateway-at-teched-bangalore-2013

     

    Schedule for Friday:

     

    Session ID

    Session Type

    H

    Title

    Track

    Speakers

    Session Date/Time/Location

    MOB108

    Lecture

    2 h

    Rapid Application and Service Development with SAP Mobile Platform 3.0

    Mobile

    Balakrishna Gottipati,

    Sujith Prathap

    Fri, 12/13  8:30a-10:30a

    Lounge 12

    CD802

    Roadmap / Q&A

    1 h

    Road Map Q&A: SAP NetWeaver Gateway - On-Premise and in the Cloud

    Custom Development

    Sudeesh K

    Fri, 12/13  5p-6p

    Show Floor (both sessions)

    CD263

    Hands On

    4 h

    ABAP on SAP HANA - Building an End-to-End App from HANA via ABAP to SAP UI5

    Custom Development

    Vishnu Prasad Hegde, Vaibhav Kumar, Prakash Kamaraj

    Fri, 12/13  1:30p-5:30p, HO2

    CD265

    Hands On

    4 h

    End-2-End Developer Experience with SAP HANA Cloud Platform and SAPUI5

    Custom Development

    Rui Nogueira, Ankur Kumar, Stephen Cherian

    Fri, 12/13  9a-1p, HO9

     

    Session ID

    Title

    Session owner

    Session Date/Time/Location

    SPK9750

    SAP NetWeaver Gateway - Introduction and Q&A

    Sudeesh K

    Fri, 12/13  2p-2:30p

    Lounge 6

    SPK9751

    SAP NetWeaver Gateway - Q&A

    Sudeesh K

    Fri, 12/13  3p-3:30p

    Lounge 2

    SPK10487

    SAP NetWeaver Gateway Services Development Insights

    Balakrishna Gottipati

    Fri, 12/13 2:30p-3p

    Lounge 2


    0 0

    Overview

    At times it is required to build a quick prototype or a solution by consuming an OData analytics service. We know that the OData Analytics service can be generated, managed and extended using the SEGW transaction. This is possible from GW 2.0 SP05 onwards. However you could also build an OData Analytics service without using SEGW transaction.

     

    However it is recommended to use SEGW; we could create an OData analytics service with minimalistic kick start using the transaction /IWBEP/ANA_SRV_GEN. This transaction is available from GW 2.0 SP04 onwards.

     

    Transaction /IWBEP/ANA_SRV_GEN

     

    Transaction.JPG

    Once the BEP model and BEP service are generated you could proceed to Gateway Hub system in activating the generated service using the transaction /IWFND/MAINT_SERVICE. Once the service is activated you could start using the OData analytics service as explained in the following blog series.

     

    Transform SAP BW Queries into OData Service: Part 2 - Analyze OData Analytics Service


    0 0

    It is a common approach applied by .NET developers to give multipart names to the individual projects in a Visual Studio solution. The name parts identify different aspects of the Visual Studio project, a typical name pattern is  "<CompanyName>.<Application>.<Component>". Example of this: "TNV.Purchase.OrderManagement".

     

     

    I applied this naming approach also for a GWPAM project to build a Microsoft Outlook AddIn: TNV.TasksClustering.OutlookAddIn. However, after I installed the compiled AddIn, Outlook failed to load it. The error details were:

     

    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "TNV_TasksClustering_OutlookAddIn.Icons.resources" was correctly embedded or linked into assembly "TNV.TasksClustering.OutlookAddIn" at compile time’


    I inspected the GWPAM generated code to analyze the problem cause. It appears that GWPAM replaces in the code that it generates, the dots ('.') in the Visual Studio project name into the underline ('_') character. Thus 'TNV.TasksClustering.OutlookAddIn' becomes 'TNV_TasksClustering_OutlookAddIn' in the generated C# code. But a side effect is that this results in a naming-inconsistency with embedded Resources: Visual Studio namely by default embeds .NET resources files in the compiled assembly with the unchanged project name, in this case thus still with the dots.

    Naming of embedded resources in GWPAM compiled assembly.jpg

    I have reported this issue to the Duet Enterprise / GWPAM product team. I expect it to be fixed in a forthcoming service pack. Until then, the pragmatic and simple workaround is to correct in the generated C# code the line that tries to load the embedded resource:

     

    Pragmatic fix to GWPAM dots issue.jpg


    0 0

    Top 5 most liked discussions for 2013 | LinkedIn

     

    Follow us on our LinkedIn group to view latest discussions:

    SAP NetWeaver Gateway | LinkedIn


    0 0

    GWPAM consumption of efficient JSON format only possible when Gateway service supports OData V3

     

    Standard the GWPAM generated AddIns consume the Gateway REST OData service via the AtomPub dataformat, and not via the more data-efficient JSON format. The reason is that the used .Net WCF Data Services Client library is not capable of consuming JSON dataformat. Because I prefer to consume REST services via the mobile-friendly JSON dataformat, I set out to augment a default generated GWPAM Outlook AddIn project to consume via OData JSON. As the service consumption is within .Net code, this is mostly a Microsoft.Net tail. However, as it turns out that to be even able to consume JSON in the Microsoft WCF client library, an important prerequisite is imposed on the consumed REST service; it also extends to there.

     

    JSON consumption via WCF Data Services Client Library

    Initially, WCF Data Services Client library only supported consumption of REST services via AtomPub dataformat. As of release 5.1 it is also possible to consume JSON, but with the limitation that the JSON format must be OData V3. Prerequisite for the consumed service is thus that it must be able to provide its data in OData JSON V3 dataformat. For the older OData versions (V1, V2), it is not [yet] possible to consume JSON in WCF Data Services Client library.

     

    Steps to augment to GWPAM project to consume JSON dataformat

    First prepare your project to be able to handle the JSON consumption:

    1. Install the latest WCF Data Services Client Library, at present this is 5.6.0. Installation is done via NuGet Package Manager, and must be applied to each GWPAM project in which you want to consume via JSON dataformat. The effect per project is that reference ‘Microsoft.Data.Services.Client’, version 5.6.0 is added; and that the (via GWPAM project template) already existing references ‘Microsoft.Data.EDM’, ‘Microsoft.Data.OData’, ‘System.Spatial’ are also upgraded to version 5.6.0.
    2. If present, remove the reference ‘System.Data.Services.Client’ from the GWPAM project(s). Note: Visual Studio 2010 default installs with that older WCF Data Services Client library.
    3. Install WCF Data Services 5.3.0 RTM Tools Installer in Visual Studio; also via NuGet.

     

    Next setup the consuming code to consume the REST service via OData. That is, if the service supports it

    1. Validate that the consumed service is able to return data in the required JSON dataformat, OData V3. Query for this the $metadata of the service, and validate that it contains “m:MaxDataServiceVersion='3.0'”
    2. Generate an EDMModel for the service, via ‘Add Service Reference’  (iso ‘Add SAP Service Reference’). Open the generated service proxy, and change the accessibility of ‘GeneratedEdmModel’ to public
    3. Edit the earlier generated SAP data services client code to consume the service via JSON dataformat
      1. In the constructor, set to initialize for ‘System.Data.Services.Common.DataServiceProtocolVersion.V3’
      2. Set the Format to link to the generated EDM Model: this.Format.LoadServiceModel =
        TNV.TasksClustering.OutlookAddIn.TaskClusterV3.TasksClusterService.GeneratedEdmModel.GetInstance;
      3. Set the Format to useJson: serviceContext.Format.UseJson()
      4. Copy the implementation + usage of methods ‘ResolveTypeFromName’ and ‘ResolveNameFromType’ from the generated service proxy in step 5. Modify the code to correspond to the full name of the SAP service proxy.

     

    GWPAM service modified to consume JSON.jpg

      1. Query the consumed REST service for JSON format; either via querystring param ‘$format=JSON’, or via Http Request Header ‘accept
        = application/json’

     

     

    That's it

    And that’s it. Now the GWPAM based Office AddIn is able to consume the REST Service via the more efficient JSON dataformat. Note that for the consumption itself it does not even has to a Gateway REST Service; it is also possible to consume REST services from other webservice platforms. But the GWPAM project templates and code generated are focussed on standard SAP NetWeaver Gateway services + data models; WFService as one evident example.


    0 0
    0 0

    How to test OData services in SAP NetWeaver Gateway is of great interest for our customers.

     

    For testing OData services in SAP NetWeaver Gateway SAP has provided the SAP NetWeaver Gateway Client that can be started using transaction /IWFND/GW_CLIENT. The Gateway Client is a built in REST client that allows to store test cases and run one or more stored test cases in a sequential order. This way it is for example possible to test the CRUD methods of an OData service by creating an object, querying the object, updating the object and finially deleting it.

     

    Customers have however requested that SAP would also offer support for performing tests using  Extended Computer Aided Test Tool (eCATT) . eCATT is used by customers frequently to create and execute functional tests. Its primary aim is the automatic testing of SAP business processes. Each test generates a detailed log that documents the test process and results.

     

    Though this functionality has not been added to the standard delivery of SAP NetWeaver Gateway our development team decided to publish the
    Gateway Test APIs as aproject on Code Exchangein SCN so that it can be leveraged by our customers.

     

    With the availability of Gateway Test APIs customer requests can be satisfied to enable eCATT based Test Automation for ODATA Services.

     

    Any feedback to the functionality we posted is welcome .

     

    Special thanks goes to my colleague Kranti Khilari for working hard on this.

     

    Best Regards,

    André

     

    Links:

     

    GITHUB: https://github.com/krantikhil/zsaplink-plugins-for-apis-enabling-test-automation-of-odata-services

    Featured Code Exchange projects: http://scn.sap.com/docs/DOC-41875


    0 0

    In my previous blog Steps to create custom Gateway service and Android application through Eclipse Part 1, I was discussing about getting PO data without CRUD operations and any filter conditions. In this blog I will explain all CRUD operations and how to build an android app based on input values. Before starting, I am expecting that you have basic idea of gateway service or you have gone through my previous blog.

     

    Below are the steps we will discuss in this blog.

    1. RFC function module with PO Number,Creation Date & PO Release indicator as input parameters.

    2. Create service in Gateway system with all the CRUD operations.(Create Read Update Delete)

    3. Test our service in 'Service Explorer'.

    4. Create Application in Exclipse and test it on Simulator.

     

    1. Create a custom RFC Function Module to get PO header and item details. ( Developed in Backend system)

    In this FM we have option to pass PO number & Creation date range. I am using custom FM for Read & Query operations only as there is no standard FM to get PO data with input as PO number Range or Date range.

    A.  FM: ZBAPI_PO_GETLIST to Read & Query Operations

    B.  FM: BAPI_PO_CREATE1 to Create.

    C.  FM: BAPI_PO_CHANGE to Delete & Update Operations

    FM1.jpg

    FM2.jpg

    You can get sample code in the attached file.

     

    2. Create service in Gateway system with all the CRUD operations.(Create Read Update Delete)

    Goto SEGW:

    1.jpg

    Import Entity type from Data Source

    2.jpg

    Entity Type for PO

    3.jpg

    Entity Type for POItems

    4.jpg

    Create Entity sets, Association and Activate it.

    5.jpg

    Map data source for READ

    6.jpg

    7.jpg

    8.jpg

    Similarly do it for Query , update & delete operations

    9.jpg

    10.jpg

    11.jpg

    Similarly map data sorce for POItemSet for Read & Query also

    13.jpg

    Goto Transaction: /IWFND/MAINT_SERVICE

    Select service and add to list

    14.jpg

    Select service and explore service:

    15.jpg

    2.jpg

    3.jpg

    In my next blog Custom Gateway service with CRUD Operations and Android application through Eclipse Part 2 I will explain various combinations of filter conditions and how to test CRUD operations.


    0 0

    WP_20140116_008.jpg

    In September last year I have been asked by Robert Eijpe from our partner NL for Business (NL4B) to give a presentation about SAP NetWeaver Gateway at the "Developer Dag" (Developer Day) of the VNSG. The VNSG is the Dutch speaking User Group for all SAP and SAP BusinessObjects users in the Netherlands and Flanders which is the Dutch speaking northern part of Belgium.

     

    What is not known to most people is that the Dutch speaking SAP user group is the third largest SAP user group in the world!

     

    The Deverloper Dag took place this Thursday (January the 15th) in the nice building where the offices of SAP Netherlands and the VNSG are located in s'Hertogenbosch.

     

     

     

    An impressive number of 140 developers had registerd for this event so that it was necessary to split the audience for the key notes in two rooms.

     

    WP_20140116_009.jpg

     

    The event started with a first key note by Robert Eijpe who provided an overview about the interesting and exciting topics that should keep SAP developers enthralled such as HANA, OData, Gateway, Cloud Development etc. 

     

    After the key note there was a packed agenda with several sessions in two parallel tracks. 

     

    In their presentations Leon Boeijen,R. Eijpe,Robin Fillerup, B. Meijs,Jan Penninkhof and myself covered various topics such as SAPUI5, SAP FIORI, SAP NetWeaver Gateway, HANA XS Development, HANA Cloud Development, Development on top of SAP NetWeaver 740 but also WebDynpro ABAP and FloorPlanManager.

     

     

     

    WP_20140116_014.jpg

     

    The event was closed by a second key note presented by Nikhil Dhairyawan about the "Future of ABAP". In his presetnation Nikhil highlighted the current innovations & improvements in SAP Application Server ABAP 7.4 and gave the participants a perspective on the role of ABAP in SAP’s platform strategy. We learned that ABAP will live 4ever .

     

    For me it was a great time in the Netherlands again and having some time to practive my Dutch.

     

    I am looking forward for the next event. Maybe presenting to the upcoming development focus group at VNSG  or by doing another .SAP CodeJam ?

     

     


    0 0

    SAP Gateway has come a long way. It’s actually quite pleasant to develop a quick REST web service these days with it. With the growing presence of Gateway services, the question keeps popping up with our clients on how to connect to non-SAP services. In this blog I’ll show one simple option for using Gateway as a proxy and hosting SAPUI5 application all in one place. Our example is an external contract management application.

     

    You can see here how the application will eventually look (SAPUI5):

     

     

     

    Our external web service itself uses XML-based REST services. We developed this quickly to demonstrate this application.

     

    We have two services. One that includes a list of contracts, and one that goes into the details of a contract.

     

    Get a list:

     

     

    Get a single contract:

     

     

    Next, in ABAP, create a function module to call these services. The function module should utilize the http client class: if_http_client.

     

    Use this class to make an outbound web service call, and parse the xml and return it to the function module.

     

    It looks like this:

     

     

    Use the same concept for the function module for the get details call.

     

    Next, jump into Gateway and use transaction SEGW to define your new service. We defined the get list, and get details.

     

    In the service implementation we call a remote rfc which are the functions we defined above:

     

     

    After activated, you can test out your new OData services:

     

     

    So now we can connect our SAPUI5 to Gateway just like any other service!

     

    If you haven’t done SAPUI5 in a while, things have really changed. The eclipse add-on is very complex to install, but sure does a great job once you have it. I particularly like the team components which streamline the upload to the BSP. Manually uploading this content was very painful!

     

    Create a new SAPUI5 project in eclipse and check it into your ABAP system as a new BSP. Start with the template that creates the index.html

     

    And include the controller and view:

     

     

     

    This guide is really a lot of help if you haven’t done this before: http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/40d59930-791c-3010-2abd-ac7793ad6c57?QuickLink=index&overridelayout=true&59017145615734

     

    I created a simple table and set a binding for my get list. I also added an event on a button in the list that creates a dialog popup and gets the details of that contract.

     

    Make sure to set your binding to your collection that matches what you have in gateway: oTable.bindRows("/ContractCollection")

     

    Once this is complete, you can go into your BSP and test your application:

     

     

    It performs very nicely. Clicking on each contract makes another ajax call to the get contract details.

     

    For more demonstrations, please see our work at Mindset Consulting: http://www.mindsetconsulting.com/solutions.html

     

    You can also follow me (Gavin Quinn) on LinkedIn: http://lnkd.in/gvjKb4

     

    Thanks to Paul Modderman, one of my favorite ABAP gurus who provided some incredible guidance on this topic: https://www.linkedin.com/pub/paul-modderman/4/680/39a


    0 0

    How to test OData services in SAP NetWeaver Gateway is of great interest for our customers.

     

    For testing OData services in SAP NetWeaver Gateway SAP has provided the SAP NetWeaver Gateway Client that can be started using transaction /IWFND/GW_CLIENT. The Gateway Client is a built in REST client that allows to store test cases and run one or more stored test cases in a sequential order. This way it is for example possible to test the CRUD methods of an OData service by creating an object, querying the object, updating the object and finially deleting it.

     

    Customers have however requested that SAP would also offer support for performing tests using  Extended Computer Aided Test Tool (eCATT) . eCATT is used by customers frequently to create and execute functional tests. Its primary aim is the automatic testing of SAP business processes. Each test generates a detailed log that documents the test process and results.

     

    Though this functionality has not been added to the standard delivery of SAP NetWeaver Gateway our development team decided to publish the
    Gateway Test APIs as aproject on Code Exchangein SCN so that it can be leveraged by our customers.

     

    With the availability of Gateway Test APIs customer requests can be satisfied to enable eCATT based Test Automation for ODATA Services.

     

    Any feedback to the functionality we posted is welcome .

     

    Special thanks goes to my colleague Kranti Khilari for working hard on this.

     

    Best Regards,

    André

     

    Links:

     

    GITHUB: https://github.com/krantikhil/zsaplink-plugins-for-apis-enabling-test-automation-of-odata-services

    Featured Code Exchange projects: http://scn.sap.com/docs/DOC-41875


    0 0

    So far using SAP NetWeaver Gateway you can annotate OData elements only with SAP annotations, now it is possible to enhance the metadata with custom-annotations also and this can be done with vocabulary-based annotation.  Basically vocabularies provide the ability to annotate metadata. A vocabulary file is a namespace that contains terms and these terms are used to annotate OData artifacts.

     

    This blog will explain how you can annotate metadata with consumer specific vocabulary using SAP NetWeaver Gateway Service Builder tool.

    This feature is available from SAP NetWeaver Gateway SP07.

     

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Step-by-Step Procedure

    Following are steps which you need to follow

    • Upload Vocabularies into the Vocabulary Repository
    • Create a Project
    • Import a vocabulary file
    • Add Vocabulary-Based Annotations
    • Generate Runtime Artifact
    • Registration and Activation of the Generated Service

    Upload Vocabularies into the Vocabulary Repository

    Start the Service Builder by using the transaction SEGW.

     

     

    To upload a vocabulary file into the Vocabulary Repository in the Service Builder, proceed as follows:

    1. From menu bar choose Extras ->Vocabulary Repository. The central Vocabulary Repository opens and shows a table for displaying the vocabulary ID, version, namespace, and description. Any previously uploaded vocabulary files are displayed here, otherwise the table is empty.UploadVocabulary.png
    2. Change to edit mode and choose Append Row to add a new row to the table.
    3. Enter a unique vocabulary ID for the vocabulary file you want to upload. Version 1 is assigned automatically to the first version of
      the vocabulary file you upload.
    4. Click the Upload icon in the Upload Vocabulary Content column to navigate to the vocabulary file you want to upload. The namespace of the vocabulary file is entered automatically.
    5. Enter a description for the newly uploaded vocabulary file.
    6. Save the changes and choose Enter.

     

    Create a Project

      1. Create a New Project by clicking on 4.jpg

     

      2. Select Service with Vocabulary-Based Annotationsin order to use custom annotations.

    Project Type.PNG

      3. Use any of the available options(like Import ,Redefine etc) to create OData service.

     

      Import a vocabulary file

    • In the edit mode, right click on the Data Model, choose Import->Vocabulary in the resulting menu.
    • The Vocabulary Repository window appears.
    • Select the required vocabulary(s) and click continue.

     

    VocabularyDialog.PNG

    • In the Tree view a new folder with the name Vocabularies will be created under the Data Model
      and the vocabularies imported into this folder.

    Vocabulary Folder.PNG

     

    • Double click on the Terms node under the Vocabularies folder to see the details of the imported annotations in the mass maintenance view.

    Terms.png

    Note: Terms can be classified into following types

      1. Core Type
      2. Type Definition
      3. Enum Type
      4. Complex Type
      5. Entity Type

     

     

    Add Vocabulary-Based Annotations

    Once the vocabulary definitions are added to the data model, the terms from the vocabulary definition can be used to annotate the vocabulary based services if the term applies to the respective OData artifacts.

     

    To add annotations to artifacts for which vocabularies define applicable terms, proceed as follows:

     

    • Double-click the subfolder that contains the artifacts you want to annotate, for example, Entity Sets. Existing entity sets are listed in the mass maintenance view.

     

    EntitySet.PNG

    • Choose the Annotations pushbutton to see the vocabulary that is valid for these entity sets. If more than one vocabulary defines applicable terms, you can select the vocabulary you want to use to annotate the entity set and, if required, toggle between the different vocabularies. If none of the imported vocabularies includes applicable terms for entity sets, for example, this pushbutton is not enabled.

     

    Annotations.PNG

    • After you have selected the vocabulary you want to use for the annotations, all entity sets are displayed in a table in the mass maintenance view with the name of the applicable vocabulary displayed as a header.
    • To create annotations for an entity set, select either the entire row to create all available annotations, or select the applicable cells for each annotation you want to create and choose the Create Annotation pushbutton. You can select more than one row and more than one cell to enable the mass maintenance of multiple entity sets and annotations, for example.

     

    • Annotation value can be maintained in Annotation Data table.

    EntitysetAnnotation.png

    • If you want to delete any annotations, select the relevant rows or cells and choose the Delete Annotation pushbutton.
    • Save your entries.

     

    Generate Runtime Artifact

    Vocabulary related code can be found in DEFINE_VOCAB_ANNOTATIONS( ) of  generated MPC class.

     

    MPC.PNG

     

    In SP7, commented code gets generated for annotation. Follow the instructions provided in method.

     

    Registration and Activation of the Generated Service

    Refer to section "Registration and Activation of the Generated Service" of my blog on SPI.

    You will find new tags namely Annotation Targets in metadata file.

    MetaData.PNG

     

    That is all for now and if need be this blog be enhanced, stay tuned Any feedback is highly appreciated


    0 0

    This blog post will walk you through how to set up ADFS (Active Directory Federation Services) to work with OAuth2 in Netweaver Gateway. We will be able to set everything up and test it without writing any code. A benefit of this approach is that you know that the issue is not in any new code. This guide was written using ADFS 2.0 and Netweaver Gateway 2.0 SP 7 running on Netweaver 7.4.

     

    The scenario we are going to be recreating is the same as in the image below from http://wiki.scn.sap.com/wiki/display/Security/Leave+Request+Approvals+on+Android+-+OAuth+2.0+powered. Before beginning the steps in this blog post, I recommend you complete the netweaver gateway steps described in that link. If your STS (Security Token Service) is ADFS, this blog is for you!

     

    Android_OAuth2.0_Demo.png

    Before we begin, make sure the following steps are completed:


    ssl certificates have been set up on both servers (Gateway and ADFS)

    ADFS must already be configured to work with active directory

    You have already completed the steps in the configuration guide

     

    Log on to your adfs server and open up ADFS 2.0 management

    Expand the foloder for trust relationships

    Select the folder for Relying party trusts

    Click Add Relying Party Trust…


    The Add Relying Party Trust Wizard will open, click the start button to begin

    Screenshot_1_20_14__2_21_PM.png

     

    On the next screen, select the radio button for “Enter data about the relying party manually” and click Next

     

    Screenshot_1_20_14__2_22_PM.png

     

    Enter a relevant display name and click Next. I chose Netweaver Gateway.

     

    Screenshot_1_20_14__2_23_PM.png

     

    Ensure that the AD FS 2.0 profile radio button is selected and click Next.

    Screenshot_1_20_14__2_24_PM.png

     

    You do not need to enter anything for the configure certificate or configure url screens. You can just click next through those. On the Configure Identifiers screen, enter the link used to obtain the oAuth2 token and click add. The link should be: https://yourGatewayServer.com/sap/bc/sec/oauth2/token

     

    Screenshot_1_20_14__2_29_PM.png

     

    On the next screen you can choose to allow all users to access this service or deny all users. You response will depend on how much you want to restrict access for oAuth services. Since users will be logged in when accessing your backend data, the sap roles should be sufficient control, so I recommend selecting the permit all users to access this relying party radiobutton.

     

    Screenshot_1_20_14__4_43_PM.png

     

    Lastly, review the settings and click next to add Netweaver Gateway as a relying party trust.

     

    Then select your newly created relying party trust and click Edit Claim Rules…

     

    You exact setting for the claim rules will depend on your system, but SAP is very specific on how the username is passed.


    For example:

    This works:<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">oneillb</NameID>

    This does not:<NameID>oneillb</NameID>

     

    In order to get the format to come through correctly, I found that you need to have two transform rules. The first one pulls the value and the second one sets the format. Additionally, the outgoing claim type must be different between the first and second rule.

     

    Here is an example for pulling a username (you may want to use email instead). This may be slightly different depending on your active directory configuration.

     

    When creating the first rule, select the template for Send LDAP Attributes as Claims and click next.

     

    Screenshot_1_20_14__5_05_PM.png

     

    I called my first rule Load username to Common Name. For me, the attribute was SAM-Account-Name and I used common Name as the outgoing claim type.

    Screenshot_1_20_14__5_04_PM.png

    For the next rule, select the rule template Transform an Incoming Claim.

     

    Microsoft_Word.png

     

    This is where you select the common name type that we set up in the previous rule and transform it to an unspecified Name ID. Note: This did not work for me when going from a Name ID to a Name ID, so make sure you are going from Common Name to Name ID.

     

    Screenshot_1_20_14__5_14_PM.png

     

    Your two rules should look like my screenshot below and be in the same order.

     

    Screenshot_1_20_14__5_15_PM.png

     

    We are now ready to test! We are going to test this using curl, but you could do the same function with custom code. I like using curl so we can quickly test and adjust until it works!

     

    So First you need to create your request. Create the below xml request in a text editor such as textWrangler or notepad ++ (not MS word) and save the document as request.txt. Items that you need to change are inred.

     

    <?xml version="1.0" encoding="utf-8"?>

    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

                <s:Header>

                            <a:Action s:mustUnderstand="1">

     

    http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>

                            <a:To s:mustUnderstand="1">https://YourADFSServer.com/adfs/services/trust/13/UsernameMixed</a:To>

                            <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" >

                                        <o:UsernameToken>

                                                    <o:Username>YourUsername</o:Username>

                                                    <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">YourPassword</o:Password>

                                        </o:UsernameToken>

                            </o:Security>

                </s:Header>

                <s:Body>

                            <trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">

                                        <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">

                                                    <a:EndpointReference>

                                                                <a:Address>https://YourNetweaverGatewayServer.com/sap/bc/sec/oauth2/token</a:Address>

                                                    </a:EndpointReference>

                                        </wsp:AppliesTo>

                                        <trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>

                                        <trust:RequestType>

     

    http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>

                                        <trust:TokenType>urn:oasis:names:tc:SAML:2.0:assertion</trust:TokenType>

                            </trust:RequestSecurityToken>

                </s:Body>

    </s:Envelope>

     

    Now lets send that request to our ADFS server with the following curl command:

    curl https://YourADFSServer.com/adfs/services/trust/13/usernamemixed --data @request.txt -H "Content-Type:application/soap+xml"  --verbose -o "output.txt"

     

    Now you can open output.txt and see the result. You should see a NameID formatted like this: <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">username</NameID> Or similar formatting if you are using email instead. If you format the result for easier xml reading make sure you undo that before continuing.

     

    Remove everything outside of the <assertion></assertion> tags and save the file.

     

    Now base64 encode the assertion and replace your xml with the encoded result This can be done using the website http://www.base64encode.org

     

    Next you need to url encode the base64 encoded assertion. You can do this through the website http://meyerweb.com/eric/tools/dencoder/

     

    Now, append the following before the encoded assertion:

    client_id=YourClientID&scope=YourScope&grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer&assertion=YourAssertion

     

    Save this as output.txt

     

    Now we want to send that base64 encoded assertion to our SAP Netweaver Gateway server in order to get an oAuth2 token. You can do this with the below curl operation. The User:Password is the username and password created as the oAuth client system user described at http://wiki.scn.sap.com/wiki/display/Security/OAuth+2.0+Client+Registration+for+the+SAML+Bearer+Grant+Type

     

    curl "https://YourNetweaverGatewayServer.com/sap/bc/sec/oauth2/token" --data @output.txt -k --user "USER:PASSWORD(base64encoded)" -H "Content-Type:application/x-www-form-urlencoded" --verbose -o "sapOut.txt"

     

    The response from Netweaver gateway should look like the below. The access token is encrypted and will be used when calling your webservice

     

    { "access_token":"TOKEN","token_type":"Bearer","expires_in":"3600","scope":"YourScope" }

     

    Your can now (finally!) call your webservice with this token in a curl command like the below:

    curl "https://YourNetweaverGatewayServer.com/sap/opu/odata/sap/YourService /?$format=json" -k -H "Authorization: Bearer YourToken" --verbose -o "sapOut2.txt"

     

    You should hopefully see the resulting data in the sapOut2.txt file!

     

    If so, congratulations everything works and your ready to create an app that can do all of the steps that you were doing in curl!

     

    My next post is going to be about what I would love to see changed about this oAuth2 implementation.

     

    If you found this useful, please leave a comment about how you are or planning to use oAuth. Also, please let me know if you notice anything that I am doing wrong or could be doing differently. Thanks!


    0 0

    With a growing number of customers deploying systems that are based on SAP NetWeaver 7.40 I am getting more often the question how to deploy SAP NetWeaver Gateway in system landscape because it is not clear which service pack of SAP NetWeaver Gateway 2.0 fits to which service pack of SAP NetWeaver 7.40 where Gateway is part of the Basis.

     

    While I have discussed the question of deployment options in my blog SAP NetWeaver Gateway deployment options in a nutshell this blog so far did not answer the question which service pack of SAP NetWeaver Gateway 2.0 should be deployed in a SAP Business Suite backend system if the SAP NetWeaver Gateway server is for example running on SAP NetWeaver 7.40 SP4.

     

    To answer this question now and in the future we have published SAP Note 1942072 - SAP NetWeaver Gateway 2.0 Support Package Stack
    Definition
    which describe which SP level on 7.40 is equivalent to which SP level of SAP NetWeaver Gateway 2.0 running on a release prior to 7.31.

     

    To answer the question raised above :

     

    ... the customer should choose IW_BEP 200 SP07 if the hub runs on top of 7.40 SP04.

     

    Best Regards,

    Andre


    0 0

    Exposing MySQL database or any database as OData service endpoint using JPA (JAVA Persistence API) and Apache Olingo OData library on Apache Tomcat web server. The JPA Model can be exposed in the form of OData service endpoint, which allows the data to be accessed via http based protocol.

     

    For more details on OData, please refer http://www.odata.org/

     

    (I had a scenario, UI5 Application should run on SAP NetWeaver Gateway and as well in other OData source).

     

    Developing of the OData endpoint using JPA Model and deployment of the OData service in Apache Tomcat in 7 steps.


    Table of Contents




    Prerequisite

    • MySQL Server 5.x
    • Apache Tomcat 7.x
    • Eclipse Kepler / Juno preferably J2EE edition
    • Dependent libraries refer topic 3


    1. Create a dynamic web project in Eclipse

    • Launch Eclipse from extracted folder by double click eclipse.exe to open it. Eclipse will ask you for workspace location. Specify a location and click ok
    • To create a Dynamic Web Project, File -> New -> Dynamic Web Project as shown
    • Enter the project name for example "emplist-web"
    • In Target runtime Click on “New Runtime...” button to define Apache Tomcat v7.0 as HTTP server to expose our JPA Model as OData service endpoint. Provide your Apache Tomcat Server folder in Tomcat installation directory.

    Tomcat1.png

    • Click on “Modify...” button in the above window and in opened window, select the “JPA” check box and click on “OK” button

    Tomcat2.png

    • In the next window, choose Platform “EclipseLink 2.5.x”, JPA implementation Type: “Disable Library Configuration”, radio button “Annotated classes must be listed in persistence.xml” and click on the “Next” button

    Tomcat3.png

    • In the "Java - src" window, click on the “Next” button
    • In the "Web Module" window, check “Generate web.xml deployment descriptor” and click on the “Finish” button. Now project has been created in the project explorer window

    Tomcat4.png

    2. Create a MySQL connection to be exposed as OData service endpoint

    • To create a MySQL Database connection, in the menu, Windows -> Show View -> Data Source Explorer
    • Go to “Data Source Explorer” tab, Right click on “Database Connection” node and click on “New...” menu item
    • In the Connection Profile window, select MySQL and click on "Next" button
    • Configure the MySQL JDBC Driver i.e. add latest driver by removing non existent old driver.
    • Specify the name for Database field and URL field end
    • Enter the Username, Password and click "Test Connection" button ensure DB connection Ping succeed.

    MySQL1.png

    • In the “Data Source Explorer”, now you can see the MySQL connection and expand to see DB objects

    MySQL2.png

    3. Add the dependent libraries to the Project

    Download and copy the required libraries to “<your eclipse project>/WebContent/WEB-INF/lib” folder.


    AddLib1.png

    1. JPA: Add EclipseLink and JPA Persistence JAR files to “Lib” folder
      1. eclipselink.jar
      2. javax.persistence_2.1.0.v201304241213.jar
    2. Database: Add MySQL connector java to “Lib” folder
      1. mysql-connector-java-5.1.28-bin.jar
    3. OData: Add Apache Olingo OData libraries JAR files to “Lib” folder
      1. olingo-odata2-core-incubating-1.0.0.jar
      2. olingo-odata2-api-incubating-1.0.0.jar
      3. olingo-odata2-api-annotation-incubating-1.0.0.jar
      4. olingo-odata2-jpa-processor-core-incubating-1.0.0.jar
      5. olingo-odata2-jpa-processor-api-incubating-1.0.0.jar
      6. javax.ws.rs-javax.ws.rs-api-2.0-m10.jar
    4. Service: Other libraries required    (main: http://central.maven.org/maven2/org/apache/cxf/)
      1. cxf-api-2.7.5.jar                          (../cxf-api/2.7.5/cxf-api-2.7.5.jar)
      2. cxf-rt-bindings-xml-2.7.5.jar          (../cxf-rt-bindings-xml/2.7.5/cxf-rt-bindings-xml-2.7.5.jar)
      3. cxf-rt-core-2.7.5.jar                     (../cxf-rt-core/2.7.5/cxf-rt-core-2.7.5.jar
      4. cxf-rt-frontend-jaxrs-2.7.5.jar       (../cxf-rt-frontend-jaxrs/2.7.5/cxf-rt-frontend-jaxrs-2.7.5.jar)
      5. cxf-rt-transports-http-2.7.5.jar      (../cxf-rt-transports-http/2.7.5/cxf-rt-transports-http-2.7.5.jar)
    5. Links: downloading for libraries
      1. JPA: http://www.eclipse.org/eclipselink/downloads/
      2. MySQL DB driver: http://dev.mysql.com/downloads/connector/j/
      3. OData: http://www.apache.org/dyn/closer.cgi/incubator/olingo/odata2/rel-1.0.0/olingo-odata2-dist-jpa-incubating-1.0.0-jpa.zip
      4. Service: There itself


    • After copying libraries to “/WebContent/WEB-INF/lib” folder, go to menu “Project” -->“Clean” and select your project by choosing “Clean projects selected below” and click on “OK” button.
    • After creating JPA entities from table, Eclipse shows error then rightclick on “WebContent/WEB-INF/lib” folder and choose “Validate” menu item.

    4. Create a JPA Model from MySQL database connection

    1. To create JPA Model, go to File --> New --> Other --> JPA Entities from Tables and click on next button

      JPA1.png

    2. Select MySQL connection and click connection button and select the schema where tables are available. Choose tables to be exposed as OData service and check “List generated classes in persistence.xml” and next window is “Table Associations”, here just click “Next” button.

      JPA2.png

    3. In Next window, check “Always generate optional JPA annotations and DDL parameters” and package can be configured here (com.<your company>.<project name>.model) and click on “Next” button.
    4. Next window click on “Finish” button.
    5. Now in “src” folder, Java classes are created as JPA Model entities.

      JPA3.png

    6. Double click on “persistence.xml” and select the tab “Connection”
    7. Transaction type: choose “Resource local” and EclipseLink connection pool area click on link “Populate from connection...” and choose Local MySQL and will populate the connection fields.

      JPA4.png

    8. Click source or select “persistence.xml” file from your project explorer will contain as follows

    <?xmlversion="1.0"encoding="UTF-8"?>

    <persistenceversion="2.1"xmlns="http://xmlns.jcp.org/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistencehttp://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

           <persistence-unitname="emplist-web"transaction-type="RESOURCE_LOCAL">

                  <class>model.Employee</class>

                  <class>model.Group</class>

                  <properties>

                         <propertyname="javax.persistence.jdbc.url"value="jdbc:mysql://localhost:3306/test"/>

                         <propertyname="javax.persistence.jdbc.user"value="root"/>

                         <propertyname="javax.persistence.jdbc.password"value="King1234"/>

                         <propertyname="javax.persistence.jdbc.driver"value="com.mysql.jdbc.Driver"/>

                  </properties>

           </persistence-unit>

    </persistence>

     

    After creating JPA entities from table, Eclipse shows error then right click on “WebContent/WEB-INF/lib” folder and choose “Validate” menu item.


    5. Expose your JPA Model as OData service using Apache Olingo

    To Expose the JPA Model from MySQL as OData service, we use Apache Olingo library. For more information: http://olingo.incubator.apache.org/

     

    Using Olingo, exposing JPA Model as OData service simple and it consists of three steps

     

    • Extend the “ODataServiceFactory” class (EmployeeListServiceFactory.java)
    • Create the new class “EmployeeListServiceFactory.java” in package “main” with following code (copy paste).

    package main;

     

    import javax.persistence.EntityManagerFactory;

    import javax.persistence.Persistence;

     

    import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;

    import org.apache.olingo.odata2.processor.api.jpa.ODataJPAServiceFactory;

    import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;

     

     

    publicclass EmployeeListServiceFactory extends ODataJPAServiceFactory {

     

      privatestaticfinal String PERSISTENCE_UNIT_NAME = "emplist-web";

     

      @Override

      public ODataJPAContext initializeODataJPAContext()

          throws ODataJPARuntimeException {

     

        ODataJPAContext oDatJPAContext = this.getODataJPAContext();

        try {

     

          EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

    oDatJPAContext.setEntityManagerFactory(emf);

          oDatJPAContext.setPersistenceUnitName(PERSISTENCE_UNIT_NAME);

     

          return oDatJPAContext;

     

        } catch (Exception e) {

     

          thrownew RuntimeException(e);

     

        }

     

      }

     

    }

    • Add necessary tags in “web.xml” file
    • Copy the contents in <servlet> and <servlet-mapping> tags

    <?xmlversion="1.0"encoding="UTF-8"?>

    <web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID"version="3.0">

      <display-name>emplist-web</display-name>

      <welcome-file-list>

        <welcome-file>index.html</welcome-file>

      </welcome-file-list>

     

      <servlet>

        <servlet-name>ODataServlet</servlet-name>

        <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>

     

        <init-param>

          <param-name>javax.ws.rs.Application</param-name>

          <param-value>org.apache.olingo.odata2.core.rest.app.ODataApplication</param-value>

        </init-param>

     

        <init-param>

          <param-name>org.apache.olingo.odata2.service.factory</param-name>

          <param-value>main.EmployeeListServiceFactory</param-value>

        </init-param>

     

        <load-on-startup>1</load-on-startup>

      </servlet>

     

      <servlet-mapping>

        <servlet-name>ODataServlet</servlet-name>

        <url-pattern>/emplist.svc/*</url-pattern>

      </servlet-mapping>

     

    </web-app>

    • Add “index.html” to “WebContent” (Right click -> New HTML file) folder with following content

    <!DOCTYPEhtml>

     

    <html>

        <head>

            <metacharset="utf8">

            <title>Employee List OData</title>

        </head>

        <body>

            <h1>Employee List OData</h1><br><br>

            <ahref="/emplist-web/emplist.svc/">Service Document</a>

        </body>

    </html>

    6. Testing OData service endpoint

    • Right click on your project in “Project Explorer”, select menu items “Run As” -> “Run on Server”.
    • In the window, choose “Tomcat v7.0 Server at localhost” and click on “Finish” button
    • After successfully web application deployed, you will get the below window (internal browser) or configured browser. In browser, “index.html” is shown and by clicking the link “Service Document”. Browser will show your OData Service document (http://localhost:8080/emplist-web/emplist.svc/). Better use Google Chrome browser. To access OData Metadata Service document add $metadata in the link (http://localhost:8080/emplist-web/emplist.svc/$metadata)

     

    7. OData service in CORS

    • Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page to make XMLHttpRequests (AJAX calls) to another domain, not the domain the JavaScript originated from. Such "cross-domain" requests would otherwise be forbidden by web browsers, per the same origin security policy.
    • UI5 application developed in other domain, requires access to your OData service forbidden by browsers.
    • Allow access to OData service in other domain (CORS) then configure below tags in “/WebContent/ WEB-INF/web.xml” file in your project or globally for all web application then update in Apache Tomcat Server folder “/conf/web.xml”.

     

     

      <!-- CORS To allow access OData service by JavaScript in other domain  -->

      <filter>

          <filter-name>CorsFilter</filter-name>

          <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>

      </filter>

      <filter-mapping>

          <filter-name>CorsFilter</filter-name>

          <url-pattern>/*</url-pattern>

      </filter-mapping>



    0 0

    Intro

    After all the theoratical introductions at recent SAP TechEd Events and some smaller projects in a local sandbox system I was finally getting to develop my own first Gateway based ODATA service that should be consumed by some website running jQuery. Setting up our little service, creating some entities, etc. was nothing really special after all the introductions and the excellent learning material in SCN.

     

    Real world scenario issues

    Of we go, our website development colleagues have included the provided service URI and are trying to read data from our service. Nothing happens within the jQuery script compared to directly calling the service in a browser where we get a nice response. What happened?

    Looking into Chrome's excellent developer tools we get a pointer to our issue:

    chrome_error.jpg

    We're continuing our journey with tools from Google and finally end up getting really useful inside on 'Cross Origin Ressource Sharing'. I recommend to have a look at the following:

     

    Options

    Looking at the blog post from Michael Herzog I would have loved to use JSONP (as outlined in a custom handler in this post). Unfortunately (to my knowledge) NetWeaver Gateway is currently not supporting JSONP and I didn't wanted to give up the complete Gateway framework and write a handler from scratch as outlined in mentioned blog from Alessandro Spadoni.

    Setting up a proxy on the server providing the website would have been an option although I wanted to avoid this for two reasons: additional server load and being able to solve this problem on my own within Gateway.

    So, next option would be sending an appropriate 'Access-Control-Allow-Origin' header in the response. I was unable to find any Gateway specific documentation regarding customizing so it seemed we need to take care of this on our own.

     

    Adding the http header

    The first and most appealing option of course would be to add the header directly in our service extension. And the good news is that one is actually able to do this. Right within your 'DPC_EXT' class you get access to method /IWBEP/IF_MGW_CONV_SRV_RUNTIME~SET_HEADER which can be used to set additional header fields. Nice and our first solution is working already.

     

    Extending the solution

    Now that we have the first solution in place I wanted to extend this a little bit in order to not send '*' as the allowed requester and with this enabling everyone who is able to call my server to execute this service within his website. In other words I wanted to check the requester against a small customer table which would whitelist potential consumers of my service. However I was not able to get access to the needed http header field 'Origin' from the request to determine the requester.

    Instead of using the service method of the entity I decided to write a small custom http handler which I could hook into SICF and which would check the requester and if ok add the header field. I won't go into the details of writing the http handler class as such. This should be documented enough around here.

    However when hooking the additional handler into SICF I stumbled over the following issues which I wanted to share to make life a little bit easier.

    Order of execution of handler classes and flow of handlers

    First of all our little handler class needs to be executed before the standard handler /IWFND/CL_SODATA_HTTP_HANDLER. Otherwise it will never be reached because after execution of the standard handler attribute if_http_extension~flow_rc will be set to 0 (or CO_FLOW_OK) which will tell the framework to not process any other handlers because request processing is complete. You can read more about this in SAP Help.

     

    Second crucial point: the order of execution is top to bottom, in other words the handler maintained in node 'odata' will be executed first and only after that the handler in your actual SICF service down the line will be executed. Combining this with the knowledge about flow the handler on the service node will probably never be reached and in theory could be deleted. We will have to add our custom handler in node 'odata' in order to make it work.

    To find out about order of execution of handler classes I would recommend the following blog by Christian Buckowitz: Debugging into a HTTP request on AS ABAP.

     

    So, finally we have everything in place, added our little handler into first place in node 'odata' but still nothing happens, a break-point in our custom handler code is not reached. What is going wrong? It took me a while to figure this one out. However by looking at function module 'HTTP_GET_HANDLER_LIST' it became clear that changes in SICF might not immediately be reflected during runtime as we have a parameter named 'SHM_PARAM'. Shared memory seems to be involved and indeed, looking into transaction SHMM in our system one can easily spot an area which seems to used for ICM:

    shmm.jpg

    After having deleted this area our changes towards the handler list of node 'odata' had finally an impact on runtime processing and our little handler does his magic to check the request and add the header.

     

    Final remarks and a word of caution

    I would strongly suggest to keep in mind that you are adding your own logic towards the processing of requests inside of Gateway if you follow the example given inside this blog. This could have all kind of side effects towards processing, security, etc. so be careful.

     

    Finally: I hope you did like the blog and hope that it invokes some discussion towards the route taken. It would be especially nice to get some information on whether something is in the pipeline for Gateway to solve this in SAP standard and whether Gateway will support JSONP in the future. Of course one could write their own JSONP handler extending Gateway. May be this is something for a follow-up blog.


    0 0

    Liberate your SAP backend Data to Consume and Share Anywhere with SAP NetWeaver Gateway


    Provide engaging experiences with customers, simplify interactions with partners, and improve productivity for your workers all with a flexible development platform. 


    Dear Customer/Partner,

    When it comes to accessing and using massive collections of data, address the critical issues head-on with SAP NetWeaver Gateway.  SAP NetWeaver Gateway liberates your
    data so you can provide engaging experiences with customers, simplify interactions with partners and improve productivity for your workers. In this session, SAP Product Management experts will take you through how SAP NetWeaver Gateway provides ease of access, enterprise readiness, and simplified development that will transform your approach to connecting People, Data and Processes. Discover the latest features of the recently released SP08 and learn how key customers are using SAP NetWeaver Gateway today.

     

    Efficiently meet IT challenges:

    • Architecture: Integrate teams, data, and processes across UIs and platforms
    • Development: Create apps faster to meet changing needs while working with your existing platforms and knowhow..
    • Technology: Help ensure robustness and security while minimizing disruptions.


    Efficiently integrate Teams, Data, and Processes

    • Seamlessly integrate: teams, data, processes, and software in a way that is non-disruptive and fits your environment.
    • Reduce UI complexity, improve process efficiency and increase workforce productivity.
    • Use your existing software and infrastructure to minimize TCO and optimize ROI.

     

    SAP NetWeaver Gateway makes your SAP data and processes consumable across a variety of platforms. Reduce app development complexity so you easily connect
    everything using your existing infrastructure and skill set.  And, it enables you to create solutions without disrupting your existing business applications


    NA/LatAm March 20th  12:00pm – 1:00pm EDT

         Customers (non s-users)                              Partners (s-users)
    registerCustomer.png                         registerpartner.png

    APJ March 26th  12:00pm – 1:00pm SGT

        Customers (non s-users)                               Partners (s-users)

    registerCustomer.png                      registerpartner.png

     

    EMEA March 27th  4:00pm – 5:00pm CET

       Customers (non s-users)                         Partners (s-users)

    registerCustomer.png                       registerpartner.png


    0 0

    Introduction

     

    In this blog I will explain creation of simple SAP NW GW OData service which will implement Create, Read, Update, Delete, Query and Function Import operations.


    Just to make it very simple, I will just have single entity and entity set. Here I will perform these operations on Z table. In real scenarios, you will use BAPIs. RFCs to perform these operations.


    I recommend to read below documents and SAP documentation for deep understanding.

    How to Develop a Gateway Service using Code based Implementation by Andre Fischer

    How to Develop Query Options for an OData Service Using Code-Based Implementationby Andre Fischer

    How to Write an OData Channel Gateway Service. Part 2 - The Runtime Data Provider Class

    SAP Help - SAP NetWeaver Gateway Foundation Developer Guide - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library

    Code Snippet - 3.2 Data Provider Class (DPC) - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library


     

    Scenario

     

    We have User information table as ZUSERINFO containing below fields

    gw1.jpg

    Now let's create OData service which will insert, read, delete, update and query this table along with one custom operation (UsersByCountry) as function import.


    From an ABAPer perspective, This is what meant by OData operations.

     

    OData Operation HTTP Method What it meant to an ABAPer
    Create POST Insert <table> from <workarea>
    Read GET Select Single * From <table> into <workarea>
    Update PUT/PATCH Update <table> set <workarea>
    Delete DELETE Delete from <table>
    Query GET Select *  From <table> Into Table
    Function Import GET/POST Everything covered by GET and POST. But only use if scenario does not fit into CRUDQ operations.


    We can correlate Entity Set as Table Type, Internal table and Entity to work area, structure!


    Entity Set Table Type or Internal Table
    Entity Structure or Work Area



    Procedure


    Let’s go to transaction SEGW and create project as ZUSERINFO.

    gw2.jpg

    Now right click on Data Model and Import --> DDIC Structure option, it will display popup window. Provide DDIC structure name. In this case table name ZUSERINFO. It will propose field and key mapping as well as object name which will be your entity name.

    gw3.jpg

    We will ignore MANDT as key field and also overwrite object name. I want my field names in upper camel case format so I will change it accordingly.  Let’s call entity type as User. It will look as below. Press enter.

    gw4.jpg

    finally our entity type User will look as below.

    gw5.jpg

    Now let’s create Entity Set as UserCollection (or UserSet or Users). You can refer Creating High-Quality OData Services - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library


    I will go with UserCollection as my entity set name.


    Right click folder name Entity Sets and click create. Provide entity set name as UserCollection and Entity Type name as User. It will display as below.

    gw6.jpg

    Now let’s generate runtime artifacts. Click on generate runtime objects button. It will display popup as below. Keep the default class names as-is and click on enter button.

    gw7.jpg

    On successful generation, you will see this kind of message log and generated artifacts. 4 classes will get generated. 2 for Data provider and 2 for Model provider.

    gw8.jpg

    Now register your service under service Maintenance folder. Click on Register button. Keep default values as-is and hit enter button.

    gw9.jpg

    On successful registration, click Maintain button. This will open service catalog window along with option to call Gateway Client. Click on Gateway Client button to test the service. (you can also call transaction /IWFND/GW_CLIENT to open SAP NW Gateway client)


    Append $metatda to base service URL and press execute button. If everything is fine then you will HTTP Response as below. Metadata provides information such as Entity type, key property, properties and Entity Set name.

    gw10.jpg

    So far we just defined single entity type and entity set. Now it’s time to code CRUDQ and function import methods.

     

    Coding


    There is no specific order to implement these methods but it is always good to 1st implement query and read operation as for Create and Update, you will need request data which you will get if you already have query/read implemented.


    1) Query Operation


    First we will start implementing query operation. Before that, I will add one record in my ZUSERINFO table as

    gw11.jpg

    Now open Runtime artifacts folder and right click on Class ZCL_ZUSERINFO_DPC_EXT and select Go to ABAP Workbench option. Select edit mode and redefine method USERCOLLECTION_GET_ENTITYSET.

    gw12.jpg

    In the simplest form, this is what minimal coding will look like in GET_ENTITYSET method.

    METHOD usercollection_get_entityset.

     

      DATA: lt_userinfo TYPETABLEOF zuserinfo,

            ls_userinfo LIKELINEOF lt_userinfo,

            ls_entity   LIKELINEOF et_entityset.

     

    *Get data from ZUSERINFO table

      SELECT * FROM zuserinfo INTOTABLE lt_userinfo.

     

    *Fill ET_ENTITYSET

      LOOPAT lt_userinfo INTO  ls_userinfo .

        ls_entity-userid    = ls_userinfo-userid.

        ls_entity-firstname = ls_userinfo-firstname.

        ls_entity-lastname  = ls_userinfo-lastname.

        ls_entity-email     = ls_userinfo-email.

        ls_entity-phone     = ls_userinfo-phone.

        ls_entity-country  = ls_userinfo-country.

        APPEND ls_entity TO et_entityset.

      ENDLOOP.

     

    ENDMETHOD.

     

    We are selecting all data from table ZUSERINFO and appending the result to exporting parameter ET_ENTITYSET.


    Now you can go to GW client transaction and execute URI  /sap/opu/odata/sap/ZUSERINFO_SRV/UserCollection which will display one record which we already added into Z table.

    gw13.jpg

    Observe the method signature. put external breakpoint in method and execute query. You will find important information in method parameters in debugging mode.


    Below table will provide brief explanation of method parameters, alternative approach to get the value of those method parameters. Last column specifies if we need to code to implement query operation.


    Here IO_TECH_REQUEST_CONTEXT refers to /IWBEP/IF_MGW_REQ_ENTITYSET


    OData Query Method Parameter Alternative way to get the value Coding required to implement Query Operation
    UserCollection?$filter=UserID eq '123' and LastName eq 'Mahajan' IT_FILTER_SELECT_OPTIONS and IV_FILTER_STRING DATA: my_filter_options TYPE /iwbep/t_mgw_select_option,
    my_filter_string
    TYPE string.
    my_filter_options
    = io_tech_request_context->get_filter( )->get_filter_select_options( ).
    my_filter_string 
    io_tech_request_context->get_filter( )->get_filter_string( ).
    Yes
    UserCollection?$select=FirstName,LastName No method parameter data: my_select_fields type /iwbep/t_mgw_tech_field_names.
    my_select_fields
    = io_tech_request_context->get_select( ).
    No

    UserCollection?$orderby=FirstName,LastName


    OR


    UserCollection?$orderby=FirstName desc,LastName desc
    IT_ORDER data: my_orderby_fields type /iwbep/t_mgw_tech_order.
    my_orderby_fields
    = io_tech_request_context->get_orderby( ).
    Yes
    UserCollection?search='test' IV_SEARCH_STRING data: my_search_string type string.
    my_search_string
    = io_tech_request_context->get_search_string( ).
    Yes
    UserCollection?$top=1 IS_PAGING-TOP

    data: my_top type string.
    my_top
    io_tech_request_context->get_top( ).

     

      data: my_skip type string.
    my_skip
    io_tech_request_context->get_skip( ).
    Yes
    In case if we had association and navigation between 2 entities IT_NAVIGATION_PATH DATA: my_nav_path type /iwbep/t_mgw_tech_navi.
    my_nav_path
    = io_tech_request_context->get_navigation_path( ).
    Yes


     

    2) Read Operation


    Now let’s implement GET_ENTITY method. Go to method USERCOLLECTION_GET_ENTITY and redefine it. Below is the minimal code that we need to have in this method.


    We need to read the key values passed from query URI and then fill the export parameter ER_ENTITY.

    METHOD usercollection_get_entity.

     

    DATA:  ls_key_tab   TYPE /iwbep/s_mgw_name_value_pair,

            lv_userid   TYPE zuserinfo-userid,

            ls_userinfo TYPE  zuserinfo.

     

    *Get the key property values

    READTABLE it_key_tab WITHKEY name = 'UserID'INTO ls_key_tab.

     

      lv_userid = ls_key_tab-value.

     

    *Get the single record from ZUSERINFO and fill ER_ENTITY

    SELECTSINGLE * FROM zuserinfo INTO ls_userinfo WHERE userid = lv_userid.

      IF sy-subrc = 0.

        er_entity-userid    = ls_userinfo-userid.

        er_entity-firstname = ls_userinfo-firstname.

        er_entity-lastname  = ls_userinfo-lastname.

        er_entity-email     = ls_userinfo-email.

        er_entity-phone     = ls_userinfo-phone.

        er_entity-country   = ls_userinfo-country.

      ENDIF.

     

    ENDMETHOD.

     

    Here IO_TECH_REQUEST_CONTEXT refers to /IWBEP/IF_MGW_REQ_ENTITY

     

    OData Query Method Parameter Alternative way to get the value Coding required to implement Query Operation
    UserCollection(UserID='Test') OR UserCollection('Test' IT_KEY_TAB DATA: lt_keys TYPE /iwbep/t_mgw_tech_pairs.
    lt_keys
    = io_tech_request_context->get_keys( ).
    Yes
    In case if we had association and navigation between 2 entities IT_NAVIGATION_PATH DATA: my_nav_path type /iwbep/t_mgw_tech_navi.
    my_nav_path
    = io_tech_request_context->get_navigation_path( ).
    Yes

    UserCollection('Test')?$select=FirstName,LastName

    No DATA: my_select_fields TYPE /iwbep/t_mgw_tech_field_names.
    my_select_fields
    = io_tech_request_context->get_select( ).
    No
    UserCollection('Test')?$format=json No No No

     


    Also note that you cannot use system query options else you will get an error as System query options '$orderby,$skip,$top,$skiptoken,$inlinecount,' are not allowed in the requested URI


    3) Create Operation


    Now we will focus on create operation by redefining method USERCOLLECTION_CREATE_ENTITY. Below is the code that will perform POST operation.


    Here we are reading the request data and then filling the exporting parameter ER_ENTITY.

    METHOD usercollection_create_entity.

      DATA: ls_request_input_data TYPE zcl_zuserinfo_mpc=>ts_user,

            ls_userinfo TYPE zuserinfo.

     

    * Read Request Data

      io_data_provider->read_entry_data(IMPORTING es_data = ls_request_input_data ).

     

    * Fill workarea to be inserted

      ls_userinfo-userid   = ls_request_input_data-userid.

      ls_userinfo-firstname = ls_request_input_data-firstname.

      ls_userinfo-lastname = ls_request_input_data-lastname.

      ls_userinfo-email    = ls_request_input_data-email.

      ls_userinfo-phone    = ls_request_input_data-phone.

      ls_userinfo-country  = ls_request_input_data-country.

     

    * Insert Data in table ZUSERINFO

      INSERT zuserinfo FROM ls_userinfo.

      IF sy-subrc = 0.

        er_entity = ls_request_input_data."Fill Exporting parameter ER_ENTITY

      ENDIF.

    ENDMETHOD.

    To test POST operation, 1st execute GET operation and then press Use as Request button which will copy the response to request window and then select operation POST and execute.


    In case you execute GET operation i.e. GET_ENITITYSET and then try to perform POST operation then you will get below kind of error. Hence make sure that you execute GET to read single entity i.e. GET_ENTITY operation and then perform POST.

    gw14.jpg

    So correct steps are,

    1) Execute GET to read single entity /sap/opu/odata/sap/ZUSERINFO_SRV/UserCollection('Test')

    2) Click Use as Request button

    3) Update your request properties.

    4) Select HTTP method as POST

    5) Query as /sap/opu/odata/sap/ZUSERINFO_SRV/UserCollection and execute

    gw15.jpg


    Here IO_TECH_REQUEST_CONTEXT refers to /IWBEP/IF_MGW_REQ_ENTITY_C


    OData Query Method Parameter Coding required to implement Query Operation
    /sap/opu/odata/sap/ZUSERINFO_SRV/UserCollection DATA: ls_request_input_data TYPE zcl_zuserinfo_mpc=>ts_user.
    io_data_provider
    ->read_entry_data( IMPORTING es_data = ls_request_input_data ).
    Yes


    In case of Create operation, you cannot use system query options else you will get an error as

    The Data Services Request contains SystemQueryOptions that are not allowed for this Request Type


    This error message comes from method PROCESS_ENTITY_SET (/IWCOR/CL_DS_PROC_DISPATCHER). Just in case if you are curious and want to know

     

    4) Update Operation


    Now we will implement update operation by redefining method USERCOLLECTION_UPDATE_ENTITY. We need to put below code in this method.

    METHOD usercollection_update_entity.

      DATA:  ls_request_input_data TYPE zcl_zuserinfo_mpc=>ts_user,

             ls_key_tab            TYPE /iwbep/s_mgw_name_value_pair,

             lv_userid             TYPE zuserinfo-userid,

             ls_userinfo           TYPE zuserinfo.

    * Get key values

      READTABLE it_key_tab WITHKEY name = 'UserID'INTO ls_key_tab.

      lv_userid = ls_key_tab-value.

      IF lv_userid ISNOTINITIAL.

     

    * Read request data

        io_data_provider->read_entry_data(IMPORTING es_data = ls_request_input_data ).

     

    * Update fields of table ZUSERINFO

        UPDATE zuserinfo SET firstname = ls_request_input_data-firstname

                             lastname  = ls_request_input_data-lastname

                             email     = ls_request_input_data-email

                             phone     = ls_request_input_data-phone

                             country   = ls_request_input_data-country

                             WHERE userid  = lv_userid.

        IF sy-subrc = 0.

          er_entity = ls_request_input_data."Fill exporting parameter ER_ENTITY

        ENDIF.

      ENDIF.

    ENDMETHOD.

    Here also first we need to execute GET operation to read the entity and then copy the response to request using Use as Request button and execute PUT operation after editing required data. Successful HTTP response will look as below with status code as 204.

    gw16.jpg

    Here IO_TECH_REQUEST_CONTEXT refers to /IWBEP/IF_MGW_REQ_ENTITY_U


    OData Query Method Parameter Alternative way to get the value Coding required to implement Query Operation
    UserCollection('Test1') IT_KEY_TAB

    DATA: lt_keys TYPE /iwbep/t_mgw_tech_pairs,

         ls_key TYPE /iwbep/s_mgw_tech_pair.

      lt_keys = io_tech_request_context->get_keys( ).
    Yes
    UserCollection('Test1') IO_DATA_PROVIDER io_data_provider->read_entry_data( IMPORTING es_data = ls_request_input_data ). Yes

     

    5) Delete Operation


    To implement Delete operation, you need to execute DELETE HTTP method for particular key. Below is the code for method USERCOLLECTION_DELETE_ENTITY.


    Here we are reading key value of the record to be deleted and executing Delete statement.

    METHOD usercollection_delete_entity.

      DATA:  ls_key_tab TYPE /iwbep/s_mgw_name_value_pair,

             lv_userid TYPE zuserinfo-userid.

    * Read key values

      READ  TABLE it_key_tab INTO ls_key_tab WITHKEY name = 'UserID'.

      lv_userid = ls_key_tab-value.

      IF lv_userid ISNOTINITIAL.

    * Delete record from table ZUSERINFO

        DELETEFROM zuserinfo WHERE userid = lv_userid.

      ENDIF.

    ENDMETHOD.

    On successful record deletion, you will see HTTP response code as 204.

    gw17.jpg

    Here IO_TECH_REQUEST_CONTEXT refers to /IWBEP/IF_MGW_REQ_ENTITY_D

     

    OData Query Method Parameter Alternative way to get the value Coding required to implement Query Operation
    UserCollection('Test1') IT_KEY_TAB

    DATA: lt_keys TYPE /iwbep/t_mgw_tech_pairs,

         ls_key TYPE /iwbep/s_mgw_tech_pair.

      lt_keys = io_tech_request_context->get_keys( ).
    Yes

     

    6) Function Import 

     

    As per SAP documentation, Function Imports - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library

    The Open Data Protocol (OData) includes standard CRUD (Create, Retrieve, Update, and Delete) operations that map to the HTTP methods POST, GET, PUT/MERGE, and DELETE.

    In addition, OData supports further service operations (function imports) that can be invoked by the HTTP methods GET or POST for anything that cannot be mapped to the standard CRUD operations. You can implement such additional service operations in the Service Builder by creating function imports within your data model.

    For example, you could create function imports for the following custom operations:

    • Confirm Work Item
    • Check Flight Availability

    While it is simple to create new function imports to invoke custom operations, if the operation you want to use can be invoked using a standard CRUD operation, you should not create a function import. That is, you should only create function imports for custom operations that cannot be invoked using a standard operation.

     

    In simple terms, if an operation cannot fit into CRUD scenario then you can perform it by function import.


    Suppose our ZUSERINFO table looks like below,

    gw18.jpg

    And we want to get users by specific country then we can implement function import. Let’s call our function import as UsersByCountry!

    Right click on Data model and create function import. Provide proper name. Again refer Creating High-Quality OData Services - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library

    gw19.jpg

    Provide required details such as mentioned below. Remember here we want to return collection of users and hence we selected Return cardinality as 0..n with return entity set and HTTP method type as GET.

    gw20.jpg

    Now click on Function Import parameters and create import parameters as shown below. In this case we just want to pass value of country and hence we will have one parameter as Country.

    gw21.jpg

    Finally save project, check project consistency and generate runtime objects. To check if everything is fine, in GW client execute service metadata URL as /sap/opu/odata/sap/ZUSERINFO_SRV/$metadata which should show you function import definition in metadata as below,

    gw22.jpg

    Now we will implement function import operation. Go to DPC_EXT class and redefine method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION.

    Put below code to implement function import.

    METHOD /iwbep/if_mgw_appl_srv_runtime~execute_action.

      DATA: ls_parameter  TYPE /iwbep/s_mgw_name_value_pair,

            lv_country    TYPE string,

            lt_userinfo   TYPETABLEOF zuserinfo,

            ls_userinfo   TYPE zuserinfo,

            ls_entity     TYPE  zcl_zuserinfo_mpc=>ts_user,

            lt_entityset  TYPE zcl_zuserinfo_mpc=>tt_user.

     

     

      IF iv_action_name = 'UsersByCountry'." Check what action is being requested

        IF it_parameter ISNOTINITIAL.

    * Read Function import parameter value

          READTABLE it_parameter INTO ls_parameter WITHKEY name = 'Country'.

          IF sy-subrc = 0.

            lv_country = ls_parameter-value.

          ENDIF.

     

          IF lv_country ISNOTINITIAL.

            SELECT  * FROM zuserinfo INTOTABLE lt_userinfo WHEREcountry = lv_country.

            LOOPAT lt_userinfo INTO  ls_userinfo .

              ls_entity-userid   = ls_userinfo-userid.

              ls_entity-firstname = ls_userinfo-firstname.

              ls_entity-lastname = ls_userinfo-lastname.

              ls_entity-email    = ls_userinfo-email.

              ls_entity-phone    = ls_userinfo-phone.

              ls_entity-country  = ls_userinfo-country.

              APPEND ls_entity TO lt_entityset.

            ENDLOOP.

    * Call methos copy_data_to_ref and export entity set data

            copy_data_to_ref(EXPORTING is_data = lt_entityset

                    CHANGING cr_data = er_data ).

     

          ENDIF.

        ENDIF.

      ENDIF.

     

    ENDMETHOD.

     

    To test function import we need to query as /sap/opu/odata/sap/ZUSERINFO_SRV/UsersByCountry?Country='US'


    If there are multiple parameters then it will be separated by comma.

    gw23.jpg

    Here IO_TECH_REQUEST_CONTEXT refers to /IWBEP/IF_MGW_REQ_FUNC_IMPORT


    OData Query Method Parameter Alternative way to get the value Coding required to implement Query Operation
    /sap/opu/odata/sap/ZUSERINFO_SRV/UsersByCountry?Country='US' IT_PARAMETER DATA: my_parameter TYPE  /iwbep/t_mgw_name_value_pair.
    my_parameter
    = io_tech_request_context->get_parameters( ).
    Yes

     

     

    Closing Remarks

     

    This is very simple example of an OData service. In real case scenarios, you will have multiple entities, relationship, association and navigation between them but when it comes to coding in DPC_EXT class methods, you will find above explanation of each method, parameters and alternative way to get the parameter values useful.

     

    I hope you enjoyed reading this blog and now ready to develop your OData service! I request you toput comments/suggestions. Please feel free if you have any different thought to improve any part of this blog as well.

     

    Happy Learning & Coding


    0 0

    How to consume an OData Service of SAP NetWeaver Gateway with Apache Olingo


    This article shows how to consume (Read) an OData Service with support of the Apache Olingolibrary.


    As OData Service a gateway demo service is used which defines a data model containingBusinessPartners and their related Products they sell. For this sample we assume an use case that a client (e.g. UI) is interested in all offered Products and in addition the related BusinessPartner which supplies the Product.


    To implement and demonstrate the described use case following steps have to be proceeded:


    • Fulfil prerequisites to access the gateway OData demo service
    • Read a single Product and Read all available Products
    • Navigation from a Product to the related BusinessPartner
    • Inclusion of information of related Entries to reduce requests
    • Selection of wanted information from Entries to reduce transfered data


    Prerequisites

    The gateway demo service is named ZGWSAMPLE_SRV and the functionality the service provides is described here. To get access to the gateway demo service it is necessary to sign up as described.


    Read

    Apache Olingo provides client functionality in form of create Requests (serialization) and interpret Responses (deserialization) based on the OData format. It does not provide functionality for sending and receiving requests so an application is free to decide whatever HTTP client library it wants to use. The methods to access provided serialization and deserialization functionality are all declared at the EntityProvider class. For basic consumption (Read) of an OData Service following methods are necessary:


    • EntityProvider.readMetadata(...) to read the metadata of the service.
    • EntityProvider.readEntry(...) to read an single entry.
    • EntityProvider.readFeed(...) to read a collection of entities.


    Read Prerequisites: EDM/$metadata


    Because Apache Olingo requires the metadata for serialization and deserialization of an entity the first step is to read the whole Entity Data Model (EDM) of an OData Service.


    public Edm readEdm(String serviceUrl) throws IOException, ODataException {  InputStream content = execute(serviceUrl + "/" + METADATA, APPLICATION_XML, HTTP_METHOD_GET);  return EntityProvider.readMetadata(content, false);
    }

    To read the Entity Data Model (EDM) a HTTP GET on the corresponding $metadata URI of the OData Service via the execute(...) method. The resulting content is passed into theEntityProvider.readMetadata(InputStream content, boolean validate) method which de-serialize the EDMX into an EDM object. This EDM object than can be used for necessary deserialization in combination of read operations.


    Read Entity: Product


    To read a single Product of the service a single request to the ProductsCollection URI with set ID is done.

     

    public ODataEntry readEntry(Edm edm, String serviceUri, String contentType, String entitySetName, String keyValue)  throws IOException, ODataException {
    // working with the default entity container
    EdmEntityContainer entityContainer = edm.getDefaultEntityContainer();
    // create absolute uri based on service uri, entity set name and key property value
    String absolutUri = createUri(serviceUri, entitySetName, keyValue);
    InputStream content = execute(absolutUri, contentType, HTTP_METHOD_GET);
    return EntityProvider.readEntry(contentType,    entityContainer.getEntitySet(entitySetName),    content,    EntityProviderReadProperties.init().build());  }

    The execute(...) method executes the request against the absolute URI and returns the response content as InputStream which then is deserialized by the EntityProvider.readEntry(...) into anODataEntry object. This contains all properties (data) of the entry in form of a Map, additional entry metadata as EntryMetadata object (which contains etag, id, association uris and uri information), the ExpandSelectTreeNode, information whether the entry contains inline entries and if the entry is a media resource additional the MediaMetadata.


    Read Entities: ProductCollection


    To read all Products of the service a single request to the ProductsCollection URI is done.


    public ODataFeed readFeed(Edm edm, String serviceUri, String contentType, String entitySetName)    throws IOException, ODataException {  EdmEntityContainer entityContainer = edm.getDefaultEntityContainer();  String absolutUri = createUri(serviceUri, entitySetName, null);  InputStream content = (InputStream) connect(absolutUri, contentType, HTTP_METHOD_GET).getContent();  return EntityProvider.readFeed(contentType,      entityContainer.getEntitySet(entitySetName),      content,      EntityProviderReadProperties.init().build());
    }

    The execute(...) method executes the request against the absolute URI and returns the response content as InputStream which then is deserialized by the EntitProvider.readFeed(...) into anODataFeed object. This contains all entities provided by the OData Service as ODataEntry in a list as well as FeedMetadata like inline count and next link.

    All used URIs


    Navigate

    The demo service defines an association between Products and their releated BusinessPartners as navigation property at a Product with the name Supplier. By following that association theBusinessPartner can be retrieved. This can be done by calling the absolute URI to a Supplier of a single Product which can be get by using the getAssociationUris(...) method of theEntryMetadata object. In this example the metadata object method is called with parameterSupplier which then returns with a list which contains the absolute URI (e.g. https://sapes1.sapdevcenter.com/sap/opu/odata/sap/ZGWSAMPLE_SRV/ProductCollection('HT-1000')/Supplier) which can be called to get the Supplier for the Product.

    For this example we prefer to already include the Supplier information for a Product into the response of our request. Therefore a read with expand system query option is the way to go (in next section).

    All used URIs


    Read more with Expand

    To read an Entry or Feed which already includes properties of a related Entry (or Entries) the$expand system query option can be used. The $expand clause is a list off all associations to be retrieved within this request. For the example the $expand parameter is set to the navigation property Supplier to be retrieved. This results in the following relative URI:"./ProductCollection('HT-1000')/?$expand=Supplier".


    The client has only to append the $expand for this case and can then again parse the result viaEntityProvider.readEntry(...). The difference now is that containsInlineEntry() is true and the Supplier properties are available as ODataEntry within the properties (i.e. Map) of the Product. To visualize the Map looks like:

     

    Product (as ODataEntry)
    \- *additional information like EntryMetadata*
    \- *all simple properties*
    \- Supplier (as ODataEntry)    \- *additional information like EntryMetadata*    \- *all simple properties*

    The above shown readEntry(...) method could be used with minor adaption of URI creation, which now has to include the name of the expanded navigation property.

     

    String absolutUri = createUri(serviceUri, entitySetName, keyValue, expand);

    All used URIs

    Read more with Expand on a Feed


    As mentioned in the section above the $expand can also be used to read a Feed so that then as example each Product already includes the related Supplier. Also EntityProvider.readFeed(...)can be used for deserialization and the only adaption in compare to normal read Feed use case is to append the $expand system query option. For the sample use case the relative URI is"../ProductCollection/?$expand=Supplier".

    All used URIs


    Read less with Select

    Each response usually contains all properties for an entry but this is not necessary for each client use case. Hence, for a use case in that a client is only interested in some properties it is possible to define the system query option $select to specify which properties of an Entry should be sent in the response payload. As example we only want the Name of each Product and the CompanyName of the related Supplier. Then we can use the $expand to include the Supplier in the response and define the $select system query option with Name,Supplier/CompanyName which results in the relative URI "../ProductCollection/?$select=Name,Supplier/CompanyName&$expand=Supplier".


    Again the EntityProvider.readFeed(...) method is used for deserialization and the only adaption in comparison to the read Feed with expand use case is appending the $select system query option in creation of the URI.

     

    String absolutUri = createUri(serviceUri, entitySetName, keyValue, expand, select);

    All used URIs


    Conclusion

    In the sections above it was shown that with the support of Apache Olingo it is relatively easy for a client to consume an OData Service. While the library takes care of serialization and deserialization of the OData formatted entities the client can focus on processing the data.

    Runnable sample client

    A sample client exists for a quick Hands-On covering the here shown read use cases and in addition containing the boiler plate code which is necessary for the URL connection handling (e.g. Proxy/Authentication support).


    To run this sample follow these steps:


    • Prerequisite: An installed JVM (Version 1.6 or above) and Maven (Version 3 or above).
    • Download it here.
    • Extract it into some folder
    • Configure proxy and/or authentication in client.properties in folder src/main/resources(with credentials provided via signing up)
    • Execute mvn compile exec:java to run Maven which compiles and executes the sample project.

    0 0

    Besides "traditional" authentication methods like X.509 Certificates or SAML 2.0 OAuth 2.0 provides further security capabilities to control the access to Gateway services.

     

    We have created an OAuth 2.0 WIKI providing you information what it's about, when to use it, how to set it up and how to develop it.

     

    Here's the link:OAuth 2.0 - Constrained Authorization and Single Sign-On for OData Services - Security and Identity Management - SCN Wik…


older | 1 | .... | 3 | 4 | (Page 5) | 6 | 7 | .... | 13 | newer