Quantcast
Channel: SCN : All Content - SAP NetWeaver Technology Platform
Viewing all articles
Browse latest Browse all 1967

Data Archiving in Composition Environment with NetWeaver Java Scheduler

$
0
0

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.

1.jpg
Step 2: One popup window come and goes to the Development Infrastructure - > Development Component and press next button in the below.2.jpg
Step 3: Then one popup will be come and choose Development Component type: Composite Application. And press next button.3.jpg
Step 4: Then choose the software component type where you are going to create your development component.4.jpg
Step 5: Then another new popup will be come and provide the details as per requirement.5.jpg
Step 6: The press next button and then finish button. It will create a CAF project into your workspace.6.jpg
Step 7: Now our project is ready.7.jpg
Step 8 : Right click on the modeled package8.jpg
Step 9: Now we are going to create a CAF BO with name BOToArchive.9.jpg
Step 10: The go to the Permission tab of CAF BO and unchecked the Permission check Enabled option10.jpg
Step 11: Then go to the structure tab of CAF BO and press the button Edit Main Structure11.jpg
Step 12: The create two fields with name a)Id data type String cardinality 0 -1 b) Value data type xLongText cardinality 0 -112.jpg
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 xLongText13.jpg
Step 14: Now we have to create one Application service with name : DataArchiveApp14.jpg
Step 15: Then one popup will be come and provide the name of the application service. Then press finish button.16.jpg
Step 16: Then it will generate the application service and check the Generate remote Interface option. Under general tab of application service.15.jpg

Step 17: Now we have to create one custom structure for input parameter of delete_ZIP method.

  Structure Name : BODeleteStruct
17.jpg

Step 18: After you create the custom structure it should look like as screenshot.

  Cardinality ; 0 - n
18.jpg

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.

  1. data_Archive
  2. restore_DAT_TO_BO
    c. delete_ZIP

19a.jpg

19b.jpg

19c.jpg

19d.jpg

Step 20: Now we are adding two CAF BO objects to our Application service via dependency tab of application service.20.jpg
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.structure21.jpg
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.23.jpg
Step 24: Now it will come as screenshot.24.jpg

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
25.jpg
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.
27.jpg
Step 28: Now we have to make few entries into ejb-j2ee-engine.xml under META-INF of ejb module of CAF project28.jpg
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 Scheduler29.jpg

Step 30: Now we have to write our Application service implementation methods.

Below are the methods we are going to implement.

  1. data_Archive
  2. restore_DAT_TO_BO
    c. delete_ZIP

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.

  1. Generate
  2. Build
    c. deploy
31.jpg

Step 32: After deployment we have to go CAF service browser to insert few data to our BO.

  BO : BOToArchive
32.jpg
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 NWA33.jpg
Step 34: Then select Example_MDB under Job Definitions Tab34.jpg
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.

35a.jpg

Then press the Next Button and provide the data as below

35c.jpg

Then press Next button.

35d.jpg

Then press Next button. And provide the start time of your scheduler.

Then press Add button.

35f.jpg

And then press finish button. It will go to the Tasks tab.

And you will see your task in the task list as below.

35g.jpg

And press the refresh button on the above screen if your task

is started then it will go to the under Jobs tab.

35h.jpg

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.

36.jpg

Below Screen Shoot of History BO

 

36a.jpg

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.

37.jpg

Then press Next button and select the specified method to execute.

37a.jpg

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.

37b.jpg

Then press Next button.

37c.jpg

Now to check whether the data will restore or not go to the

CAF service browser and double click the BOToArchive CAF BO.

37d.jpg

Now if we go to the History BO it will be empty.

37e.jpg

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://java.sun.com

http://help.sap.com

http://jaxb.java.net



Viewing all articles
Browse latest Browse all 1967

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>