<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SAP Integration Experts - DataXstream &#187; SAP ABAP Blog</title>
	<atom:link href="http://www.dataxstream.com/category/sap-consultants-blog/sap-technical/sap-abap-blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dataxstream.com</link>
	<description>SAP Certified Consultants</description>
	<lastBuildDate>Sat, 24 Jul 2010 11:29:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Coming Soon: SAP .NET Connector (NCo) 3.0</title>
		<link>http://www.dataxstream.com/2010/07/sap-net-connector-nco-3-0-overview/</link>
		<comments>http://www.dataxstream.com/2010/07/sap-net-connector-nco-3-0-overview/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 13:40:15 +0000</pubDate>
		<dc:creator>Craig Stasila</dc:creator>
				<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Basis Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[Craig Stasila]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[NCo]]></category>
		<category><![CDATA[SAP .Net Connector]]></category>
		<category><![CDATA[Xstream Connector]]></category>
		<category><![CDATA[XstreamConnector]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=5499</guid>
		<description><![CDATA[SAP is announcing a new version of SAP Connector for Microsoft .NET 3.0 (now called &#8220;NCo 3.0&#8243;). A beta program for selected customers and partners is currently underway (Q3, 2010) with the general release of the software coming soon thereafter.  I will highlight some of the major differences between the SAP Connector for Microsoft .NET [...]]]></description>
			<content:encoded><![CDATA[<p>SAP is announcing a new version of SAP Connector for Microsoft .NET 3.0 (now called &#8220;NCo 3.0&#8243;). A beta program for selected customers and partners is currently underway (Q3, 2010) with the general release of the software coming soon thereafter.  I will highlight some of the major differences between the SAP Connector for Microsoft .NET 2.0 and NCo 3.0 (besides the obvious, and much-needed name-shortening).</p>
<div id="_mcePaste"><span id="more-5499"></span></div>
<h2>NCo 3.0 Logon</h2>
<div>Security got vital improvements in NCo 3.0.  The component handling logon and authentication was redesigned to thwart the following attacks:</div>
<div>
<ul>
<li>The unauthorized reading of sensitive logon data from the .NET configuration file (e.g. app.config).</li>
<li>The potential to create a malevolent application which replaces the customized logon data with it’s own logon data to obtain backend user sessions with different authorizations.</li>
<li>The potential to create a malevolent application which gains access to an open connection that was originally intended for a different application.</li>
</ul>
</div>
<p>One of the new features implemented to combat the malevolent for RFC client attacks is the interface <span style="font-family: Courier;">IDestinationConfiguration</span>.  This interface contains method <span style="font-family: Courier;">IDestinationConfiguration.GetParameters(string destinationName)</span> which allows .NET programmers to provide their own secure method for storing and retrieving logon information, be it encrypted database, encrypted file, or even LDAP.  There is also a corresponding interface and method to secure NCo 3.0 RFC servers.</p>
<p>Additionally, there is updated functionality to support single sign-on (SSO) and X.509 certificates.</p>
<h2>Say Goodbye to Data Containers and Generated Code</h2>
<p>In SAP Connector 2.0, working with RFCs required the generation of proxy code via the SAP .NET Connector design-time tool.  This tool would convert the IMPORTING, EXPORTING, CHANGING, and TABLES parameters from the RFC you were calling/serving to .NET representations of the same.  With NCo 3.0 there is no longer any kind of generated code.  Instead of one generated proxy method for each function module, there is one single <span style="font-family: Courier;">RfcFunction</span> class, whose <span style="font-family: Courier;">Invoke()</span> method dynamically executes every given ABAP function module.  Additionally, all ABAP parameters will be represented by the class <span style="font-family: Courier;">RfcStructure</span> instead of a dedicated generated class for every structure; All tables will be represented by class <span style="font-family: Courier;">RfcTable</span>.  So, instead of hard-coding all of the data and variable bindings statically at design time, NCo 3.0 now handles everything dynamically at runtime.</p>
<p>NCo 3.0 uses SAP&#8217;s data dictionary to determine the function interface for the called RFCs.  While this data is cached locally for performance reasons, NCo 3.0 is robust enough to detect changes in RFC interface signatures so your code will still execute if you&#8217;ve added, deleted, or changed RFC parameters.  If there arises a situation where the dynamic lookup of RFC interface signature is not wanted, there is also an option to hard code the RFC parameter metadata.</p>
<p>The biggest benefit of NCo 3.0&#8242;s new dynamic function handling is that NCo 3.0 no longer has a design-time component.  This releases the Visual Studio version restriction that .NET 2.0 had.  Let me rephrase that, <strong>NCo 3.0 will work with any version of Visual Studio you like!</strong> The only requirement is that at runtime, a .NET Framework version is installed that is compatible with the NCo 3.0 libraries.</p>
<h2>Anxiously Waiting</h2>
<p>NCo 3.0 figures to be a much-needed update to a vital SAP integration technology.  I, for one, cannot wait for the new functionality to be generally released.  Once NCo 3.0 is released we&#8217;ll be posting blogs highlighting the new features.  We&#8217;ll also include helpful information regarding a .NET Connector 2.0 to NCo 3.0 upgrade.  In the meantime, if you have any leave any questions or comments you have regarding NCo 3.0 below.  You may also email me directly at <a href="mailto:cstasila@dataxstream.com">cstasila@dataxstream.com</a> if you&#8217;d like to set up a detailed conversation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/07/sap-net-connector-nco-3-0-overview/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SAP Data Migration &#8211; Answering the Important Questions (Part 1)</title>
		<link>http://www.dataxstream.com/2010/07/sap-data-migration-and-data-conversion-1/</link>
		<comments>http://www.dataxstream.com/2010/07/sap-data-migration-and-data-conversion-1/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 14:00:20 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Project Management]]></category>
		<category><![CDATA[SAP Strategy]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[SAP Testing]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[Data Migration]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP programming]]></category>
		<category><![CDATA[SAP testing]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=5138</guid>
		<description><![CDATA[It is data migration time on your SAP business project.  Whether your project is implementation, acquisition, or merger, the goal is pretty much the same: the seamless inbound acquisition of master and transactional data from one or more external data sources while ensuring that this activity has minimal impact on the rest of the business.  [...]]]></description>
			<content:encoded><![CDATA[<p>It is data migration time on your SAP business project.  Whether your project is implementation, acquisition, or merger, the goal is pretty much the same: the seamless inbound acquisition of master and transactional data from one or more external data sources while ensuring that this activity has minimal impact on the rest of the business.  This is where we attempt to move years of neglected master and transactional data from a loosely structured, anything-goes legacy system into a very tightly integrated and highly structured SAP system.  You must consider the likelihood that the concept of master data management had not been invented yet when the legacy or source system providing your data was implemented.</p>
<p>How much data to move? How much data to leave behind? What to automate, and what to execute manually?  How to gracefully orchestrate and execute a data migration cutover from one system to another?  Where and how to fit the data migration plan into the overall business implementation plan?  How to continue to run the business during the data migration phase of the business project implementation? These questions are all part of the planning fun!</p>
<p><span id="more-5138"></span></p>
<h2>Data Migration Testing</h2>
<p>Processes that we have exercised and continue to exercise on a regular basis are no big deal, do not cause anxiety, or raise any blood pressures.  The daily report, the custom transaction, the interface that runs several hundred times a week – they are all second nature now.  They happen, and no one notices.</p>
<p>But reflect back to the very first time these processes went live.  This is precisely where you are with data migration.  For most, it is a once in a lifetime event.  It is important, then, to raise confidence levels, and reduce anxiety levels surrounding this activity.  This is achieved by practice, practice, practice.</p>
<p>Typically, I like to see at least three data migration test cycles executed in an isolated data migration client.  This allows for several attempts at exercising and fine-tuning the data migration plan; collecting nominal run time statistics to have some idea of how long the data migration might take; identifying and fixing any data migration program object defects; identifying and fixing any data mapping and content defects; and identifying and fixing any functional configuration issues. Each of these tasks are done with the goal of significantly improving the fallout rate with each data migration test cycle.  These data migration test cycles also give us the opportunity to practice our legacy extract skills, our fallout analysis skills, and our fallout manual cleanup skills.</p>
<h2>Source Data Quality</h2>
<p>Each data migration test cycle begins with the legacy or source data extract.  An important activity between data migration test cycles is the cleanup of the legacy or source data.  The data migration process will most likely discover many data problems.  Customer and vendor address data alone are enough to bring your bolt-on tax jurisdiction determination software to its knees – that zip code that is too short, too long, or just plain incorrect when combined with the associated city and state; the various abbreviations used in place of the actual city name; the city and state entered in the same field when they should have been entered into separate fields; etc.   If the source data is not fixed, your data migration test cycles will begin to look like the movie Groundhog Day.</p>
<p>Source data provisioning and cleanup could very well be problematic, especially in an acquisition or merger scenario where the providers are part of a different organization and have no incentive to participate in your project.  If you encounter this scenario, you will most likely need to engage the appropriate management level from your organization to have a serious discussion with the appropriate management level from the providing organization.  Recognize this, be in control, and raise that flag early.    Do not sit around for several days waiting for data to arrive, as this will only set your project behind schedule.</p>
<h2>Data Migration Support for Other Testing</h2>
<p>In any business project scenario, the development team will salivate at the thought of testing their customizations against your real data in the conversion test cycle box.  Likewise, the functional team will be chomping at the bit to use your real data to test configuration scenarios.  And the interface team and the data warehouse team can’t ever get enough data to play with.</p>
<p>While working within your three data migration test cycles, just say NO.  You absolutely need a controlled environment for data migration test cycles, and these other teams will not respect that.  They have a different focus and purpose which requires changing and manipulating degrees of freedom that you need held constant.</p>
<p>But, we are all on the same team trying to move the project to the finish line within the expected project timeline.  So to help your other team members, plan for additional data migration cycles to provide this data to these teams.  That’s more data migration practice for you, and it gives everyone else what they need.</p>
<h2>The Perfect World of Data Migration</h2>
<p>In a perfect world, for each data object to be converted:</p>
<ol>
<li>The functional specification and mapping documents are well-written and clear.</li>
<li>A data load file is built exactly in conformity to the well-written functional specification and mapping documents.</li>
<li>The data migration ABAP objects are built exactly as specified by the well-written functional specification and data mapping documents.</li>
<li>No one is insisting that we move a square peg into a round hole.</li>
</ol>
<p>In a perfect world, for each set of data that is to be migrated:</p>
<ol>
<li>The legacy system data has been thoroughly cleansed.</li>
<li>The providers of the legacy data are genuinely interested in providing accurate data on time.</li>
<li>Server-resident load files in a Unicode system are correctly encoded to UTF-8.</li>
<li>A delimiter other than comma has been specified for the load file.</li>
</ol>
<p>In a perfect world, the data migration test cycle client:</p>
<ol>
<li>Is built in a box that is not the development box.</li>
<li>Is configured exactly like the client where the data migration ABAP objects were built and tested.</li>
<li>Is not open for configuration, unless by design.</li>
<li>Is not part of a transport path. to prevent the current cycle of conversion testing from being blindsided by any new configuration changes.</li>
<li>Is locked down so that only data migration and data validation tasks can be performed.</li>
<li>Is configured to handle a more background and update processes and fewer dialog processes.</li>
<li>Is built in a box that has enough disk space to be the repository for the primary load files and any intermediate processing files needed.</li>
</ol>
<p>In a perfect world, at the project level:</p>
<ol>
<li>There is an overall business cutover or implementation plan into which you can assimilate your data migration plan.</li>
<li>The data migration plan integrates nicely into the overall business cutover plan.</li>
<li>There is a strategy in place to bring the data current between the time the cutover freeze is enforced and the implementation date.</li>
</ol>
<h2>Stay Tuned!</h2>
<p>In the real world, the fun is just beginning.  Those perfect world scenarios just never seem to happen.   But stay tuned!  In my next blog post in this series, I will discuss the details of the Data Migration Plan.  After that, in subsequent posts, I will drill down into some real world scenarios that I have encountered and discuss how I dealt with them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/07/sap-data-migration-and-data-conversion-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Native SQL in an ABAP Proxy</title>
		<link>http://www.dataxstream.com/2010/05/using-native-sql-in-an-abap-proxy/</link>
		<comments>http://www.dataxstream.com/2010/05/using-native-sql-in-an-abap-proxy/#comments</comments>
		<pubDate>Thu, 13 May 2010 13:30:22 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP PI Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP ABAP]]></category>
		<category><![CDATA[SAP programming]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4929</guid>
		<description><![CDATA[To implement a case-insensitive WHERE clause in ABAP, you simply needed to use the native SQL UPPER() construct. The database system that is being used is Microsoft SQL Server, but the UPPER() function and its syntax is similar across different database platforms. This seemed like an easy nut to crack. But, as I soon found out, I actually had a lot to learn.]]></description>
			<content:encoded><![CDATA[<p>Recently, I was looking at a requirements document to build an interface to an external system that wants to query customer master data by the customer first name and last name.  As I read this, there were a cacophony of thoughts, all demanding equal attention, racing through my head:</p>
<blockquote>
<ul>
<li><span style="color: #0000ff;">How will I ever match the inbound interface parameter &#8220;Tom&#8221; with &#8220;TOM&#8221;, or &#8220;tom&#8221;?</span></li>
<li><span style="color: #0000ff;">How will I ever match the inbound interface parameter &#8220;Smith&#8221; with &#8220;SMITH&#8221; or &#8220;smith&#8221;?</span></li>
<li><span style="color: #0000ff;">The ABAP WHERE clause is <strong>not</strong> case-INsensitive.</span></li>
<li><span style="color: #0000ff;">There could be hundreds of customers named Tom Smith.</span></li>
<li><span style="color: #0000ff;">KNA1-NAME1 and KNA1-NAME2 are not indexed fields.</span></li>
<li><span style="color: #0000ff;">And no, we are not storing any portion of either first or last name in an existing indexed field like SORTL.</span></li>
<li><span style="color: #0000ff;">There are well over one million customers in the database.</span></li>
<li><span style="color: #0000ff;">We have already decided to use PI for all interfaces.</span></li>
<li><span style="color: #0000ff;">I will have to buy the BASIS team a case of beer to get them to agree to create indices on the fields KNA1-NAME1 and KNA1-NAME2 in a table with over one million records</span>.</li>
</ul>
</blockquote>
<p>I arrived at the conclusion that I need a case-insensitive database query, along with database indices created for the fields KNA1-NAME1 and KNA1-NAME2.</p>
<p>But, what is a case-insensitive WHERE clause?  A little research and help from colleagues revealed that many had gone before me, and this was nothing new.  To implement a case-insensitive WHERE clause in ABAP, you simply needed to use the native SQL UPPER() construct.  The database system that is being used is Microsoft SQL Server, but the UPPER() function and its syntax is similar across different database platforms.  This seemed like an easy nut to crack.  But, as I soon found out, I actually had a lot to learn.
<span id="more-4929"></span></p>
<h3>Take 1</h3>
<p>The examples I found were very explicit, showing actual code snippets.  Using my research examples as a template, I built what was to be my first attempt at using native SQL in a ZTEST ABAP program:</p>
<pre style="background-color: #eaeaea; color: #222;">exec sql.
  select kunnr name1 name2
    from kna1
    into table i_cust
    where upper(name1) like :l_name1
      and upper(name2) like :l_name2
endexec.</pre>
<p>Well, as a native SQL rookie, I was stopped dead in my tracks.  Native SQL does not allow a select into a table – you can only select into a work area.</p>
<h3>Take 2</h3>
<p>In my ZTEST ABAP program, I changed the code to SELECT into a work area and append the work area to an internal table in a subroutine:</p>
<pre style="background-color: #eaeaea; color: #222;">exec sql performing append_cust.
  select kunnr, name1, name2
    from kna1
    into :wa_cust
    where upper(name1) like :l_name1
      and upper(name2) like :l_name2
endexec.

form append_cust.
  append wa_cust to i_cust.
endform.</pre>
<p>I really thought that this would work.  But, I was getting a syntax error from native SQL – the table name was not being recognized.  A little more research revealed that, in <em>some</em> cases, only UPPER CASE is valid for table names and field names.  OK.  I can handle that.</p>
<h3>Take 3</h3>
<p>I changed the native SQL statement to all UPPER CASE in my ZTEST ABAP program:</p>
<pre style="background-color: #eaeaea; color: #222;">EXEC SQL PERFORMING APPEND_CUST.
  SELECT KUNNR, NAME1, NAME2
    FROM KNA1
    INTO :WA_CUST
    WHERE UPPER(NAME1) LIKE :L_NAME1
      AND UPPER(NAME2) LIKE :L_NAME2
ENDEXEC.

form append_cust.
  append wa_cust to i_cust.
endform.</pre>
<p>This <em>appeared</em>to work just fine&#8230;  Except, I noticed that too many records were being returned.  A little more analysis showed that I was getting records from ALL clients, not just my logon client.</p>
<h3>Take 4</h3>
<p>Again, in my ZTEST ABAP program, specify the client:</p>
<pre style="background-color: #eaeaea; color: #222;">EXEC SQL PERFORMING APPEND_CUST.
  SELECT KUNNR, NAME1, NAME2
    FROM KNA1
    INTO :WA_CUST
    WHERE UPPER(NAME1) LIKE :L_NAME1
      AND UPPER(NAME2) LIKE :L_NAME2
      <span style="color: #ff0000;">AND MANDT = :L_MANDT</span>
ENDEXEC.

form append_cust.
  append wa_cust to i_cust.
endform.</pre>
<p>Now I was getting the results that I wanted!!!!  So, I pasted this ZTEST ABAP code into the ABAP proxy.</p>
<p>A syntax check of the code immediately rejected the use of subroutines &#8211; they are not allowed in OO ABAP.  I suppose I should have known that.  The error message indicated that I needed to use a cursor instead of the subroutine.  So, I started cursing – a lot!!!</p>
<h3>Take 5 (The Final Version)</h3>
<p>Here is the final version of the code which works for OO ABAP, and, hence, the ABAP proxy:</p>
<pre style="background-color: #eaeaea; color: #222;">EXEC SQL.
  OPEN CUSTCURSOR FOR
    SELECT KUNNR, NAME1, NAME2
      FROM KNA1
      WHERE UPPER(NAME1) LIKE :L_NAME1
        AND UPPER(NAME2) LIKE :L_NAME2
        AND MANDT = :L_MANDT
ENDEXEC.

DO.
  EXEC SQL.
    FETCH NEXT CUSTCURSOR INTO :WA_CUST
  ENDEXEC.

  IF SY-SUBRC NE 0.
    EXIT.
  ELSE.
    APPEND WA_CUST TO I_CUST.
  ENDIF.
ENDDO.

EXEC SQL.
  CLOSE CUSTCURSOR
ENDEXEC.</pre>
<p>Well, I finally got it right after five tries.  As mentioned before, I found many explicit code examples, but none were for OO ABAP with a database  requiring UPPER CASE be used, so that the table and field names would be recognized in the native SQL SELECT statement.</p>
<p>I learned something new about SAP.  I hope that I never stop learning.  I also hope that this blog might save someone a bit of distress in trying to work through a similar situation.  Now, I just need to figure out what kind of beer to buy the BASIS team to get those indexes created&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/05/using-native-sql-in-an-abap-proxy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Art of Writing an SAP Functional Specification</title>
		<link>http://www.dataxstream.com/2010/04/writing-sa-functional-spec/</link>
		<comments>http://www.dataxstream.com/2010/04/writing-sa-functional-spec/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 13:00:25 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Functional]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[functional specification document]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[RICEF]]></category>
		<category><![CDATA[SAP]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4599</guid>
		<description><![CDATA[The Art of Writing a Functional Specification Document Overview I am currently working on an SAP implementation project that is just starting its realization phase.  One of my first tasks, as a member of the technical implementation team, is to review completed functional specification documents for RICEF objects.  These documents, written by functional subject matter [...]]]></description>
			<content:encoded><![CDATA[<h2 style="text-align: center;">The Art of Writing a Functional Specification Document</h2>
<h3>Overview</h3>
<p>I am currently working on an SAP implementation project that is just starting its realization phase.  One of my first tasks, as a member of the technical implementation team, is to review completed functional specification documents for RICEF objects.  These documents, written by functional subject matter experts, are supposed to detail business requirements that address gaps, and which need to be incorporated into the system being implemented. The purpose of the review is to make sure that the functional specification documents are complete, accurate, and contain the approval signatures required to move on to the technical design phase.</p>
<p><span id="more-4599"></span>
In my career, I have had the pleasure of working with some first-rate functional analysts who know how to draft an excellent functional specification document in a timely manner.  It is this type of performance that helps to move a project along in the right direction, on schedule, and within budget.  Likewise, I have had the not-so-pleasant task of working with not-so-first-rate functional analysts, who draft functional specification documents that are not clear, inaccurate, and incomplete.  The risks here are ultimately manifest as project delays and cost overruns.</p>
<h3>The Good…</h3>
<p>A really good functional specification document contains enough detailed information about the business process to enable a technical designer to use it as the foundation for drafting a complete and accurate technical design document.  The functional specification document should not only highlight the presence of a gap, but should demonstrate how the business process, accompanied by automation, will close the gap.  This document must also indicate the abnormal processing requirements – what should happen when that report or interface does not run, what are the recovery steps, how are key employees notified of the problem, etc.  The content of a functional specification document must be tuned to the flavor of the RICEF object that it is describing.  Since they perform very different tasks, a report specification document should be very much different from an interface, conversion, enhancement, or form functional specification document.  Using functional specification templates helps to insure the appropriate content for each type of RICEF object.</p>
<h3>… and the Not-So-Good.</h3>
<p>I am sometimes astonished by the sparse content that is actually offered up for review.  “We need a report” really does not tell me a whole lot about the business process that I am supposed to automate.  Nor does it even hint at the report purpose, content, layout, user interface, execution mode, authorization requirements, or error handling.  And likewise, “Build me an interface” does not even begin to describe the direction, payload content, mapping, frequency, error handling and recovery steps.  It would be so wrong for me to attempt to build a technical design on such meager functional definitions.   One of my favorite cartoons shows a development manager standing in front of rows of programmers saying “You guys start coding.  I’ll go and find out what they want”.</p>
<p>I am further astonished by:</p>
<p style="padding-left: 30px;">a)      the project managers who apply pressure to accept inaccurate and incomplete functional specification documents, to give the impression that the project is actually moving forward and making meaningful progress.</p>
<p style="padding-left: 30px;">b)      the functional analysts who whine incessantly when their paltry functional specification document is not accepted.</p>
<p>A functional specification document that does not meet expectations must be upgraded until it does.  But bouncing a functional specification document back and forth like a ping pong ball between the functional team and a technical reviewer is inefficient and wasteful.  I find that the best way to quickly firm up a weak functional specification document is to thoroughly research all of the issues that I found in the document, formulate proposed solutions where possible, and then schedule a face to face collaborative meeting with the functional analyst and the business process owner(s).  This type of collaboration can save hours, days, or even weeks of wasted ping-pong posturing, and that is always best outcome for the project.</p>
<h3><a href="http://www.dataxstream.com/2010/03/sap-upgrades-offshore-resources/">Off-Shore Technical Resources</a></h3>
<p>This face-to-face quick resolution scenario typically cannot happen if you have an off-shore technical contingent in play.  In this case, it is absolutely imperative that the functional specification document be most accurate and complete to mitigate the risk of excessive time loss.   Why is that?</p>
<p>Off-shore resources are sometimes time zone shifted eight or more hours ahead of where the project is located.  If a functional specification document is released for review, it will not be analyzed until we have left for the day.  If the off-shore reviewer has questions or raises issues, we will not see these questions or issues until the next day when we arrive at the project site.  When we respond to the questions or issues, the off-shore team will not see our response until we have left for the day.  And so on.</p>
<p>Under these conditions, a poorly written functional specification document with issues takes days instead of hours to resolve.  This leads to unnecessary project delays and cost overruns.</p>
<h3>When One is Really Many</h3>
<p>That 3PL interface, which was scoped and planned by the business process owners as a single RICEF object named “The 3PL Interface”; and for which only one interface functional specification document is written, is actually many RICEF objects.  We need to move purchase orders, inventory receipts, advance ship notices, inventory picks, and cycle counts between the two interfacing partners.  Each of these represents a different payload, different mapping, is triggered by a different point in the business process, has separate error handling and recovery procedures, and requires a separate RICEF development object.</p>
<p>That single enhancement functional specification document, which addresses all of SD pricing, has the potential to extend into many different user exits.  I just finished coding an ABAP proxy that was functionally specified as one interface.  In fact it was four.  The requirement was to search the database for sales and invoice data starting with either an invoice number, sales order number, customer name, or company name.  Each of these search techniques required the development of a separate method.  The only pieces of code that were shared among the four search techniques were the input parameters and the output return table.</p>
<p>The point here is to make sure that the project planners understand the real complexity and effort required on the development side, and to make sure that the project plan and budget reflects these more realistic metrics.  This really goes a long way to stop everyone from wondering, “It’s only one interface!  What is taking development so long?”</p>
<h3>Great Expectations</h3>
<p>So what is a reasonable set of expectations for a really good functional specification document?  What is it that we are asking the business analyst to do?</p>
<p>First, let me describe what I do not expect.  I do not expect a business analyst to write code, build tables, design efficient database retrievals, or to decide that one BAPI, function module, class, or IDOC is better than another.</p>
<p>Here is what I do expect:</p>
<p style="padding-left: 30px;">A clear definition of a business process that is repeatable, and which actually works.  As a pre-automation test for data conversions, I always require the functional analyst to manually enter one of whatever, using the standard SAP transaction for which a conversion program is to be built. Many times, they can’t because the system is not configured correctly, the supporting data is not present, or any number of other reasons which cause the transaction to fail.  An interesting observation is that there is much indignant huffing and puffing during this manual entry “test” process.  But when the manual test fails, I simply remind them that I cannot automate a broken or non-existent business process.</p>
<p style="padding-left: 30px;">A clear definition of what should happen under abnormal or failure circumstances.  This must include error handling, notification, recovery and reprocessing steps.</p>
<p style="padding-left: 30px;">A business process that can efficiently be automated.  Requiring a search of sales order header text for the phrase “This is a red order” is a very bad design for automation purposes.  While such a design is technically possible to build, it will certainly be inefficient at run time, and may not always produce all of the red orders.  This is because the key value is a free-form phrase that can and will be misspelled, and abbreviated, along with countless other mutilations of the key phrase “This is a red order”.  There are much better business processes and technical implementations that will more efficiently and more accurately find all of the red orders in your system.</p>
<p style="padding-left: 30px;">An explanation of the need for development.  Exactly what is the gap, and how will automating the business process close the gap?</p>
<p style="padding-left: 30px;">Screen shots from SAP transactions depicting data that is to be retrieved or stored.  From the screen shot in the transaction, I can usually determine the exact table and field in the SAP database.  Note that some business analysts are very adept at identifying the actual underlying table and field name.</p>
<p style="padding-left: 30px;">Clear and concise details with respect to data mappings, formulae, data transformations, conditional processing, etc.  If I come to an intersection and it is unclear whether I should continue to go straight, turn left, or turn right, then the functional specification document needs a bit more detail behind it.</p>
<p style="padding-left: 30px;">
<h3>How to insure Consistency in Functional Specification Document Review</h3>
<p>Design a separate functional specification document review checklist for each flavor of RICEF object.  Distribute these checklists to the functional specification writers so that they know what the expectations are.  Using a checklist will help to make sure that your review process is consistent and accurate.  Improve these checklists over time.  My Form functional specification checklist document now includes the following check:</p>
<p style="padding-left: 30px;">Is it physically possible to print the specified content on the specified form using the specified font style and size?  Was an actual printed mock-up provided as proof?</p>
<p>- but only after I had received a functional spec for a form that required four inches of print content on a one inch label.  And somehow, the business analyst who wrote this particular request erroneously thought that it was my problem to solve.   After all, writing code is magic!  Isn’t it?  In this case, I pushed back and insisted that an actual printed mock-up be produced &#8211; one that I would then agree to automate.</p>
<h3>Summary</h3>
<p>A good functional specification document will help tremendously in moving a project forward in the right direction with minimal cost and risk.  A poor functional specification document has serious potential to cause project delays, and  schedule and cost overruns.  The best goal for the project is to achieve a good functional specification document, using whatever means required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/04/writing-sa-functional-spec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Too Many Developers Spoil The Code</title>
		<link>http://www.dataxstream.com/2010/03/too-many-developers-spoil-the-code/</link>
		<comments>http://www.dataxstream.com/2010/03/too-many-developers-spoil-the-code/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 13:24:42 +0000</pubDate>
		<dc:creator>Craig Stasila</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[BADI]]></category>
		<category><![CDATA[Craig Stasila]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[SAP ABAP]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4689</guid>
		<description><![CDATA[You may have heard the following idiom before: Too many cooks spoil the broth The common meaning extracted from this saying is that too many people working on a single task tend to make a mess of it.  But, what happens when you have too many developers working in a single piece of ABAP code? [...]]]></description>
			<content:encoded><![CDATA[<p>You may have heard the following idiom before:</p>
<blockquote><p>Too many cooks spoil the broth</p></blockquote>
<p>The common meaning extracted from this saying is that too many people working on a single task tend to make a mess of it.  But, what happens when you have too many developers working in a single piece of ABAP code?  That&#8217;s right, you get a big mess.  This issue is especially difficult to deal with when there are multiple functional requirements leveraging the same custom code object, form-based user-exit, or function-based user-exit.</p>
<p>While current releases of SAP (those built on SAP NetWeaver 2004s and later) have good built-in handling of enhancements and customizations via implicit and explicit enhancement points and BADIs, there still exists many old-school user-exits.</p>
<h2>Multiple Developers; One Code Object</h2>
<p>I recently worked on a project where three separate developers were creating three separate interfaces based on the outbound delivery IDOC.  While the development for all three interfaces was occurring at the same time, the go-live date for each of the interfaces were different (we&#8217;ll discuss that project management glitch at another time).  Each interface required a separate set of custom fields and, therefore, it&#8217;s own IDOC extension.  The problem is there is only one appropriate user-exit in IDOC_OUTPUT_DELVRY and three developers needed to be developing in it at the same time!</p>
<p>How did we solve this problem?
<span id="more-4689"></span></p>
<h2>An Object To Call One&#8217;s Own</h2>
<p>To allow each developer his own development object and transport timeline, I decided to implement a custom multiple-use, filtered BADI <em>inside</em> the SAP user-exit function EXIT_SAPLV56K_002.  Actually, you can implement your own BADI almost anywhere you need alternate logic execution&#8211;even custom code!</p>
<p>So you might be saying, &#8220;Create my own multi-use, filtered BADI definition? Sounds complicated.&#8221; Well, it&#8217;s easier than you think!</p>
<p>NOTE: This solution was done on an ECC6 system based on SAP NetWeaver 2004s.  The steps to implement this type of solution in ECC5 (SAP NetWeaver 2004) are very similar.</p>
<h2>Create A Custom BADI Definition</h2>
<ol>
<li>To create a new enhancement spot definition, use transaction SE18.  I named my enhancement spot Z_EXIT_SAPLV56K_002 because the enhancement spot will be used in user-exit function EXIT_SAPLV56K_002.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-01.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4694" title="BADI 01" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-01.jpg" alt="" width="399" height="179" /></a></li>
<li>In the ensuing dialog box, enter a description and choose <em>BAdi</em> <em>Definition</em> for the Technology
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-02.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4695" title="BADI 02" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-02.jpg" alt="" width="646" height="149" /></a></li>
<li>Next, create a new BADI definition.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-03.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4696" title="BADI 03" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-03.jpg" alt="" width="614" height="191" /></a></li>
<li>Specify that the new BADI definition will be multiple use and limited to filtered use.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-04.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4697" title="BADI 04" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-04.jpg" alt="" width="538" height="95" />
</a>Making the BADI definition multiple use means that each developer can create his or her own BADI implementation.  Each BADI is implemented in its own class.  This promotes code separation and the proper reuse of shared development objects.
Making the BADI definition limited to filter use ensures that the BADI implementations are separate and cannot affect every interface using the user-exit.</li>
<li>Now, create a new filter.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-05.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4698" title="BADI 05" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-05.jpg" alt="" width="262" height="102" /></a>
BADI filtering in SAP NetWeaver 2004s is much more powerful than in previous versions of SAP.  Read more about BADI filtering <a href="http://help.sap.com/saphelp_nw04/helpdata/en/eb/3e7cf7940e11d295df0000e82de14a/frameset.htm" target="_blank">here</a>.</li>
<li><a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-05.jpg" rel="shadowbox[post-4689];player=img;"></a> The BADI we are defining will be used to populate IDOC extensions.  Each IDOC extension has its own message type (e.g. ZMHL_DESADV, ZQTC_DESADV, ZMHL_SHPORD), therefore the message type of the IDOC being processed is a good value to filter on.  I named my BADI filter EDI_MESTYP.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-06.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4710" title="BADI 06" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-06.jpg" alt="" width="588" height="288" /></a>
SAP allows for the automatic checking of BADI implementation filter values.  The standard domain EDI_MESTYP has a value range of table EDMSG attached to it.  This is exactly the range of values I want as allowable values, so I configure the BADI filter to automatically check the filter values against dictionary object EDI_MESTYP.</li>
<li>Next, create the BADI interface that will be inherited by each implementing class
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-07.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4700" title="BADI 07" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-07.jpg" alt="" width="572" height="149" /></a></li>
<li>The original user-exti function EXIT_SAPLV56K_002 is executed after each segment is added.  Our BADI will do the same.  Create a new public interface method SEGMENT_ADDED.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-08.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4701" title="BADI 08" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-08.jpg" alt="" width="560" height="118" /></a></li>
<li>The BADI we are creating is replicating user-exit function EXIT_SAPLV56K_002.  Here is the function interface for EXIT_SAPLV56K_002:
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09_1.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4711" title="BADI 09_1" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09_1.jpg" alt="" width="602" height="383" /></a>
Here is the same data being passed via the interface method.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4702" title="BADI 09" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09.jpg" alt="" width="582" height="218" /></a></li>
<li>Lastly, the BADI has to be called from the existing user-exit.  I will not cover the steps required for implementing user-exit function EXIT_SAPLV56K_002 here, but once you have the user-exit implemented, add the following code.  This code should be the only logic directly inside the user-exit.  Any data processing logic should be implemented via a BADI implementation:
<pre style="background-color: #eaeaea; color: #222;">DATA: GO_BADI TYPE REF TO Z_EXIT_SAPLV56K_002.
DATA: L_STR TYPE STRING.
L_STR = MESSAGE_TYPE.

* Get BADI class based on IDOC message type
GET BADI GO_BADI
   FILTERS EDI_MESTYP = L_STR.

* Execute SEGMENT_ADDED BADI method
CALL BADI GO_BADI-&gt;SEGMENT_ADDED
   EXPORTING
     MESSAGE_TYPE       = MESSAGE_TYPE
     SEGMENT_NAME       = SEGMENT_NAME
     DATA               = DATA
     TAB_IDOC_REDUCTION = TAB_IDOC_REDUCTION
     FLT_VAL            = MESSAGE_TYPE
   CHANGING
     CONTROL_RECORD_OUT = CONTROL_RECORD_OUT
     IDOC_DATA          = IDOC_DATA[].</pre>
</li>
</ol>
<p>We&#8217;re done with creating the BADI definition!  Save and activate your work.  I bet you&#8217;re saying to yourself, &#8220;Wow, that was easy!&#8221;</p>
<h2>BADI Implementation</h2>
<p>Implementing the BADI you just created in the steps above is just like implementing any other BADI in SAP, so here are the Cliff Notes version of implementation instructions.</p>
<ol>
<li>Using transaction SE19, create a new enhancement spot implementation for Z_EXIT_SAPLV56K_002.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-10.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4703" title="BADI 10" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-10.jpg" alt="" width="547" height="180" /></a></li>
<li>Enter the BADI implementation details.  This particular BADI implementation is for RICEF ID MHL-IO-007, so I added that identification to the BADI implementation name and implementing class name.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-12.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4705" title="BADI 12" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-12.jpg" alt="" width="572" height="280" /></a></li>
<li>In the BADI definition, we required each BADI implementation to be filtered on message type. This particular BADI implementation is for message type ZMHL_SHPORD.  Create the filter combination for the BADI implementation.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-13.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4706" title="BADI 13" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-13.jpg" alt="" width="586" height="149" /></a></li>
<li>This ensures that the other interfaces using this BADI (ZMHL_DESADV, ZQTC_DESADV) will not execute the code implemented with this BADI.
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-14.jpg" rel="shadowbox[post-4689];player=img;"><img class="alignnone size-full wp-image-4707" title="BADI 14" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-14.jpg" alt="" width="518" height="255" /></a></li>
<li>The final steps are to add the code to the SEGMENT_ADDED method just like you would in user-exit function EXIT_SAPLV56K_002.  Once you are done, save and activate your changes!</li>
</ol>
<h2>Summary</h2>
<p>As you can see, with a few extra steps, it is possible to have your cake and eat it, too, by create a custom BADI definition that can be used by other developers.  All this talk of food is making me hungry.  Is it lunchtime yet?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/03/too-many-developers-spoil-the-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Ergonomic User Interface</title>
		<link>http://www.dataxstream.com/2010/03/the-ergonomic-user-interface/</link>
		<comments>http://www.dataxstream.com/2010/03/the-ergonomic-user-interface/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 14:00:53 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Functional]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[build an interface]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP programming]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4110</guid>
		<description><![CDATA[Every Monday morning I hop on a plane, arrive at my destination city, pick up a rental car, and drive to my client’s site.  The car rental company gives me a different make and model car every week.  And yet, somehow, I am successfully able to open the car, adjust the seat and mirrors, start [...]]]></description>
			<content:encoded><![CDATA[<p>Every Monday morning I hop on a plane, arrive at my destination city, pick up a rental car, and drive to my client’s site.  The car rental company gives me a different make and model car every week.  And yet, somehow, I am successfully able to open the car, adjust the seat and mirrors, start the car, shift gears, and drive.  I can also operate the radio, air conditioning, heat, windshield wipers, and headlights.</p>
<p>Now, put me behind a keyboard in front of a computer application which I have never seen before. My user experience is all over the map – somewhere in the continuum between most excellent and very poor.  Some application user interfaces are extremely intuitive, well-designed and easy to navigate, logically follow the business process flow, and provide real meaningful help when needed.  Other application user interfaces are extremely difficult to navigate, are not intuitive, do not follow a logical business process flow, and offer little or no meaningful help. And sometimes in these difficult user interfaces, not only has the location of the steering wheel been moved to a totally unsuspecting location, but its appearance has been changed so that, even when I see it, I do not even recognize it as being the application’s steering wheel.</p>
<p>A well-engineered user interface is no accident.  It doesn’t just magically happen.  It must be woven into the fabric of the design and the code; and it should never be shoe-horned into the application as an after-thought.   It takes a lot of up front planning, designing, testing, functional effort and technical effort to produce a really good application user interface.  And yes, designing, building, testing, and implementing a good user interface for your application will extend the delivery time of whatever it is that you are building.</p>
<p>Why is a well-designed and ergonomic user interface so important?  You could have built the best application ever developed.  But if it is unusable, it will never get very far.   Countless hours are lost every day as thousands of frustrated users spend extra time and effort wrestling with poorly designed user interfaces, rather than focusing on their jobs.  And when the frustration levels reach a certain trigger point, the users will seek out and find alternative ways to perform their duties.</p>
<p>Here are a few examples of some very interesting user interface experiences that I have personally encountered.</p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<h2><span id="more-4110"></span>Let’s Punish the User</h2>
<p>I thought we had gotten over this one a long time ago, but I was bitten by it recently while I was completing a web form.  Here is the scenario:</p>
<p style="padding-left: 60px;">I am completing a screen form containing several fields, and I make an entry error in one of the fields.  When I try to submit the data, the application rejects the submission, and sends me a message indicating where the error field is, <strong>and then clears all of the fields on the screen and makes me re-enter all of</strong> <strong>the data again.</strong></p>
<p style="padding-left: 60px;"><span style="color: #3366ff;"> </span><em><span style="color: #3366ff;">Bad User!  And, because you made a mistake, you get to start the entire form all over again …   and again … and again … and again </span>&#8230; </em></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>When Help is not Help</h2>
<p>I am especially fond of this one.  I need help, so I look for the HELP ICON.  I find the HELP ICON (because it looks like a help icon should look, and it is located where a help icon is typically located … well, sometimes it is) and I press it.  The anticipation of actually getting the help I need is overwhelming.     And the help information finally appears on my screen and reads something like this:</p>
<p style="padding-left: 30px;">The exact details of what you want to know are located somewhere in our behemoth website.   Now, we could tell you exactly where and actually help you to solve your problem very quickly,    but we’re not going to, because then you won’t have spent hours wandering aimlessly through our website’s colossal labyrinth.  And while you are in there, don’t let the Minotaur get you!   Please go to <a href="http://www.needleinthehay.com/">www.needleinthehay.com</a>.</p>
<p>Well, at least they said “please”.</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>The Errant Error Message</h2>
<p>I can’t tell you how many times I have made a data entry mistake, only to be “helped” by this not-so-helpful error message:</p>
<p><span style="color: #3366ff;"><strong> Incorrect Entry</strong></span></p>
<p>This is irritating.  If I don’t know <strong>why</strong> it is incorrect, I can’t fix it!  If the application is intelligent enough to determine that the entry is incorrect, it certainly is intelligent enough to tell me which of its check rules were violated (in plain user-oriented language please).</p>
<p>I really like this one:</p>
<p><span style="color: #3366ff;"><strong>Program Error 1776</strong></span></p>
<p>This truly tells me everything I need to know!!!  Maybe the developer knows what error 1776 is, but I don’t.  Maybe I can find the meaning of error 1776 at <a href="http://www.needleinthehay.com/">www.needleinthehay.com</a>. (I hope the answer is not too close to the Minotaur’s lair.)</p>
<p>Hey developer – can I have your phone number so I can call you every time I see one of these messages?  Maybe then you will get the hint and stop the madness!</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>I’ve fallen in and I can’t get out</h2>
<p>Sometimes, I manage to navigate to a screen that has no obvious means of escape.  So I’m trapped until I can figure out the top-secret mouse click or keystroke combination.  Should I place the blue orb on the green pedestal?  I guess I really should have left a breadcrumb trail.  Or maybe the developer was a ZORK player!  Let’s try XYZZY!!!</p>
<p><strong><span style="text-decoration: underline;"><strong><span style="text-decoration: underline;"> </span></strong></span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>Just Give me a Good Example</h2>
<p>Like pictures, a good example is worth a thousand words.  Good examples are worth their weight in gold.  A really good example can get me to where I want to be – understanding what I need to know – much more quickly than an entire chapter of words.  Good examples are hard to come by.  They require lots of thought and planning.</p>
<p>Here is an example of a bad example:</p>
<p>2  @  2   =  4         where ‘@’ is some arithmetic operation.</p>
<p>OK &#8211; did we add or multiply here?  Who knows?  This is totally ambiguous, and a bad example.</p>
<p>Here is an example of a better example:</p>
<p>2  @  3   =  5         where ‘@’ is some arithmetic operation.</p>
<p>It is obvious here that the “arithmetic operation” was addition.</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>The Cluttered Screen</h2>
<p>One of my favorite games as a child was the type of puzzle where a group of objects is hidden somewhere in a very busy picture.  The names of the hidden objects are listed on the side of the page, and the object of this type of puzzle is to “find the hidden objects” that are on the list.</p>
<p>Some user interface designers and builders are very adept at hiding items on their incredibly busy user interface screens.   Perhaps in their youth, like me, they liked to play with “find the hidden objects” puzzles also.  The problem here is that they are designing “find the hidden objects” puzzles into their user interfaces!  Is it really necessary to squeeze in every data field and push button onto a single screen?  Is the perception here that a single screen, no matter how extremely busy, is somehow easier to use?</p>
<p>My end-user work instructions tell me that if I push the “show details” button, I will then know the meaning of life, the universe, and everything.  But where is the “show details” button?  I am really good at playing “Where’s Waldo”!  Just give me an hour or two and I will find it!</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>The Plethora of Scattered Screens</h2>
<p>The opposite of the tightly packing everything onto a single cluttered screen is the scattering of the user interface among way too many screens.  It becomes a memory exercise to remember the user interface elements that I have already touched, and a scavenger hunt to locate the interface elements that I haven’t found yet.  Let’s see … what was that part number that I entered on screen 152?  Or was it on screen 376?  And where do I go from here to get the order number?  Does anyone have a roadmap that I can follow?</p>
<p>Maybe if we could consolidate the enormous number of screens down to a few that represented logical work flow groupings, I could spend less time screen hopping and be more productive.</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>Let’s Get Colorful and Fontsy</h2>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2020/12/userinterface.jpg" rel="shadowbox[post-4110];player=img;"><img class="aligncenter size-full wp-image-4356" title="userinterface" src="http://www.dataxstream.com/wp-content/uploads/2020/12/userinterface.jpg" alt="" width="660" height="75" /></a>
They use several different font styles, sizes, and colors.</p>
<p>I suppose that’s OK, isn’t it?  It really wasn’t too difficult to read the sentence above, was it?</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>Consistency is Key</h2>
<p>Let’s examine the rental car scenario that I posed at the beginning of this blog.  The reason that I am able to quickly enter the car and drive away is because a recognized user interface standard has been established and consistently applied to all automobile makes and models.  Among the various cars that I am faced with, the gas pedal always looks like a gas pedal, and is always located on the driver’s side floor to the right.  Likewise for the steering wheel, the brake pedal, and most other major user interface elements found in a car &#8211; they all adhere to standards of look and feel and placement.</p>
<p>It should not be too surprising then, that the not-so-ergonomic user interfaces that I have encountered do not even recognize that a standard might even exist. The really difficult user interfaces mix things up, and change the appearance, behavior, and location of controls from screen to screen.</p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<h2>Summary</h2>
<p>The ergonomic user interface – the one that is intuitive, provides real help when needed, follows an organized logical workflow, and is easy to use are important components of a really great application that end users will want to use because it actually will be the best way to do their job.</p>
<p>Here are a few guidelines that I use whenever I build a user interface:</p>
<p>1)      Totally and completely understand what the business requirements are, and what the user needs to accomplish.  This is the first and most important step to building a good user interface.</p>
<p>2)      Design the user interface to follow the workflow.</p>
<p style="padding-left: 30px;">Organize and logically group functions together.</p>
<p>3)      Determine if standards exist and consistently use them everywhere.</p>
<p style="padding-left: 30px;">Position controls in expected and predictable locations.</p>
<p>4)      Give feedback to the user in a timely manner.</p>
<p style="padding-left: 30px;">Don’t wait until screen 3 to inform the user that there is a problem back on screen 1.</p>
<p>5)      Craft meaningful error messages in user-oriented language.</p>
<p style="padding-left: 30px;">Temper the messages appropriately – if everything is hot, then nothing is hot.</p>
<p>6)      Make sure that the “help” you provide really helps.</p>
<p style="padding-left: 30px;">Ask the user to confirm before deleting anything.</p>
<p style="padding-left: 30px;">Use list of values help whenever possible.</p>
<p>7)      Use default values whenever possible.</p>
<p style="padding-left: 30px;">This avoids potential data entry errors and makes the user interface more efficient.</p>
<p style="padding-left: 30px;">For example, if I work in warehouse 2, I should not have to enter that information every time I ship an item.</p>
<p style="padding-left: 30px;">Display default values in pre-populated, grayed-out fields; but add a pushbutton to allow for the rare occasion when the user must override the default value.</p>
<p>8)      Keep training documents current.</p>
<p style="padding-left: 30px;">As a developer, you may not own the training documents – but someone does.</p>
<p style="padding-left: 30px;">There is nothing more frustrating than a training document that does not match the actual program behavior screen for screen and mouse click for mouse click.</p>
<p style="padding-left: 30px;">
<p>I hope that this blog can provide some useful hints for building effective and efficient user interfaces.  Please reply to this blog if you have any most interesting user interface stories that you would like to share with our readers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/03/the-ergonomic-user-interface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SAP Event Driven Batch Job</title>
		<link>http://www.dataxstream.com/2010/03/sap-event-driven-batch-job/</link>
		<comments>http://www.dataxstream.com/2010/03/sap-event-driven-batch-job/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 05:00:32 +0000</pubDate>
		<dc:creator>Steve Park</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP ABAP Performance]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[batch job]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[Steve Park]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=3839</guid>
		<description><![CDATA[When creating SAP batch jobs to run a program, most of the scheduling can be accomplished by setting a periodic time for when the job is executed.  For example, execute the job every 10min, 30min, or 1 hour.  But what if you needed more control of when a batch job was executed? At one of [...]]]></description>
			<content:encoded><![CDATA[<p>When creating SAP batch jobs to run a program, most of the scheduling can be accomplished by setting a periodic time for when the job is executed.  For example, execute the job every 10min, 30min, or 1 hour.  But what if you needed more control of when a batch job was executed?</p>
<p><span id="more-3839"></span></p>
<p>At one of my clients they had a requirement to run a batch job every 5 minutes.  Sometimes the batch job would take longer than 5 minutes to complete.  Thus, the same program would start in a new batch job before the previous batch job had time to finish.  The same program would collide with itself and cause issues.</p>
<p>It seems that SAP&#8217;s built-in job scheduler does not have a standard way of preventing overlapping job executions.  I was hoping to find a checkbox that would deny an execution of a job if it finds the same active job running, but that would be too easy.  However, SAP does have some different options in its toolbelt to satisfy this requirement.  The approach that I will demonstrate will use an event-driven approach to execute a SAP batch job.</p>
<p>First I will detail the High level overview of what needs to happen.  Then, after you understand the big picture, then I will go into more detail about how to code and configure this scenario.</p>
<h2>High level Overview</h2>
<p>Basically 2 SAP batch jobs are needed:</p>
<p>1) SAP Job #1</p>
<ul>
<li>This job will execute every 5min or so depending on your requirment and execute a simple custom program that will check the status of Job #2.
<ul>
<li>If the status of job Job #2 is <strong>not </strong>running, then the custom program will raise an event</li>
<li>If the status of Job #2 is running, then the custom program will do nothing</li>
</ul>
</li>
</ul>
<p>2) SAP Job #2</p>
<ul>
<li>This job is setup to start only when an event is raised
<ul>
<li>If an event is Raised from Job #1 then Job #2 will start.  Job #2 will contain the actual programs that you need to execute.</li>
</ul>
</li>
</ul>
<p>Sound easy enough?</p>
<h2>Step-By-Step Instructions</h2>
<p>Now let’s get to business and see what configuration and coding we need to do.</p>
<p>1)      First let’s define an Event.</p>
<p>Transaction SM64 – I defined my event as Z_JOB_START_XXXXX</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3850" title="pic1" src="http://www.dataxstream.com/wp-content/uploads/2010/01/pic1.png" alt="pic1" width="600" height="233" /></p>
<p style="text-align: center;">
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3851" title="2" src="http://www.dataxstream.com/wp-content/uploads/2010/01/2.png" alt="2" width="599" height="122" /></p>
<p>2)     Next,  Create simple Custom program ZJOB_CREATE_EVENT to Raise the Event.   This program will basically check if the specified job is currently running.  If it is not running then Raise an event which was created in the previous step above.   In my case, I will  raise event ‘Z_JOB_START_XXXXX’.   Create a variant here with the Event Name(Z_JOB_START_XXXXX) and the Job #2 name (ZJOB_XXXXX).</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3852" title="3" src="http://www.dataxstream.com/wp-content/uploads/2010/01/3.png" alt="3" width="554" height="636" /></p>
<p style="text-align: center;">3)      For Job #1.  Basically set this job as Periodic Time driven job to run every 5 minutes or so with the custom program ZJOB_CREATE_EVENT.  Also make sure you include the variant with the Job #2 name and Event.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3853" title="4" src="http://www.dataxstream.com/wp-content/uploads/2010/01/4.png" alt="4" width="485" height="133" /></p>
<p>4)      For Job #2.  Define this job as an Event Driven batch job and define the actual program (I used test program ZSPTEST) that needs to be executed.  Specify the event Z_JOB_START_XXXXX that this job will be waiting for.  Also checkbox ‘Periodic job’ to schedule another event job.</p>
<p style="text-align: center;"><img class="aligncenter size-large wp-image-3854" title="5" src="http://www.dataxstream.com/wp-content/uploads/2010/01/5-856x1024.png" alt="5" width="599" height="717" /></p>
<p style="text-align: center;">
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3855" title="6" src="http://www.dataxstream.com/wp-content/uploads/2010/01/6.png" alt="6" width="603" height="604" /></p>
<p>That’s it…Now the batch job will only execute if the same batch job is not running.</p>
<h2>Testing</h2>
<p>For testing purposes, I will demonstrate by manually execute program ZJOB_CREATE_EVENT to show that how this all works.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3856" title="7" src="http://www.dataxstream.com/wp-content/uploads/2010/01/7.png" alt="7" width="606" height="357" /></p>
<p>The event ZJOB_START_XXXXX has been raised by program ZJOB_CREATE_EVENT.  Now you can see the ZJOB_XXXXX is Active/Running</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-3857" title="8" src="http://www.dataxstream.com/wp-content/uploads/2010/01/8.png" alt="8" width="391" height="145" /></p>
<p>During the time the job is active, I attempted to execute program ZJOB_CREATE_EVENT again.   This time, the program knows that the job is still active and, therefore, it does not raise the event.  The only time the event will be raised again is once the job is finished .</p>
<p>This is only one scenario in where an event driven batch job is needed.  Now you can see how you can utilize an event driven batch job to put some control around how some programs are executed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/03/sap-event-driven-batch-job/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Software Component</title>
		<link>http://www.dataxstream.com/2010/02/software-component/</link>
		<comments>http://www.dataxstream.com/2010/02/software-component/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 05:00:34 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[SAP]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=3913</guid>
		<description><![CDATA[In my last blog entitled What’s in a Namespace, I discussed the value of developing deliverable custom solutions in a reserved unique namespace.    In this blog, I will discuss how a namespace is related to a software component.   I will also discuss the typical product lifecycle, the software component version, and the convention which we [...]]]></description>
			<content:encoded><![CDATA[<p>In my last blog entitled <a href="http://www.dataxstream.com/2010/01/namespace/">What’s in a Namespace</a>, I discussed the value of developing deliverable custom solutions in a reserved unique namespace.    In this blog, I will discuss how a namespace is related to a software component.   I will also discuss the typical product lifecycle, the software component version, and the convention which we use for establishing the software component version release increments.</p>
<p>DataXstream, an SAP Solution Partner, builds, packages, and distributes custom solutions for our clients.  We develop all of our custom add-on products in our own reserved and unique namespace /XSTREAM/.  But, we also need to reserve a separate unique namespace for each add-on product that we package and deliver using the SAP Add-on Assembly Kit.  So, we have a single development namespace /XSTREAM/ and a separate “packaging and delivery” namespace for each add-on product.  Why is that?</p>
<p><span id="more-3913"></span></p>
<h2>Software Component Name and Software Component Version</h2>
<p>Let’s begin with the software component name.  A software component name references a set of objects that are always delivered together.  It contains all of the programs, classes, function modules, tables, message classes, BADIs, basic types, transaction codes, … etc. – all of the objects which constitute a custom add-on product.   We try to make our software component names meaningful, so if we are building a product named PRODUCTA, we will try to create its software component name also as PRODUCTA.</p>
<p>This product has a product lifecycle which begins with its initial major release at version 1.0.  As bugs are discovered and fixed or as small enhancements are made, minor updates are released, let’s say at version 1.1, version 1.2, etc.  And after some serious product re-engineering, the product is then distributed as major release 2.0.  So, the software component name represents all of the objects which constitute the product, and the software component version represents the context of the product within its own product lifecycle.  The complete picture is provided by the combination of the software component name and the software component version.  For example, we might refer to PRODUCTA at release 1.3, which is different from PRODUCTA at release 1.2, which is different from PRODUCTB at release 2.5.</p>
<p>At DataXstream, we build and distribute several add-on products, so you can imagine that each product currently exists at a different release level within its own product lifecycle.  PRODUCTA may be at release level 1.3, while PRODUCTB may be at release level 2.5, and PRODUCTC may still be under construction and not yet released.  If we fix bugs in or make minor enhancements to PRODUCTA, then we need to bump the software component version of PRODUCTA (and only PRODUCTA) from release 1.3 to 1.4.</p>
<p>Let me add another degree of complexity to this picture.  We build and deliver the same add-on product to different SAP environments.  For example, we have clients who are running SAP in the 4.7, the ECC 5.0 and the ECC 6.0 environments.  Since these environments are different, it is possible that the same product may exist at different releases in its lifecycle across all of these three SAP environments.</p>
<p>To help us manage this complexity, the actual software component version release names that we actually use are a bit more descriptive than 1.0, 1.1, 2.5, etc.   This will be explained in detail later on in the section <strong>Maintaining the Software Component Version.</strong></p>
<h2>Maintaining the Software Component Name and its link to a Namespace</h2>
<p>The software component name is derived directly from a valid namespace that has already been registered on your SAP system.  It is, in fact, the namespace name without the two enclosing ‘/’ characters.  This establishes a relationship between the software component name and the namespace.  SAP checks and enforces this relationship when maintaining software component names.  We try to make our software component names meaningful, so if we are building an add-on product named PRODUCTA, we will reserve and register namespace /PRODUCTA/.   This allows us to then create the software component name PRODUCTA.</p>
<p>In SAP, we establish our software component name using transaction SSDC.  This is the Software Delivery Composer which is part of the SAP Add-on Assembly Kit.  From the initial screen in SSDC, the menu path is <strong>Environment -&gt; Create/Update Add-on Software Component</strong>.</p>
<p><img class="aligncenter size-full wp-image-4036" title="swcpic1" src="http://www.dataxstream.com/wp-content/uploads/2025/12/swcpic1.bmp" alt="swcpic1" /></p>
<p>On this next screen, you enter the software component name that you wish to maintain.  The software component name must be derived from an already-registered valid namespace.  For example, if you have already registered the namespace /ABCD/, then you can create a software component that is named ABCD.  SAP checks this relationship, and issues an error message if you try to create an invalid software component name that cannot be derived from an already existing namespace.</p>
<p><img class="aligncenter size-full wp-image-4033" title="swcpic2" src="http://www.dataxstream.com/wp-content/uploads/2010/01/swcpic2.bmp" alt="swcpic2" /></p>
<p>SAP allows as many as ten characters for the software component version or release name.  This allows us to build meaningful release names, which really helps to sort things out when you are dealing with many products over several SAP environments.  Here are a few demonstrative examples of how we build our release names:</p>
<table border="1" cellspacing="0" cellpadding="0" width="643">
<tbody>
<tr>
<td width="179" valign="top"><strong>Software Component Version or Release Name</strong></td>
<td width="86" valign="top"><strong>SAP Environment</strong></td>
<td width="378" valign="top"><strong>Description</strong></td>
</tr>
<tr>
<td width="179" valign="top">100_470</td>
<td width="86" valign="top">4.7</td>
<td width="378" valign="top">Version 1.0 first major release in SAP 4.7</td>
</tr>
<tr>
<td width="179" valign="top">101_470</td>
<td width="86" valign="top">4.7</td>
<td width="378" valign="top">Version 1.1 first  minor enhancement to version 1 in SAP 4.7</td>
</tr>
<tr>
<td width="179" valign="top">200_470</td>
<td width="86" valign="top">4.7</td>
<td width="378" valign="top">Version 2.0 second major release in SAP 4.7</td>
</tr>
<tr>
<td width="179" valign="top">103_500</td>
<td width="86" valign="top">ECC 5.0</td>
<td width="378" valign="top">Version 1.3 third minor enhancement to version 1 in SAP ECC 5.0</td>
</tr>
<tr>
<td width="179" valign="top">205_600</td>
<td width="86" valign="top">ECC 6.0</td>
<td width="378" valign="top">Version 2.5 fifth minor enhancement to version 2 in SAP ECC 6.0</td>
</tr>
</tbody>
</table>
<h2>Maintaining the Software Component Version</h2>
<p>On this screen, you enter the software component version or release name, and a description, then press the SAVE icon.</p>
<p><img class="aligncenter size-full wp-image-4034" title="swcpic3" src="http://www.dataxstream.com/wp-content/uploads/2010/01/swcpic3.bmp" alt="swcpic3" /></p>
<h2>Another Piece of the Puzzle – the Package</h2>
<p>We want each of our products to have its own unique software component, because each software component or product has its own unique set of objects and needs to exist at its own software component version within its own product lifecycle.  We need to allow all of the development objects for PRODUCTA to be at release 101_470 and all of the development objects for PRODUCTB to be at release 103_500. But, if we perform all of our development for all of our products in the /XSTREAM/ namespace, how do we assign all of the /XSTREAM/ development objects for PRODUCTA to software component PRODUCTA, and all of the /XSTREAM/ development objects for PRODUCTB to software component PRODUCTB?</p>
<p>The answer is in the package or development class.  When creating a package, you must specify the software component that the all of package objects will be assigned to.  The example below shows the creation of a package or development class /XSTREAM/PRODUCTA.  One of the parameters of the package is the software component.  We would assign software component PRODUCTA to this package.</p>
<p>So, when building the product PRODUCTA, we create many development objects (programs, classes, tables, etc.) in the /XSTREAM/ namespace, we assign those objects to the /XSTREAM/PRODUCTA package, which in turn, assigns those objects to the software component PRODUCTA which exists at a particular release level in its lifecycle.</p>
<p><img class="aligncenter size-full wp-image-4035" title="swcpic4" src="http://www.dataxstream.com/wp-content/uploads/2010/01/swcpic4.bmp" alt="swcpic4" /></p>
<h2>Summary</h2>
<p>To summarize, because of the dependencies between namespaces, software components, packages, and development objects, these actions must occur in the following order:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="50" valign="top"><strong>Order</strong></td>
<td width="449" valign="top"><strong>Action</strong></td>
<td width="139" valign="top"><strong>SAP Transaction</strong></td>
</tr>
<tr>
<td width="50" valign="top">1</td>
<td width="449" valign="top">Register the namespace on the development system</td>
<td width="139" valign="top">SE03</td>
</tr>
<tr>
<td width="50" valign="top">2</td>
<td width="449" valign="top">Maintain the software component and software component version</td>
<td width="139" valign="top">SSDC</td>
</tr>
<tr>
<td width="50" valign="top">3</td>
<td width="449" valign="top">Create a package</td>
<td width="139" valign="top">SPACKAGE or SE80</td>
</tr>
<tr>
<td width="50" valign="top">4</td>
<td width="449" valign="top">Develop objects and assign them to the package</td>
<td width="139" valign="top">Various</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/02/software-component/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To Implement Field-Level HRMD_A Reduction</title>
		<link>http://www.dataxstream.com/2010/02/how-to-implement-field-level-hrmd_a-reduction/</link>
		<comments>http://www.dataxstream.com/2010/02/how-to-implement-field-level-hrmd_a-reduction/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 13:08:42 +0000</pubDate>
		<dc:creator>Craig Stasila</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ALE]]></category>
		<category><![CDATA[Craig Stasila]]></category>
		<category><![CDATA[HRMD_A]]></category>
		<category><![CDATA[IDOC]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[SAP programming]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4289</guid>
		<description><![CDATA[I love ALE.  It is super-powerful and, once you get the hang of it, is a snap to configure.  Recently, I was setting up an HRMD_A interface for my client.  Everything was going smoothly until I ran into a requirement to filter out the social security number (PERID), birthdate (GBDAT), and gender (GESCH) for privacy [...]]]></description>
			<content:encoded><![CDATA[<p>I love ALE.  It is super-powerful and, once you get the hang of it, is a snap to configure.  Recently, I was setting up an HRMD_A interface for my client.  Everything was going smoothly until I ran into a requirement to filter out the social security number (PERID), birthdate (GBDAT), and gender (GESCH) for privacy reasons.  All of these fields are in segment E1P0002.  Initially, I thought that this requirement was easy enough to accomplish.  I just created a IDOC reduction in transaction BD53 and filtered out the three fields.  I soon found out that while entire segments were getting reduced from the IDOC as configured, the individually reduced fields were still showing up in the IDOC.  What&#8217;s going on?!?
<span id="more-4289"></span> Well, after some digging, I found <a href="https://service.sap.com/sap/bc/bsp/spn/sapnotes/index2.htm?numm=381766" target="_blank">OSS Note 381766</a>.  This note&#8217;s cause section states:</p>
<blockquote><p>The reduction at segment level (see also Note 301223) was facilitated in order to be able to copy message type HRMD_A. This involved setting the reduction at field level, which was not taken into account in the code because it is not possible to centrally determine which fields are mandatory and which are dependent for all country versions. In addition, for one info type there may several records for different periods of time, which may also cause a problem when you are reducing fields.</p></blockquote>
<p>So, in essence, field-level reduction isn&#8217;t supported for HRMD_A.  The solution supplied in the OSS note suggests creating user-exit code to filter out the unwanted fields.  I already have implemented BADI HRALE00OUTBOUND_IDOC to add some other processing logic (if you&#8217;re lucky I&#8217;ll cover that logic in this blog, too), so I have a module in which I can place the code. And while the code to loop through an IDOC and clear out all instances of E1P0002-PERID, E1P0002-GBDAT, and E1P0002-GESCH is very easy, I can&#8217;t help but think I can make the code more useful.  You see, I hate unitasking code.  I can see it now.  If I take the shortcut path and wrote the unitasking code to clear those 3 fields, the code won&#8217;t be in production for more than a month before the requirements change and now there is another field that needs to be filtered out as well.  With unitasking code, I would have to crack open the code, create a transport, unit test, transport to Q, integration test, wait for a transport window, blah, blah, blah.  Ugh!  What a waste of time for a minor change.  We can do better.</p>
<p>I decided to create a multi-tasking module that will work for HRMD_A message types.  The fields to be cleared will be stored in TVARV in the format &lt;SEGMENT&gt;-&lt;FIELD&gt; (e.g. E1P0002-PERID).  That way, whenever the HR functional team wanted to filter out a new field, all they had to do was to update a TVARV variable.</p>
<p>To implement the solution, I created a new method called CLEAR_IDOC_FIELDS in my class implementation for BADI HRALE00OUTBOUND_IDOC.  CLEAR_IDOC_FIELDS has the same method signature as IF_EX_HRALE00OUTBOUND_IDOC~IDOC_DATA_FOR_RECEIVER_MODIFY:</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/00-Method-Signature.jpg" rel="shadowbox[post-4289];player=img;"><img class="alignnone size-full wp-image-4293" title="00 Method Signature" src="http://www.dataxstream.com/wp-content/uploads/2010/02/00-Method-Signature.jpg" alt="" width="605" height="163" /></a></p>
<p>The code is pretty straight forward.  To allow multiple interfaces to coexist in method CLEAR_IDOC_FIELDS, the TVARV variable that stores the fields to clear is in the format &#8216;ZHR_CLR_&#8217; concatenated with the IDOC message type.</p>
<pre style="background-color: #eaeaea; color: #222;">METHOD CLEAR_IDOC_FIELDS .
*----------------------------------------------------------------------*
* Class:     ZCL_IM_HRALE00OUTBOUNDIDOC                                *
* Method:    CLEAR_IDOC_FIELDS                                         *
* Author:    Craig Stasila                                             *
*----------------------------------------------------------------------*

  TYPES: BEGIN OF TY_FILTER,
           TABNAME   TYPE DFIES-TABNAME,
           FIELDNAME TYPE DFIES-FIELDNAME,
           POSITION  TYPE DFIES-POSITION,
           OFFSET    TYPE DFIES-OFFSET,
           LENG      TYPE DFIES-LENG,
        END OF TY_FILTER.

  DATA: WA_FILTER      TYPE TY_FILTER,
        LT_FILTER      TYPE TABLE OF TY_FILTER,
        LS_TABNAME     TYPE DDOBJNAME,
        LS_SAV_TABNAME TYPE DDOBJNAME.

  DATA: LS_NAME   TYPE TVARV-NAME,
        LT_TVARVC TYPE TABLE OF TVARVC,
        WA_TVARVC TYPE TVARVC.

  DATA: LT_DFIES TYPE TABLE OF DFIES,
        WA_DFIES TYPE DFIES.

  DATA: LR_SEGNAM TYPE RANGE OF EDIDD-SEGNAM,
        WR_SEGNAM LIKE LINE OF LR_SEGNAM.

  FIELD-SYMBOLS: &lt;FS&gt; TYPE LINE OF EDIDD_TT.

* Fields to clear are in variable
  CONCATENATE 'ZHR_CLR_' MESTYP INTO LS_NAME.

* Get list of fields to clear from TVARV
  SELECT * FROM TVARVC
    INTO TABLE LT_TVARVC
   WHERE NAME = LS_NAME
     AND TYPE = 'S'.

  CHECK SY-SUBRC = 0.

* Build list of fields to clear
  LOOP AT LT_TVARVC INTO WA_TVARVC.
    CLEAR WA_FILTER.
    SPLIT WA_TVARVC-LOW AT '-' INTO WA_FILTER-TABNAME WA_FILTER-FIELDNAME.
    CHECK SY-SUBRC = 0.

    COLLECT WA_FILTER INTO LT_FILTER.
  ENDLOOP.

  SORT LT_FILTER BY TABNAME.
  CLASS CL_ABAP_CHAR_UTILITIES DEFINITION LOAD.

* Get field offsets
  LOOP AT LT_FILTER INTO WA_FILTER.
    LS_TABNAME = WA_FILTER-TABNAME.

    IF LS_TABNAME NE LS_SAV_TABNAME.

      CALL FUNCTION 'DDIF_NAMETAB_GET'
        EXPORTING
          TABNAME   = LS_TABNAME
        TABLES
          DFIES_TAB = LT_DFIES
        EXCEPTIONS
          NOT_FOUND = 1
          OTHERS    = 2.

      IF SY-SUBRC &lt;&gt; 0.
        CONTINUE.
      ENDIF.

      SORT LT_DFIES BY TABNAME FIELDNAME.

    ENDIF.

    LS_SAV_TABNAME = LS_TABNAME.

    READ TABLE LT_DFIES INTO WA_DFIES
         WITH KEY TABNAME   = WA_FILTER-TABNAME
                  FIELDNAME = WA_FILTER-FIELDNAME
         BINARY SEARCH.

    CHECK SY-SUBRC = 0.

    WA_FILTER-POSITION = WA_DFIES-POSITION.
    WA_FILTER-OFFSET   = WA_DFIES-OFFSET / CL_ABAP_CHAR_UTILITIES=&gt;CHARSIZE.
    WA_FILTER-LENG     = WA_DFIES-LENG.

    MODIFY LT_FILTER FROM WA_FILTER.

* Build segment name range
    IF SY-SUBRC = 0.
      WR_SEGNAM-SIGN   = 'I'.
      WR_SEGNAM-OPTION = 'EQ'.
      WR_SEGNAM-LOW    = WA_FILTER-TABNAME.
      COLLECT WR_SEGNAM INTO LR_SEGNAM.
    ENDIF.
  ENDLOOP.

* Loop at IDOC to clear fields
  LOOP AT IDOC_DATA ASSIGNING &lt;FS&gt;.
    IF &lt;FS&gt;-SEGNAM IN LR_SEGNAM.
      LOOP AT LT_FILTER INTO WA_FILTER WHERE TABNAME = &lt;FS&gt;-SEGNAM.
        CLEAR &lt;FS&gt;-SDATA+WA_FILTER-OFFSET(WA_FILTER-LENG).
      ENDLOOP.
    ENDIF.
  ENDLOOP.
ENDMETHOD.</pre>
<p>I also added the following code to IF_EX_HRALE00OUTBOUND_IDOC~IDOC_DATA_FOR_RECEIVER_MODIFY:</p>
<pre style="background-color: #eaeaea; color: #222;">* Clear IDOC fields
CALL METHOD ME-&gt;CLEAR_IDOC_FIELDS
  EXPORTING
     IDOC_CONTROL = IDOC_CONTROL
     RECEIVER     = RECEIVER
     MESTYP       = IDOC_CONTROL-MESTYP
  CHANGING
     IDOC_DATA    = IDOC_DATA.</pre>
<p>Finally, I maintained the following TVARV variable:</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/01-TVARV-Variable.jpg" rel="shadowbox[post-4289];player=img;"><img class="alignnone size-full wp-image-4311" title="01 TVARV Variable" src="http://www.dataxstream.com/wp-content/uploads/2010/02/01-TVARV-Variable.jpg" alt="" width="611" height="362" /></a></p>
<p>That&#8217;s all it takes!  Now individual field values can be easily be filtered from outbound HRMD_A IDOCs!.</p>
<p><em>UPDATE: </em>My colleague informed me that instead of using TVARV, I should continue to use BD53 to manage the IDOC reduction and change my code to look up the field reductions in TBD24.  This would be a great idea, but my full HRMD_A solution uses custom filter objects and a custom IDOC formatting function module.  <a href="http://www.dataxstream.com/2010/02/bd53-doesn%E2%80%99t-play-well-with-others/" target="_self">And BD53 does not play well with these customizations.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/02/how-to-implement-field-level-hrmd_a-reduction/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How To Debug ABAP Web Service on SAP Web Application Server (WAS)</title>
		<link>http://www.dataxstream.com/2009/11/how-to-debug-abap-web-service/</link>
		<comments>http://www.dataxstream.com/2009/11/how-to-debug-abap-web-service/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 11:39:53 +0000</pubDate>
		<dc:creator>Craig Stasila</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP debugger]]></category>
		<category><![CDATA[Craig Stasila]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP ABAP]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=3173</guid>
		<description><![CDATA[Debugging a web service on the ABAP stack of SAP Web Application Server is a very useful procedure to know.  Here's how you do it.]]></description>
			<content:encoded><![CDATA[<p>One of the more confounding aspects of developing in the SAP space is the lack of good, low-level, helpful instructions.  While this post is merely regurgitating information that is readily available elsewhere, it will be done in a manner that (hopefully) will actually be useful to vast majority of ABAP developers out there that,  like me, find a lot of SAP&#8217;s implementation of web services on the ABAP stack confusing.</p>
<p>Debugging a web service on the ABAP stack of SAP Web Application Server is a very useful procedure to know.  Here&#8217;s how you do it.</p>
<p><em><span id="more-3173"></span>Note: This example is for ECC 5.0</em></p>
<ol>
<li>Locate the web service definition in the HTTP Service Hierarchy.  There are two ways to do this:
<ul>
<li><strong>Option 1:</strong> Use transaction <strong>WSCONFIG</strong> and display the configuration for your web service.  Click on the ICF Details button
<a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-01.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3174 aligncenter" title="Debug ABAP Web Service 01" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-01.jpg" alt="Debug ABAP Web Service 01" width="492" height="221" /></p>
<p></a></li>
<li><strong>Option 2:</strong> Start transaction <strong>SICF</strong>. Navigate directly to <em>/sap/bc/srt/rfc/sap</em> for your default host.</li>
</ul>
</li>
<li>Regardless of the method used to get to the service definition for your web service enabled function module, you should have it selected as in this example.
<a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-02.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3175 aligncenter" title="Debug ABAP Web Service 02" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-02.jpg" alt="Debug ABAP Web Service 02" width="599" height="410" /></p>
<p></a></li>
<li>Next, enable the debugger by selecting the <em>Edit\Debugging\Activate Debugging</em> menu.
<p style="text-align: center;"><a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-03.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3176 aligncenter" title="Debug ABAP Web Service 03" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-03.jpg" alt="Debug ABAP Web Service 03" width="522" height="179" />
</a></p>
</li>
<li><a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-03.jpg" rel="shadowbox[post-3173];player=img;"></a>In the ensuing dialog box, confirm the debugging options (the defaults are usually OK).
<span style="background-color: #ffffff;"> <a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-04.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3177 aligncenter" title="Debug ABAP Web Service 04" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-04.jpg" alt="Debug ABAP Web Service 04" width="445" height="222" /></p>
<p></a></p>
<p></span></li>
<li>To exercise the debugger, test your web service.  For this example, I will use the SAP WAS web service test tool, but the application calling the web service can be anything as long as it connects with the debugger&#8217;s user ID.
<a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-05.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3178 aligncenter" title="Debug ABAP Web Service 05" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-05.jpg" alt="Debug ABAP Web Service 05" width="399" height="165" /></p>
<p></a></li>
<li><a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-05.jpg" rel="shadowbox[post-3173];player=img;"></a>When the web service is executed, the debugger will start in a new SAPGUI session (make sure you are already logged in via the SAPGUI prior to executing the web service).
<a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-06.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3185 aligncenter" title="Debug ABAP Web Service 06" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-06.jpg" alt="Debug ABAP Web Service 06" width="468" height="427" /></p>
<p></a></li>
<li>In the debugger, choose <em>Breakpoints\Breakpoint at\Function  Module</em> from the  menu to create a new breakpoint.
<a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-07.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3186 aligncenter" title="Debug ABAP Web Service 07" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-07.jpg" alt="Debug ABAP Web Service 07" width="500" height="178" /></p>
<p></a></li>
<li>Specify the function module that implements your web service.  In the debugger, press F8 to run to your newly created breakpoint.
<span style="background-color: #ffffff;"><a href="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-08.jpg" rel="shadowbox[post-3173];player=img;"><img class="size-full wp-image-3187 aligncenter" title="Debug ABAP Web Service 08" src="http://www.dataxstream.com/wp-content/uploads/2009/11/Debug-ABAP-Web-Service-08.jpg" alt="Debug ABAP Web Service 08" width="405" height="71" /></a>
</span> If the debugger doesn&#8217;t get to your breakpoint, the most likely culprit is malformed input XML.  Check the payload of the message to ensure that it conforms to the specifications of the web service.</li>
</ol>
<p>Once the debugger has started, it is just like debugging any other SAP application.  If you have any specific tips or tricks regarding debugging web services, please share them in the comments section of this blog.</p>
<p><script src="http://www.stumbleupon.com/hostedbadge.php?s=5"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2009/11/how-to-debug-abap-web-service/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
