Creating pdf in the backend:
The scenario is as follows:
User entering data for creation of sales order on client side (mobile device).
Sales order data to be saved with the signature of the customer in form of PDF.
The same pdf needs to be printed on printer
This PDF also need to be transferred to the backend and saved there. The scenario that's mentioned above had to be modified since we were not being able to create pdf at client side. Due to unavailability of supporting api's in the Crème (JRE for mobile devices) like String.split method. StringBuffer.append and many more the functionality could not be achieved. *There are different approaches that can be taken to create pdf's at the backend:*
1) All the sales order data in the backend a smart form must be created. This smart form then creates a spool which in turn is sent to spool to pdf functionality to create a pdf at the backend.
a. Disadvantage: Cannot embed signature captured at client side. Since smart form requires an image to be already present in the backend. Also it accepts only .bmp format.
2) The pdf could be created using Adobe Live Cycle designer and ADS (Adobe Document Service). So all the sales order which is stored in SAP internal table can be passed to the ADS which creates a pdf for the same. The template for the pdf needs to be created in the Adobe Live Cycle Designer.
a. Disadvantages:
i. This is probably best of developing PDF's in backend but there are licensing cost involved for the ADS and Adobe Live Cycle Designer.
ii. Also ADS can be installed only on Java stack. So if a client does not have Java stack this solution does not work
b. Advantage: With this solution the image can be embedded in pdf as StringBase64 format with the use Graphic Content and ImageField option in Interface created and Adobe Live Cycle Designer Layout created respectively.
3) The solution that we used was to call a Java program which read values from an internal table using JCO and created a PDF using itext.jar utility. This could be good solution considering the licensing cost involved in implementing in the second solution of using ADS. I shall be explaining the process of creating pdf using the third solution in detail. The scenario can be used for different environments but I am explaining the same with the following assumptions:
1) The scenario is such that the calling program is in one system and the pdf needs to be created in another System. System A is has the program that is the trigger point or the System from where the sales order is going to get posted
System B is where the java program exists and creates a PDF.
Steps:
1) Create a TCP/IP Destination using sm59 transaction giving the appropriate parameters
Incase the invoking system(System A) is UNICODE system enable the Unicode radio button.
1) The calling program (this is example program which can be replaced complete implementation to suit your need).
*&---------------------------------------------------------------------*
*& Report ZTEST_KUMAR
*&---------------------------------------------------------------------*
REPORT ZTEST_KUMAR.
types: begin of ty_data,
line type TDLINE,
end of ty_data.
data : it_data type standard table of ZDATA_STRING.
DATA : W_RET TYPE char255,
w_val TYPE char255,
itab TYPE STANDARD TABLE OF ZTEST_PDF,
wa like line of itab.
Parameters : p_file type ibipparms-path.
at selection-screen on value-request for p_file.
CALL FUNCTION 'F4_FILENAME'
* EXPORTING
* PROGRAM_NAME = SYST-CPROG
* DYNPRO_NUMBER = SYST-DYNNR
* FIELD_NAME = ' '
IMPORTING
FILE_NAME = p_file.
[Please don't add this it is just comments
The above code was to read the base64 encoded string from a.txt file and insert It into a table (TABLE OF ZTEST_PDF).]
Start-of-selection.
perform file_upload.
clear wa.
clear WA-CUST1I.
clear wa-TEMP.
wa-CUST1I = 'CUSTOMER1'.
wa-TEMP = 'PRODUCT1'.
append wa to itab.
wa-CUST1I = 'CUSTOMER2'.
wa-TEMP = 'PRODUCT3'.
append wa to itab.
w_val = 'TEST PDF FOR SALES ORDer'.
[Please don't add this it is just comments
The code below calls the dummy function module which is described in the next point at the destination which is created above in point no 1]
CALL FUNCTION 'ZTEST_PDF_CREATE' DESTINATION 'ECD_GULFNEWS2'
EXPORTING
TEST = w_val
TEST_TABLE = itab
IT_DATA = it_data
IMPORTING
RETURNVAL1 = w_ret.
[Please don't add this it is just comments
Printing data returned back by the java program]
LOOP AT itab INTO WA.
WRITE WA-CUST1I.
write wa-TEMP.
ENDLOOP.
end-of-selection.
WRITE W_VAL.
WRITE W_RET.
*&---------------------------------------------------------------------*
*& Form FILE_UPLOAD
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM FILE_UPLOAD .
DATA : lw_string TYPE string.
lw_string = p_file.
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
FILENAME = lw_string
FILETYPE = 'ASC'
* HAS_FIELD_SEPARATOR = ' '
* HEADER_LENGTH = 0
* READ_BY_LINE = 'X'
* DAT_MODE = ' '
* CODEPAGE = ' '
* IGNORE_CERR = ABAP_TRUE
* REPLACEMENT = '#'
* CHECK_BOM = ' '
* VIRUS_SCAN_PROFILE =
* NO_AUTH_CHECK = ' '
* IMPORTING
* FILELENGTH =
* HEADER =
TABLES
DATA_TAB = it_data
* EXCEPTIONS
* FILE_OPEN_ERROR = 1
* FILE_READ_ERROR = 2
* NO_BATCH = 3
* GUI_REFUSE_FILETRANSFER = 4
* INVALID_TYPE = 5
* NO_AUTHORITY = 6
* UNKNOWN_ERROR = 7
* BAD_DATA_FORMAT = 8
* HEADER_NOT_ALLOWED = 9
* SEPARATOR_NOT_ALLOWED = 10
* HEADER_TOO_LONG = 11
* UNKNOWN_DP_ERROR = 12
* ACCESS_DENIED = 13
* DP_OUT_OF_MEMORY = 14
* DISK_FULL = 15
* DP_TIMEOUT = 16
* OTHERS = 17
.
IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM. " FILE_UPLOAD
3. Create a dummy function module in System B with all the import/export/table parameters which are needed to be passed. The function module is just dummy function module
1) Pre-requisites for the Java program to execute and also the Sample Java program
a. We would be using JCO to access the data which is being passed to the dummy function module mentioned above. For java program to use JCO the following files would be required based on the operating system and processor (32 bit or 64 bit processor). The JCO version used sapjco-ntintel-2.1.8.
i. sapjco.jar
ii. sapjcorfc.dll
iii. librfc32.dll
b. We would also require itext.jar. We have used itext-1.4.8 version which does not have any other dependencies. Also since the itext-1.4.8.jar downloaded from any site is for 32bit OS we need to recompile the same on 64 bit JVM.
c. The code for Java program can be kept in folder. The following are the commands to compile and run the code
i. javac -classpath C:\testpdf\sapjco.jar;C:\testpdf\sapjcorfc.dll;C:\testpdf\librfc32.dll;C:\testpdf\iText.jar; PDF_Create.java
ii. java -classpath C:\testpdf\sapjco.jar;C:\testpdf\sapjcorfc.dll;C:\usr\sap\ECD\librfc32.dll;C:\testpdf\iText.jar; PDF_Create
d. The code for the java program
import com.sap.mw.jco.*;
import com.sap.mw.jco.JCO.MetaData;
import java.io.*;
import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import java.text.SimpleDateFormat;
import java.util.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
public class PDF_Create implements JCO.ServerExceptionListener,
JCO.ServerErrorListener
{
static { JCO.MetaData fmeta = new JCO.MetaData("ZTEST_PDF_CREATE"); //fmeta.addInfo("REQUTEXT", JCO.TYPE_CHAR, 255, 0, 0,JCO.IMPORT_PARAMETER, null); //fmeta.addInfo("ECHOTEXT", JCO.TYPE_CHAR, 255, 0, 0,JCO.EXPORT_PARAMETER, null); //fmeta.addInfo("RESPTEXT", JCO.TYPE_CHAR, 255, 0, 0,JCO.EXPORT_PARAMETER, null); // repository.addFunctionInterfaceToCache(fmeta); }
/**
* This is the actual Server (Listener) object
*/
static public class Server extends JCO.Server
{
/* * Simple constructor. Just call superclass to initialize everything * properly. / public Server(String gwhost, String gwserv, String program_id, IRepository repos) { super(gwhost, gwserv, program_id, repos); this.setProperty("jco.server.unicode", "1"); }
/**
* This function will be invoked when a transactional RFC is being
* called from a SAP R/3 system. The function has to store the TID in
* permanent storage and returntrue
. The method has to
* returnfalse
if the a transaction with this ID has
* already been process. Throw an exception if anything goes wrong. The
* transaction processing will be aborted thereafter. Derived
* servers must override this method to actually implement the
* transaction ID management.
*
* @param tid
* the transaction ID
* @returntrue
if the ID is valid and not in use
* otherwise,false
otherwise
*/
protected boolean onCheckTID(String tid)
{ return true; }
/**
* This function will be called after the local transaction
* has been completed. All resources assiciated with this TID can be
* released. Derived servers must override this method to actually
* implement the transaction ID management.
*
* @param tid
* the transaction ID
*/
protected void onConfirmTID(String tid)
{ }
/*\*
\* This function will be called afterallRFC functions
\* belonging to a certain transaction have been successfully completed.
\*Derived servers can override this method to locally commit the
\* transaction.
\*
\* @param tid
\* the transaction ID
\*/
protected void onCommit(String tid) { }}
/**
* This function will be called if an error in one of the RFC functions
* belonging to a certain transaction has occurred. Derived servers
* can override this method to locally rollback the transaction.
*
* @param tid
* the transaction ID
*/
protected void onRollback(String tid)
{ }
/**
* Called upon an incoming requests
*/
protected void handleRequest(JCO.Function function) {
try {
JCO.ParameterList input = function.getImportParameterList();
JCO.ParameterList output = function.getExportParameterList();
JCO.ParameterList tables = function.getTableParameterList();
JCO.Table table =(JCO.Table) input.getValue("TEST_TABLE");
JCO.Table table1 =(JCO.Table) input.getValue("IT_DATA");
if (function.getName().equals("ZTEST_PDF_CREATE"))
{ Document document = new Document(); SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy_HHmmss");
PdfWriter writer; File salesorderfile = new File(sdf.format(new Date()) + ".pdf");
writer = PdfWriter.getInstance(document, new FileOutputStream(salesorderfile)); document.open();
PdfPTable tablepdf = new PdfPTable(table1.getNumColumns()); // Code 1*/
for(int i=0;i
String imagestring = new String();
for(int i=0;i
{ imagestring+=table1.getValue("TDLINE").toString(); table1.nextRow(); } //
document.add(tablepdf);
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
byte[] imageBytes1 = new sun.misc.BASE64Decoder().decodeBuffer(imagestring);
BufferedImage bi = javax.imageio.ImageIO.read(new
ByteArrayInputStream(imageBytes1));
javax.imageio.ImageIO.write(bi,"jpg", new File("invoicenumber.jpg"));
com.lowagie.text.Image logo;
logo = com.lowagie.text.Image.getInstance("invoicenumber.jpg");
logo.scalePercent(50);
document.add(logo);
document.add(new Paragraph(input.getString("TEST")));
document.close();
output.setValue(salesorderfile .getName(), "RETURNVAL1");
}
} catch (Exception e)
{ e.printStackTrace(); }
// This will cause a short-dump in R/3 that indicates that we cannot
// handle the request.
}
}
/**
* Called if an exception was thrown anywhere in our server
*/
public void serverExceptionOccurred(JCO.Server srv, Exception ex)
{ System.out.println("Exception in Server " + srv.getProgID() + ":n" + ex); ex.printStackTrace(); }
/**
* Called if an error was thrown anywhere in our server
*/
public void serverErrorOccurred(JCO.Server srv, Error err)
{ System.out.println("Error in Server " + srv.getProgID() + ":n" + err); err.printStackTrace(); }
// System IDs of the system that we gonna using be for dictionary calls
String POOL_A = "bomw069a.in002.siemens.net";
String POOL_B = "SYSTEM_B";
// The server objects that actually handles the request
int MAX_SERVERS = 2;
Server servers[] = new Server[Community:MAX_SERVERS];
/**
* Constructor. Creates a client pool, the repository and a server.
*/
public PDF_Create()
{ // IRepository repository; // Add a connection pool to a remote R/3 system A. // We will use this connected to dynamically // request dictionary information for incoming function calls. // !!! Please, fill in the necessary login and system parameters !!! JCO.addClientPool("POOL", 3, "100", "IC009689SR", "killer82", "EN", "bomw069a", "00"); // Create repository for System A IRepository repository = JCO.createRepository("REP", "POOL"); // Create a new server and register it with system A servers[0] = new Server("bomw069a", "sapgw00", "GNJ2EEGCD", repository); // Add a connection pool to a remote R/3 system B. // We will use this connected to dynamically // request dictionary information for incoming function calls. // !!! Please, fill in the necessary login and system parameters !!! // JCO.addClientPool(POOL_B,3,"000","user","password","EN","system_b","02"); // Create repository for system B // repository = JCO.createRepository("SYSTEM_B", POOL_B ); // Create a new server and register it with system B // servers[1] = new Server("SystemB", "sapgw02", "SERVER_B", // repository); // Register ourselves such that we get exceptions from the servers JCO.addServerExceptionListener(this); // Register ourselves such that we get errors from the servers JCO.addServerErrorListener(this); }
/**
* Start the server
*/
public void startServers()
{ try { servers[0].start(); }
catch (Exception ex)
{ ex.printStackTrace(); System.out.println("Could not start servers !n"); }// try
}
/**
* Simple main program driver
*/
public static void main(String[] argv)
{ PDF_Create obj = new PDF_Create(); obj.startServers(); }
}
No comments:
Post a Comment