1 6 7 8 9 10 Previous Next

thomas.jung

144 Posts
Introduction
In the last weblog I took a look at how we implemented Single Sign On for the BSP environment. Now that we have users logged into our BSP system, that is really only half of the solution. Remember that we have a split environment where our BSP system sits on a 620 WebAS on one server and our R/3 system sits on a separate system on release 46C. We also have a BW environment on another server again. We will be connecting to our R/3 system via RFC. The question is how best to setup this RFC?

The Requirements
Our first requirement for this setup was to keep the authorizations as simple as possible in the WebAS environment. Our security group didn't really want to maintain two sets of complex authorization objects. Our goal was to reuse all the roles we already had in R/3 and have all users have one very simple and generic role in the WebAS. We also wanted to pass through to the R/3 environment the users' personalization settings such as date format, time zone, etc.

In the past our company had setup two different types of RFC connections, anonymous ones with a system user ID and password imbedded in it and ones without a user id and password so that you would be prompted for one when making the RFC call. The second option obviously doesn't work from BSP since there is no prompt for authentication. Even if the system could prompt, that would defeat all the work we had done to get SSO into the WebAS. The anonymous option as technically possible but opened up many problems. First you would need lots of authentication on the WebAS before you even make the call to R/3. Even with lots of complex security in the WebAS this option made our security people a little nervous. This also made it very difficult to properly use the user's personization settings on the R/3 side. The solution came to us as a 3rd type of RFC connection that we had never used before - Trusted RFC.

Trusted RFC to the Rescue
Trusted RFC is nothing new to the SAP environment. Nor is it anything specific to BSP. It was simply a technology that we had never had a driving need for before now. Basically setting up a trusted RFC allows one SAP system that trusts another to accept its user authentication without question.

Let's look at our system landscape. We setup in advance that our R/3 system trusts our WebAS. Therefore when it receives an RFC call from the WebAS, it also trusts that the WebAS as already properly authenticated that user. This allows the user's identity to pass through the RFC connection without any exchange of passwords. However this only gets the user into the R/3 system. Once in the system, all the user's regular roles and authorizations are in effect. That way all that time and money you put into building good roles in R/3 is put to further use without any additional authorizations work in the WebAS.

Setup of Trusted RFC
The first thing we need to do is go to our R/3 system and tell it who we trust. You can do this from RFC Destination Maintenance (SM59). Choose Menu RFC->Trusted Systems. From here you hit create to start the process of defining a new trusting relationship. You will be prompted for an already existing RFC connection to this system. This will be used to make the settings in both systems for the Trust. You then will receive the following screen showing you the settings that will be used for the trust:
image

Destination Setup
Now that we have our systems trusting each other (isn't a little trust a wonderful thing?), lets setup the RFC destination itself. For that we go back over to our WebAS system and go to RFC Destination Maintenance (SM59). Everything is the same as a normal destination until we reach the Logon/Security section. The following are the settings that we use. This allows for a trusted connection for the current user in the user's current logon language.
image

Authorization Check
There is only one last thing to do before we run off and start making trusted RFC calls. There is a special authorization object that is checked on the destination side before accepting Trusted RFC calls. By default this authorization is not included in any roles - not even SAP_ALL. The Authorization is S_RFCACL. You can read all about this authorization check and the whole process described here in OSS note 128447.

What Happens When Something Goes Wrong?
By now you should be up and running making trusted RFC calls. But you might be wondering what happens when you have a problem. Let's say that the user in the WebAS isn't setup in the R/3 system or that user isn't authorized for the action in question. Well if you don't do any additional coding in your RFC call you will get the following Short Dump in your WebAS:
image

Here is the example code that produced this dump:


Actually if you debug this code you will find that the first two RFC calls execute successfully. The dump only occurs on the third call. It appears that functions in the SRFC function group can be called even if you don't have an account in the destination system. The lesson there is don't rely on an RFC_PING to tell you that your user's are authorized in the destination system. I created a simple RFC call in our systems that serves the function of the RFC ping (to make sure your destination is correct) but because it isn't in the SRFC group you also get an early authorization check. I put this call at the beginning of my BSP Application (Usually in the ON_START method of my application class). That way if my user or the RFC destination isn't setup correctly we find out right away.

Catching Destination Errors
But you might be thinking that a short dump isn't a very friendly way of letting your users know that something is wrong. The good news is that you can catch these types of setup errors by adding some special exceptions to your RFC call. They are COMMUNICATION_FAILURE and SYSTEM_FAILURE. These two exceptions are always available when making any type of RFC call. They are especially use in that they can put the details of the error into a message area. They are very useful for catching all kinds of error situations and make for a much nicer response to the user. The following is the same program example with these exceptions and the output I received:

image

Closing
I hope everyone has enjoyed our dip into the deep end of the security pool. Next time we will have some fun with the IGS charting tool. There have been several posts and a few weblogs already on the subject. I will take you through one of our BSP applications as an example and share with you some of the tips we have found.

Introduction
There have been recent discussion in the BSP forum on BSP and Excel. I would like to take this one step further and discuss how to do this same download, but with the data in Unicode.

 

The example code in this thread works great until you hit one situation. If you have a Unicode or MDMP SAP system and you are downloading data from more than one code page or from a different code page than the default codepage of the OS that the client is running, you will have a problem. The data stream that is sent to Excel will be encoded with the default codepage for the logged on language and it will then corrupt any characters from another code page.

 

Example
To give you a concrete example I will tell you about our system. We have English and Polish both installed in our system (using MDMP we have two code pages Latin-1 for English and Latin-2 for Polish). My Windows XP client is Unicode capable as is Microsoft Office. However your pc also has to work in a single non-Unicode code page when dealing with non-Unicode data. This is normally set by the country version of the OS you are running (In Windows XP you can switch this value in the Region Settings). My PC for instance is US based and therefore runs English (Latin-1) as its default codepage. I then run a BSP page logged on to the WebAS in Polish. I need to download a report with Material Descriptions that are in Polish. However the download from SAP by default will be in Polish (latin-2) and my PC and Excel won't understand it since they are expecting English (Latin-1). As you can see from this screen shot, what I end up with is quite a mess. The BSP output is on the top and is formatted correctly. However the Excel display on the bottom has many incorrect and corrupted characters:
image

 

Looking at MS Excel
I would like to give you some code samples that will expand on those in the given Forum posting. I want to stress that these samples will work even in a non-Unicode SAP system. I have tested them on WebAS 620. The first thing we have to understand is what kind of Unicode file does MS Excel want. After doing a little research, I found out that Excel expects a UTF-16 encoded file (evidently all the Microsoft Office tools use UTF-16 when saving files in their primary format) with a byte order mark of Little Endian. If UTF-16 and Byte Order Mark (BOM) are unfamiliar, I suggest some light reading on the Unicode Home Page.

 

I wanted to verify this information I had found on the web. I opened Excel and typed in some Polish national characters. I then saved my spreadsheet as Unicode Text. This creates a tab-delimited text file in Unicode format. I then opened the file in a Hex Editor. Sure enough, there was my UTF-16le (Little Endian) Byte Order Mark - FF FE - right at the beginning of the of the file.

 

image

 

Possible BOM Values
For reference the following are the possible values for the Byte Order Mark:

BytesEncoding Form
00 00 FE FFUTF-32, big-endian
FF FE 00 00UTF-32, little-endian
FE FFUTF-16, big-endian
FF FEUTF-16, little-endian
EF BB BFUTF-8

 

 

ABAP Code Changes
Now we are ready to start making changes to the ABAP code from our BSP examples. The first thing we need to change is the application type string.
Old Code

APP_TYPE = 'APPLICATION/MSEXCEL'.


New Code

app_type = 'APPLICATION/MSEXCEL; charset=utf-16le'.


With this change we have now set our output character set to UTF-16 Little Endian. The call to SCMS_STRING_TO_XSTRING will now use UTF-16le as the destination format as it converts our source string to our output binary string:

call function 'SCMS_STRING_TO_XSTRING' 
       exporting text = l_string mimetype = app_type importing buffer = l_xstring.

For Reference the SAP internal Code page numbers are 4102 for utf-16be, 4103 for utf-16le, and 4110 for utf-8. These can be found in table TCP00A or by calling function module: SCP_CODEPAGE_BY_EXTERNAL_NAME.

 

That was actually quite easy. Now we have our output formatted as Unicode Text Tab Delimited. We just need to add the Byte Order Mark to the beginning of the binary string:

concatenate cl_abap_char_utilities=>byte_order_mark_little 
   l_xstring into l_xstring in byte mode.


Here we used the wonderful little class CL_ABAP_CHAR_UTILITIES. It already has the Byte Order Marks for UTF-8, UTF-16be, and UTF-16le defined for us.

 

Closing
As you can see in this final screen shot, out output in Excel now matches what we saw on the screen in BSP:
image

 

Full Code
Here is the complete code sample taken from the original forum posting and adjusted with the changes I have suggest here. Just in case the original forumn posting ever becomes unreachable. Special thanks to Suresh Babu for originally posting this code to the BSP forumn.

***ITAB contains my data so.. 
LOOP AT ITAB INTO WA.
     CONCATENATE L_STRING WA-PARTNER WA-ADR_KIND WA-ADDRNUMBER
     CL_ABAP_CHAR_UTILITIES=>CR_LF
     INTO L_STRING SEPARATED BY SPACE.
ENDLOOP.

APP_TYPE = 'APPLICATION/MSEXCEL; charset=utf-16le'.

call function 'SCMS_STRING_TO_XSTRING'
     exporting text = l_string
                     MIMETYPE = APP_TYPE
     IMPORTING BUFFER = l_xstring.
* Add the Byte Order Mark - UTF-16 Little Endian
concatenate cl_abap_char_utilities=>byte_order_mark_little l_xstring
              into l_xstring in byte mode.

response->set_header_field( name = 'content-type' value = APP_TYPE ).
* some Browsers have caching problems when loading Excel Format
response->delete_header_field( name = if_http_header_fields=>cache_control ).
response->delete_header_field( name = if_http_header_fields=>expires ).
response->delete_header_field( name = if_http_header_fields=>pragma ).
* start Excel viewer either in the Browser or as a separate window
response->set_header_field( name = 'content-disposition' value = 'attachment; filename=webforms.xls' ).
* finally display Excel format in Browser
l_len = xstrlen( l_xstring ).
response->set_data( data = l_xstring length = l_len ).
navigation->response_complete( ).
Introduction
To understand our requirements for user authentication, you have to understand where we were coming from. Before we began development on the WebAS, all of applications were written for and ran on Microsoft IIS. Because of this we always used Integrated Windows Authentication. For anyone not familiar with this, it is a function of the combination of Microsoft IE and IIS. It allows you to reuse a Windows Domain authentication for your web based authentication. To the user everything is transparent. They never have to login to a webpage. It just as if the website already knows who they are. In reality the browser is passing authentication information to the web server. The web server then verifies this information with the windows domain.

This is a nice solution for intranet development when everything runs on the Microsoft platform. Naturally our users expected the same the same transparent type of authentication. To them, even having to logon on to a web application once was unheard of. So to start off we knew that we wanted to use some form of Single Sign On. However the SAP Enterprise Portal was out of scope at the time. Even to this day (2 years later) we have yet to implement EP. It is still an ongoing project. Our goal was clear - find some way to provide seamless SSO without user interaction, which works with SAP WebAS BSP and perferably took advantage of our windows security environment. Oh, and we couldn't spend any money either.

The ITS
These requirements lead us to what is probably a fairly unusual solution. We starting looking at the ITS. As a leftover, from the old workplace 2.11 days, ITS has some functionality call PAS (Pluggable Authentication Service). The install Package, NTAUTH.SAR can still be found in the Service Marketplace under the Patches Area->SAP NetWeaver->SAP NetWeaver components ( < SAP NW 04) -> SAP Workplace ->SAP Workplace 2.11 -> Workplace 2.11 ITS Package. Details about this solution can also be read in OSS note 361064 and 493107.

The PAS module allowed us to setup the ITS to do authentication based upon NTLM (Windows integrated authentication). This package contains a simple service file called sapntauth, that you can copy from and setup services for each of our BSP applications. In this service you setup what url you want to redirect to after the ITS has generated your SAP SSO2 ticket.

That way users actually launch an ITS webpage. This is the ITS that is setup for our standalone WebAS. This ITS first uses the PAS to talk to the underlying IIS server and get the user's Windows authentication. The ITS then connects to the WebAS via SNC (Secure Network Communications). The WebAS first authentications that it trusts the ITS that is calling it. It then uses a cross reference table to verify the user's Windows Authentication and to lookup their corresponding SAP User ID (which doesn't necessarily have to be the same). If everything checks out, the WebAS generates a SSO2 ticket and passes it back to the ITS. The ITS then sends this ticket back to the user's browser along with a redirect to the BSP page that you actually want to load. To the end user, this process is all transparent and nearly instantaneous. All they see is that they are logged into a BSP page without any request for user name or password.

More Detail
Now there are several things that need to be setup for this work. Naturally you have to have an ITS and you have to connect using SNC between the AGate and the backend WebAS. Of course if you want Windows Integrated Authentication your ITS has to run on top of IIS. In our system we actually run the ITS on the same physical server that our WebAS is running on. Just make sure that you use different HTTP ports for your WebAS and for your ITS virtual web server. There are several nice documents already available on the Service Marketplace that talk about setting the ITS with secure connection to the backend SAP system. In particular have a look at the marketplace alias SECURITY.

The next step is to setup your WebAS for SSO. You can also find some excellent document in the SECURITY alias as well as several articles within SDN. Even with all the good documentation that is out there, this is still a rather complicated process. I can offer you the following: these are all the profile parameters from our instance profile that we set to turn on SNC with the ITS and SSO2.
sec/libsapsecu f:\usr\sap\D15\sys\exe\run\sapcrypto.dll ssf/name SAPSECULIB ssf/ssfapi_lib f:\usr\sap\D15\sys\exe\run\sapcrypto.dll snc/enable 1 snc/gssapi_lib c:\winnt\system32\gsskrb5.dll snc/identity/as p:SAPServiceD15@kii.kimball.com ssl/ssl_lib f:\usr\sap\D15\sys\exe\run\sapcrypto.dll snc/accept_insecure_cpic 1 snc/accept_insecure_gui 1 snc/accept_insecure_rfc 1 snc/permit_insecure_start 1 snc/extid_login_rfc 1 snc/extid_login_diag 1 snc/accept_insecure_r3int_rfc 1 snc/data_protection/max 1 snc/data_protection/min 1 snc/data_protection/use 1 login/accept_sso2_ticket 1 login/create_sso2_ticket 2


Next it helps to know where to do the External Identification Mapping. This is where you can setup the trust relationship for SNC with the ITS and where you setup the user Mapping for authentication. This is a screen shot of the IMG path in our WebAS (I had to reduce it quite a bit to meet SDN file size limits. Hopefully it will still help you find your way):
image

Finallly I thought I might include a look at what one of our ITS redirect service files look like:
############################################################################### # @Copyright SAP AG 2002 # Example Service File for the Pluggable Authentication Service (PAS) # # Remark:The PAS Modul sapextauth must be included in ~xgateways in global.srvc # There are following types for PAS on ITS: # # X509 --> ITS 4.6D # NTLM --> ITS 4.6D # NTPassword --> ITS 4.6D # LDAP --> ITS 6.10 (remark also note: 509237) # HTTP --> ITS 4.6D (see note: 493107 and 494984) # # The following settings are an example for NTLM : # For detailed information see documentation (http://service.sap.com/security) ############################################################################### ~theme 99 ############################################################################### # Module ~xgateway sapextauth # possible settings -> X509 , NTLM , NTPassword , LDAP , HTTP ~extauthtype NTLM # For NTLM and NTPassword: NT , for LDAP: LD , for HTTP: define your # own mapping in USREXTID # Remark: extid_type UN (user name) can also be set. Then you dont have to # map in USREXTID, but the authentication mechanism must provide the unique # SAP System user ID. This might be useful for LDAP and/or HTTP mechanism. ~extid_type NT # ############################################################################### # predefine Domainname - only for type NTPassword ~ntdomain # ############################################################################### # for LDAP connect - only for type LDAP #~ldaphost ldap.sap.com ~ldaphost #~ldapport 389 ~ldapport #~ldapbasedn //Base DN ~ldapbasedn #~ldapuid //User Attribute Name e.g. cn ~ldapuid #~ldapsapuid //SAP User Attribute Name e.g. sapuid ~ldapsapuid # Remark: ~ldapsapuid should be only set in combination with ~extid_type UN #~maxtrials 3 //limits the ldap logon trails ~maxtrials # ############################################################################### # define which HTTP Header Variable contain the User - only for type HTTP #~remote_user_alias - the most common and useful value is REMOTE_USER # which will be set by webservers for authenticated users # please remark here note 494984 for the WGate settings ~remote_user_alias # ############################################################################### # settings for PAS service self ~client 088 ~language en #get a SSO2 Ticket ~mysapcomgetsso2cookie 1 ~timeout 10 #converts the login input to upper case. Might useful for LDAP and NTPassword #if in doubt, set to 1 and maintain USREXTID mapping in caps. ~login_to_upcase 1 # ############################################################################### # after external authentication # Hostname which should redirected ~redirectHost kww-d15s.kimball.com # path to another service ~redirectPath /sap/bc/bsp/sap/zeq_eqi_2003/default.htm #~redirectQS (Query String): ITS specific service parameters can be set there ~redirectQS ~redirectHttps 0 ~login_template login # if 1, user get only a ticket, if there is no ~dont_recreate_ticket 1 # ############################################################################### ~sncNameR3 p:SAPServiceD15@kii.kimball.com #~sncQoPR3 9 ~mysapcomusesso2cookie 1 ~mysapcomnosso1cookie 0 ~mysapcomssonoits 1


Closing
I realize that this weblog was a little different from my past ones. There wasn't even a single line of ABAP code in it! It also was a little heavy on the system setup side. I hope that I haven't scared anyone off. Next time we will step back into the ABAP world a little more as we talk about Trusted RFC. I will warn you though this one is still heavy in system setup as well. If that isn't your particular interest then, I promise I will get back to development with Part 10 - IGS Charting.

Introduction
When I first started working for my current employer, Kimball International, nearly a decade ago; I can't say that our operations
were all that international. We did have a showroom in Canada and a production facility right inside the Mexico/Texas border.
During these years however, I have seen our global footprint really grow. Today we have very active operations in Poland and
Thailand in addition to our North American ones. As much as we would like to think that our business language is English, there
is always a need for applications and information in the local language.

Background
If you remember back to one of my very first weblogs, the multi-language capabilities of BSP and the WebAS were one of the
deciding factors in our decision to go with this technology. Our R/3 system is currently setup as a MDMP system. This is a SAP
technology that allows our system to operate in multiple code pages without the use of Unicode. The application server sets your
code page when you logon and it is set for your entire session. This way the user interface can be translated (SAP provides various
levels of translation for different languages) to be displayed in the local language. This also allows for limited data input in the local
language. However any field in SAP that is not language keyed should only contain USASCII7 characters. If you are interested in MDMP
I suggest that you check out http://service.sap.com/globalization. You get English and German delivered in a SAP system standard.
We have also installed and configured Polish, Spanish and Thai. English, German, and Spanish all share the ISO-8859-1 Latin-1 code page.
Polish resides in the ISO-8859-2 Latin-2 code page. Thai has its own unique code page ISO-988/2533. We have setup all the matching
configuration in our WebAS so that we use MDMP and all listed languages.



Simple Translation
First of all you have all the translation capabilities that can be found in your R/3 system. You can create text elements, language dependent
texts, data dictionary descriptions, etc. You then can use the same tools that you do in R/3 to translate these items (SE63). I'm not going to
cover the tools that can be found in R/3 as well. There is plenty of documentation in the R/3 system on this. However when working with BSP
you have an additional translation tool - OTR. OTR or Online Text Repository is a tool that allows for translation inside your HTML code. You simply
surround your text with the OTR tag. This text will then be exposed for translation.


<!code><htmlb:textView design="HEADER2" >

<!code>  

<!code>


You then can translate this in the OTR tool. The following is screen shot of this tool:


!https://weblogs.sdn.sap.com/weblogs/images/1918/OTR1.jpg|height=393|alt=image|width=579|src=https://weblogs.sdn.sap.com/weblogs/images/1918/OTR1.jpg|border=0!

The following is example of this same text displayed in English and Spanish:
!https://weblogs.sdn.sap.com/weblogs/images/1918/OTR2.jpg|height=67|alt=image|width=254|src=https://weblogs.sdn.sap.com/weblogs/images/1918/OTR2.jpg|border=0! &nbsp image

 



Field Labels
OTR tags are great for user interface elements like tab strips, buttons, and content areas but let's move on to field labels. Just like
in regular ABAP, there are lots of ways to reuse the data dictionary element descriptions for these field labels. The first way to do
this is to use MVC and allow the data binding to automatically fill in the field label for you. This works if the data dictionary element
for the field you are referencing exists in the WebAS. In this example we will have a user selection for Plant (WERKS). The following is
the code we place in our View:


<!code><htmlb:label for      = "//model/WERKS"

<!code>      required = "TRUE" />

<!code>

<!code><htmlb:dropdownListBox id = "mq_werks"

<!code>         table = "//model/WERKS_VALUES"

<!code>     selection = "//model/WERKS"

<!code>nameOfKeyColumn = "key"

<!code>nameOfValueColumn = "value" />


By using Model View binding, the Model class will do all the work for you. It will lookup the description for the field referenced, in the current logon language.



The Model View binding works great - as long as the data dictionary element exists in the WebAS. However often we find ourselves
reading data from R/3 where that isn't the case. We could recreate all the data dictionary elements and all their translations in the WebAS,
but that would be a lot of work. Instead we created an RFC that allows us to read the description from R/3. I usually just add another
element to my model class that will hold the description. Then in the initialization of the model I make the call to R/3 to pre-fetch all my
descriptions. The following is the code in the function module that reads the descriptions:


"----


"

*"Local interface:

*"  IMPORTING

*"     VALUE(ROLLNAME) TYPE  ROLLNAME

*"     VALUE(LANGUAGE) TYPE  SY-LANGU DEFAULT SY-LANGU

*"  EXPORTING

*"     VALUE(DDTEXT) TYPE  SCRTEXT_M

*"----


clear ddtext. 

select single scrtext_m        

  from dd04t        

  into ddtext       

where rollname   = rollname

   and ddlanguage = language

   and as4local   = 'A'.

  if sy-subrc ne 0 or

     ddtext is initial.

    select single scrtext_m

         from dd04t

         into ddtext

        where rollname   = rollname

          and ddlanguage = 'E'

          and as4local   = 'A'.

  endif.


You can see that if the description is missing in the logon language we fall back to our business default language of English.



Data from Mixed Code Pages
We have talked about multi-language and translations issues for the user interface, but that only takes us half way.
Now let's talk about displaying data from multiple languages. In R/3 46C, with MDMP, you can only display one set of
code pages at a time. That means that there is no way to show Thai and Polish text together on the same screen.
Even though the WebAS may not be setup as Unicode, the ICM can return Unicode encoded data to your browser.
You can use this functionality to accomplish what 46C can't. The following screen shows data from R/3 on the same
web page encoded in Unicode but from multiple source code pages:

 

image

 


Unless you can read Polish and Thai, I guess you will have to take me on my word that this is displaying properly.



Lets talk in a little more detail about how you can accomplish this. First I mentioned earlier that the application server
sets your code page when you logon. However every time you execute an RFC you really logon on new. Using this
functionality you can setup separate RFC destinations for the same system with different logon languages.
By calling these different RFC destinations, you can in fact switch from code page to code page. So now we are logged
onto R/3 in the code page of the language we want to read data from. In order to get the data back to the WebAS
without corrupting it, we need to cast the character string into a binary string. The following is some example code
that will read a document info record description and do the binary cast:


"----


"

*"Local interface:

*"  EXPORTING

*"     VALUE(O_XSTRING) TYPE  XSTRING

*"----


  data: dktxt type dktxt.

  select single dktxt from drat into dktxt

          where dokar = 'ISS'           

            and doknr = '0000000010000000000002195'

            and dokvr = '00'

            and doktl = '000'

            and langu = sy-langu.

  field-symbols:   The next weblog in this series will take a close look at User Authentication - specifically how we setup Single Sign On in our WebAS Environment.  

*Introduction*  We were now well on our way. We had several BSP applications in Production. We were beginning to feel like we actually knew what we were doing. Therefore we decided that it was time for a little self-promoting. We had talked about creating a website for our ABAP development team for quite some time but had never gotten around to it. It seemed only appropriate that our home page be developed in BSP.     In addition to a site that stored our documentation and was useful to the implementation team, we wanted something that we could use to show off what we could do. We wanted something that would convince our group's internal customers that their next website just had to be developed in BSP. What we ended up with looks like the following (Please note that the image was considerable reduced in quality to fit into this weblog): image  We tried to include any of BSP Extensions that we though would catch the user's eye. We used trees, tables, collapsible areas, tab strips, etc.     *BSP Extension Details*  Before I jump in and staring showing the insides of this website I wanted to talk about a few of the things we learned about the BSP Extension Libraries.   1. New functionality is delivered with new support packages. Those of us use to ABAP might be a little surprised by this. We are used to having to wait until major releases to any new functionality. However we have seen significant enhancements to the BSP Extensions over the support package life cycle on release 620. We started out at about Support Package 7 and are now at 35.  2. With new functionality come new bugs and incompatible changes. I do have to say that this was much more a problem in the early support packages. The last two support package applications we have done we did complete regression testing and didn't have any broken applications. However earlier in our implementation we weren't quite as lucky.   3. SAP has delivered whole new BSP Extension libraries. I can't believer the number of developers that I have spoken with that don't even know the other libraries exist. If you are only using HTMLB you are missing out on the great new functionality in XHMTLB and PHTMLB. Do have a look at OSS note 598860 to see requirements for each Extension library however. Whereas HTMLB is supported with in Classic, Design2002, and Design2003; XHMTLB only support Design2002 and Design2003. Furthermore PHTML only supports Design2003.  3. There are different Designs that can be set using the CONTENT HTMLB tag. These Designs have more than just an impact on how our webpage looks. They also affect compatibility and performance. We saw nice performance increases on web sites once we converted from Design2002 to Design2003. The following are the browser requirements for each Design:  Classic: IE>=5.01 and Netscape>=6.20  Design2002: IE>=5.50 and Netscape>=6.20  Design2003: IE>=5.50 and Netscape>=7.00  Also if you use SAP's Enterprise Portal with your BSP applications, you will want to be aware of the relationship between design and EP release. Have a look at OSS Note 597914 for the details, but basically EP5 supports Design2002 and EP6 supports Design2003 or Design2002.    *Header Design*  As we were building our ABAP home page, we were also beginning to develop a style for our websites. This revolved heavily around the use of the BSP Extensions, but also came from the use of one common page header for all applications. We wanted this header to provide lots of useful functions, but also a unifying factor amongst our applications. Since we weren't yet implementing SAP's Enterprise Portal, this page header became a poor-man's portal of sorts.     After studying some of SAP's sample applications we decided that we liked something similar to the page headers they were using in the SBSP* examples. We decided to borrow their design for our starting point (after all a good programmer never starts from scratch :). The following is what our finished product ended up looking like (compressed in width to fit into the weblog): image   Well we didn't want to include the coding for this page header directly into each application. This seemed the perfect opportunity for our first customer bsp extension. We started by reading some of the on-line help. Next we looked at some of the many extensions provided by SAP. Thank goodness SAP delivers the ABAP source code to the customer. I'm not sure we would have had much success without these examples to start from. We looked at some of the smaller, simpler HTMLB extension such as the LABEL or in the INPUT FIELD.     As it turns out the process of creating the custom extension was surprisingly easy. I would suggest that you start by building your extension as a regular BSP page. From there you can translate the implementation of this page into the BSP Extension Class. The only tricky part might be not having something similar to the VIEW to enter any BSP Elements you are going to use in your Extension. Once again I was surprised at how easy this was. From ABAP you can work with any of the SAP BSP Element's directly via their classes. The best way to explain this is just to look at some sample code.       data: label type ref to cl_htmlb_label.  label ?= cl_htmlb_label=>factory( for = 'Spras'  text = lang_desc ).    These two simple lines of code are all you need to create a label. Now we will send this label to the HTML Writer.    while m_page_context->element_process( element = label ) = co_element_continue.  endwhile.    Here is also a little more complex example. This is drop down list box. It shows you how to pass a pointer to a table into the BSP Element.     data: drop_down type ref to cl_htmlb_dropdownlistbox.  data: selection type string.  move sy-langu to selection.  drop_down ?= cl_htmlb_dropdownlistbox=>factory(  id = 'Spras'  selection = selection  onselect = 'HandleLangSubmit'  onclientselect = clientclick  nameofkeycolumn = 'key'  nameofvaluecolumn = 'value' ).   get reference of languages into drop_down->table.  while m_page_context->element_process( element = drop_down ) = co_element_continue.  endwhile.      *Language* image Let's look at the functions of our Extension one at a time. First up is the language selection. We operate in a multi-language environment at our company. Although BSP can pickup the language from our browser settings or via the URL, we wanted an easier way to switch languages on the fly - especially when testing applications. In this drop down we also only wanted to list the languages actually installed in our system. The following is the code we used to grab the installed languages:    select t002t~sprsl t002t~sptxt        into     (ls_t002t-sprsl, ls_t002t-sptxt)        from     t002t        join     t002c        on       t002t~sprsl = t002c~spras        where    t002t~spras = sy-langu        and      t002c~lainst = 'X'        order by t002t~sptxt.     clear wa_line.     move ls_t002t-sprsl to wa_line-key.     move ls_t002t-sptxt to wa_line-value.     append wa_line to languages.   endselect.   If the user chooses a new language we activate the change by reloaded the page and adding the sap-language URL parameter.   if htmlb_event->server_event eq 'HandleLangSubmit'.  concatenate url  '?sap-language='  s_spras  into url.   navigation->exit( url ).  endif.      *Themes* image Next up is the Theme. Starting with Design2003, SAP offers several visual themes. If you are running in the Enterprise Portal, these themes will be inherited from the portal user settings. However we wanted the user to be able to set their own themes. We also wanted this setting to carry over from one BSP application to another. We simply record the current theme into a customer table by user and reload the setting with each application load. You can use the runtime object to read or set the BSP theme from ABAP:    *Set the Theme mc_runtime->set_external_theme_root( selection ).  *Read the Theme  selection = mc_runtime->get_external_theme_root( ).      *With Accessibility*  Next up we have a simple little check box that allows you to turn on Visual Accessibility. We don't have a business requirement for this right now so it is mostly in there for testing purposes. Once again you can use the runtime object to query for this flag.    s_accessibility = mc_runtime->with_accessibility( ).      *User Settings* image If you remember, we are running on a stand-alone WebAS. Therefore when a user changes their personalization options in R/3 those changes are not made in the WebAS. When we first went live we had user's who couldn't understand why their date or number format wasn't correct on the web page output. We added this link to launch SU3 via the ITS WebGui for the WebAS. This way the users can change their settings without needing any SAPGui access to the stand-alone WebAS.    *System Information* image Next we wanted an area that shows system information in a popup when you click on the displayed system id. This area is similar to the popup in the bottom right hand corner of your SAPGui. However we set this up to not necessarily show the system information of the WebAS. If the application uses a remote R/3 system, this was the information we wanted to show here. This information has proven to be very valuable in troubleshooting user problems, especially security issues.    *System Messages* image
One of those days...
Ever just have one of those days. You come into work, ready to get started on the day's development. You've got a nice cup of coffee, maybe even a donut (or whatever your regional breakfast drink and food of choice is). The next thing you know your phone is ringing. It's your Basis group on the line letting you know that one of YOUR programs is creating short dumps in THEIR system. OK, its probably user error. You log in and have a look at ST22. 300 dumps, 50 different users - probably not user error.

Who made the change?
So you have a look at the BSP application that is having the problem. According to version management it hasn't changed in over 4 months. The problem has to do with an invalid parameter on a call to an RFC. But wait, the RFC hasn't been changed in over 4 months either. It turns out that someone added a field to the end of a structure that was being used in a table type in one of the exporting parameters of the RFC. Everything tested fine with the programs and RFCs in R/3 because all the objects shared the same table type definition. Unfortunetly no one told the stand alone WebAS about this change. This turned out to be an easy fix - just adjust the definition of the parameter that had originally been generated by the BAPI Browser (See Last Weblog if you are confused by the term BAPI Browser). However I wanted to find some way to avoid this problem in the future. Next time it happens it might not be the morning, but rather the middle of the night when the problem occurs.

XML to the Rescue
The idea we came up with was to use XML. Instead of predefined interface parameters, we would just return an XML stream on the RFC. The calling program could then deserialze the XML and pick out the data it wanted. More than one program could share the same XML interface. They could add addtional fields without fear of breaking any other calling programs. The following is what the XML call itself looks like:
data: i_xml type xstring. call function 'Z_E_RFC_GET_PERSON_TRAIN' destination rfcdest exporting uname = wa_itab-uname importing xml = i_xml exceptions others = 1.


Example Application
Let's look at this example in more detail. You can probably get an idea of what we are doing by looking at this function call alone. We want to take a user id and look up all the HR Personnel and Training information for this user and display it to them on a BSP page. This was actually the RFC call that caused the original problem. Someone had added a new field from HR that wasn't used in this BSP page but was needed elsewhere.

Creating the XML
First let's examine the ABAP code in R/3 that we will use to create the XML stream. First we looked at what SAP had to offer for working with XML. What you are going to want to look at is everything in the SIXML development class. (I should note that this code is all based upon a 46C system. I'm not sure that the iXML class libraries that contain the basic serialization functionality are available before 46C.) In this development class you will find all the interfaces, classes, and example programs you will need to get started.
We start the processing by creating a pointer to the XML library and creating an empty XML document:
* create document ixml = cl_ixml=>create( ). document = ixml->create_document( ).

Next we are ready to create a new element in our XML document:
data: jobs_element type ref to if_ixml_element. call method document->create_element exporting name = 'JOBS' receiving rval = jobs_element. call method document->append_child exporting new_child = jobs_element.

Now that we have an element you can create some attributes of this element:
clear value. move jobs_line-objid to value. call method jobs_element->set_attribute exporting name = 'OBJID' value = value.

Next we can serialize the data. Because the serialization is performed by the Kernel and not in ABAP you have the option of choosing UTF-8 or Unicode as your output format even on a non-Unicode system. The data will be passed back to ABAP as a byte stream so the Unicode format will be maintained. This is what serialization logic looks like:
* write data into string data: s_encoding_type type string. streamfactory = ixml->create_stream_factory( ). s_encoding_type = encoding_type. encoding = ixml->create_encoding( character_set = s_encoding_type byte_order = 0 ).

Now we will give SAP a pointer to the output area for the serialized data. In this case it is a variable called b_xml. This is a variable defined as a XString (Byte String):
ostream = streamfactory->create_ostream_xstring( b_xml ).

Finally we tell SAP that we are ready to render the XML into the output area:
call method ostream->set_encoding exporting encoding = encoding. call method document->render exporting ostream = ostream recursive = 'X'. ressize = ostream->get_num_written_raw( ).

Here is a little sample of what the human readable version of the XML would look like:
image

Consuming the XML
Well we have our XML data as a byte string and we have passed that byte string back to our BSP application. Now why don't we have a look at how this XML string can be turned back into something a little more usable in ABAP.
First we have a few useful data declarations:
data: i_xml type xstring. data: ixml type ref to if_ixml. data: document type ref to if_ixml_document. data: streamfactory type ref to if_ixml_stream_factory. data: istream type ref to if_ixml_istream. data: parser type ref to if_ixml_parser. data: element type ref to if_ixml_element.


Just like in the outbound example we will start by creating a instance of the XML factory class and a XML Document:
*-- create the main factory ixml = cl_ixml=>create( ). *-- create the initial document document = ixml->create_document( ).

Next we will take that byte stream that we received and feed it into the XML parser:
streamfactory = ixml->create_stream_factory( ). istream = streamfactory->create_istream_xstring( i_xml ).

Now we can tell SAP to parse the XML:
parser = ixml->create_parser( stream_factory = streamfactory istream = istream document = document ). parser->parse( ).


With the parsing done, we can go back through the document and pull out the pieces of data that we are interested in.
element = document->get_root_element( ). fname = element->get_attribute( name = 'VORNA' ).


Are we there yet?
Now you may be saying to yourself that this was a lot of work. The code samples can be a little overwhelming at first, I admit. Believe me that boiling them down for presentation in the weblog format was quite a challenge. I hope that these sample explanations have been helpful. I can tell you that the best way to learn it is to do it. After a little programming time with the XML interface it really becomes quite simple. Not only is this tool a solution to the problem put forth in the weblog, but is useful to know in other instances. With this you can parse XML from many different external sources. You will also see later when we discuss the IGS Charting, that XML processing in ABAP is quite important. The other thing that I should mention is that XML is perfect for passing hierarchical data(like HR data). This way you avoid multiple tables that need to be linked up or complex table types. As you process through your deserialized data you have the perfect opportunity to build a tree control from the data using the XML structure itself to control parent/child relationships.

Look Ahead
For those of you who may feel that this weblog was a little light on actual BSP, just wait. The next edition of this weblog will dive right into the deep end as we take apart a productive BSP application, looking especially at custom BSP Extensions. It should be lots of fun!

Well we are off and developing now. The first problem we obviously encountered is the fact that our WebAS is a separate system from R/3. Writing our applications isn't going to as easy as just coding some SQL. But as you will see, they aren't going to be that much more complicated either.

RFCs
Having been around the SAP Universe for a few years, the idea of calling a SAP function module remotely (or RFC) wasn't a new topic at all. I would imagine that most ABAPers know about the magic radio button labeled Remote-enabled module on the Function Builder Attributes tab. This wonderful option is about all it takes to expose your function to any tool capable of communicating with SAP. The only other thing to keep in mind is to mark all your parameters as Pass by Value. Even at that you don't have to remember. The editor will yell at you if you forget. Also keep in mind that what SAP calls a BAPI is really just an RFC. BAPIs are linked to a business object and usually have additional documentation, but from a technical standpoint they are just plain RFCs.

Example Call
RFCs are incredibly easy to call from ABAP. All you have to do is add the Destination parameter to the call. For anyone who might never have seen an RFC in use here you go:
call function 'Z_E_RFC_FIELD_DESCRIPTINS' destination 'DEV' exporting rollname = 'CVFLAG' language = sy-langu importing ddtext = currv_desc.
Wow this is all so incredibly easy. What in the world am I going to write about? Wait - don't worry. It doesn't take long to run into the first problem.

First Problem
It is easy to call an RFC from within an R/3 system. You will have all the data elements and structures necessary to define the importing and exporting parameters. Oops - I knew we were missing something! Our standalone WebAS didn't have most of these same data elements and structures since it was the technology stack only. And it certainly didn't have any customer created elements unless we copied them over to the WebAS. Of course we could always create all the missing elements by hand, but as developers we have a long tradition of work avoidance to live up to. It would be great if SAP had a tool that would read the exporting/importing parameters on an RFC and generate the necessary data statements for us.

BAPI Browser
Well we were in luck. There is just such a tool. It is called the BAPI Browser.
image
This great little tool can be accessed from within SE80. If you are editing a BSP application and are in a Page or View, you can launch the BAPI Browser from the menu via Goto -> Bapi Browser or Ctrl+Shift+F1. You can then browse though a list of BAPIs for an RFC destination (hence the name) or do a Direct Entry search for any RFC enabled function. As you can see from my screen shot you get all the data declarations you need in addition to a sample call of the function module. The main draw back is that if the function interface changes, you have to rerun the BAPI Browser and change the declarations manually. In my next weblog I will discuss using XML to get around this little problem. Also if anyone from SAP is reading this, I have a suggestion for the BAPI Browser: I would like to be able to launch it from anywhere in SE80, not just BSP coding. Quite often I am coding inside a Model or Application class and that is where I need to call my BAPI. However I have to switch back to a BSP View or Page to activate the tool.

Elements Delivered
I should note that SAP actually delivered a lot of the most important data elements with one of the early support packages. Even though this is a technology system only, you can now find such elements as MATNR (Material Number) and WERKS_D (plant) just to name a few. This makes your work easier but there are still plenty of elements missing in order to need the BAPI Browser.

System Exceptions
Now that we are off and calling our RFCs everything is fine, right. Well until the calling system isn't available, or the RFC destination is setup wrong, or the user isn't authorized for the activity, or any other of a number of things that might go wrong. Normally these activities will create a nice short dump. However from a BSP page, the short dump doesn't really make for the best user experience. Wouldn't it be nice to be able to catch all of these System-type exceptions? Well you can. Just look at the following example.
data: msg_text(80) type c. call function 'Z_E_RFC_QUERY_UG_AUTH_CHECK' destination rfcdest exceptions communication_failure = 1 message msg_text system_failure = 2 message msg_text not_authorized = 3.

As you can see here I have added two special exceptions that aren't implicitly declared by the function itself. COMMUNICATION_FAILURE and SYSTEM_FAILURE are two exceptions that are automatically available to any function that is being called remotely. All of the types of problems I mentioned before will be trapped by these exceptions. The details of the error will be placed into a variable that you declare. In my example this is msg_test. I find that it is better to stop processing but display the details from this message back to the user rather than show the generate message.

Dynamic Selection of Destinations
I have just one final learning that I wanted to share before I close out this weblog. Overtime we found that it was becoming a maintenance nightmare to maintain RFC Destinations. You either end up creating a RFC destination for each application in each system or you end up hard coding destinations. Neither option ends up being very flexible. We decided to create a table where we could hold the name of the function module and the associated RFC destination. This way we could easily have different destinations maintained in each system in our landscape. The following is what our usual RFC call actually looks like:
select single rfcdest from zes_rfc_dest into rfcdest where name = 'Z_E_RFC_DOC_SEARCH'. call function 'Z_E_RFC_DOC_SEARCH' destination rfcdest exceptions communication_failure = 1 message msg_text system_failure = 2 message msg_text not_authorized = 3.


Closing
I hope that everyone enjoyed this first look at RFCs. As I have already hinted, my next weblog will still look at RFC and how we can use XML with them.

Recap
To recap from the last weblog, we were just at the point where we were ready to start doing some real development in BSP. We had the tools, the servers, and the support from management. All we needed now was developers that knew how to use the tools.

Getting Started
You have to remember that at this point, there was no SDN. There were also no books published on the subject. We had some experiences and presentations from SAP conferences. However what you pick up from a conference is often just a good introduction to a subject. Quite often you need something more substantial to really get developing production applications. We also checked out what SAP offered as far as formal training. We did send one developer to the only class that SAP offered at the time. It was a course on 610. Although a good introduction, we really wanted to write MVC (Model-View-Controller) application with the HTMLB libraries(BSP Extensions). Since all this functionality was in 620, it wasn't covered in the class.

We soon realized we were somewhat on our own. The decision was that one developer would try to learn as much as possible by studying the release notes, on-line help, and the samples in the system. This one developer would then hold a training course for the other developers in our group.

Training Course
I began my research for the course by looking at every SAP provided BSP application in our system. I set breakpoints and debugged to see how they flowed. I copied some of them so that I could make changes and see what happened. Of particular helpfulness were the sample applications that began with IT* (IT01 - IT05 and ITMVC) and the ones that begin with SBSPEXT* (IE: SBSPEXT_HTMLB). Overall I learned a lot from these existing applications.

Delta Training
As I sat down to write the training materials I realized something: there is a lot of new functionality in ABAP going from 46C to 620 in addition to BSP. My training was slowly changing from BSP specific to ABAP Delta Training. To give you an idea of what the final training looked like I have included the Table of Contents from the course:
Unit 1 SE80 in 620
Unit 2 New Basic Syntax
Unit 3 Object Orientation Extensions
Unit 4 New Exception Handling
Unit 5 Java Script
Unit 6 XML Processing
Unit 7 Sending E-Mail
Unit 8 BSP (General)
Unit 9 BSP (Custom Tags)
As you can see, BSP ended up only being about 1 day of our 3 day training course.

Training Today
Overall I think we did the best that we could with the information we had to work with. Our developers were off to a better start than if they all had to do the research on their own. If we were starting today we would do the same, but we would have additional resources. Now we have SDN. Between the weblogs and the forums, there are plenty of new learning opportunities every day. I would look especially at any of the weblogs authored by Brian McKellar. There is also a nice introductory book that can be found on the SAP-Press website.

First Applications
With our training in hand we were now ready to start developing our first two real business applications in BSP. One was going to be an Exchange Rate website and the other was going to be an Engineering Change website. Something very interesting happened as we started these two applications. We assigned two different developers to each application. These two developers had very different backgrounds and therefore the finished applications ended up looking very different.

I was one of the two developers. My background was heavily ABAP with almost no outside web development experience. The other developer was a traditional web developer with a background in ASP and ColdFusion, but very new to ABAP.

Developer Differences
The developer with the web background had a harder time separating this presentation and application logic using MVC because he was used to mixing them in ASP. I found myself liking MVC because it allowed me to program web applications very similar to the way I would program a dynpro. Also I was already using Global ABAP classes for my application logic in 46C dynpros.

JavaScript
The other big difference was the use of JavaScipt. Our developer with the web background was used to coding lots of JavaScript into his application. He would do almost all validation on the front end with JavaScript and lots of hidden fields. He also didn't use as many of the BSP Extensions (HTMLB tags). He was used to using his own style sheets and the native controls. On the other hand I had almost no JavaScript in my web pages.

Although it was true that I really didn't know much JavaScript, I never felt that I was missing anything. I found that by using the BSP Extensions that I just didn't need a lot of JavaScript. I relied on the functionality provided by the BSP Extensions. This kept me from having to come up with a look and feel for my BSP application (which is a good thing since I am hardly an artist or a designer). It was provided by the BSP Extension.

Validation
I also found myself doing most of the validation on the Server where I could use ABAP. Even with the additional round trips to the server for validation, both websites had similar response times to the users. Actually we found that on some pages, a application with lots of client side JavaScript would execute quite slowly on older machines, whereas we got fairly consistent performance from a application with Server side validation.

Advantages
Over the past year we have seen that the use of the BSP Extensions has paid off. With newer support packages, SAP has enhanced the code within these Extensions. I will cover the functionality we found in these extensions in more detail in Part VI. Over time we saw that rendering performance increased and the visual look of the extensions got better with the introduction of new Designs and Themes. The applications that were developed using these Extensions are able to take advantage of these new features with little or no coding changes. The users also appreciated the common user interface that begins to form via the use of the extensions. What they learn from the use of one website can be reused in others.

ABAPers and BSP
People usually look at me funny when I say this; but I think that developers with a good solid background in SAP and ABAP will have an easier time developing with BSP than a traditional web developer. The concepts used in BSP web development match well with those of traditional ABAP development. I think BSP feels like the natural progression of ABAP. Combine that with the fact that you are quite often accessing and building addtional business logic using ABAP in the backend, and your ABAP developers should right at home.

Outlook
For all you code-junkies, I promise a fix in the next edition of this weblog. I will have at least a small amount of sample code. We will talk about RFCs and the BAPI Browser.

Example
As I close today I will leave you with a screen shot of our first 'Productive' BSP application. In the winter of 2002, most of our team was in Thailand for our R/3 implementation. Although it was hot enough to fry an egg on the sidewalk in Thailand, it was snowing back home in Indiana. To make our team feel a little more connected to home, we created a website that they could go to in order to get pictures of home. Actually we used the SAP Content and Cache Server to store the documents so that they could retrieve them quickly (but the details on that would be a story for another WebLog).

image

Welcome back to the BSP Developer's Journal.  In this part we will take a look at the process we went through to get our system environment setup.

Budget Blues
Well we had our development group convinced that we wanted to give BSP development a try, now all we had to do is convince management to give us some money to go forward. If your corporation is anything like ours, you know that this can be quite a chore. No one wants to give you money until you can prove the business benefits. However it is difficult to research and demonstrate these benefits without first spending some money on at least a sandbox environment. Our approach was to build a sandbox but not tell anyone about it. We found a small server that was well past the end of its useful life. We affectionately referred to this server as The Heater. On a cold day you could warm your hands by the heat coming off this old workhorse. We secretly installed WebAS 610 not even telling our Basis group about the new system.

We began the process of learning about BSP by building several simple applications. It didn't take too long to convince us that this was the approach that we wanted to take; however going to management and asking them to spend money to just provide us with a better development tool wasn't going to get us anywhere. We needed something that would really catch the business's attention. Our company is a global operation with facilities in North America, Asia, and Europe. Our R/3 system is a MDMP system (a technology that allows you to operate a SAP system in multiple code pages without Unicode). We were beginning to face the challenge of creating web applications that operate as well in multiple languages as R/3 does. We decided that this was the business angle that we were going to use.

 

Multi-language is the key
We configured our WebAS as MDMP and installed Spanish, Thai, and Polish into it. We prepared several sample applications that ran in multiple languages. We demonstrated how we could pull descriptions from R/3. We also showed how easy it was to translate the user interface using the tools we were already familiar with from R/3. We also demonstrated the use of multiple language versions of Mimes and the use of OTR tags. We didn't even realize that this was just the beginning of the functionality the WebAS offered for multiple languages. Part VII of this weblog will dive into this subject in greater detail. Management was impressed and we finally received our official go-ahead.

Choosing a Platform
Now we faced the challenge of moving forward with the project and choosing a platform. Our R/3 system was 4.6C. Even if R/3 Enterprise, with its built in 620 WebAS, had been available at the time, we wouldn't have been considering an upgrade. We wanted to complete our R/3 rollout to all of our facilities before we did any upgrades to R/3. Our only option was to build a separate landscape for stand alone WebAS. I don't know how many people realize that you can run just the technology layer of SAP, otherwise know as the WebAS. This allowed us to advance our SAP Technology while remaining on the same release of R/3. We would still execute all our application logic in R/3. We would just access it from the WebAS via RFC.

Unfortunately people within our company didn't fully realize the difference between a R/3 system and a Standalone WebAS. Their first impression was that we would run our WebAS on the same platform as our R/3 - HP-UX and Oracle. The original spec had us running on a huge system with 32gigs of memory and a 1/2 a terabyte of disk space. Although most tech folks would love to have a system that powerful for their web server, it just isn't necessary for the standalone WebAS. The first thing to understand is that although the WebAS still has a database, it just isn't as large nor does it grow like a R/3 system. Because your application data is still over in R/3, the WebAS database really just has to store your Object Repository. Initially our Production WebAS's database was just a little over 6Gig. After more than a year and a half in production, it has only grown to 9Gig.

Now I'm not wanting to start a argument on who's operating system is best (although Operating System Holy Wars can be interesting to observer), but we did end up choosing windows/MSSQL for our platform. Given the standards within our company and the experience we had in house for support, this platform provided the best price/performance point for us. The only other database we considered was SAP's own database, SAPDB or as it is now known MaxDB. We could have saved money on licensing with this option, but we just didn't feel like we had the experience in house to properly support the platform.

We ended up with dual 2.8GHz CPU servers with 4 Gigs of memory. With nearly 1000 named users and 50 or so simultaneous connections at any time, the Production server hardly ever breaks a sweat. We have been able to scale the servers a bit by adding more work processes as more and more applications are rolled out. We still have plenty of overhead within our 4 Gigs of memory to add more as we grow. We have certainly seen that the number of users has a direct correlation to the amount of memory needed and we have been able to plan for our growth accordingly.

Transports
We decided to setup our WebAS Transport structure separately from our R/3 one. Originally we made this decision to keep the landscape setup as simple as possible. We also didn't want to do anything to disrupt our running R/3 environment. If there is some code that needs to exist in both landscapes, we simply copy the Transport file from our Unix R/3 transport directory to our Windows WebAS Transport directory. The other thing that this allows us to do is let the developers do their own transports (even to Production). In R/3, for control and separation of duties, the developers of course can not do their own transports. However because the WebAS doesn't contain the application logic, we have less restrictive standards. We even setup TMS workflow to make the process very simple and fast.

We did make one mistake in the original system setup. Unlike our R/3 landscape where we have a Sandbox, Development, Quality, Training, and Production instances, we only created a Development and Production WebAS. In the beginning this appeared to make sense in order to save money. However as we became a victim of our own success, it became increasingly difficult to do development while testing was going on in the same system. We also began to be hurt by the fact that we didn't have any place to test patches and system maintenance before trying them in Development. About 9 months after our Production system went live we did end up adding both a Small Sandbox and a Quality system that exactly matches our Production Hardware. This also provides us a poor man's high availability. Because of the identical hardware we could simply swap the drives between the two servers in the case of a hardware failure.

Reunification
To make reintegration of R/3 and the WebAS a possibility someday, we have tried to plan ahead. We setup any new development class in both landscapes. We use a separate naming convention for any object in the WebAS that doesn't exist in R/3 as well. That way we hope to avoid any future conflicts. Someday we plan to upgrade R/3 and migrate some of the WebAS applications back over there. On the other hand, I don't necessarily see the stand alone WebAS going away. It is nice to have the separation of the two systems. We have much more freedom to upgrade and patch our WebAS without disturbing the business and causing retesting of all the R/3 business transactions.

Looking Ahead
Next week's weblog will detail the impact of implementing BSP had on our Development Team (We would never be the same again :) ). In case these weblogs have been a little too lacking in code samples, you should look forward to Part IV. In this part we will hit the code for the first time as we discuss RFCs and the BAPI Browser.

Filter Blog

By date:
By tag: