With SL Toolset SP2, there is an option provided to integrate CTS+ with your own applications. This document describes the interfaces and configuration steps that are required to be able to use CTS+ with applications CTS+ is not supported in the standard delivery.
How To... Implement CTS+ for Your Application
ABAP proxy to SFTP with PGP Encryption using SAP PI 7.4 dual stack
Step by step to develop ABAP proxy to SFTP with PGP encryption:
Technical Flow:
Pre-requsities to communicate SFTP with PI.
- SFTP PGP ADDON installation on PI.
- BASIS team to generate a new public key certificate.
- After generating the certificate need to send to SFTP server admin to generate server finger prints.
- Then the server finger prints should be maintained in PI server.
- ESR & ID config.
- Proxy connectivity setup between ECC and PI.
Steps to install PGP ADDONS in PI:
1. Open the NetWeaver System Information using following URL
http://<host>:<port>/nwa/sysinfo
2. Open Tab “Components Info”
3. If you are able to find the Component Name “PIB2B_SFTP”. That means PI server is successfully deployed with SAP PI SFTP PGP ADDON.
check that SFTP Application is started from NWA->Operations->Start & Stop->Java Applications
Generating Certificates:
1. Generate Private and Public Certificate in PI System and Extract Public certificate
Generate and Extract the public X.509 Certificate from SAP PI NetWeaver Administrator -> Configuration ->Certificates and Keys using Button “Export Entry”
2. Convert Public PI X.509 certificated into SSH compatible public key.
Since PI NWA key storage doesn't support SSH keys for Private key based authentication, OpenSSL utility is required convert SSL keys to SSH keys and vice versa. OpenSSL can be installed separately in SFTP server.
To import the public key in SSH compatible SFTP server. First convert the PI X.509 certificate into SSH based public key.
PuTTY can use as client software to connect to SFTP server. It works as command prompt screen to execute key convert commands provided by OpenSSL. Conversion can take place in two steps.
Convert X.509 Certificate into Open SSL based certificate. We can use following command in SSH based client like putty
openssl x509 -in {X.509 Certificate}.cert -noout -pubkey > {Open SSL based certificate}.pkey
File has been generated now.
Convert Open SSL Based certificate into SSH based certificate. We can use following command in SSH based client like putty.
ssh-keygen -i -m PKCS8 -f {Open SSL based certificate}.pkey > {SSH based certificate}.pkey.pkey
File has been generated now.
Keys are generated in SFTP directory.
Import PI public certificate in SFTP Server:
SAP PI converted public key must be registered with the SSH server, typically by copying it into the server's authorized_keys file.
Keys are imported in user folder: <user>/.ssh as shown in above screen shot and this user would be used while making connection to SFTP server.
Go to the root folder of the user account & check for the folder „.ssh‟.
Create one, if the folder does not exist. Check for the file - authorized keys‟, Create one if it‟s not available.
File must be entered in exactly one line
If server need to authorise multiple public key for particular user, Paste the public key content in new line as following screen shot.
Generated server finger prints :
To Establish proxy Connectivity set up between ECC and PI:
- Create RFC Destination in ECC to connect to PI system.
- Configuration Business System as Local Integration Engine (ECC System)
- Create RFC destination (TCP/IP) LCRSAPRFC for the SLD connection to establish the connection between Business System and SLD (ECC System)
- Create RFC destination (TCP/IP) SAPSLDAPI for the SLD connection in ECC
- Maintaining the SAP J2EE Connection parameters for LCRSAPRFC and SAPSLDAPI in SAP J2EE Engine
ESR Part:
Message Mapping:
ID Part:
For proxy no need to create sender communication channel and sender agreement.
Receiver communication channel:
Module Configuration to convert XML to Plain with PGP encryption:
Testing:
File has been placed in SFTP folder with PGP encryption
PGP Encryption:
SAP Insider - Guide to SAP Development Tools
This document provides an overview and guide to SAP's development tools - both Eclipse and Web based.
Data Archiving in Composition Environment with NetWeaver Java Scheduler
Applies to:
SAP NetWeaver CE 7.2 (SP 03) / CE 7.1 Ehp 1 (SP 03), JDK 1.6/ JDK 1.5, XML, JAXB.
Summary:
In many custom business application we are using CAF Business objects their might be requirement of archive data of CAF Business Objects for auditing and future purposes. Here I am discussing step by step configuration of NetWeaver Scheduler and corresponding custom java coding.
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on: 22 January 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Service as Assistant Consultant and development of SAP EP , composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Introduction
In custom composite application for data storing, normally we are using CAF Business Objects. But we required archiving them after certain time of period for auditing or future purposes. For this requirement I have made a custom application via which we can easily archive our CAF BO data and restore them when required to CAF BO. The data archive application will be triggered via NetWeaver Scheduler. The mechanism I have used to do the custom application as follows: a) read the desired CAF BO and generate one xml file with help of JAXB api into the Hard disk of the server and delete the content of the CAF BO b ) then using java util zip api to create one zip file and put the xml file into it and delete the xml file from the hard disk of the server c) and store the name of the CAF BO with actual path where the zip file stored into server into another CAF BO. d) When restore mechanism will triggered from the zip file read the content and data will be back to the actual CAF BO and entry will be delete from the History CAF BO.
Create Projects
For this custom application we required one CAF project. With the name: example/ce/archive
Implementation
CAF Project
To do the CAF project please follow the below instruction.
Steps | Screen Shots |
---|---|
Step 1: Choose File -> New - > Project of your Netweaver Developer Studio of CAF perspective. | ![]() |
Step 2: One popup window come and goes to the Development Infrastructure - > Development Component and press next button in the below. | ![]() |
Step 3: Then one popup will be come and choose Development Component type: Composite Application. And press next button. | ![]() |
Step 4: Then choose the software component type where you are going to create your development component. | ![]() |
Step 5: Then another new popup will be come and provide the details as per requirement. | ![]() |
Step 6: The press next button and then finish button. It will create a CAF project into your workspace. | ![]() |
Step 7: Now our project is ready. | ![]() |
Step 8 : Right click on the modeled package | ![]() |
Step 9: Now we are going to create a CAF BO with name BOToArchive. | ![]() |
Step 10: The go to the Permission tab of CAF BO and unchecked the Permission check Enabled option | ![]() |
Step 11: Then go to the structure tab of CAF BO and press the button Edit Main Structure | ![]() |
Step 12: The create two fields with name a)Id data type String cardinality 0 -1 b) Value data type xLongText cardinality 0 -1 | ![]() |
Step 13: We have to create another CAF BO for storing archive path and CAF BO names. Provide the new CAF BO name : History and create two fields a)Id data type string b)Path data type xLongText | ![]() |
Step 14: Now we have to create one Application service with name : DataArchiveApp | ![]() |
Step 15: Then one popup will be come and provide the name of the application service. Then press finish button. | ![]() |
Step 16: Then it will generate the application service and check the Generate remote Interface option. Under general tab of application service. | ![]() |
Step 17: Now we have to create one custom structure for input parameter of delete_ZIP method. Structure Name : BODeleteStruct | ![]() |
Step 18: After you create the custom structure it should look like as screenshot. Cardinality ; 0 - n | ![]() |
Step 19: Now we have to create custom method to our application service. To do those go to the operations tab of our application service. Then press the Add button one popup will be come and choose the first radio button with option Custom operation and then provide the name of operation.
| |
Step 20: Now we are adding two CAF BO objects to our Application service via dependency tab of application service. | ![]() |
Step 21: Now we have to create few general java class for archive our data. Please go to the Java perspective and create name : JAXB_Data_Structure with package : com.tcs.jaxb.data.structure | ![]() |
Step 22: Now we have to create another java class name : JaxbUtil with lot of methods with package : com.tcs.jaxb.util | package com.tcs.jaxb.util;
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; import java.util.Calendar; import java.util.Random; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException;
/** *@author * */ publicclass JaxbUtil {
/** *Thismethodcreatethezipfile andreturntheAbsolutefilepath * *@paramstringsFileName- * PasstheFileNametobeZIP *@return-Astringobjectwithabsolutepath */ publicstatic String createZIP (String stringsFileName,String stringBOName) {
String zipFileName = ""; zipFileName = createDirectory() + "/" + stringBOName+"-"+createId() + ".zip";
try { File file = new File(zipFileName); ZipOutputStream out = new ZipOutputStream( new FileOutputStream(file)); out.putNextEntry (new ZipEntry(stringsFileName));
BufferedReader bufferedReader = new BufferedReader (new FileReader(stringsFileName)); String string; while ((string = bufferedReader.readLine()) != null) { out.write(string.getBytes()); } bufferedReader.close(); out.closeEntry(); out.flush(); out.close(); zipFileName = file.getAbsolutePath(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
return zipFileName; }
/** *ThisMethodCreateUniqueID * *@return-AStringobjectwiththeID */ publicstatic String createId() { return Long.toHexString (Calendar.getInstance().getTimeInMillis()) + "-" + Integer.toHexString ((new Random()).nextInt() % 65536); }
/** *ThismethodReadtheZIPFileand returnsContentoftheFileinaString *object * *@paramstringFileName- * PasstheFilenametoberead *@return-ContentofthefileinaStringobject */ publicstatic String readZipFile(String stringFileName) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ZipFile zipFile = new ZipFile(new File(stringFileName));
ZipInputStream zipInputStream = new ZipInputStream( new FileInputStream(stringFileName));
ZipEntry zipEntry = zipInputStream.getNextEntry();
BufferedReader reader = new BufferedReader(new FileReader( stringFileName)); byte[] bs = reader.readLine().getBytes(); reader.close();
zipInputStream.closeEntry(); zipInputStream.close();
InputStream inputStream = zipFile.getInputStream(zipEntry);
int len; while ((len = inputStream.read(bs)) > 0) {
byteArrayOutputStream .write(bs, 0, len); } inputStream.close(); byteArrayOutputStream.close();
} catch (ZipException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return byteArrayOutputStream.toString();
}
/** *ThismethodDeletethepassedfile. * *@paramstringFileName- * Passthefilepathtobedelete */ publicstaticvoid deleteFile(String stringFileName) { File file = new File(stringFileName); if (file.exists() && file.isFile()) { file.delete(); } }
/** *ThismethodcreateaNewFile andwritecontentstotheNewlyCreated *file * *@paramstringFileContent- * Passthecontentofthefiletobewritten *@return-Astringobjectwith AbsoluteFileDirectory */ publicstatic String writeToHD(String stringFileContent) { String string = null; try { string = createDirectory() + "/" + createId() + ".xml"; File file = new File(string);
if (!file.exists()) { file.createNewFile(); } BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter( file)); bufferedWriter.write(stringFileContent); bufferedWriter.close(); string = file.getAbsolutePath(); } catch (IOException e) { // TODO Auto-generated catch block
} return string; }
/** *ThisMethodconvertsJavaObject toXMLTreeandReturntoStringObject * *@paramobject- * forJavaObjectDataStructure(WithData) *@paramclass1- * forJavaClass(DataStructureClassInstance) *@return-AStringObjectWithXMLFormat */ publicstatic String jaxbMarshalConvertJavaObjectToXMLTree(Object object, Class<?> class1) { StringWriter writerPage = new StringWriter(); try { JAXBContext jaxbContextPage = JAXBContext.newInstance(class1); jaxbContextPage .createMarshaller().marshal(object, writerPage); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return writerPage.toString(); } /** *ThismethodconvertsXMLTreeObjecttoJavaObject. * *@paramstringReadPage- * PassDataStreamlikeaStringobject *@paramclass1- * PassTheDataStructureClassInstance *@return-ObjectofJavaDataStructure, youhavetoCastwhereyou * callingthismethodwithJavaDataStructure */ public static Object jaxbUNMarshalConvertXMLTreeToJavaObject( String stringReadPage, Class<?> class1) { Object dataStructureReadPage = null; try { JAXBContext jaxbContextPage = JAXBContext.newInstance(class1); dataStructureReadPage = (Object) jaxbContextPage .createUnmarshaller().unmarshal( new StringReader(stringReadPage)); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return dataStructureReadPage; }
/** *ThismethodcreateaDirectoryintheHD inthedefineddirectorye.g: *"/usr/sap/"+SystemName+"/XML_DAS/" * *@return-AStringObjectwithdetailsof AbsolutePathofDirectory */ public static String createDirectory() { File file = null;
String sysNam = System.getProperty("SAPSYSTEMNAME"); String stringDirPathName = "/usr/sap/" + sysNam + "/" + "XML_DAS" + "/"; if (stringDirPathName != null && !"".equals(stringDirPathName)) { file = new File(stringDirPathName); if (!file.mkdirs()) { file.mkdirs(); } } if (null != file.getAbsolutePath()) { stringDirPathName = file.getAbsolutePath(); } return stringDirPathName; } } |
Step 23: Now we have to add DC reference to use SAP NetWeaver Scheduler mechanism into our project to do that open the project into component properties and go to the dependency tab and press the add button one popup will be come and chose ENGFACADE[sap.com] and from this tree select tc/je/scheduler/api and press next button and select deploy time and build time options. And press the finish button. | ![]() |
Step 24: Now it will come as screenshot. | ![]() |
Step 25: Now we have to create Message driven bean for scheduler. Create a message driven bean of name : Example_Shcedule with supper class MDBJobImplementation with destination name : MyDestinations and then press next button and then press the finish button without changing any default configuatraion. Package : com.tcs.nw.scheduler | ![]() |
Step 26: Now we have to access the Application service due to that we have to use EJB annotation. | package com.tcs.nw.scheduler;
import javax.ejb.ActivationConfigProperty; import javax.ejb.EJB; import javax.ejb.MessageDriven; import javax.jms.MessageListener;
import com.tcs.example.ce.archive.modeled .appsrv.dataarchiveapp. DataArchiveAppServiceLocal; import com.sap.scheduler. runtime.JobContext; import com.sap.scheduler. runtime.mdb.MDBJobImplementation;
/** *Message-DrivenBean implementationclassfor:Example_Shedule * */ @MessageDriven( activationConfig = {@ActivationConfigProperty( propertyName="messageSelector", propertyValue="JobDefinition='Example_JobBean'"), @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Queue" ) }, mappedName = "MyDestination") publicclass Example_Shedule extends MDBJobImplementation implements MessageListener {
privatestaticfinallongserialVersionUID = 4485561670312885280L;
@EJB(name="com.tcs.example.ce.archive.modeled. appsrv.dataarchiveapp.DataArchiveApp") DataArchiveAppServiceLocal dataArchiveAppServiceLocal; /** *@seeMDBJobImplementation #MDBJobImplementation() */ public Example_Shedule() { super(); // TODO Auto-generated constructor stub }
@Override publicvoid onJob(JobContext arg0) throws Exception { // TODO Auto-generated method stub dataArchiveAppServiceLocal.dataArchive(); }
} |
Step 27: Now we have to create job-defination.xml file into META-INF folder of ejb module of CAF project for searching the job from NetWeaver Administrator. | ![]() |
Step 28: Now we have to make few entries into ejb-j2ee-engine.xml under META-INF of ejb module of CAF project | ![]() |
Step 29 : Now we have to create few entries into application-j2ee-engine.xml file under META-INF folder of ear project of CAF for NetWeaver Scheduler | ![]() |
Step 30: Now we have to write our Application service implementation methods. Below are the methods we are going to implement.
| import java.util.ArrayList; import java.util.Calendar; import java.util.List;
import com.tcs.example.ce.archive.modeled.BOToArchive; import com.tcs.example.ce.archive.modeled.History; import com.tcs.example.ce.archive.modeled.bonode .botoarchive.botoarchive.BOToArchiveServiceLocal; import com.tcs.example.ce.archive.modeled .bonode.history.history.HistoryServiceLocal; import com.tcs.jaxb.data.structure.JAXB_Data_Structure; import com.tcs.jaxb.util.JaxbUtil; import com.sap.caf.rt.exception.CAFCreateException; import com.sap.caf.rt.exception.CAFDeleteException; import com.sap.caf.rt.exception.CAFFindException; import com.sap.caf.rt.exception.CAFLockException; import com.sap.caf.rt.exception.CAFUpdateException; ------------------------------------------------------------------------------------------------------------- public void dataArchive() { JAXB_Data_Structure data_Structure = new JAXB_Data_Structure(); List<BOToArchive> list_BOToArchive_OUT = new ArrayList<BOToArchive>();
BOToArchiveServiceLocal archiveServiceLocal = this.getBOToArchiveService(); try { List<BOToArchive> list_BOToArchive = archiveServiceLocal.findAll(); if(list_BOToArchive != null && list_BOToArchive.size() > 0){ for (BOToArchive toArchive : list_BOToArchive) { list_BOToArchive_OUT.add(toArchive); archiveServiceLocal.delete(toArchive); } } } catch (CAFFindException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFDeleteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); }
Calendar calendar = Calendar.getInstance(); // Set the Data to JAXB Data Structure data_Structure. setList_BOToArchive(list_BOToArchive_OUT); // Convert Java Object to XML Tree String string_JavaObjectToXMLTree = JaxbUtil. jaxbMarshalConvertJavaObjectToXMLTree (data_Structure, JAXB_Data_Structure.class); // Write Content To HD String string_ZIP_FILE_NAME_IN_HD = JaxbUtil.writeToHD(string_JavaObjectToXMLTree); //Create ZIP File String string_ZIP_FILE_NAME = JaxbUtil.createZIP (string_ZIP_FILE_NAME_IN_HD, "BOToArchive-" +String.valueOf(calendar.getTime())); //Delete The HD File JaxbUtil.deleteFile(string_ZIP_FILE_NAME_IN_HD);
// Store Actual BO & Path Name in HIstroty BO HistoryServiceLocal historyServiceLocal = this.getHistoryService(); try { History history = historyServiceLocal.create(); history.setId(("BOToArchive"+"-"+ String.valueOf(calendar.getTime())+"-"+JaxbUtil.createId())); history.setPath(string_ZIP_FILE_NAME); historyServiceLocal.update(history); } catch (CAFCreateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFUpdateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
------------------------------------------------------------------------------------------------------ public void restoreDATTOBO(java.lang.String nameofTheArchiveBO, java.lang.String merge_Indicator) {
HistoryServiceLocal historyServiceLocal = this.getHistoryService(); BOToArchiveServiceLocal archiveServiceLocal = this.getBOToArchiveService();
try {
List<History> list_History = historyServiceLocal.findAll(); if(merge_Indicator != null && !"".equals(merge_Indicator) && merge_Indicator.equalsIgnoreCase("Y")){ this.dataArchive(); } for (History history : list_History) { if(nameofTheArchiveBO !=null && !"".equals(nameofTheArchiveBO) && nameofTheArchiveBO.equalsIgnoreCase(history.getId())){ //Convert XML Tree to Java Object String string_ZipFile = JaxbUtil.readZipFile(history.getPath()); JAXB_Data_Structure object_JAXB_Data_Structure = (JAXB_Data_Structure)JaxbUtil .jaxbUNMarshalConvertXMLTreeToJavaObject(string_ZipFile, JAXB_Data_Structure.class); List<BOToArchive> list_BOToArchive = object_JAXB_Data_Structure.getList_BOToArchive(); for (BOToArchive toArchive : list_BOToArchive) { BOToArchive archive = archiveServiceLocal.create(); archiveServiceLocal.update(archive); toArchive.setCreatedAt(archive.getCreatedAt()); toArchive.setCreatedBy(archive.getCreatedBy()); toArchive.setKey(archive.getKey()); toArchive.setModifiedAt(archive.getModifiedAt()); toArchive.setModifiedBy(archive.getModifiedBy()); archiveServiceLocal.update(toArchive); } historyServiceLocal.delete(history); break; }
} } catch (CAFFindException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFCreateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFUpdateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFDeleteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } -------------------------------------------------------------------------------------------------------- public void deleteZIP(com.tcs.example.ce. archive.modeled.BODeleteStruct delete) {
HistoryServiceLocal historyServiceLocal = this.getHistoryService();
if(delete != null){ List<String> list_String = delete.getPaths(); try { List<History> list_History = historyServiceLocal.findAll(); if(list_String != null && list_String.size() > 0){ for (String string : list_String) { for (History history : list_History) { if(history.getId().equalsIgnoreCase(string)){ //Delete The File JaxbUtil.deleteFile(history.getPath()); historyServiceLocal.delete(history); } } } } } catch (CAFFindException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFDeleteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
Step 31: Now we have to deploy our project to SAP Application server.
| ![]() |
Step 32: After deployment we have to go CAF service browser to insert few data to our BO. BO : BOToArchive | ![]() |
Step 33: Now we have to configure our scheduler to archive our BO data in specified time. To do that we have to log on to the SAP WAS Application server. Under NWA | ![]() |
Step 34: Then select Example_MDB under Job Definitions Tab | ![]() |
Step 35: Then we have to create a new task for our job. Please go to the Tasks tab and press the button Add. Then select your Job. | Then press the Next Button and provide the data as below Then press Next button. Then press Next button. And provide the start time of your scheduler. Then press Add button. And then press finish button. It will go to the Tasks tab. And you will see your task in the task list as below. And press the refresh button on the above screen if your task is started then it will go to the under Jobs tab. |
Step 36: Our scheduler completed its task. Now we have to go to the CAF service browser to see whether our Data is archived or not from BO: BOToArchive, it should be blank at this time and our another CAF BO : History will contain with single entry. | Below Screen Shoot of History BO
|
Step 37: If we want restore our data from the archive file to CAF BO we have to execute the custom method: restore_DAT_TO_BO of our application service. | Please go the Web Service Navigator of your SAP WAS Application server. And find your web service. Then press Next button and select the specified method to execute. Now we have to provide the credentials the name of BO to restore with merge indicator Y or N. If Y then the current data of the BO will merge with old data of the BO and entry from the History Bo will be deleted. If N then if the BO if some data is their first archive the data and restore the old data if no data is their then it will load the old data and entry form the History BO will be deleted.
Please collect the BO name from the History BO the Id filed value. Then press Next button. Now to check whether the data will restore or not go to the CAF service browser and double click the BOToArchive CAF BO. Now if we go to the History BO it will be empty. |
Note : | To get the SAP WAS Application server name via code you have to writhe below code. String sysNam = System.getProperty("SAPSYSTEMNAME"); |
Useful Links: | http://jaxb.java.net |
SNMP Print Job Status Feedback User Guide
This document provides an overview of the feature “Status Feedback for Print Jobs using the SNMP protocol (Simple Network Management Protocol)”. It details the steps how to enable the feature in transaction SPAD (intended for System administrators) and then how to check the status of the print jobs in the output controller which were submitted from the SAP system to the printer (intended for application users).
SAP BPA Security Guide V9
SAP BPA Security Guide V9.
SAP BPA Troubleshooting Guide V9
SAP BPA Troubleshooting Guide V9.
SAP BPA Installation Guide V9
SAP BPA Installation Guide V9.
SAP BPA Administration Guide V9
SAP BPA Administration Guide V9.
SAP BPA Quick Install Guide
SAP BPA Quick Install Guide.
OS level monitoring activation for remote host
Introduction :
This document is based on configuration of CCMS agent in order to get OS level information in ST06, OS07, OS07N transactions for database host as well as any other remote host .
Contents :
1. Pre-requisite Checks .
2. Create CMSREG user.
3. Files to be downloaded
4. Create custom profile for standalone CCMS agent .
5. Generate Configuration file for agent
6. Register CCMS agent
7. Check the connection RFC in RZ21
8. Check the OS level data in OS07
1. Pre-requisite Checks:
- If your system is having SAP BASIS < 702 SP16 & SAP Kernel > 710 then you can follow rest of the steps .
For more information , please check following notes :
1. 1491115
2. 1304555
3. 1368389
In order to proceed with Web Service CCMS API connection , SAP_BASIS should be at least on 702 SP 16 & kernel version should be greater than equal to 710 .
- Host Agent should be installed & it should be up & running
To check this, log into the host with root user and go to /usr/sap/hostctrl/exe & run following command to check whether it’s up or not :
from root > /usr/sap/hostctrl/exe/saphostexec -status
2. Create CMSREG user.
Create CSMREG user from RZ21 transaction through following path :
- RZ21 > Technical Infrastructure > Configure Central System > Create CSMREG user
3. Files to be downloaded
Download non-unicode 7.20 sapccmsr agent as per OS version (64 bit/ 32 bit) & NW version
https://service.sap.com/swdc> Support Packages & Patches > Browse our download catalog > SAP Netweaver & Complementatry Products > SA Netweaver > (Choose netweaver version) > Entry By Components > Application Server ABAP > SAP KERNEL 7.20 64-BIT> (Choose OS) > DB Independent > Then choose the CCMS Agent SAR file & Download
Now create /usr/sap/ccms/bin directory & extract the .SAR file to it .
4. Create custom profile for standalone CCMS agent
Create a file named sapccmsr.pfl in /usr/sap/tmp and make following entry into it :
exe/saposcol = /usr/sap/hostctrl/exe/saposcol
5. Generate Configuration file for agent
Execute RZ21 and click on following link :
Save the file in your desktop and then move to followingf location :
Microsoft Windows: \\<hostname>\saploc\prfclog\sapccmsr
UNIX: /usr/sap/tmp/sapccmsr
6. Register CCMS Agent
- Put following entry in host agent profile and restart the host agent :
ccms/enable_agent = 0
- Run following command from /usr/sap/ccms/bin/.
./sapccmsr -R pf=/usr/sap/tmp/sapccmsr.pfl
[Give all the necessary inputs as per your Central Monitoring System ]
7. Check the connection RFC in RZ21
Click on following option and TEST the connection :
8. Check the OS level data in OS07
Execute OS07 and select the host from the pop up and double click on it . it will show all the OS relevant details . More more information click on "Detail Analysis Menu" .
Hope it would help SAPians !!
Looking forward , I would love to receive more feedback so that this document can be enriched with more useful information .
Regards,
Nilutpal Sharmah
SAP on Oracle Development Update
A regular update on the current state-of-play for SAP on Oracle.
Clear Queue Of PI Message Monitoring Of SAP NetWeaver Application Server
Applies To: JDK 1.5 / 1.6, CE 7.3/ 7.4
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on: 12th February 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Services as Assistant Consultant and development of SAP EP, composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Requirement:
In many case we were facing issue to passing the message via JMS queue of Application server.
In some situation at a single point of time more than 10,000 messages was passing via JMS queue of Application Server java, if due to some error one of the message was not able to pass from the queue then rest of the message would stuck in the queue.
If we restart the application server, even though queue would not getclear, and application server would try to post rest of the message again and would reach to the same situation.
To overcome the situation we have to update the message status from “DLNG” to “FAIL”.
Implementation :
- Create one EJB.
- Write one business method.
- And expose the ejb as web service.
In the class below imports are required :
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
For back end connectivity we required Data Source.
Please declare Data Source as below.
@Resource(mappedName = "SAP/CAF_RT")
DataSource dataSource;
Business method implementation as below
@javax.ejb.TransactionAttribute (javax.ejb.TransactionAttributeType.REQUIRES_NEW)
public void clear() {
try {
Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement
("UPDATE BC_MSG SET STATUS = ? WHERE STATUS = ?");
preparedStatement.setString(1, "FAIL");
preparedStatement.setString(2, "DLNG");
preparedStatement.executeUpdate();
preparedStatement.close();
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Restart SAP Application Server Java using Java Code
Applies To: All JDK
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on: 13th February 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Services as an Assistant Consultant and development of SAP EP, composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Requirement:
In many situations, we might require to re-start our server. But to do so, we required SAP Basis support.
Assumption:
AS java should have single server node.
Advantage:
- Clear all the Garbage collection
- Clear all the heap memory
Implementation:
- Create one EJB
- Write Business Method
- Expose EJB as webservice
- Run the web service to re-start the AS Java.
Method Implementation:
@javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
Public void restartASJava(){
System.exit(0);
}
Lock / Unlock of CAF Business Objects
Applies To: Jdk 1.6, CE 7.3 / 7.4
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on: 16th February 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Services as Assistant Consultant and development of SAP EP, composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Requirement:
Let say, we have to generate unique numbers by an application as well as we have to handle x no of treads at single point of time and also we have to consider duplicate number should not generate.
Implementation:
To solve the issue, we should implement the lock and unlock mechanism.
Let say, we have one CAF BO named: P2S Number Range, where only last number would persist. If we have multiple threads and all the thread have access to that particular table at single point of time, then we might get duplicate number from the application because threads would read the configuration of the business object. To solve the issue we have should introduce the lock and unlock mechanism on CAF Business Object.
At single point of time only one thread should have access to the table. After the thread complete its work then only application should trigger the unlock method and after that another thread should get access and do its work. In this way we would be able to stop generating the duplicate numbers.
We have to lock the business object, so we have to read GUID of the CAF BO.
Below are the imports which are required.
import com.sap.caf.rt.bol.IBusinessObjectNodeServiceBase;
import com.sap.caf.rt.exception.CAFLockException;
import com.sap.caf.rt.exception.CAFPessimisticLockException;
import com.example.bo.modeled.bonode.p2snumberrange.p2snumberrange.P2SNumberRangeServiceLocal;
We have to do one ejb injection into our implementation ejb as below for CAF Business Object.
@EJB(name="com.example.bo.modeled.bonode.p2snumberrange.p2snumberrange.P2SNumberRange")
private P2SNumberRangeServiceLocal numberRangeServiceLocal;
We have to declare below line for the type of lock.
private static final char modeW = IBusinessObjectNodeServiceBase.MODE_WRITE;
Now we have to implement the unlock method as below:
public boolean unlock(String string_GUID){
boolean b_Unlock = false;
try {
numberRangeServiceLocal.unlock(string_GUID, modeW);
b_Unlock = true;
} catch (CAFPessimisticLockException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b_Unlock;
}
Now we have to implement the lock method as below:
private boolean getLock(String string_GUID){
boolean b_Lock = false;
try {
if(string_GUID != null && !"".equals(string_GUID)){
numberRangeServiceLocal.lock(string_GUID, modeW);
}
} catch (CAFPessimisticLockException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b_Lock;
}
Now we have to implement the business method where we would call the lock and unlock methods.
public void businessMethod(){
To read the GUID we have to write below code.
P2SNumberRangeBean bean_GUID = new P2SNumberRangeBeanImpl();
String string_GUID = bean_GUID._objectGuid;
/*Get Lock*/
boolean b_GetLock = getLock(string_GUID);
if(b_GetLock){
/*Write Business Logic to Update the CAF BO & If any other business logic*/
// Now we have to unlock the CAF BO
unlock(string_GUID);
}
}
Way To Restart WAS Java via code
Applies To : All JDK
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on:17th February 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Services as an Assistant Consultant and development of SAP EP,
composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/
J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Requirement:
In many situations, we might require to re-start our server. But to do so, we required SAP Basis support.
Assumption:
Java code would only work on jvm of server instance.
We should know about Heap Memory, below is few information about Heap Memory
Heap Memory:
The JVM has a heap that is the runtime data area from which memory for all class instances and arrays are allocated. It is created at the JVM start-up.
The heap size may be configured with the following VM options:
-Xmx<size> - to set the maximum Java heap size
-Xms<size> - to set the initial Java heap size
By default, the maximum heap size is 64 Mb.
Heap memory for objects is reclaimed by an automatic memory management system which is known as a garbage collector. The heap may be of a fixed size or may be expanded and shrunk, depending on the garbage collector's strategy.
Advantage :
1. If we restart the JVM, we would get fresh JVM from begin.
Implementation:
1. Create one EJB
2. Write Business Method
3. Expose EJB as webservice
4. Run the webservice to re-start the WAS Java.
Method Implementation :
@javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
Public void restartASJava(){
System.exit(0);
}
Data Archiving in Composition Environment with NetWeaver Java Scheduler
Applies to:
SAP NetWeaver CE 7.2 (SP 03) / CE 7.1 Ehp 1 (SP 03), JDK 1.6/ JDK 1.5, XML, JAXB.
Summary:
In many custom business application we are using CAF Business objects their might be requirement of archive data of CAF Business Objects for auditing and future purposes. Here I am discussing step by step configuration of NetWeaver Scheduler and corresponding custom java coding.
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on: 22 January 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Service as Assistant Consultant and development of SAP EP , composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Introduction
In custom composite application for data storing, normally we are using CAF Business Objects. But we required archiving them after certain time of period for auditing or future purposes. For this requirement I have made a custom application via which we can easily archive our CAF BO data and restore them when required to CAF BO. The data archive application will be triggered via NetWeaver Scheduler. The mechanism I have used to do the custom application as follows: a) read the desired CAF BO and generate one xml file with help of JAXB api into the Hard disk of the server and delete the content of the CAF BO b ) then using java util zip api to create one zip file and put the xml file into it and delete the xml file from the hard disk of the server c) and store the name of the CAF BO with actual path where the zip file stored into server into another CAF BO. d) When restore mechanism will triggered from the zip file read the content and data will be back to the actual CAF BO and entry will be delete from the History CAF BO.
Create Projects
For this custom application we required one CAF project. With the name: example/ce/archive
Implementation
CAF Project
To do the CAF project please follow the below instruction.
Steps | Screen Shots |
---|---|
Step 1: Choose File -> New - > Project of your Netweaver Developer Studio of CAF perspective. | ![]() |
Step 2: One popup window come and goes to the Development Infrastructure - > Development Component and press next button in the below. | ![]() |
Step 3: Then one popup will be come and choose Development Component type: Composite Application. And press next button. | ![]() |
Step 4: Then choose the software component type where you are going to create your development component. | ![]() |
Step 5: Then another new popup will be come and provide the details as per requirement. | ![]() |
Step 6: The press next button and then finish button. It will create a CAF project into your workspace. | ![]() |
Step 7: Now our project is ready. | ![]() |
Step 8 : Right click on the modeled package | ![]() |
Step 9: Now we are going to create a CAF BO with name BOToArchive. | ![]() |
Step 10: The go to the Permission tab of CAF BO and unchecked the Permission check Enabled option | ![]() |
Step 11: Then go to the structure tab of CAF BO and press the button Edit Main Structure | ![]() |
Step 12: The create two fields with name a)Id data type String cardinality 0 -1 b) Value data type xLongText cardinality 0 -1 | ![]() |
Step 13: We have to create another CAF BO for storing archive path and CAF BO names. Provide the new CAF BO name : History and create two fields a)Id data type string b)Path data type xLongText | ![]() |
Step 14: Now we have to create one Application service with name : DataArchiveApp | ![]() |
Step 15: Then one popup will be come and provide the name of the application service. Then press finish button. | ![]() |
Step 16: Then it will generate the application service and check the Generate remote Interface option. Under general tab of application service. | ![]() |
Step 17: Now we have to create one custom structure for input parameter of delete_ZIP method. Structure Name : BODeleteStruct | ![]() |
Step 18: After you create the custom structure it should look like as screenshot. Cardinality ; 0 - n | ![]() |
Step 19: Now we have to create custom method to our application service. To do those go to the operations tab of our application service. Then press the Add button one popup will be come and choose the first radio button with option Custom operation and then provide the name of operation.
| |
Step 20: Now we are adding two CAF BO objects to our Application service via dependency tab of application service. | ![]() |
Step 21: Now we have to create few general java class for archive our data. Please go to the Java perspective and create name : JAXB_Data_Structure with package : com.tcs.jaxb.data.structure | ![]() |
Step 22: Now we have to create another java class name : JaxbUtil with lot of methods with package : com.tcs.jaxb.util | package com.tcs.jaxb.util;
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; import java.util.Calendar; import java.util.Random; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException;
/** *@author * */ publicclass JaxbUtil {
/** *Thismethodcreatethezipfile andreturntheAbsolutefilepath * *@paramstringsFileName- * PasstheFileNametobeZIP *@return-Astringobjectwithabsolutepath */ publicstatic String createZIP (String stringsFileName,String stringBOName) {
String zipFileName = ""; zipFileName = createDirectory() + "/" + stringBOName+"-"+createId() + ".zip";
try { File file = new File(zipFileName); ZipOutputStream out = new ZipOutputStream( new FileOutputStream(file)); out.putNextEntry (new ZipEntry(stringsFileName));
BufferedReader bufferedReader = new BufferedReader (new FileReader(stringsFileName)); String string; while ((string = bufferedReader.readLine()) != null) { out.write(string.getBytes()); } bufferedReader.close(); out.closeEntry(); out.flush(); out.close(); zipFileName = file.getAbsolutePath(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
return zipFileName; }
/** *ThisMethodCreateUniqueID * *@return-AStringobjectwiththeID */ publicstatic String createId() { return Long.toHexString (Calendar.getInstance().getTimeInMillis()) + "-" + Integer.toHexString ((new Random()).nextInt() % 65536); }
/** *ThismethodReadtheZIPFileand returnsContentoftheFileinaString *object * *@paramstringFileName- * PasstheFilenametoberead *@return-ContentofthefileinaStringobject */ publicstatic String readZipFile(String stringFileName) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ZipFile zipFile = new ZipFile(new File(stringFileName));
ZipInputStream zipInputStream = new ZipInputStream( new FileInputStream(stringFileName));
ZipEntry zipEntry = zipInputStream.getNextEntry();
BufferedReader reader = new BufferedReader(new FileReader( stringFileName)); byte[] bs = reader.readLine().getBytes(); reader.close();
zipInputStream.closeEntry(); zipInputStream.close();
InputStream inputStream = zipFile.getInputStream(zipEntry);
int len; while ((len = inputStream.read(bs)) > 0) {
byteArrayOutputStream .write(bs, 0, len); } inputStream.close(); byteArrayOutputStream.close();
} catch (ZipException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return byteArrayOutputStream.toString();
}
/** *ThismethodDeletethepassedfile. * *@paramstringFileName- * Passthefilepathtobedelete */ publicstaticvoid deleteFile(String stringFileName) { File file = new File(stringFileName); if (file.exists() && file.isFile()) { file.delete(); } }
/** *ThismethodcreateaNewFile andwritecontentstotheNewlyCreated *file * *@paramstringFileContent- * Passthecontentofthefiletobewritten *@return-Astringobjectwith AbsoluteFileDirectory */ publicstatic String writeToHD(String stringFileContent) { String string = null; try { string = createDirectory() + "/" + createId() + ".xml"; File file = new File(string);
if (!file.exists()) { file.createNewFile(); } BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter( file)); bufferedWriter.write(stringFileContent); bufferedWriter.close(); string = file.getAbsolutePath(); } catch (IOException e) { // TODO Auto-generated catch block
} return string; }
/** *ThisMethodconvertsJavaObject toXMLTreeandReturntoStringObject * *@paramobject- * forJavaObjectDataStructure(WithData) *@paramclass1- * forJavaClass(DataStructureClassInstance) *@return-AStringObjectWithXMLFormat */ publicstatic String jaxbMarshalConvertJavaObjectToXMLTree(Object object, Class<?> class1) { StringWriter writerPage = new StringWriter(); try { JAXBContext jaxbContextPage = JAXBContext.newInstance(class1); jaxbContextPage .createMarshaller().marshal(object, writerPage); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return writerPage.toString(); } /** *ThismethodconvertsXMLTreeObjecttoJavaObject. * *@paramstringReadPage- * PassDataStreamlikeaStringobject *@paramclass1- * PassTheDataStructureClassInstance *@return-ObjectofJavaDataStructure, youhavetoCastwhereyou * callingthismethodwithJavaDataStructure */ public static Object jaxbUNMarshalConvertXMLTreeToJavaObject( String stringReadPage, Class<?> class1) { Object dataStructureReadPage = null; try { JAXBContext jaxbContextPage = JAXBContext.newInstance(class1); dataStructureReadPage = (Object) jaxbContextPage .createUnmarshaller().unmarshal( new StringReader(stringReadPage)); } catch (JAXBException e) { // TODO Auto-generated catch block e.printStackTrace(); } return dataStructureReadPage; }
/** *ThismethodcreateaDirectoryintheHD inthedefineddirectorye.g: *"/usr/sap/"+SystemName+"/XML_DAS/" * *@return-AStringObjectwithdetailsof AbsolutePathofDirectory */ public static String createDirectory() { File file = null;
String sysNam = System.getProperty("SAPSYSTEMNAME"); String stringDirPathName = "/usr/sap/" + sysNam + "/" + "XML_DAS" + "/"; if (stringDirPathName != null && !"".equals(stringDirPathName)) { file = new File(stringDirPathName); if (!file.mkdirs()) { file.mkdirs(); } } if (null != file.getAbsolutePath()) { stringDirPathName = file.getAbsolutePath(); } return stringDirPathName; } } |
Step 23: Now we have to add DC reference to use SAP NetWeaver Scheduler mechanism into our project to do that open the project into component properties and go to the dependency tab and press the add button one popup will be come and chose ENGFACADE[sap.com] and from this tree select tc/je/scheduler/api and press next button and select deploy time and build time options. And press the finish button. | ![]() |
Step 24: Now it will come as screenshot. | ![]() |
Step 25: Now we have to create Message driven bean for scheduler. Create a message driven bean of name : Example_Shcedule with supper class MDBJobImplementation with destination name : MyDestinations and then press next button and then press the finish button without changing any default configuatraion. Package : com.tcs.nw.scheduler | ![]() |
Step 26: Now we have to access the Application service due to that we have to use EJB annotation. | package com.tcs.nw.scheduler;
import javax.ejb.ActivationConfigProperty; import javax.ejb.EJB; import javax.ejb.MessageDriven; import javax.jms.MessageListener;
import com.tcs.example.ce.archive.modeled .appsrv.dataarchiveapp. DataArchiveAppServiceLocal; import com.sap.scheduler. runtime.JobContext; import com.sap.scheduler. runtime.mdb.MDBJobImplementation;
/** *Message-DrivenBean implementationclassfor:Example_Shedule * */ @MessageDriven( activationConfig = {@ActivationConfigProperty( propertyName="messageSelector", propertyValue="JobDefinition='Example_JobBean'"), @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Queue" ) }, mappedName = "MyDestination") publicclass Example_Shedule extends MDBJobImplementation implements MessageListener {
privatestaticfinallongserialVersionUID = 4485561670312885280L;
@EJB(name="com.tcs.example.ce.archive.modeled. appsrv.dataarchiveapp.DataArchiveApp") DataArchiveAppServiceLocal dataArchiveAppServiceLocal; /** *@seeMDBJobImplementation #MDBJobImplementation() */ public Example_Shedule() { super(); // TODO Auto-generated constructor stub }
@Override publicvoid onJob(JobContext arg0) throws Exception { // TODO Auto-generated method stub dataArchiveAppServiceLocal.dataArchive(); }
} |
Step 27: Now we have to create job-defination.xml file into META-INF folder of ejb module of CAF project for searching the job from NetWeaver Administrator. | ![]() |
Step 28: Now we have to make few entries into ejb-j2ee-engine.xml under META-INF of ejb module of CAF project | ![]() |
Step 29 : Now we have to create few entries into application-j2ee-engine.xml file under META-INF folder of ear project of CAF for NetWeaver Scheduler | <reference reference-type="hard"><reference-target target-type="service" provider-name ="sap.com">scheduler~runtime</reference-target></reference> and under module we should include below tag<entry-name>jar file of ejb module </entry-name> and <container-type>scheduler~container</container-type> |
Step 30: Now we have to write our Application service implementation methods. Below are the methods we are going to implement.
| import java.util.ArrayList; import java.util.Calendar; import java.util.List;
import com.tcs.example.ce.archive.modeled.BOToArchive; import com.tcs.example.ce.archive.modeled.History; import com.tcs.example.ce.archive.modeled.bonode .botoarchive.botoarchive.BOToArchiveServiceLocal; import com.tcs.example.ce.archive.modeled .bonode.history.history.HistoryServiceLocal; import com.tcs.jaxb.data.structure.JAXB_Data_Structure; import com.tcs.jaxb.util.JaxbUtil; import com.sap.caf.rt.exception.CAFCreateException; import com.sap.caf.rt.exception.CAFDeleteException; import com.sap.caf.rt.exception.CAFFindException; import com.sap.caf.rt.exception.CAFLockException; import com.sap.caf.rt.exception.CAFUpdateException; ------------------------------------------------------------------------------------------------------------- public void dataArchive() { JAXB_Data_Structure data_Structure = new JAXB_Data_Structure(); List<BOToArchive> list_BOToArchive_OUT = new ArrayList<BOToArchive>();
BOToArchiveServiceLocal archiveServiceLocal = this.getBOToArchiveService(); try { List<BOToArchive> list_BOToArchive = archiveServiceLocal.findAll(); if(list_BOToArchive != null && list_BOToArchive.size() > 0){ for (BOToArchive toArchive : list_BOToArchive) { list_BOToArchive_OUT.add(toArchive); archiveServiceLocal.delete(toArchive); } } } catch (CAFFindException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFDeleteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); }
Calendar calendar = Calendar.getInstance(); // Set the Data to JAXB Data Structure data_Structure. setList_BOToArchive(list_BOToArchive_OUT); // Convert Java Object to XML Tree String string_JavaObjectToXMLTree = JaxbUtil. jaxbMarshalConvertJavaObjectToXMLTree (data_Structure, JAXB_Data_Structure.class); // Write Content To HD String string_ZIP_FILE_NAME_IN_HD = JaxbUtil.writeToHD(string_JavaObjectToXMLTree); //Create ZIP File String string_ZIP_FILE_NAME = JaxbUtil.createZIP (string_ZIP_FILE_NAME_IN_HD, "BOToArchive-" +String.valueOf(calendar.getTime())); //Delete The HD File JaxbUtil.deleteFile(string_ZIP_FILE_NAME_IN_HD);
// Store Actual BO & Path Name in HIstroty BO HistoryServiceLocal historyServiceLocal = this.getHistoryService(); try { History history = historyServiceLocal.create(); history.setId(("BOToArchive"+"-"+ String.valueOf(calendar.getTime())+"-"+JaxbUtil.createId())); history.setPath(string_ZIP_FILE_NAME); historyServiceLocal.update(history); } catch (CAFCreateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFUpdateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
------------------------------------------------------------------------------------------------------ public void restoreDATTOBO(java.lang.String nameofTheArchiveBO, java.lang.String merge_Indicator) {
HistoryServiceLocal historyServiceLocal = this.getHistoryService(); BOToArchiveServiceLocal archiveServiceLocal = this.getBOToArchiveService();
try {
List<History> list_History = historyServiceLocal.findAll(); if(merge_Indicator != null && !"".equals(merge_Indicator) && merge_Indicator.equalsIgnoreCase("Y")){ this.dataArchive(); } for (History history : list_History) { if(nameofTheArchiveBO !=null && !"".equals(nameofTheArchiveBO) && nameofTheArchiveBO.equalsIgnoreCase(history.getId())){ //Convert XML Tree to Java Object String string_ZipFile = JaxbUtil.readZipFile(history.getPath()); JAXB_Data_Structure object_JAXB_Data_Structure = (JAXB_Data_Structure)JaxbUtil .jaxbUNMarshalConvertXMLTreeToJavaObject(string_ZipFile, JAXB_Data_Structure.class); List<BOToArchive> list_BOToArchive = object_JAXB_Data_Structure.getList_BOToArchive(); for (BOToArchive toArchive : list_BOToArchive) { BOToArchive archive = archiveServiceLocal.create(); archiveServiceLocal.update(archive); toArchive.setCreatedAt(archive.getCreatedAt()); toArchive.setCreatedBy(archive.getCreatedBy()); toArchive.setKey(archive.getKey()); toArchive.setModifiedAt(archive.getModifiedAt()); toArchive.setModifiedBy(archive.getModifiedBy()); archiveServiceLocal.update(toArchive); } historyServiceLocal.delete(history); break; }
} } catch (CAFFindException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFCreateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFUpdateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFDeleteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } -------------------------------------------------------------------------------------------------------- public void deleteZIP(com.tcs.example.ce. archive.modeled.BODeleteStruct delete) {
HistoryServiceLocal historyServiceLocal = this.getHistoryService();
if(delete != null){ List<String> list_String = delete.getPaths(); try { List<History> list_History = historyServiceLocal.findAll(); if(list_String != null && list_String.size() > 0){ for (String string : list_String) { for (History history : list_History) { if(history.getId().equalsIgnoreCase(string)){ //Delete The File JaxbUtil.deleteFile(history.getPath()); historyServiceLocal.delete(history); } } } } } catch (CAFFindException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFDeleteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CAFLockException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
Step 31: Now we have to deploy our project to SAP Application server.
| ![]() |
Step 32: After deployment we have to go CAF service browser to insert few data to our BO. BO : BOToArchive | ![]() |
Step 33: Now we have to configure our scheduler to archive our BO data in specified time. To do that we have to log on to the SAP WAS Application server. Under NWA | ![]() |
Step 34: Then select Example_MDB under Job Definitions Tab | ![]() |
Step 35: Then we have to create a new task for our job. Please go to the Tasks tab and press the button Add. Then select your Job. | Then press the Next Button and provide the data as below Then press Next button. Then press Next button. And provide the start time of your scheduler. Then press Add button. And then press finish button. It will go to the Tasks tab. And you will see your task in the task list as below. And press the refresh button on the above screen if your task is started then it will go to the under Jobs tab. |
Step 36: Our scheduler completed its task. Now we have to go to the CAF service browser to see whether our Data is archived or not from BO: BOToArchive, it should be blank at this time and our another CAF BO : History will contain with single entry. | Below Screen Shoot of History BO
|
Step 37: If we want restore our data from the archive file to CAF BO we have to execute the custom method: restore_DAT_TO_BO of our application service. | Please go the Web Service Navigator of your SAP WAS Application server. And find your web service. Then press Next button and select the specified method to execute. Now we have to provide the credentials the name of BO to restore with merge indicator Y or N. If Y then the current data of the BO will merge with old data of the BO and entry from the History Bo will be deleted. If N then if the BO if some data is their first archive the data and restore the old data if no data is their then it will load the old data and entry form the History BO will be deleted.
Please collect the BO name from the History BO the Id filed value. Then press Next button. Now to check whether the data will restore or not go to the CAF service browser and double click the BOToArchive CAF BO. Now if we go to the History BO it will be empty. |
Note : | To get the SAP WAS Application server name via code you have to writhe below code. String sysNam = System.getProperty("SAPSYSTEMNAME"); |
Useful Links: | http://jaxb.java.net |
Featured Content for SAP NetWeaver Technology Platform
|
|
* Previously featured |
Way to Read SAP.APPLICATION.GLOBAL.PROPERTIES File via Java code
Applies To: Jdk 1.5 and onwards, CE 7.3/7.4
Author(s): Biplab Ray
Company: Tata Consultancy Services
Created on: 20th February 2015
Author Bio:
Biplab Ray is working for Tata Consultancy Services as an Assistant Consultant and development of SAP EP, composite applications using CAF, BPM, BRM, WebDynpro for Java. He also works in technologies like Java/J2EE and has depth understanding on eSOA, Webservice, Enterprise Service, XML.
Requirement:
- In normal j2ee, if we want to modify the any value of property file then we have to touch the file and build the application and deploy and then only the new value would take effect.
- To solve the issue SAP introduce new concept of sap.application.global.properties file is that, without touching the code we could modify values via NWA and the changes would take effect without restart the server.
- To read the file we have to do a j2ee project.
Implementation:
- Create a J2EE project including ejb and ear module.
- Create one Ejb via which application would read the keys of the property file and return value.
- Create one normal java class which should implement the ApplicationPropertiesChangeListener.
- Add one DC: tc/je/appconfiguration/api under Software Component: ENGFACADE to ejb module of the J2EE project.
- Create a file named “sap.application.global.properties” under META-INF folder of EAR module of J2EE project.
Few words about the property file:
Description: Descriptions can be short or long. They are used by adding a prefix (## for short and # for long) and the description itself, in a line within the property file.
Meta-flags : Some meta-flags like meta-flags for specifying a property as secure, onlinemodifiable, parameterized, computed, propertylinked and final, are used by adding a prefix #? and the flag name-value pair, in a line within the sap.application.global.properties file, e.g:, #? onlinemodifiable = true. A property with a meta-flag onlinemodifiable = true means that property can be modified by NWA. If a property has a meta-flag onlinemodifiable = false then it cannot be modified by NWA.
Other meta-flags like meta-flags for specifying the type, range and visibility of a property are used by adding a prefix #% and the flag name-value pair, in a line within the property file e.g : #% type = STRING. This means the data type of the property would be interpreted as a string.
Below is one example of the entry of key-value pair in the property file.
## Test Information
#? onlinemodifiable = true
#% type = STRING
key-test = Test Information
Note: At the time of entry each set of above data into property file please make sure enter should be pressed.
We have to modify the application-j2ee.xml under META-INF folder of ear module of j2ee project.
We have to enter below xml tag to add a hard reference.
<reference reference-type=”hard”>
<reference-target target-type=”service”>tc~je~appconfiguration~app</reference-target>
</reference>
Now we have to implement the below java class.
ApplicationPropertiesHandler | ||
---|---|---|
|
Create one EJB under the same package com.example and write the business method as below.
public String getTheValueOfProperty(String stringKeyOfProperty) {
return ApplicationPropertiesHandler.getInstance().getStringValue(stringKeyOfProperty);
}
And expose the ejb as webservice and test via ws navigator.
And if you want to modify the value , then please go to the NWA and then configuration management -> infrastructure -> java system properties then select the instance of the server and under the application tab search the project name and in the below table it would display the name of the application ear.
Select the ear and one more table would show the name –value pair which was entered into the property file. Now if any one want to set any custom value then have to set value into the custom value field this feature only applicable those was set as onlinemodifiable as true only.
Process Integration 7.4 AEX Advanced Adapter Engine Extended on standalone SAP JAVA Installation and Configuration
Content
- Software Download
- Software Upload
- Hardware and Software Requirement
- Other Requirement
- AEX Configuration
- Post Installation Activity
- Optional Activity
SOFTWARE DOWNLOAD AND UPLOAD
· Software Download from MarketPlace
Description |
NW 7.4 SR2 Java 2/2 |
NW 7.4 SR2 Java 1/2 |
NW 7.4 SR2 Language 2/2 |
NW 7.4 SR2 Language 1/2 |
SAP Kernel 7.42 AIX 64bit |
NW 7.4 SR2 Installation Export |
ORACLE Client 11.2.0.4 V2 |
Oracle 11.2.0.4 RDBMS AIX 64bit 8/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 7/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 6/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 5/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 4/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 3/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 2/8 |
Oracle 11.2.0.4 RDBMS AIX 64bit 1/8 |
NW 7.0 Presentation - 7.40 Compilation 1 Present. 1 |
SWPM10SP06 |
·
File system of the target System:
· In this case you can have a new system or already used system from your landscape
- All the ports should be open stop the archive.
- You need to have sufficient space so that you can take the backup of some important directory of existing system(if required by the business )
- You need to have root access to complete the installation
- Upload your Software and give full permission.
HARDWARE AND SOFTWARE REQUIREMENT
- Please refer the Master Guide to get the detailed Software and Hardware requirement.
- Check the PAM at service.sap.com/pam for OS release.
- For general information on AIX OS read SAP Note 1972803
- For Oracle database distribution RAID5 is recommended by SAP.
- Please check RAM, paging space, swap space, Version , kernel parameter, OS patches, Additional Software , Hostname
- This parameter mentioned in Master Guide are very important, if these parameters are not as per Master Guide you can’t start the installation process.
- After the entire prerequisite you can start the process.
Extract SWPM Software downloaded from Market place
/SAPCAR -xvf SWPM10SP06_6-20009697.SAR -R SWPM/
- Create the TEMP, TMP, and TMPDIR Directory before starting installation.
· Start SWPM
- Then you can select Oracle database Installation type
- You can check the parameters for Advance Oracle Configuration.
- In my case I have followed simple installation
· Select an option for usage of SLD
- Check all the parameter again and verify the inputs. Once confirmed then chick “NEXT”
- Installation of oracle 11g
- Run the Script to complete the Oracle Installation
- For Troubleshooting 1451753 - Filtering administration requests for AS Java
- If you do not want to restrict access to the administration requests to certain clients, remove the lines from the file or turn the lines into a comment:
#if %{REMOTE_ADDR} !stricmp 127.0.0.1 [AND]
#if %{REMOTE_ADDR} !stricmp ::1
#RegIRedirectUrl ^/webdynpro/resources/sap. com/tc~lm~itsam~ui~mainframe~wd/(.)*$ /nwa/remote_access_error [<SID>]
- Now restart the system
· You set the required permissions for sapstartsrv and sapuxuserchk in the /<sapmnt>/<SAPSID>/exe, and /usr/sap/<SAPSID>/SYS/exe, and /usr/sap/<SAPSID>/<Instance_Name>/exe directories as described
- Now install a new license
AEX CONFIGURATION
- Start AEX Configuration by https://<host>:<port>/sld/fun
· Check the Technical Data, Extended User Management, Adapter Configuration
Cretae Business System to solve the error
- Checking the AEX Configuration
· To check whether the configuration was successful, perform the following steps:
· Check the user names and roles:
- Go to the Application Server Java start page at: http://<host>:<port>/startPage.
- Choose User Management.
- Search for the user names that you specified in the configuration wizard.
- Choose Roles and check whether the UME roles were assigned.
- Appropriate roles must be assigned to all users.
- More information: SAP Note 1435392
- 1435392 - PI CTC: SLD Configuration after PI AEX initial setup
- Check the SLD configuration:
a. Enter https://<host>:<port>/sld .
b. Choose Technical Systems .
c. Select Technical System Types: Process Integration . Check the existence of the following five entities:
i. Adapter Engine on <SID><DB Host>
ii. Domain <DB Host>
iii. Integration Directory on <SID><DB Host>
iv. Integration Repository on <SID><DB Host>
v. Integration Server on <SCS Host>
Check the registration of a business system for the Integration Engine Java in the SLD:
vi. Enter https://<host>:<port>/sld .
vii. Choose Business System Integration Engine Java <SID> Integration .
viii. The pipeline URL must be: http://<host_fully_qualified>:<port>/XISOAPAdapter/MessageServlet?ximessage=true .
- More information: SAP Note 1435392
- Check the Java system properties:
a. In the SAP Netweaver Administrator, choose Configuration Infrastructure Java System Properties.
b. Choose Services and check XPI Service: AII Config Service.
c. The property com.sap.aii.ibrep.core.usage_type should have the value AEX.
d. Also check that the *.serviceuser.name properties contain the correct user names.
- Check the content import:
a. Go to the PI start page: https://<host>:<port>/dir/start/index.jsp .
b. Start the Enterprise Services Repository (ESR) and log on as PISUPER.
Check whether the import of the SAP Basis content of your release was successful
- SLD Patching
S Select CIM First
· Then select CRDelta And Upload the Files
Configuring Online Help for the PI Tools on AEX
- . Start SAP Netweaver Administrator and choose Configuration Infrastructure Java System Properties.
- . Select the Services tab and search for Service XPI: All Config Service.
- . Under Extended Details, search for the property com.sap.aii.docu.url .
- Enter the URL that points to the SAP Help Portal, for example http://help.sap.com/saphelp_nw74/helpdata/en/8e/995afa7a8d467f95a473afafafa07e/frameset.htm / for the documentation of EHP 1 for SAP Netweaver Process Integration 7.3.
- . Under Extended Details, search for the property com.sap.aii.docu.languages .
- . Enter the language, for example EN or DE.
POST INSTALLATION STEPS
· http://help.sap.com/saphelp_nw74/helpdata/en/c9/78bc4d3c304930b72840a594091b7b/content.htm
Configuring Advanced Adapter Engine Extended (PI-AEX)
· http://help.sap.com/saphelp_nw74/helpdata/en/76/0e3c9a1b114788a7400da8fd113f68/frameset.htm
SAP SECURITY GUIDE
· http://help.sap.com/saphelp_nw74/helpdata/en/03/6231e2ad004215908d2f453fd42b82/content.htm
· To update the Oracle optimizer statistics, perform the following:
1. Execute the following commands as the ora<dbsid> user:brconnect -u / -c -f stats -t system_stats;
brconnect -u / -c -f stats -t oradict_stats;
2. Execute the following commands with SQLPlus:
SQL> exec dbms_scheduler.disable('GATHER_STATS_JOB');
SQL> exec dbms_scheduler.disable('ORACLE_OCM.MGMT_CONFIG_JOB');
SQL> exec dbms_scheduler.disable('ORACLE_OCM.MGMT_STATS_CONFIG_JOB');
· For Oracle 11g, also execute the following command:
SQL> exec DBMS_AUTO_TASK_ADMIN.DISABLE
OTHER OPTIONAL ACTIVITY
· Configure Java IDoc Adapter
· Configure CTS - SAP note 1287108