Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

This Article is all about accessing KM of SAP portal 7.0x, in a web Dynpro java application, developed using NWDS CE 7.1 or higher versions, for maintaining documents.

Introduction

In most of the portal applications, we may come across a requirement of uploading a file or an image from one part of the application and later access these files or images from the other part of the same application or from different application. This requires the uploaded files to be stored somewhere. One of the simplest solutions is to have a backend table and store these files into it, for future reference. But this approach leads to huge data transfer between the front end application and backend tables, degrading the performance. To achieve better performance one can store these files into KM of the portal from where it can be accessed later, but the difficulty comes in Netweaver CE 7.1/CE 7.2 portal where KM is not available. This issue can be handled by accessing the KM of 7.0, into which the uploaded files can be stored by the Web Dynpro Java Application developed in NWDS CE 7.1 or higher versions, directly. These files can also be downloaded, versioned, locked etc. Thus we can do all those functionality that can be done in KM.  In this article I have tried to explain the steps to achieve this functionality. SAP portal 7.0x provides a standard web service RepositoryFrameworkWS to allow access to KM from any other external systems. This web service can be used in the Web Dynpro Java Application developed in NWDS CE 7.1, as Adaptive web service model, but the CreateDocument method/Request, used to upload documents, doesn’t work. So I have created an EJB Wrapper which consumes this web service and this EJB DC can be consumed in any WDJ application as Enterprise JavaBean Model.

Prerequisites

  • Basic Java Programming.
  • Basic Web Dynpro Hands-On Experience.
  • Basic Knowledge about Enterprise Portal and Knowledge Management (KM) functionalities.
  • Login credentials for 7.0 portal. Also this user credential should have Full permission or at least Read/Write permission on the target folder in KM, into which documents can be uploaded and can be downloaded from.

Preview

The screenshots displayed below show the three views in the application. When the application is launched, the WelcomeView appears, from where you can navigate to the file upload or file download scenarios

In the UploadFileViews, you can upload a file or an image from your PC to the folder in KM of SAP portal 7.0x. Once a MIME object has been uploaded, the system displays details of the uploaded file, such as file name and file size.


In the DownloadFileView, you can download a file or an image placed in a folder in KM of SAP portal 7.0x, into your local PC and display it on the user interface.

Step by Step Solution:

EJB DC Name: kmdemoejb
EJB Bean Name: KmdemoBean
EAR DC Name: Kmdemoejbear
Web Dynpro Project Name: uploadfile_wd
Application Name: UploadFileApp
Component Name: UploadFileComp
View Names:  WelcomeView, UploadFileView, DownloadFileView

Creation of an EJB DC

Open Java EE Perspective in NWDS → File → New → others... → Expand Development Infrastructure and Select Development Component and choose Next → Expand the root node with the vendor ID (sap.com) and select J2EE and then EJB Module. Choose Next → Expand the node Local Development and select MyComponents [demo.sap.com] and Choose Next.

Enter kmdemoejb in the Name field to specify the name of the DC. Leave the other settings unchanged and choose Next → Select 5.0 for the Java EE version and choose Finish.

Creating and Implementing the Session Bean and Deployable Enterprise Application

In the Project Explorer, expand your EJB DC. In the context menu of ejbModule, choose New → other... → Expand EJB and choose EJB Session Bean 3.0 -> Choose Next.

Enter Kmdemo in the EJB class Name field and com.km.ejb in the Default EJBPackage field. Set the Local option (select the check box "Local") and choose Next → the next screen confirms that the Business Interface KmdemoLocal is automatically created → Choose Finish.

File → New → Project...→ A New Project Wizard appears, Choose Development Infrastructure → Development Component. Choose Next → Expand the root node with the vendor ID (sap.com) and select J2EE, and then Enterprise Application. Choose Next → Expand the node Local Development → MyComponents. Choose Next

Enter kmdemoejbear in the Name field. Choose Next → Select 5.0 for Java EE version. Choose Next →  Assign the reference to the EJB DC project you have created in the last procedure and choose Finish.

Thus we have created an EJB DC and a deployable EAR DC with reference to EJB DC. Structure of the two DCs looks as shown below,

Consuming the Web service in EJB DC and Business logic in bean to execute it

In the Project Explorer, expand your EJB DC. In the context menu of the EJB DC, choose Import → Import… → Expand Web services and choose WSDL → Choose Next.

In the WSDL Import Wizard choose Remote Location/File System and click on Next → Enter the URL of the Web service RepositoryFrameworkWS as follows and choose Finish. http://<Host name of 7.0 portal>:50000/RepositoryFrameworkWS/Config1?wsdl

Expand your EJB DC. In the context menu of the imported WSDL file (rootwsdl_RepositoryFrameworkWS.wsdl), choose Web Services -> Choose Generate Java bean skeleton and click on Next in the "Web Service" window displayed.

In the next window choose Specify JAX-WS customization files and choose Next -> In the next window choose Finish.

The EAR DC will be deployed with warnings on click of finish. This is because one of the package created in this process will be named as java.lang and as it is the name of a standard JAVA package, deployment will not be successful.

To resolve this issue rename this package to com.km.java.lang as explained later, but before that we have to create the proxy client for the web service. Expand your EJB DC. In the context menu of the imported WSDL file (rootwsdl_RepositoryFrameworkWS.wsdl), choose Web Services -> Choose Generate Client and follow the same steps as explained above choosing Specify JAX-WS customization files. This will generate the RepositoryFrameworkWS.java class that will be used to execute the web service.

Now Expand the EJB DC and the ejbModule folder. In the context menu of package named java.lang choose Refactor -> Rename… -> Enter com.km.java.lang in the New name field and choose OK. This will result in compilation error in some of the .java files. Resolve the issue in each of these files by clicking on Ctrl+Shift+O or by importing the package com.km.java.lang manually.

Now we can write the business logic in the KmdemoBean.java class to execute the web service. Before this we will create one more class to return the content and mime type of the downloaded document. In the context menu of ejbModule choose Package and enter the name as com.km.ejb.response and choose Finish. In the context menu of  the newly created package choose Class and enter the name as DownloadResponse and choose Finish.

Write the below code in the newly created class, DownloadResponse.java.

public class DownloadResponse {
     private String base64;
     private String mimeType;
     private String errorMsg;
     public String getBase64() {
          return base64;
     }
     public void setBase64(String base64) {
          this.base64 = base64;
     }
     public String getMimeType() {
          return mimeType;
     }
     public void setMimeType(String mimeType) {
          this.mimeType = mimeType;
     }
     public String getErrorMsg() {
          return errorMsg;
     }
     public void setErrorMsg(String errorMsg) {
          this.errorMsg = errorMsg;
     }
}

Write the below code in the KmdemoBean.java class.

public class KmdemoBean implements KmdemoLocal {
public String createDocument (String base64, String mimetype, String parentRID, String fileName){
     FileInputStream ipStream = null;
     try {
          byte [] fileContent = Base64.decode(base64);
          URL wsdlLocation = new URL(http://<Host Name of 7.0 portal>:50000/RepositoryFrameworkWS/Config1?wsdl);
          RepositoryFrameworkWS rf =
          new RepositoryFrameworkWS(wsdlLocation, new QName("urn:RepositoryFrameworkWSWsd","RepositoryFrameworkWS"));
          RepositoryFrameworkWSViDocument vi = rf.getConfig1Port_Document();
          ((BindingProvider) vi).getRequestContext().put(BindingProvider.USERNAME_PROPERTY , "UserName");
          ((BindingProvider) vi).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY , "Password");
          Content content = new Content ();
          JAXBElement md = new JAXBElement(new QName("urn:com.sap.netweaver.bc.rf.ws.content", "content"),byte[].class, fileContent);
          content.setContent(md);
          ContentMetadata contentMetadata = new ContentMetadata(); contentMetadata.setLength(fileContent.length);
          JAXBElement fmtype =
          new JAXBElement (new QName("urn:com.sap.netweaver.bc.rf.ws.content","type"),String.class, mimetype);
          contentMetadata.setType(fmtype);
          JAXBElement meta = new JAXBElement(new QName("urn:com.sap.netweaver.bc.rf.ws.content", "metadata"),ContentMetadata.class, contentMetadata);
          content.setMetadata(meta);
          Resource resource =
          vi.createDocument(parentRID, fileName, new OrderPosition(), true, new LockDescriptor(), new ArrayOfProperty(), content, new FetchGroup());
          if(resource == null){
               return "1";
          }
          else{
               return "0";
          }
     }
     catch (CreateDocumentComSapNetweaverBcRfWsExceptionInvalidParameterExceptionDoc e) {
          e.printStackTrace();
          return e.toString();
     }
     catch (CreateDocumentComSapNetweaverBcRfWsExceptionOperationFailedExceptionDoc e) {
          e.printStackTrace();
          return e.toString();
     }
     catch (Exception e) {
          e.printStackTrace();
          return e.toString();
     }
     finally{
          if(ipStream != null){
               try{
                    ipStream.close();
               }
               catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }
}

public DownloadResponse downloadDocument(String parentRID, String fileName){
     DownloadResponse response = new DownloadResponse();
     FileInputStream ipStream = null;
     try {
          URL wsdlLocation = new URL("
http://<Host Name of 7.0 portal>:50000/RepositoryFrameworkWS/Config1?wsdl");
          RepositoryFrameworkWS rf = new RepositoryFrameworkWS(wsdlLocation, new QName("urn:RepositoryFrameworkWSWsd","RepositoryFrameworkWS"));
          RepositoryFrameworkWSViDocument vi = rf.getConfig1Port_Document();
          ((BindingProvider)vi).getRequestContext().put(BindingProvider.USERNAME_PROPERTY , "UserName");
          ((BindingProvider)vi).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY , "Password");
          Content content = vi.getContent(parentRID+fileName);
          if(content == null){ response.setErrorMsg("1");
               return response;
          }
          else{
               String base64 = Base64.encode(content.getContent().getValue());
               response.setBase64(base64);
               response.setMimeType(content.getMetadata().getValue().getType().getValue());
               response.setErrorMsg("0");
               return response;
          }
     }    
     catch (Exception e) {
          e.printStackTrace();
          response.setErrorMsg(e.toString());
          return response;
     }
     finally{
          if(ipStream != null){
               try{
                    ipStream.close();
               }
               catch (IOException e) {
                    e.printStackTrace();
               }
          }
     }
}
}

The createDocument method is used to upload the document passed as a string in BASE64 format, into the specified folder path (parentRID) of KM and the downloadDocument is used to download a document with the given file name (fileName), from the specified folder path (parentRID) of KM. In both the methods, first of all URL instance of the WSDL url is created and this is used to create an instance of the proxy class RepositoryFrameworkWS. Using this class instance, a reference to the interface RepositoryFrameworkWSViDocument is retrieved to perform, create and download operations.

In the createDocument method, “base64” is the content of the file to be uploaded and is formatted in com.sun.org.apache.xerces.internal.impl.dv.util.Base64 format, “mimetype” is corresponding mime type of the file and “parentRID” is the folder path of the target folder in KM. If the given document is successfully created in the specified folder, then the method returns “0” else it returns “1”. In case of any exception, corresponding exception message is returned.

In the downloadDocument method, “parentRID” is the folder path of the target folder in KM and “fileName” is the name of the file to be downloaded. If the document with the given name is successfully downloaded, then it returns an instance of DownloadResponse class with content of the file in com.sun.org.apache.xerces.internal.impl.dv.util.Base64 format, its mime type and error message as “0” else it returns an instance of DownloadResponse class with error message as “1” and in case of any exceptions it returns error message with the corresponding exception message.

In the same lines deleteDocument method can also be implemented, by calling deleteResource(parentRID + fileName) method of RepositoryFrameworkWSViDocument. To delete a document, the credentials used in above code, should have full permission on the target folder.

NOTE: The getContent method of the interface RepositoryFrameworkWSViDocument can be used to download files of size less than 1 MB. To download files of larger size, we can use getFirstChunk and getNextChunk methods to download the file in chunks and then combine them to form the intended file.

Once the business logic has been return we need to add these methods into the Local interface as explained below.

Expand the KmdemoBean class and in the context menu of createDocument method choose EJB methods → Add to Local Interfaces.Follow the same procedure to add downloadDocument method to Local interface.

Specifying Permissions in the EJB DC

Select the project node for the EJB DC and choose Development Component → Show in → Component Properties in the context menu. A multi page editor appears where you can specify DC-specific properties. → Select the Permissions tab and activate the option Entity Forwarding Allowed. To perform the DC Build, select the project node again and choose Development Component → Build.

Creating the Public Part in the Enterprise Application DC

Select the project node for the Enterprise Application DC (kmdemoejbear) and choose Development Component → Show in → Component Properties, in the context menu → in the properties editor, select the Public Parts tab → Choose Add… to create a new public part → Enter ejb_pp in the Name field and select Compilation as Purpose option. Then choose Finish.

Select the node for just created public part and choose Reference Entities in the context menu → In the next screen, you have to reference the public part of the EJB DC i.e. Expand the MyComponents [demo.sap.com] tree and select the EJB DC (kmdemoejb) → Then mark the client public part → Choose Finish → OK. To perform the Build for Enterprise Application DC, select the project node again and choose Development Component → Build.

Deploying the Java EE Application

Open Development Infrastructure perspective → expand Local Development folder in Component browser → expand MyComponents → choose kmdemoejbear DC → choose Deploy from the context menu.  OR 

Open the Servers view via the menu path Window → Show View → Other… → Server → Servers → Choose Add and Remove Projects from the context menu of the servers node → Add the Enterprise Application project kmdemoejbear and start the deployment with Finish.

Creating a Web Dynpro DC

Choose the menu path File → New → Project... → Expand the Development Infrastructure and select Development Component. Choose Next → Expand the root node with the vendor ID (sap.com) and select Web Dynpro. Choose Next → Expand the node Local Development and select MyComponents [demo.sap.com]. Choose Next → Enter uploadfile_wd in the Name field to specify the name of the DC. Leave the other settings unchanged and choose Next and then Finish in the next screen.

Specifying Dependences

In the context menu of the newly created Web Dynpro DC (uploadfile_wd) choose Development Component → Show in → Component Properties. Choose Dependencies tab → Add… → Expand the MyComponents [demo.sap.com] and select the kmdemoejbear project. Choose Finish.

Defining the Basic Project Structure

Expand the Web Dynpro node in the structure of the project. → To start the relevant wizard, open the context menu of the Applications node and choose Create Application → Enter a name for the Web Dynpro application, as UploadFileApp, and specify the package and choose Next → Choose Create a new component and choose Next → Provide the component name and package and choose Next → retain the predefined settings for the window, the interface view, and the startup plug. Choose Finish.

At the end of these steps a DC is created with an application, a component and a default View named UploadFileCompView. Rename this view as WelcomeView.

Creation of UI

  • Create two more Views named UploadFileView and DownloadFileView.
  • Place appropriate UI elements in these views to get the layout as shown in the figures 1.1 to 1.3. In UploadFileView we use FileUpload UI element to select the file from client’s file system. Once you have created the project template in the SAP Netweaver Developer Studio 7.1 CE, you will see the following structure in the Web Dynpro Explorer.
    Web Dynpro Project Structure
    Web Dynpro Project: Uploadfile_wd
    Web Dynpro Application: UploadFileApp
        Web Dynpro Component: UploadFileComp
             View: Welcome View
             In this view, you can choose to either upload or download a file.
             View: UploadFileView
             In this view, you can upload a file from your PC to a common the folder in KM of NWDS 7.0.
             View-Layout: contains pre-defined UI elements.
             Actions: BackToWelcomeView, UploadFile

             View: DownloadFileView
             In this view, you can download a file from the folder in KM of NWDS 7.0 to your PC by providing the file  name along with its Extension.
             View-Layout: contains pre-defined UI elements.
             Actions: BackToWelcmeoView, DownloadFile

             Window: UploadFileWin
             Contains the three views described above together with the definitions of the View Compositions (navigation links between inbound and outbound plugs).

Creating Enterprise JavaBean Model

In the project structure, expand the node Web Dynpro →  Models. From the context menu, choose Create Model → Choose the Enterprise JavaBean Model option and choose Next → Enter KmEjbModel in the Model Name field and specify com.sap.km.model as the Model Package and choose Next → Select the Enterprise Application DC kmdemoejbear that provides the public part with the Enterprise JavaBeans required for model import. Choose Next. A list of Session Beans, Local interfaces and their business methods appears → select all the methods from the KmdemoLocal interface and choose Next → a list of model classes to be generated, is displayed on the next screen. Choose Next → Start the model generation routine with Finish.

Adding a Model to the Web Dynpro Component

Expand the project structure Components → UploadFileComp → Used Models → In the context menu of the Used Models node, choose Add and select the Model you have created in the last step and confirm with OK.

Business Logic in Web Dynpro application to consume EJB model

  • Switch to UploadFileView.
  • Choose the Context tab page and add a value attribute Va_Resource of type com.sap.ide.webdynpro.uielementdefinitions.Resource.
  • Add two more value attributes Va_FileName and Va_FileSize of type String, and a value attribute Va_FileDetailsVisibility of type com.sap.ide.webdynpro.uielementdefinitions.Visibility.
  • Bind context attribute Va_Resource to resource property of the FileUpload UI element, Va_FileDetailsVibility to Visibility property of transparent container which holds file details UI elements, Va_FileName and Va_FileSize to the corresponding TextView UI elements.
  • Context attribute Va_Resource of type resource holds the entire file uploaded. This file in the resource type will be converted to Byte Array and then to a string represented in Base 64 format which will be passed to ejb model, in which it is converted back to byte array before passing it to KM web service.

After the file is browsed and selected from the local PC and Upload action has been triggered on the user interface, the chosen file is transported to the context attribute Va_Resource. The associated file information, like MIME type and file name, is derived using appropriate APIs as shown in the code below. The file size is also determined and these details are stored into the context attributes. Insert the following program code in method onActionUpload( ).

public void onActionUpload(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent ) {
     //@@begin onActionUpload(ServerEvent)
     try{
          String contentType = "";
          String unit = "";
          String fileSize = "";
          DecimalFormat myFormatter = new DecimalFormat("###.##");
          KmEjbModel model = new KmEjbModel();
          Request_KmdemoLocal_createDocument request = new Request_KmdemoLocal_createDocument(model);
          IWDResource resource = wdContext.currentContextElement().getVa_Resource();
          if(resource != null){
               InputStream  inputStream = resource.read(false);
               int noOfBytes = inputStream.available();
               byte[] byteArray = new byte[noOfBytes];
               inputStream.read(byteArray, 0, noOfBytes);
               String base64 = Base64.encode(byteArray);
               String fileName = resource.getResourceName();
               if (noOfBytes < 1024) {
                    unit = " Bytes";
               }
               else if (noOfBytes < 1048576) {
                    noOfBytes = noOfBytes / 1024;
                    unit = " KB";
               }
               else if (noOfBytes < 1073741824) {
                    noOfBytes = noOfBytes / 1024 / 1024; unit = " MB";
               }
               fileSize = myFormatter.format(noOfBytes) + unit;
               contentType = resource.getResourceType().getHtmlMime();
               request.setBase64(base64);
               request.setFileName(fileName);
               request.setMimetype(contentType);
               request.setParentRID("/documents/TargetFolder/");
               request.execute(); 
               String returnString = request.getResponse().getReturn();
               if("0".equals(returnString)){ wdContext.currentContextElement().setVa_FileName(fileName);
                    wdContext.currentContextElement().setVa_FileSize(fileSize);
                    wdComponentAPI.getMessageManager().reportSuccess("File named: "+fileName

                         + " is successfully uploaded into KM");
                    wdContext.currentContextElement().setVa_FileDetailsVisibility( WDVisibility.VISIBLE);
               }
               else{
                    wdComponentAPI.getMessageManager().reportException("Exception Details: "+returnString);
               }
          }    
          else{
               wdComponentAPI.getMessageManager().reportException("Please select a file to be uploaded.");
          }
     }
     catch (Exception e) {
          wdComponentAPI.getMessageManager().reportException("Exception Details: "+e.toString());
     }

}

Here in parentRID passed to the web service “TargetFolder” is the name of the folder created manually in KM under “documents” which in turn is under “root”. This target folder can be created under any path in KM, and the relative path of which is provided appropriately. Method OnActionBackToWelcomeView( ) will be triggered on click of BackToWelcomeView button. In this method outbound plug is fired to navigate back to WelcomeView.

  • Now Switch to DownloadFileView.
  • Choose the Context tab page and add a value attribute Va_FileName of type String and bind it to Input field with id if_FileName.

After the proper filename is typed in DownloadFileView and Download action has been triggeredon the user interface, if the file name is valid and the file is already placed in the specified folder, web service is executed through ejb model by passing the given file name and the file is downloaded. Ejb model returns the file in base 64 string format which is then converted to byte array. The byte array is then converted to Resource type, by using appropriate APIs as show in the code and is opened with the corresponding application software. Insert the following lines code in method onActionDownload( ).

public void onActionDownload(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent) {
     //@@begin onActionDownload(ServerEvent)
     String fileName = wdContext.currentContextElement().getVa_FileName();
     String extn = "";
     if(null != fileName){
          extn = fileName.substring(fileName.lastIndexOf(".")+1);
     }
     else{
          wdComponentAPI.getMessageManager().reportException("Please enter the file name.");
     }
     KmEjbModel model = new KmEjbModel();
     Request_KmdemoLocal_downloadDocument request = new Request_KmdemoLocal_downloadDocument(model);
     request.setFileName(fileName);
     request.setParentRID("/documents/TargetFolder/");
     String base64 = null;
     String mimeType = "";
     String errMsg = "";
     try{ request.execute();
          DownloadResponse response = request.getResponse().getReturn();
          errMsg = response.getErrorMsg();
          if("0".equals(errMsg)){
               base64 = response.getBase64();
               mimeType = response.getMimeType();
          }
          else{
               wdComponentAPI.getMessageManager().reportException(errMsg);
          }
     }
     catch (Exception e) {
          wdComponentAPI.getMessageManager().reportException(e.toString());
     }
     if(base64 != null){
          byte [] con = Base64.decode(base64);
          WDWebResourceType resourceType = WDWebResourceType.getWebResourceType(mimeType.trim(), extn.toUpperCase());
          IWDResource resource = WDResourceFactory.createResource(con, fileName, resourceType);
          if(resource != null){ resource.download();
          }
          else{
               wdComponentAPI.getMessageManager().reportException("The file was not downloaded.");
          }
     }
     else{
          wdComponentAPI.getMessageManager().reportException("The file was not downloaded.");
     } //@@end
}

Method OnActionBackToWelcomeView() is triggered on click of BackToWelcomeView button. In this method outbound plug is fired to navigate back to WelcomeView.

Deploying and Running the Web Dynpro Application

  • Save all metadata. Select Rebuild Project from the context menu of Uploadfile_wd DC. Now select Deploy New Archive and Run from the context menu of UploadFileApp (Web Dynpro Application).
  • After deploying and running the application provide the file to be uploaded using Browse button and after successful uploading, check the specified location (mentioned in application) of KM where the file has to be stored.

Conclusion

In this way we can upload a file/image into the target folder in KM of SAP portal 7.0x from a Web Dynpro Java Application developed in NWDS 7.1 CE. From this target folder the file/image can be fetched in future by any other application or other part of the same application, avoiding the storage of these files/images in the backend R3 system and thereby increasing the performance.

Future Enhancements

A Z-table can be maintained in the SAP backend, to store only the name of the files uploaded into the target folder in KM of SAP portal 7.0x by the Web Dynpro application, for future reference. Couple of BAPIs can be created to write the names into the table and read them when required. In this way we can have a track of the files uploaded.

Related Content

Developing User Interfaces with Web Dynpro for Java
File Upload (SAP-Library)
Integrating EJB 3.0 into Web Dynpro Using the EJB Model Importer

3 Comments
Labels in this area