Some tips and tricks for adapter modules lifecycle management
Posted: January 25, 2015 Filed under: Uncategorized Leave a commentFrom my SCN blog : http://scn.sap.com/community/pi-and-soa-middleware/blog/2015/01/25/some-tips-and-tricks-for-adapter-modules-lifecycle-management
Recently I was involved in migrating lot of adapter modules from a PI 7.0 system to a PI 7.4 environment. Creating a custom adapter module is not too complicated but like anything else, we need to be clear of all the components involved and their implications. There is a very good SDN document about the steps to create one. However, in my experience keeping the following points i makes the development process much smoother.
1. Understanding the descriptor files:
Most of the issues with adapter modules occur as one of the descriptors is wrong. Let’s go through them.
a) ejb-j2ee-engine.xml: This file will be in the EJB project. This links the EJB name with the JNDI name. Hence, if you are getting a module not found error, most likely you need to check your jndi-name.
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?>
<ejb-j2ee-engine
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“
xsi:noNamespaceSchemaLocation=”ejb-j2ee-engine.xsd”>
<enterprise-beans>
<enterprise-bean>
<ejb-name>ToUpperCase</ejb-name>
<jndi-name>ToUpperCase</jndi-name>
</enterprise-bean>
</enterprise-beans>
</ejb-j2ee-engine>
b) ejb-jar.xml : This is in the EJB project as well . This has the actual class name, EJB interface names, bean type etc. The key thing here is to check the ejb-name and the class name. The home,local, remote and local-home names always stay the same.( to standard SAP values ). This causes a lot of errors as normally people just accept the default provided names for these interfaces and it causes errors.
<?xml version=“1.0“ encoding=“UTF-8“?> | |
<ejb-jar xmlns=“http://java.sun.com/xml/ns/j2ee“xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance“ id=“ejb-jar_ID“ version=“2.1“xsi:schemaLocation=“http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd“> | |
<enterprise-beans> | |
<session> | |
<icon/> | |
<ejb-name>ToUpperCase</ejb-name> | |
<home>com.sap.aii.af.lib.mp.module.ModuleHome</home> | |
<remote>com.sap.aii.af.lib.mp.module.ModuleRemote</remote> | |
<local-home>com.sap.aii.af.lib.mp.module.ModuleLocalHome</local-home> | |
<local>com.sap.aii.af.lib.mp.module.ModuleLocal</local> | |
<ejb-class>com.demo.ToUpperCasebean</ejb-class> | |
<session-type>Stateless</session-type> | |
<transaction-type>Container</transaction-type> | |
</session> | |
</enterprise-beans> | |
</ejb-jar> |
c) application-j2ee-engine.xml : This file is in the EAR project and stays the same, unless the project needs additional libraries.
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?>
<application-j2ee-engine
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:noNamespaceSchemaLocation=”application-j2ee-engine.xsd”>
<reference
reference-type=”hard”>
<reference-target
provider-name=”sap.com”
target-type=”service”>engine.security.facade</reference-target>
</reference>
<reference
reference-type=”hard”>
<reference-target
provider-name=”sap.com”
target-type=”library”>engine.j2ee14.facade</reference-target>
</reference>
<reference
reference-type=”hard”>
<reference-target
provider-name=”sap.com”
target-type=”service”>com.sap.aii.af.svc.facade</reference-target>
</reference>
<reference
reference-type=”hard”>
<reference-target
provider-name=”sap.com”
target-type=”interface”>com.sap.aii.af.ifc.facade</reference-target>
</reference>
<reference
reference-type=”hard”>
<reference-target
provider-name=”sap.com”
target-type=”library”>com.sap.aii.af.lib.facade</reference-target>
</reference>
<reference
reference-type=”hard”>
<reference-target
provider-name=”sap.com”
target-type=”library”>com.sap.base.technology.facade</reference-target>
</reference>
<provider-name>sap.com</provider-name>
<fail-over-enable
mode=”disable”
xsi:type=”fail-over-enableType_disable”/>
</application-j2ee-engine>
This file has references of libraries etc. when the application is running. A good way to check that the references are correct is by going to Java Class Loader on the application server and give the component name.
In the below screen-shot we’re able to fins component type “service” with name “engine.security.facade” as updated in application-j2ee-engine.xml .
Addiing additional references: If we’re using additional libraries, we need to update the reference in the below way.
– Add the client libraries to allow compilation. Many of the libraries are already available in NWDS plugins ( e.g. JCO 2/3 libraries ). However, in some cases they will need to be obtained from SAP PI application server.
– Refer Javadoc to understand the DC that contains the class. Taking interface ApplicationPropertiesAccess as an example. Javadoc at
gives the DC as:
[sap.com] tc/je/appconfiguration/api
Hence, the deployment descriptor will need to be updated as:
<reference reference-type=”hard”>
<reference-target provider-name=”sap.com”
target-type=”service“>
tc~je~appconfiguration~api
</reference-target>
</reference>
2. Renaming adapter module name: We need to update a module name many a times. Some of the reasons could be:
– While testing, we gave a “test” name and want to change the module name without rewriting the whole project.
– Create a new version and test it out in some scenarios before changing configuration everywhere.
The adapter module name that we configure in adapter modules is actually the JNDI name in ejb-j2ee-engine.xml. So initially the ejb and jndi names were the same.
In the below screenshot, I changed the JNDI name to Convert2Up
After making only the JNDI name, I sent a test message after updating the adapter module config parameters and it works fine.
3. Adding software component information: The adapter module can be deployed directly from NWDS by running the EAR project on the application server. However, it is better to organise custom software components like SAP delivered software components in its own namespace so that it’s easier to track the inventory and get all the benefits of application lifecycle management.
Without the software component information, we can verify the bean is successfully deployed by checking JNDI browser.
However, if there are multiple beans, we need to know their names. It’s better to organise in their own namespace. We need to go through the below process : EAR –> SDA –> SCA
The steps required are :
– Convert EAR to SDA file ( which is EAR file along with SAP specific manifest info in SAP_MANIFEST.MF file )
– Add SDA file to a SCA file along with the software component information
The easiest approach is to use nwpacktool . Update the batch file with JAVA_HOME and NWPACKTOOLLIB.
Then lanuch the batch ( or .sh ) file. As an example, to create a SDA file from the EAR.
Now, add component information and create a SCA file.
Now, deploy the SCA file . We can display all custom modules created under the same component.In the below screen-shot, two beans are deployed under SC “AdaptModules” with the first bean having version 3.
It’s easier to deploy to any system as well since there is only one SCA file to be updated .
Storing password in SAP PI modules
Posted: January 21, 2015 Filed under: Uncategorized Leave a commentFrom my SCN blog : http://scn.sap.com/community/pi-and-soa-middleware/blog/2015/01/21/storing-password-in-sap-pi-modules
Storing password in SAP PI modules.
Setting user and password inside a module is slightly different from normal adapter module parameters as the text can’t be kept in clear-text in module parameters.
Three strategies we can use:
1) Use hard-coded user id and password in the module. Not a great approach but sometimes this can be the only feasible option. The advantage of course is that there is no risk of locking the user.
2) Setting in comm channel as a secure parameter ( displayed as asterisk ).
Here, user can be set as a normal string parameter. For passwords, we don’t want the password to show up in clear text. Hence, password can be the following:
- – If password parameter starts with pwd, it’s displayed as asterisks when entered and displayed. However, the database folder is unencrypted.
- – If password parameter starts with cryptedpassword, the database folder is encrypted. This is more secure as the database folder is encrypted.
The advantage is that the values can be configured for each system and the drawback being if the password is not correctly entered it can get locked and trying to find the comm channel which is locking the user can be time consuming.
3) Setting values in Application Properties. This combines the best of both worlds – we’re able to configure values in each environment and as we’re configuring it in only one location, the chances of accidentally locking the user due to incorrect values is reduced.
The values can be modified from NWA. The path is:
Configuration Management->Infrastructure->Java System Properties
Steps required to add configuration capacity.
a) Add sap.com~tc~je~configuration~impl.jar to the module EJB project.
Path to get the client library: /usr/sap/<SID>/<instance>/j2ee/cluster/bin/services/configuration/lib/private/sap.com~tc~je~configuration~impl.jar
b) Create sap.application.global.properties file under META-INF. It’s essentially a .properties file.
Sample content to make User modifiable and appear as clear text
## Comment for user
#? secure = false; onlinemodifiable = true
#% type = STRING;
User =
Sample content to make User modifiable and appear as asterisk when entering in NWA.
## Comment for password
#? secure = true; onlinemodifiable = true
#% type = STRING;
Password =
c) Update module code to read the property
Sample code will look something like this ( to be added in the module code )
// Obtain the JNDI context
InitialContext ctx = new InitialContext();
// access the Application-Configuration-Façade service
ApplicationPropertiesAccess appCfgProps = (ApplicationPropertiesAccess) ctx.lookup(“ApplicationConfiguration”);
java.util.Properties appProps = appCfgProps.
if (appProps == null) {
// perform error handling
}
else
{
userID = appProps.getProperty(“
password = appProps.getProperty(“Password”);
}
d) Update application deployment descriptor to indicate the library being used. Add this to application-j2ee-engine.xml .
<reference reference-type=”hard”>
<reference-target provider-name=”sap.com”
target-type=”service”>
tc~je~appconfiguration~api
</reference-target>
</reference>
Understanding SLD API for mass creation of business systems / other SLD objects
Posted: November 6, 2014 Filed under: Uncategorized Leave a commentFrom my blog on SCN:
oData AND SAP NW Gateway OVERVIEW
Posted: September 10, 2014 Filed under: oData, SAP Gateway Leave a commentLink to presentation on “oDATA AND SAPGateway”I did earlier this year.
http://slides.com/sakiv/odatagatewayintro#/
SAPUI5 with Gateway
Posted: September 10, 2014 Filed under: HMTL5, SAP, SAP Gateway, SAP Mobile, SAPUI5/OpenUI5 Leave a commentLink to presentation I did earlier for training my colleagues.
http://slides.com/sakiv/sapui5withgateway#/
Understanding CSV files and their handling in ABAP
Posted: September 10, 2014 Filed under: SAP, SAP ABAP Leave a commentFrom my blog on SCN
http://scn.sap.com/community/abap/blog/2014/09/09/understanding-csv-files-and-their-handling-in-abap
Mac – add ADB to path ( Android )
Posted: September 1, 2014 Filed under: Android, Mobile Leave a commentcd
create file .bash_profile
touch .bash_profile
open file with TextEdit
open -e .bash_profile
insert line into TextEdit
export PATH=$PATH:/Users/username/custompath/sdk/platform-tools/
save file and reload file
source ~/.bash_profile
check if adb was set into path
adb version
Installation and version management of mobile applications without any MDM solution
Posted: August 23, 2014 Filed under: iOS/ ObjectiveC, Mobile, SAP, SAP Mobile Leave a comment
Retain selection screen values on program restart for transactions with chosen selections
Posted: August 20, 2014 Filed under: SAP, SAP ABAP | Tags: SAP, SAP ABAP Leave a commentFrom my blog on SCN
I had an interesting last week and what looked easy at the outset did my head in for quite a while. I tried various methods and the below approach was able to give me a satisfactory solution.
Let’s have a look at the high level requirement.
– Copy a standard SAP transaction and customise it . Below picture describes the requirement
The transaction is started with only few fields of the complete selection screen as the selection screen has too many fields and may confuse the users.
The users need to navigate back and forth between different modes of output screen. At the first display of output screen ( let’s call them as levels – so the output screen is at level 0 when initially displayed and if called again goes to level 1 and so on . Similarly when the user comes back from a higher level of screen, the level will decrease : from 1 to 0 ). And of course when the program navigates back from level 0 of selection screen, it should display the selection screen.
I prototyped using a simple program using flight model.
– Selection Screen : Contains all fields.
However, the transaction is always run with a variant which hides the last field.
– Let’s test with some data.
We get the level 0 output screen.
Now click on filter ( search icon on top right )
and we get level 1 screen.
Looks good so far. Now, let’s try going back – going back to level 0 gives the screen as anticipated. However, when we go back and see that the selection screen parameters have gone back. The selection screen has gone blank !
Let’s see what’s going on.
As we need to keep track of different levels of screen, if the level of screen is greater than 0.
…….
ELSEIF sy–ucomm = ‘EXIT’.
IF gv_list_level > 0.
gv_list_level = gv_list_level – 1.
gt_flight[] = gt_master_flight[].
CALL SCREEN 100.
ENDIF.
When we want to go back to selection screen from screen at level 0, we use below:
SUBMIT zsubmit_flight
WITH report EQ ‘ZTESTFLIGHT’
WITH variant = ‘ZFLIGHT_VAR’
WITH SELECTION-TABLE gt_seltab .
zsubmit_flight is a standard SAP report used by the report and can’t be changed by us.
SUBMIT (REPORT) WITH VARIANT = VARIANT
USING SELECTION–SET VARIANT
VIA SELECTION-SCREEN
Workaround:
1) Store selected values by call of RS_REFRESH_FROM_SELECTOPTIONS
2) Export the selection table before doing a program restart.
EXPORT gt_seltab TO MEMORY ID gc_sel_mem.
3) Retrieve the selection table AT SELECTION-SCREEN OUTPUT.
RS_VARIANT_CONTENTS gives the parameters and select-options actually visible in the variant.
IMPORT gt_seltab FROM MEMORY ID gc_sel_mem.
IF NOT gt_seltab[] IS INITIAL.
CALL FUNCTION ‘RS_VARIANT_CONTENTS’
EXPORTING
report = ‘ZTESTFLIGHT’
variant = ‘ZFLIGHT_VAR’
TABLES
l_params = lt_params
l_selop = lt_selops
valutab = lt_value
EXCEPTIONS
variant_non_existent = 1
variant_obsolete = 2
OTHERS = 3.
IF sy–subrc <> 0.
clear: lt_value,
lt_selops,
lt_value.
ENDIF.
* Update parameters values
LOOP AT lt_params INTO lw_param.
READ TABLE gt_seltab REFERENCE INTO lo_values WITH KEY selname = lw_param–name.
IF sy–subrc = 0.
lv_attr = lo_values->selname.
TRANSLATE lv_attr TO UPPER CASE.
ASSIGN (lv_attr) TO <fs_attr_val>.
<fs_attr_val> = lo_values->low.
ENDIF.
ENDLOOP.
* Update select-option values
LOOP AT lt_selops INTO lw_param.
READ TABLE gt_seltab REFERENCE INTO lo_values WITH KEY selname = lw_param–name.
IF sy–subrc = 0.
CONCATENATE lo_values->selname ‘SIGN’ INTO lv_attr SEPARATED BY ‘-‘.
TRANSLATE lv_attr TO UPPER CASE.
ASSIGN (lv_attr) TO <fs_attr_sign>.
<fs_attr_sign> = lo_values->sign.
CONCATENATE lo_values->selname ‘OPTION’ INTO lv_attr SEPARATED BY ‘-‘.
TRANSLATE lv_attr TO UPPER CASE.
ASSIGN (lv_attr) TO <fs_attr_option>.
<fs_attr_option> = lo_values->option.
CONCATENATE lo_values->selname ‘LOW’ INTO lv_attr SEPARATED BY ‘-‘.
TRANSLATE lv_attr TO UPPER CASE.
ASSIGN (lv_attr) TO <fs_attr_low>.
<fs_attr_low> = lo_values->low.
CONCATENATE lo_values->selname ‘HIGH’ INTO lv_attr SEPARATED BY ‘-‘.
TRANSLATE lv_attr TO UPPER CASE.
ASSIGN (lv_attr) TO <fs_attr_high>.
<fs_attr_high> = lo_values->high.
lv_attr = lo_values->selname.
TRANSLATE lv_attr TO UPPER CASE.
ASSIGN (lv_attr) TO <fs_attr_main>.
CONCATENATE lv_attr ‘[]’ INTO lv_attr_tab.
ASSIGN (lv_attr_tab) TO <fs_attr_tab>.
IF lo_values->low IS NOT INITIAL OR lo_values->high IS NOT INITIAL.
REFRESH <fs_attr_tab>.
APPEND <fs_attr_main> TO <fs_attr_tab>.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
– Create a transaction ‘ZFLIGHT’ with program ZTESTFLIGHT , variant ZFLIGHT_VAR.
The code can be referred here:
The code can be referred here:
ZSUBMIT_FLIGHT
https://github.com/viksingh/ABAP_Demo/blob/master/ZSUBMIT_FLIGHT
Program ZTESTFLIGHT with issues:
https://github.com/viksingh/ABAP_Demo/blob/master/ZTESTFLIGHT_1
Program ZTESTFLIGHT with corrections:
ABAP_Demo/ZTESTFLIGHT_2 at master · viksingh/ABAP_Demo · GitHub
The key here is function module RS_VARIANT_CONTENTS and the dynamic update of selection screen after restart of a transaction.
ZSUBMIT_FLIGHT
https://github.com/viksingh/ABAP_Demo/blob/master/ZSUBMIT_FLIGHT
Program ZTESTFLIGHT with issues:
https://github.com/viksingh/ABAP_Demo/blob/master/ZTESTFLIGHT_1
Program ZTESTFLIGHT with corrections:
ABAP_Demo/ZTESTFLIGHT_2 at master · viksingh/ABAP_Demo · GitHub
The key here is function module RS_VARIANT_CONTENTS and the dynamic update of selection screen after restart of a transaction.
ABAP dynamic internal table sort saves the day
Posted: August 16, 2014 Filed under: SAP, SAP ABAP Leave a commentRequirement to refresh the ALV to display only display unique fields. Thankfully the sort fields of an itab can be specified dynamically now.
TRY.
SORT gt_output BY (lt_sorttab).
DELETE ADJACENT DUPLICATES FROM gt_output COMPARING ALL FIELDS.
CATCH cx_sy_dyn_table_ill_comp_val.
gt_output[] = lt_output[].
ENDTRY.