Thursday 18 February 2010

"javax.naming.Name is an interface, and JAXB can't handle interfaces" - Deployment Issues when using Eclipse to Deploy a JavaBean Web Service in to SAP Java AS

Hit an issue today when deploying an Enterprise JavaBen (EJB) web service today via Eclipse. I was exposing the SAP UWL through the UWL API - but it wouldn't deploy. I kept getting the following error in the deployment trace:
[com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
javax.naming.Name is an interface, and JAXB can't handle interfaces.]




Looking at all my @WebMethod annotations, there didn't seem to be any obvious problem:

@WebMethod(operationName="Test", exclude=false)
public int Test() throws UWLException, NamingException
{
IUser user = com.sap.security.api.UMFactory.getAuthenticator().getLoggedInUser();

I examined the Eclipse debug trace to about line 100, I found an issue - that there was a problem with serialization:
Unable to generate serialization framework for web service UWLFacadeService

Turns out the deployment exception was really trying to tell me that "NamingException" is not serializable - and so cannot be surfaced through a Web Service. I changed my method to handle the NamingException errors internally (via try..catching them), and removed the throws statement on the Method. Without the requirement to serialize the exception, the deployment errors for my test EJB web service went away!


......

Wednesday 17 February 2010

SAP Purchase Order Creation Error via BAPI - "In case of account assignment, please enter acc. assignment data for item" Some of the quirks of BAPI_PO_CREATE1 (via a custom BAPI)

I have been calling the SAP BAPI "BAPI_PO_CREATE1" indirectly via a custom BAPI created by one of the other guys in my development team. However, I have found out some things about this the hard way:
  1. If you haven't applied all the most recent SAP fixes to your install since mid 2009 til now (Feb 2010), you will be in a world of pain as it is IMPOSSIBLE to post a service item entry (ItemCat = "D" against a purchase order header). You will always get the following error (aka error 06 436):
    "'In case of account assignment, please enter acc. assignment data for item'"
    I spent hours butting my head against the wall because of this obscure bug when trying to call our custom BAPI. Some basic details are in the SAP Note 1373051 below (As per the image, German is considered to be the 'Master' language'!)  I believe this problem would also occur with the SAP Purchase Order Enterprise services as they call the BAPI directly.

  2. As described in https://forums.sdn.sap.com/thread.jspa?threadID=877029, to get the BAPI_PO_CREATE1 to work at all with a service item (Item Category = 'D' (Service) and Spend type of 'K' (Cost Centre), you need to create all the correct entries in the following BAPI tables:
    a) POITEM
    b) POITEMX (Change Flags - must have entries for all columns that have data)
    c) POACCOUNT
    d) POACCOUNTX (Change Flags - must have entries for all columns that have data)
    e) POSERVICES (This doesn't have a matching change flag table) - which goes into the ESLL table in SAP)
    f) POSRVACCESSVALUES

    If you don't put this information in, you will get the error "Please maintain services or limits"

    As described in the link:

    For service items: POITEM-PCKG_NO = ‘0000000001’. (assign package no as a dummy number)

    Set PCKG_NO flag in POITEMX table as ‘X’.

    Package No is the link that connect POITEM table to POACCOUNT table through tables POSERVICES and POSRVACCESSVALUES.

    Set POACCOUNT-SERIAL_NO to ‘01’.

    Set same PCKG_NO to ‘0000000001’ in POSERVICES table. Maintain two entries in POSERVICES table like this:

    WA_POSERVICES-PCKG_NO = ‘0000000001’.
    WA_POSERVICES-LINE_NO = ‘0000000001’.
    WA_POSERVICES-OUTL_IND = ‘X’.
    WA_POSERVICES-SUBPCKG_NO = ‘0000000003’. (Dummy No.)
    WA_POSERVICES-QUANTITY = ‘100.000’.
    WA_POSERVICES-BASE_UOM = ‘EA’.
    WA_POSERVICES-PRICE_UNIT = ‘1’.
    WA_POSERVICES-GR_PRICE = ‘100.000’. 
    WA_POSERVICES-SHORT_TEXT = ‘SERVICE TEST’.
    APPEND WA_POSERVICES TO IT_POSERVICES.
    
    WA_POSERVICES- PCKG_NO = ‘0000000003’.
    WA_POSERVICES- LINE_NO = ‘0000000002’.
    WA_POSERVICES-QUANTITY = ‘10.000’.
    WA_POSERVICES- BASE_UOM = ‘EA’.
    WA_POSERVICES--PRICE_UNIT = ‘1’.
    WA_POSERVICES-GR_PRICE = ‘100.000’. 
    WA_POSERVICES-SHORT_TEXT = ‘SERVICE 1’.
    WA_POSERVICES-MATL_GROUP = ‘0012’.
    APPEND WA_POSERVICES TO IT_POSERVICES.
    
    Set PCKG_NO as SUB_PCKG_NO in table POSRVACCESSVALUES this:
    WA_POSRVACCESSVALUES-PCKG_NO = ‘0000000003’.
    WA_POSRVACCESSVALUES-LINE_NO = ‘0000000002’.
    WA_POSRVACCESSVALUES-SERNO_LINE = ‘01’.
    WA_POSRVACCESSVALUES-SERIAL_NO = ‘01’.
    WA_POSRVACCESSVALUES-QUANTITY = ’10.000’.
    APPEND WA_POSRVACCESSVALUES TO IT_ POSRVACCESSVALUES.
  3. Also note that if you get errors relating to "Cost Object XXXXXX does not exist on DD.MM.YYYY", then you have likely set the value of "CostObject" on the Account Parameter. Depending on your config, it is typically OK to just leave this blank, and feed your cost object information into the relevant column on the Account Table (Asset/Cost Centre/Project etc).
PS. Why not use Enterprise Services rather than the custom BAPIs? I've more recently learnt that the official best way to do some of these changes (rather than writing custom BAPIs) is to EXTEND the Enterprise Service Extensions (according to Jan from SAP who visited us recently). However there is scant documentation on this so is only really in the realm of "Internal SAP Employees Only" development.

I've found that SAP Enterprise Services are even more complex and are more difficult to customize than the simpler BAPI mechanisms we have established here at my current client. Custom BAPIs have the main disadvantage of duplicating some datatypes (there are global datatypes defined in SAP Enterprise Services) and an increased difficulty in data type governance and consolidation that this entails.

Friday 5 February 2010

SAP ABAP Rule - Make sure you commit your transactions to Avoid Phantom Numbers

An absolutely bizarre issue ocurred today - I was calling a custom SAP BAPI for the creation of purchase orders from .NET (via a web service) and it was returning a Purchase Order number - but it was never appearing in the client system in SAP. Essentially the Purchase order numbers I was receiving in the web service response never got into the EKKO table in SAP.

Turns out that if you get phantom numbers like this, you may not be committing your transaction correctly. Make sure you call a commit like so:
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.


Otherwise the Purchase Orders will just disappear when your BAPI completes.

FUNCTION Z_PO_CREATE .
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(I_POHEADER) LIKE  BAPIMEPOHEADER STRUCTURE  BAPIMEPOHEADER
*"     VALUE(I_POHEADERX) LIKE  BAPIMEPOHEADERX STRUCTURE
*"        BAPIMEPOHEADERX OPTIONAL
*"     VALUE(I_POADDRVENDOR) LIKE  BAPIMEPOADDRVENDOR STRUCTURE
*"        BAPIMEPOADDRVENDOR OPTIONAL
*"     VALUE(I_TESTRUN) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_MEMORY_UNCOMPLETE) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_MEMORY_COMPLETE) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_POEXPIMPHEADER) LIKE  BAPIEIKP STRUCTURE  BAPIEIKP
*"       OPTIONAL
*"     VALUE(I_POEXPIMPHEADERX) LIKE  BAPIEIKPX STRUCTURE  BAPIEIKPX
*"       OPTIONAL
*"     VALUE(I_VERSIONS) LIKE  BAPIMEDCM STRUCTURE  BAPIMEDCM OPTIONAL
*"     VALUE(I_NO_MESSAGING) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_NO_MESSAGE_REQ) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_NO_AUTHORITY) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_NO_PRICE_FROM_PO) LIKE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_PARK_COMPLETE) TYPE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_PARK_UNCOMPLETE) TYPE  BAPIFLAG-BAPIFLAG OPTIONAL
*"     VALUE(I_PROCESSTITLE) TYPE  ZSBPMLOG-PROCESSTITLE OPTIONAL
*"     VALUE(I_PROCESSSTARTDATE) TYPE  ZSBPMLOG-PROCESSSTARTDATE
*"       OPTIONAL
*"     VALUE(I_PROCESSSTARTTIME) TYPE  ZSBPMLOG-PROCESSSTARTTIME
*"       OPTIONAL
*"     VALUE(I_PROCESSOWNER) TYPE  ZSBPMLOG-PROCESSOWNER OPTIONAL
*"     VALUE(I_STEPNAME) TYPE  ZSBPMLOG-STEPNAME OPTIONAL
*"     VALUE(I_STEPSTARTDATE) TYPE  ZSBPMLOG-STEPSTARTDATE OPTIONAL
*"     VALUE(I_STEPSTARTTIME) TYPE  ZSBPMLOG-STEPSTARTTIME OPTIONAL
*"     VALUE(I_STEPOWNER) TYPE  ZSBPMLOG-STEPOWNER OPTIONAL
*"     VALUE(I_MESSAGE1) TYPE  ZSBPMLOG-MESSAGE1 OPTIONAL
*"     VALUE(I_MESSAGE2) TYPE  ZSBPMLOG-MESSAGE2 OPTIONAL
*"     VALUE(I_MESSAGE3) TYPE  ZSBPMLOG-MESSAGE3 OPTIONAL
*"     VALUE(I_MESSAGE4) TYPE  ZSBPMLOG-MESSAGE4 OPTIONAL
*"     VALUE(I_MESSAGE5) TYPE  ZSBPMLOG-MESSAGE5 OPTIONAL
*"     VALUE(I_OBJKEY) TYPE  SWO_TYPEID
*"     VALUE(I_OBJTYPE) TYPE  SWO_OBJTYP
*"     VALUE(I_LOGSYS) TYPE  LOGSYS OPTIONAL
*"     VALUE(I_TITLE) TYPE  SOOD-OBJDES
*"     VALUE(I_URL) TYPE  SO_URL
*"  EXPORTING
*"     VALUE(E_EXPPURCHASEORDER) LIKE  BAPIMEPOHEADER-PO_NUMBER
*"     VALUE(E_EXPHEADER) LIKE  BAPIMEPOHEADER STRUCTURE
*"        BAPIMEPOHEADER
*"     VALUE(E_EXPPOEXPIMPHEADER) LIKE  BAPIEIKP STRUCTURE  BAPIEIKP
*"     VALUE(E_URL_LINK) TYPE  BORIDENT-OBJKEY
*"  TABLES
*"      T_RETURN STRUCTURE  BAPIRET2 OPTIONAL
*"      T_POITEM STRUCTURE  BAPIMEPOITEM OPTIONAL
*"      T_POITEMX STRUCTURE  BAPIMEPOITEMX OPTIONAL
*"      T_POADDRDELIVERY STRUCTURE  BAPIMEPOADDRDELIVERY OPTIONAL
*"      T_POSCHEDULE STRUCTURE  BAPIMEPOSCHEDULE OPTIONAL
*"      T_POSCHEDULEX STRUCTURE  BAPIMEPOSCHEDULX OPTIONAL
*"      T_POACCOUNT STRUCTURE  BAPIMEPOACCOUNT OPTIONAL
*"      T_POACCOUNTPROFITSEGMENT STRUCTURE
*"        BAPIMEPOACCOUNTPROFITSEGMENT OPTIONAL
*"      T_POACCOUNTX STRUCTURE  BAPIMEPOACCOUNTX OPTIONAL
*"      T_POCONDHEADER STRUCTURE  BAPIMEPOCONDHEADER OPTIONAL
*"      T_POCONDHEADERX STRUCTURE  BAPIMEPOCONDHEADERX OPTIONAL
*"      T_POCOND STRUCTURE  BAPIMEPOCOND OPTIONAL
*"      T_POCONDX STRUCTURE  BAPIMEPOCONDX OPTIONAL
*"      T_POLIMITS STRUCTURE  BAPIESUHC OPTIONAL
*"      T_POCONTRACTLIMITS STRUCTURE  BAPIESUCC OPTIONAL
*"      T_POSERVICES STRUCTURE  BAPIESLLC OPTIONAL
*"      T_POSRVACCESSVALUES STRUCTURE  BAPIESKLC OPTIONAL
*"      T_POSERVICESTEXT STRUCTURE  BAPIESLLTX OPTIONAL
*"      T_EXTENSIONIN STRUCTURE  BAPIPAREX OPTIONAL
*"      T_EXTENSIONOUT STRUCTURE  BAPIPAREX OPTIONAL
*"      T_POEXPIMPITEM STRUCTURE  BAPIEIPO OPTIONAL
*"      T_POEXPIMPITEMX STRUCTURE  BAPIEIPOX OPTIONAL
*"      T_POTEXTHEADER STRUCTURE  BAPIMEPOTEXTHEADER OPTIONAL
*"      T_POTEXTITEM STRUCTURE  BAPIMEPOTEXT OPTIONAL
*"      T_ALLVERSIONS STRUCTURE  BAPIMEDCM_ALLVERSIONS OPTIONAL
*"      T_POPARTNER STRUCTURE  BAPIEKKOP OPTIONAL
*"      T_POCOMPONENTS STRUCTURE  BAPIMEPOCOMPONENT OPTIONAL
*"      T_POCOMPONENTSX STRUCTURE  BAPIMEPOCOMPONENTX OPTIONAL
*"      T_POSHIPPING STRUCTURE  BAPIITEMSHIP OPTIONAL
*"      T_POSHIPPINGX STRUCTURE  BAPIITEMSHIPX OPTIONAL
*"      T_POSHIPPINGEXP STRUCTURE  BAPIMEPOSHIPPEXP OPTIONAL
*"      T_SERIALNUMBER STRUCTURE  BAPIMEPOSERIALNO OPTIONAL
*"      T_SERIALNUMBERX STRUCTURE  BAPIMEPOSERIALNOX OPTIONAL
*"      T_INVPLANHEADER STRUCTURE  BAPI_INVOICE_PLAN_HEADER OPTIONAL
*"      T_INVPLANHEADERX STRUCTURE  BAPI_INVOICE_PLAN_HEADERX OPTIONAL
*"      T_INVPLANITEM STRUCTURE  BAPI_INVOICE_PLAN_ITEM OPTIONAL
*"      T_INVPLANITEMX STRUCTURE  BAPI_INVOICE_PLAN_ITEMX OPTIONAL
*"      T_URL_RETURN STRUCTURE  BAPIRET2 OPTIONAL
*"----------------------------------------------------------------------
* Create SAP BPM Log Entry
*  ZSBPMLOG-PROCESSTITLE      = I_PROCESSTITLE.
*  ZSBPMLOG-PROCESSSTARTDATE  = I_PROCESSSTARTDATE.
*  ZSBPMLOG-PROCESSSTARTTIME  = I_PROCESSSTARTTIME.
*  ZSBPMLOG-PROCESSOWNER      = I_PROCESSOWNER.
*  ZSBPMLOG-STEPNAME          = I_STEPNAME.
*  ZSBPMLOG-STEPSTARTDATE     = I_STEPSTARTDATE.
*  ZSBPMLOG-STEPSTARTTIME     = I_STEPSTARTTIME.
*  ZSBPMLOG-STEPOWNER         = I_STEPOWNER.
*  ZSBPMLOG-MESSAGE1          = I_MESSAGE1.
*  ZSBPMLOG-MESSAGE2          = I_MESSAGE2.
*  ZSBPMLOG-MESSAGE3          = I_MESSAGE3.
*  ZSBPMLOG-MESSAGE4          = I_MESSAGE4.
*  ZSBPMLOG-MESSAGE5          = I_MESSAGE5.
*  INSERT ZSBPMLOG.

*Create PO Record
  CALL FUNCTION 'BAPI_PO_CREATE1'
    EXPORTING
      POHEADER               = I_POHEADER
      POHEADERX              = I_POHEADERX
      POADDRVENDOR           = I_POADDRVENDOR
      TESTRUN                = I_TESTRUN
      MEMORY_UNCOMPLETE      = I_MEMORY_UNCOMPLETE
      MEMORY_COMPLETE        = I_MEMORY_COMPLETE
      POEXPIMPHEADER         = I_POEXPIMPHEADER
      POEXPIMPHEADERX        = I_POEXPIMPHEADERX
      VERSIONS               = I_VERSIONS
      NO_MESSAGING           = I_NO_MESSAGING
      NO_MESSAGE_REQ         = I_NO_MESSAGE_REQ
      NO_AUTHORITY           = I_NO_AUTHORITY
      NO_PRICE_FROM_PO       = I_NO_PRICE_FROM_PO
      PARK_COMPLETE          = I_PARK_COMPLETE
      PARK_UNCOMPLETE        = I_PARK_UNCOMPLETE
    IMPORTING
      EXPPURCHASEORDER       = E_EXPPURCHASEORDER
      EXPHEADER              = E_EXPHEADER
      EXPPOEXPIMPHEADER      = E_EXPPOEXPIMPHEADER
    TABLES
      RETURN                 = T_RETURN
      POITEM                 = T_POITEM
      POITEMX                = T_POITEMX
      POADDRDELIVERY         = T_POADDRDELIVERY
      POSCHEDULE             = T_POSCHEDULE
      POSCHEDULEX            = T_POSCHEDULEX
      POACCOUNT              = T_POACCOUNT
      POACCOUNTPROFITSEGMENT = T_POACCOUNTPROFITSEGMENT
      POACCOUNTX             = T_POACCOUNTX
      POCONDHEADER           = T_POCONDHEADER
      POCONDHEADERX          = T_POCONDHEADERX
      POCOND                 = T_POCOND
      POCONDX                = T_POCONDX
      POLIMITS               = T_POLIMITS
      POCONTRACTLIMITS       = T_POCONTRACTLIMITS
      POSERVICES             = T_POSERVICES
      POSRVACCESSVALUES      = T_POSRVACCESSVALUES
      POSERVICESTEXT         = T_POSERVICESTEXT
      EXTENSIONIN            = T_EXTENSIONIN
      EXTENSIONOUT           = T_EXTENSIONOUT
      POEXPIMPITEM           = T_POEXPIMPITEM
      POEXPIMPITEMX          = T_POEXPIMPITEMX
      POTEXTHEADER           = T_POTEXTHEADER
      POTEXTITEM             = T_POTEXTITEM
      ALLVERSIONS            = T_ALLVERSIONS
      POPARTNER              = T_POPARTNER
      POCOMPONENTS           = T_POCOMPONENTS
      POCOMPONENTSX          = T_POCOMPONENTSX
      POSHIPPING             = T_POSHIPPING
      POSHIPPINGX            = T_POSHIPPINGX
      POSHIPPINGEXP          = T_POSHIPPINGEXP
      SERIALNUMBER           = T_SERIALNUMBER
      SERIALNUMBERX          = T_SERIALNUMBERX
      INVPLANHEADER          = T_INVPLANHEADER
      INVPLANHEADERX         = T_INVPLANHEADERX
      INVPLANITEM            = T_INVPLANITEM
      INVPLANITEMX           = T_INVPLANITEMX.

* Create PO Attachments
  IF I_URL IS NOT INITIAL.
    CALL FUNCTION 'Z_GOS_URL_CREATE'
      EXPORTING
        I_OBJKEY   = I_OBJKEY
        I_OBJTYPE  = I_OBJTYPE
        I_LOGSYS   = I_LOGSYS
        I_TITLE    = I_TITLE
        I_URL      = I_URL
      IMPORTING
        E_URL_LINK = E_URL_LINK
      TABLES
        T_RETURN   = T_URL_RETURN.
  ENDIF.

 CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.

* Create SAP BPM Log Entry
*  ZSBPMLOG-PROCESSTITLE      = I_PROCESSTITLE.
*  ZSBPMLOG-PROCESSSTARTDATE  = I_PROCESSSTARTDATE.
*  ZSBPMLOG-PROCESSSTARTTIME  = I_PROCESSSTARTTIME.
*  ZSBPMLOG-PROCESSOWNER      = I_PROCESSOWNER.
*  ZSBPMLOG-STEPNAME          = I_STEPNAME.
*  ZSBPMLOG-STEPSTARTDATE     = I_STEPSTARTDATE.
*  ZSBPMLOG-STEPSTARTTIME     = I_STEPSTARTTIME.
*  ZSBPMLOG-STEPOWNER         = I_STEPOWNER.
*  ZSBPMLOG-MESSAGE1          = I_MESSAGE1.
*  ZSBPMLOG-MESSAGE2          = I_MESSAGE2.
*  ZSBPMLOG-MESSAGE3          = I_MESSAGE3.
*  ZSBPMLOG-MESSAGE4          = I_MESSAGE4.
*  ZSBPMLOG-MESSAGE5          = I_MESSAGE5.
*  INSERT ZSBPMLOG.

ENDFUNCTION.

Thursday 4 February 2010

WCF Client Factory (Using Reflection & Generic Parameters) to set ClientCredentials

The following method (using reflection) works around the fact that the WCF generated proxies in .NET don't have a common non-generic interface. See code for a WCF proxy factory that sets basic client credentials (from a ConfigurationHelper class) and then returns the properly initialized client.

/// 
    /// Class for creating and initializing WCF proxy clients.
    /// 
    public class WCFClientFactory
    {
        /// 
        /// Gets an instance of WCF Proxy Class(Type "T"), and sets the credentials on it.
        /// 
        /// 
        /// /// 
        public static T CreateClient(CredentialType type)
        {
            object client = Activator.CreateInstance(typeof(T));
            ClientCredentials clientCredentials = 
                (ClientCredentials)client.GetType().GetProperty("ClientCredentials").GetValue(client, null);
            UserNamePasswordClientCredential credentials = clientCredentials.UserName;

            if (type == CredentialType.SAPBasic)
            {
                credentials.UserName = ConfigHelper.BackgroundUserName;
                credentials.Password = ConfigHelper.BackgroundUserPassword;
            }
            else if (type == CredentialType.MDM)
            {
                credentials.UserName = ConfigHelper.MDMUserName;
                credentials.Password = ConfigHelper.MDMPassword;
            }
        
            //Return initialized Proxy from Factory
            return (T)client;
        }

        //parameterless overload.
        public static T CreateClient()
        {
            return CreateClient(CredentialType.SAPBasic);
        }

You then call it like so:
Z_PO_CreateClient client = WCFClientFactory.CreateClient();

Wednesday 3 February 2010

SharePoint 2007 - "The trial period for this product has expired." Error message when Editing Page Content or viewing InfoPath Forms

If you get exception when Editing SharePoint objects or opening up Infopath Forms like the one shown below:

The trial period for this product has expired.


It was not caused by the other 101 things detailed on the web that can also cause the issue (e.g. Antivirus, Permissions problems with DCOM - such as detailed here http://msmvps.com/blogs/shane/archive/2008/02/05/the-trial-period-for-this-product-has-expired.aspx).

I'm so used to spurious and misleading errors in SharePoint that the most obvious answer was the last I considered - it may be that the original installer didn't enter an Enterprise Product key during the install process (unbeknownst to you). Before you go trying all the other options, you should check your current license status by going to:

Central Administration -> Operations -> Convert License Type

This will tell you your current license status and allow you to enter your relevant license key (Enterprise or Standard).


In addition to what is mentioned here(http://technet.microsoft.com/en-us/library/cc263204.aspx), you also have to do an iisreset to get the error to disappear.

DDK

Tuesday 2 February 2010

How to Perform Wild Card Matches in SAP ABAP (for a Find or Search Function)

The following BAPI has several optional criteria that are only added to the filter if they have a value. It uses the RANGE keyword and the IN keyword together to build up the query filter. It is an alternative to building a dynamic query (based purely on string concatenation). Note that this works because the range object is null in the final comparison statment in this BAPI so it will not be added to the filter, (e.g. "AND BUKRS IN R_BUKRS" will effectively be "AND BUKRS IN NULL" and so will not be evaluated in the WHERE clause.).

FUNCTION Z_PO_FIND.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(I_PO_NUMBER) TYPE EKKO-EBELN OPTIONAL
*" VALUE(I_COMPANY_CODE) TYPE EKKO-BUKRS OPTIONAL
*" VALUE(I_PURCH_GROUP) TYPE EKKO-EKGRP OPTIONAL
*" VALUE(I_DOC_START_DATE) TYPE EKKO-AEDAT DEFAULT '01.01.0001'
*" VALUE(I_DOC_END_DATE) TYPE EKKO-AEDAT DEFAULT '31.12.9999'
*" TABLES
*" T_EKKO STRUCTURE EKKO OPTIONAL
*"----------------------------------------------------------------------
RANGES: R_EBELN FOR EKKO-EBELN,
R_BUKRS FOR EKKO-BUKRS,
R_EKGRP FOR EKKO-EKGRP,
R_AEDAT FOR EKKO-AEDAT.

DATA: W_WILD TYPE C LENGTH 1 VALUE '*',
W_PO_NUMBER LIKE EKKO-EBELN.

* Set PO Number range
IF I_PO_NUMBER IS NOT INITIAL.
SHIFT I_PO_NUMBER LEFT DELETING LEADING '0'.
CONCATENATE W_WILD I_PO_NUMBER W_WILD INTO W_PO_NUMBER.

R_EBELN-OPTION = 'CP'.
R_EBELN-SIGN = 'I'.
R_EBELN-LOW = W_PO_NUMBER.
APPEND R_EBELN.
ENDIF.

* Set Company Code range
IF I_COMPANY_CODE IS NOT INITIAL.
R_BUKRS-OPTION = 'EQ'.
R_BUKRS-SIGN = 'I'.
R_BUKRS-LOW = I_COMPANY_CODE.
APPEND R_BUKRS.
ENDIF.

* Set Purchasing Group range
IF NOT I_PURCH_GROUP IS INITIAL.
R_EKGRP-OPTION = 'EQ'.
R_EKGRP-SIGN = 'I'.
R_EKGRP-LOW = I_PURCH_GROUP.
APPEND R_EKGRP.
ENDIF.

* Set date range
R_AEDAT-OPTION = 'BT'.
R_AEDAT-SIGN = 'I'.
R_AEDAT-LOW = I_DOC_START_DATE.
R_AEDAT-HIGH = I_DOC_END_DATE.
APPEND R_AEDAT.

* Select records from table EKKO
SELECT * FROM EKKO INTO T_EKKO
WHERE EBELN IN R_EBELN
AND BUKRS IN R_BUKRS
AND EKGRP IN R_EKGRP
AND AEDAT IN R_AEDAT.
APPEND T_EKKO.
ENDSELECT.

ENDFUNCTION.

Monday 1 February 2010

Fix for Error: "The provided URI scheme 'https' is invalid; expected 'http'. Parameter name: via." when calling Web Service in SAP

Today I got an exception after using the default bindings generated by the .NET svcutil.exe tool. This occurred as the tool incorrectly detected that it should be using an httpsTransport, and we didn’t have https internally. This was because the SAP wsdl supports both https and http bindings.

To get around this issue, I changd the binding to use 'security mode="TransportCredentialOnly"':

<binding name="Binding_T_HTTPS_A_HTTP_Z_CONTRACT_FIND_CE_ERP">
          <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
              messageVersion="Soap11" writeEncoding="utf-8">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          </textMessageEncoding>
          <httpsTransport manualAddressing="false" maxBufferPoolSize="524288"
              maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Basic"
              bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
              keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
              realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
              useDefaultWebProxy="true" requireClientCertificate="false" />
        </binding>

I changed it to use a basic authentication proxy, and it works (not secure – but this is for an internal dev box, not using https). This suits my purpose:

<basicHttpBinding>
        <binding name="SAPBasicHttpBinding" closeTimeout="00:01:00"
  openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
  allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
  maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
  messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
  useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="TransportCredentialOnly" >
            <transport clientCredentialType="Basic" proxyCredentialType="Basic"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>