SAP XI IN ACTION-I



Please read the blog SAP XI IN ACTION before continuing further. I actually planned to depict the implementation of entire approach in this blog but we are stuck up with the XI server issues and due to which I cannot take good snapshots. In this blog , I just want to share a generic mapping object which is used extensively in the design. We have used generic mapping object for converting any flat file structure to any hierarchical idoc structure. It is required because file adapter has the generic interface structure as specified in the previous blog and sample xml file generated for MRI interface would look like this:


It has to be converted to the hierarchical structure of MRI Idoc as shown below. It cannot be done at the file adapter CC due to the limitation of adapter. I have taken a simple Idoc structure for ease of demonstration.


XML after file CC





It is very complex to design the mapping in graphical editor so I went for java mapping. Even in this case we have to develop mapping programs for every interface and each developer has to put his own logic for his interface. Instead I thought of an approach, which would make the code generic, and each developer just specifies the Idoc structure in his interface specific code and generic code will convert any file structure to hierarchical structure .It cuts down the development efforts as each individual has to just specify the structure and the generic code transforms the input Idoc structure as specified in the interface. It worked out really fantastic in the project.


Idoc Structure




Interface Specific Code :


MRIGenToHierMap.java


/*****************************************************************************************************

  • Mapping Program to Convert NOM IDOC Master Structure to the Generic structure Expected by

  • the FTP Receiver adapter

******************************************************************************************************/

import com.sap.aii.mapping.api.*;

import java.io.*;

import java.util.Map;

import java.util.Vector;

import javax.xml.parsers.*;

import javax.xml.transform.*;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.*;

import org.xml.sax.*;

//Specify the Hirearchial Structure

class MRIGenToHierMap implements StreamTransformation

{

 

 

     public Vector v;

    private Map map;

    /** * method setParamters is required, but we do not anything with it */

     public void setParameter(Map param)

     {

          map = param;

     } /** * method execute is called by the XI mapping program */

 

public void buildXsd()

{

 

 

  Relation  mriRel ;

  v = new Vector();

  mriRel = new Relation();

  mriRel.parents = new String[1];

  mriRel.elements = new String[6];

  mriRel.node =  "A00" ;

  mriRel.parents[0] =   "NULL" ;

  mriRel.elements[0] =  "TRANSACTION_TYPE" ;

  mriRel.elements[1] =  "ORGANISATION_ID" ;

  mriRel.elements[2] =  "FILE_TYPE" ;

  mriRel.elements[3] =  "CREATION_DATE" ;

  mriRel.elements[4] =  "CREATION_TIME" ;

  mriRel.elements[5] =  "GENERATION_NUMBER" ;

  v.add(mriRel) ;

 

  mriRel = new Relation();

  mriRel.parents = new String[1];

  mriRel.elements = new String[39];

  mriRel.node = "N90";

  mriRel.parents[0] =   "NULL" ;

  mriRel.elements[0] =  "TRANSACTION_TYPE" ;

  mriRel.elements[1] =  "CONFIRMATION_REFERENCE" ;

  mriRel.elements[2] =  "METER_POINT_REFERENCE" ;

  mriRel.elements[3] =  "EFFECTIVE_DATE" ;

  mriRel.elements[4] =  "METER_LOCATION_CODE" ;

  mriRel.elements[5] =  "METER_LOCATION_DESCRIPTION" ;

  mriRel.elements[6] =  "METER_INSTRUCTIONS" ;

  mriRel.elements[7] =  "BUILDING_NUMBER" ;

  mriRel.elements[8] =  "BUILDING_NAME" ;

  mriRel.elements[9] =  "DEPENDENT_STREET" ;

  mriRel.elements[10] =  "PRINCIPAL_STREET" ;

  mriRel.elements[11] =  "DEPENDENT_LOCALITY" ;

  mriRel.elements[12] =  "POST_TOWN" ;

  mriRel.elements[13] =  "COUNTY" ;

  mriRel.elements[14] =  "METERING_SET_REFERENCE" ;

  mriRel.elements[15] =  "BYPASS_FITTED_INDICATOR" ;

  mriRel.elements[16] =  "METER_SERIAL_NUMBER" ;

  mriRel.elements[17] =  "METER_MODEL_NAME" ;

  mriRel.elements[18] =  "IMPERIAL_METER_INDICATOR" ;

  mriRel.elements[19] =  "METER_NO_OF_DIGITS_OR_DIALS" ;

  mriRel.elements[20] =  "METER_MECHANISM" ;

  mriRel.elements[21] =  "METER_STATUS" ;

  mriRel.elements[22] =  "METER_COLLAR_FITTED_INDICATOR" ;

  mriRel.elements[23] =  "METER_PULSE_VALUE" ;

  mriRel.elements[24] =  "METER_READING_FACTOR" ;

  mriRel.elements[25] =  "CORRECTOR_SERIAL_NUMBER" ;

  mriRel.elements[26] =  "NO_OF_CORRECTED_DIALS" ;

  mriRel.elements[27] =  "NO_OF_UNCORRECTED_DIALS" ;

  mriRel.elements[28] =  "CORRECTION_FACTOR" ;

  mriRel.elements[29] =  "LAST_READ_DATE" ;

  mriRel.elements[30] =  "LAST_INSPECTION_DATE" ;

  mriRel.elements[31] =  "GAS_ACT_OWNERSHIP_TYPE" ;

  mriRel.elements[32] =  "METER_MANUFACTURER_CODE" ;

  mriRel.elements[33] =  "METER_MANUFACTURED_YEAR" ;

  mriRel.elements[34] =  "CONVERTER_MANUFACTURER" ;

  mriRel.elements[35] =  "CONVERTER_MODEL" ;

  mriRel.elements[36] =  "CONVERTER_MANUFACTURED_YEAR" ;

  mriRel.elements[37] =  "CONVERTER_READING_UNITS" ;

  mriRel.elements[38] =  "CORRECTOR_CORRECTION_FACTOR" ;

  v.add(mriRel) ;

 

  mriRel = new Relation();

  mriRel.parents = new String[1];

  mriRel.elements = new String[39];

  mriRel.node = "U06";

  mriRel.parents[0] =   "NULL" ;

  mriRel.elements[0] =  "TRANSACTION_TYPE" ;

  mriRel.elements[1] =  "CONFIRMATION_REFERENCE" ;

  mriRel.elements[2] =  "METER_POINT_REFERENCE" ;

  mriRel.elements[3] =  "EFFECTIVE_DATE" ;

  mriRel.elements[4] =  "METER_LOCATION_CODE" ;

  mriRel.elements[5] =  "METER_LOCATION_DESCRIPTION" ;

  mriRel.elements[6] =  "METER_INSTRUCTIONS" ;

  mriRel.elements[7] =  "BUILDING_NUMBER" ;

  mriRel.elements[8] =  "BUILDING_NAME" ;

  mriRel.elements[9] =  "DEPENDENT_STREET" ;

  mriRel.elements[10] =  "PRINCIPAL_STREET" ;

  mriRel.elements[11] =  "DEPENDENT_LOCALITY" ;

  mriRel.elements[12] =  "POST_TOWN" ;

  mriRel.elements[13] =  "COUNTY" ;

  mriRel.elements[14] =  "METERING_SET_REFERENCE" ;

  mriRel.elements[15] =  "BYPASS_FITTED_INDICATOR" ;

  mriRel.elements[16] =  "METER_SERIAL_NUMBER" ;

  mriRel.elements[17] =  "METER_MODEL_NAME" ;

  mriRel.elements[18] =  "IMPERIAL_METER_INDICATOR" ;

  mriRel.elements[19] =  "METER_NO_OF_DIGITS_OR_DIALS" ;

  mriRel.elements[20] =  "METER_MECHANISM" ;

  mriRel.elements[21] =  "METER_STATUS" ;

  mriRel.elements[22] =  "METER_COLLAR_FITTED_INDICATOR" ;

  mriRel.elements[23] =  "METER_PULSE_VALUE" ;

  mriRel.elements[24] =  "METER_READING_FACTOR" ;

  mriRel.elements[25] =  "CORRECTOR_SERIAL_NUMBER" ;

  mriRel.elements[26] =  "NO_OF_CORRECTED_DIALS" ;

  mriRel.elements[27] =  "NO_OF_UNCORRECTED_DIALS" ;

  mriRel.elements[28] =  "CORRECTION_FACTOR" ;

  mriRel.elements[29] =  "LAST_READ_DATE" ;

  mriRel.elements[30] =  "LAST_INSPECTION_DATE" ;

  mriRel.elements[31] =  "GAS_ACT_OWNERSHIP_TYPE" ;

  mriRel.elements[32] =  "METER_MANUFACTURER_CODE" ;

  mriRel.elements[33] =  "METER_MANUFACTURED_YEAR";

  mriRel.elements[34] =  "CONVERTER_MANUFACTURER" ;

  mriRel.elements[35] =  "CONVERTER_MODEL" ;

  mriRel.elements[36] =  "CONVERTER_MANUFACTURED_YEAR" ;

  mriRel.elements[37] =  "CONVERTER_READING_UNITS" ;

  mriRel.elements[38] =  "CORRECTOR_CORRECTION_FACTOR" ;

  v.add(mriRel) ;

 

  mriRel = new Relation();

  mriRel.parents = new String[2];

  mriRel.elements = new String[6];

  mriRel.node =  "K15" ;

  mriRel.parents[0] =   "N90" ;

  mriRel.parents[1] = "U06";

  mriRel.elements[0] =  "TRANSACTION_TYPE" ;

  mriRel.elements[1] =  "METER_INSTALLATION_DATE" ;

  mriRel.elements[2] =  "METER_LINK_CODE" ;

  mriRel.elements[3] =  "GAS_NOMINATION_TYPE_CODE" ;

  mriRel.elements[4] =  "DATA_LOGGER_SERIAL_NUMBER" ;

  mriRel.elements[5] =  "DATA_LOGGER_UNIQUE_NUMBER" ;

  v.add(mriRel) ;

 

 

}

public void execute(InputStream in, OutputStream out) throws com.sap.aii.mapping.api.StreamTransformationException

{

     MRIGenToHierMap rel = new MRIGenToHierMap();

     rel.buildXsd();

     new GenToHierMap(in,out,rel.v,"MRI_ABSTRACT","urn:horzon:MRI");

 

}

public static void main (String[] args) throws Exception

     {

          try

          {

               MRIGenToHierMap rel = new MRIGenToHierMap();

               FileInputStream in = new FileInputStream ("H:/j2sdk1.4.2_07/bin/DOM_IN.xml");

               FileOutputStream out = new FileOutputStream ("H:/j2sdk1.4.2_07/bin/DOM_OUT.xml");

               rel.buildXsd();

               new GenToHierMap(in,out,rel.v,"MRI_ABSTRACT","urn:horzon:MRI");

 

          }catch(Exception e) {e.printStackTrace();}

     }

}

 

//Transformation of flat structure to hirearchial structure

 

All the 3 files have to be kept in the same directory and the generic java files should be compiled. Input XML has to be kept in the folder specified in the generic code. I would blog more details about the code depending on the demand for the same.

Ravikumar Allampallam

SAP XI IN ACTION

Posted by Ravikumar Allampallam Jun 22, 2005

SAP XI IN ACTION

Blog highlights the approach followed in the real time for integrating 3rd party file system with SAP IS-U using the SAP XI. It also throws light on the pro’s and con’s of the approach. This blog discusses the approach specific for file to idoc scenarios. In our current project we have around 80 different outbound file based interfaces, which has to be posted as Idocs into SAP IS-U system. We have to configure the 80 file adapters to poll the files, which will be a performance bottleneck. We as a team decided to go for a common approach, which can overcome the above bottleneck. We implemented it and found it really easy and useful. We also developed lot of generic objects, which benefited the project and the team. I will share them in the upcoming blogs.

Let me quickly depict the approach:

1.3rd Party file system sends files and those files are routed to a common folder.
2.Common file CC adapter will poll for CSV files belonging to any interface.
3.After files are received, common file adapter routes them to a common ccBPM.
4.Common ccBPM does content based routing to interface specific ccBPM using the file type in the payload of the file.
5.Interface specific ccBPM converts the common file structure into interface specific idoc structure.
6.Idoc adapter converts the incoming XML file into Idoc format and routes it to the receiver configured in the integration directory.

It can be depicted graphically as shown below:

Generic Approach

Pro’s:

1.Good Performance.

2.Re-usable integration directory and repository objects.

3.Cut down of development effort.

4.Approach itself can be re-used across any XI projects, which involve File-Idoc scenarios.

Con’s:

1.Having one file adapter might slow down the performance, as it is queue based messaged processing. Messages might be held up in case the file adapter is down. However, appropriate number of file adapters can be designed basing on the volume and frequency of file specific to XI project.

2.Initial efforts have to be done to make the proto-type work. Since already the initial efforts are done to make the prototype work, which I will be sharing in the upcoming blogs, the efforts for the upcoming projects are minimized.

Please wait for the upcoming blogs for granule details of the implementation!!!!!!!!!!!!

In this weblog we will see how to give access in a controlled manner to the user to change or create new layouts for the reports. We will also see how the user can select a layout on the selection screen, i.e., even before executing the report



How to restrict the user from creating new layout / changing existing layouts.



Before going into the details we need to understand that there 2 different types layouts available – Global layout and User-Defined layouts. As the name suggests global layouts will be available for all the users, where as the user-defined layouts will be available for only those users who have created it.



Normally this is what the user sees, when an ALV report is displayed.

image

Here the user has got access to do everything with the layouts.



Not sure if you have observed in the last weblog when the SET_TABLE_FOR_FIRST_DISPLAY method was called, there was a parameter called I_SAVE and we passed a value ‘A’ to it. This implies that the user will have all kinds of access to the layouts. Now if we do NOT pass anything to this parameter, the user will loose the privileges to delete / create new layouts. However he will still be able to select a different layout and change an existing one, however he will not be able to save the changed one.



image

Next variation - I_SAVE = ‘X’.



This is where the trick happens. When you pass ‘X’, although you see all the options for the layouts, the user will not be able save User-Defined Layouts.



image

image

Next variation - I_SAVE = ‘U”.



This is exactly opposite to the previous one. The user will be able save only user-define layouts.



image

So, here is the summary.

I_SAVE = SPACE (Default)- Layouts cannot be saved

I_SAVE = ‘U’ - Only User-Define Layouts can be saved

I_SAVE = ‘X’ - Only Global Layouts can be saved

I_SAVE = ‘A’ - Both user-defined and global layouts can be saved.



In addition to these we will see how to remove some of the standard functionality given the standard ALV toolbar.



Now, that we have seen how to control the layouts, we will now see how to access them on the selection screen.



Define a parameters on the selection – screen (Eg: P_LAYOUT LIKE DISVARIANT-VARIANT)



Invoke the following subroutine on value request for the parameter






This subroutine will throw a message if there are no layouts




image


Or, show the list of layouts if available

image


You can select one of the layouts and the name will be populated in the parameter field. Now the question is how to you make sure that this layout is used while showing the grid.



If you have observed there was one more parameter that we passed to SET_TABLE_FOR_FIRST_DISPLAY called IS_VARIANT and the variable that we passed to this was WA_VARIANT. Fill the variable as shown below and the layout tha was selected on the selection will be used to display the grid.



WA_VARIANT-REPORT = SY-REPID.
WA_VARIANT-USERNAME = SY-UNAME.
WA_VARIANT-VARIANT = P_LAYOUT.



Now we know all the options to play with Layouts. However the combination the IS_VARIANT and I_SAVE also play a crucial role. So, use them according to your requirements.



In the next weblog we will see how to restrict the user from using some standard features of the ALV toolbar by not displaying them. Also, we will see how to add custom functions to the toolbar and respond to the events.

Most of us have been developing and using ALV reports for quite sometime now. I haven’t noticed any web logs that give steps of how to go about creating an ALV report from scratch, using control framework technology. Using reusable function module, I am sure the programmers should be able figure out how to use the same. So, I thought it would be a good idea to give the basic steps in creating an ALV report and then follow it up with next web logs where the advanced features of the ALV grid will be used.


Once we reach a certain stage with ALV grid, we will move on to other controls that SAP provides (Tree Control, Text Edit Control etc).


The main difference between a classical report and an ALV report is that we need to create a screen with controls on the same in an ALV report as opposed to in a classical report where we do NOT deal with screens directly, rather use a write statement.


In the example report we will try to develop a simple report to display the material details.


Following the basic structure of a report program ...





In the Screen 100

On the screen, place a control (Can found in the toolbar on the left hand side and maximize to occupy the entire screen (200 x 240). In the attributes of the screen, check the resizing options for both vertical and horizontal. By doing this system will automatically take care of the double scroll bars that might appear, one for the grid if you have got more data and the other one for the screen.


image



image





This report should display a basic ALV Report with the standard toolbar of ALV, which will give the user options to SORT, change the display order, total, sub-total by a specific column etc.



In the next weblog we will see how to control access to the save / change layouts, how to select a layout at the selection screen level etc etc.