Oracle Form调用JavaBean开发教程


简介原理

Oracle Form开发时都是基于组件的,比如canvas、button、text等等,其实底层就是一个个的JavaBean,在执行时会被转换成Java Applet在JVM中运行。在Form Builder的组件属性中可以看到一个叫“实施类”的属性,其实就是该组件对应的java类,一般标准的组件都为空,无须明确指出。
在这里插入图片描述
当然Oracle也允许我们开发自己的组件并应用到form中,但是局限还是挺大的。客制化的JavaBean必须继承Oracle提供的VBean,仅提供了set_custom_property和get_custom_property两个方法调用JavaBean,在JavaBean中也可以通过发布CustomEvent来触发Form的触发器WHEN-CUSTOM-ITEM-EVENT,从而执行相应的处理。

  • Form调用JavaBean:
    Set_custom_property(<BeanName>,<InstanceId>,<MethodName>,<Value>)对应JavaBean setter
    Get_custom_property(<BeanName>,<InstanceId>,<MethodName>)对应JavaBean getter
  • JavaBean调用form:
    1)dispatchCustomEvent(new CustomEvent(<Handler>, < PropertyID>))
    触发form中Bean区域项的When-Custom-Item-Event
    2)System.Custom_Item_Event保存Java发布的事件名称
    3)Custom_Item_Event_Parameters获取Java发布事件时设置的属性值

一、JavaBean开发实例(上传Excel文件)

1、准备工作

1)下载jar包frmmain.jar,服务器路径cd $ORACLE_HOME/forms/java,或者用本地Oracle开发套件安装目录下的也可以D:\DevSuiteHome_1\forms\java
2)使用Idea导入jar包frmmain.jar

2、Javabean开发

这里用了IntelliJ IDEA来开发,依赖管理用maven,Java代码如下

package com.bitland.ebs.forms.beans;

import oracle.ewt.util.WindowUtils;
import oracle.forms.api.FException;
import oracle.forms.handler.IHandler;
import oracle.forms.properties.ID;
import oracle.forms.ui.CustomEvent;
import oracle.forms.ui.VBean;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;

import java.awt.*;
import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

/**
 * @author qiucheng.he
 * @version 1.0.0
 * @ClassName: UploadBean
 * @Description: 导入本地文件
 * @date 2020-11-20 11:09
 */
public class UploadBean extends VBean {
    
    

    private final static ID FILETOREAD = ID.registerProperty("FILETOREAD");
    private final static ID LASTDIR = ID.registerProperty("LASTDIR");
    private final static ID SHEETCOUNT = ID.registerProperty("SHEETCOUNT");
    private final static ID ROWCOUNT = ID.registerProperty("ROWCOUNT");
    private final static ID SHEETNUM = ID.registerProperty("SHEETNUM");
    private final static ID RETURNCODE = ID.registerProperty("RETURNCODE");
    private final static ID RETURNMSG = ID.registerProperty("RETURNMSG");
    private final static ID SQLSTATMENT = ID.registerProperty("SQLSTATMENT");
    private final static ID VALUESTATMENT = ID.registerProperty("VALUESTATMENT");

    private final static ID OPENDIALOG = ID.registerProperty("OPENDIALOG");
    private final static ID CREATEWORKBOOK = ID.registerProperty("CREATEWORKBOOK");
    private final static ID CREATESHEET = ID.registerProperty("CREATESHEET");
    private final static ID READROW = ID.registerProperty("READROW");
    private final static ID RELEASE = ID.registerProperty("RELEASE");

    private final static String CRLF = "\r\n";
    private final static String ORACLENULL = "false"; //Oracle Null值转换为java的object为"false"
    private final static String NULLSTRING = "";
    private final static int MAXCOLUMN = 60;
    private static String fileLastDir = "";
    private static String fileToRead = "";
    private static int sheetNum = 0;
    private static int sheetCount = 0;
    private static int rowCount = 0;
    private static String splitStr = "~#~";
    private static String sqlStatment = "";
    private static String valueStatment = "";
    private static MessageBean msgBean = new MessageBean("S", "");

    private Workbook workbook;
    private Sheet sheet;

    IHandler mHandler;

    //init
    public void init(IHandler handler) {
    
    
        super.init(handler);
        mHandler = handler;
    }

    /**
     * 设置bean属性,set_custom_property调用
     *
     * @param id
     * @param value
     * @return
     */
    public boolean setProperty(ID id, Object value) {
    
    
        try {
    
    
            if (id == OPENDIALOG) {
    
    
                selectFile(value.toString());
            } else if (id == LASTDIR) {
    
    
                fileLastDir = value.toString();
            } else if (id == RETURNCODE) {
    
    
                msgBean.setCode(value.toString());
            } else if (id == RETURNMSG) {
    
    
                msgBean.setText(value.toString());
            } else if (id == CREATEWORKBOOK) {
    
    
                creatWorkbook();
            } else if (id == CREATESHEET) {
    
    
                createSheet(value.toString());
            } else if (id == READROW) {
    
    
                readRow(Integer.parseInt(value.toString()));
            } else {
    
    
                return super.setProperty(id, value);
            }
        } catch (FException e) {
    
    
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 获取Bean属性,get_custom_property调用
     *
     * @param id
     * @return
     */
    public Object getProperty(ID id) {
    
    
        if (id == FILETOREAD) {
    
    
            return fileToRead;
        } else if (id == LASTDIR) {
    
    
            return fileLastDir;
        } else if (id == RETURNCODE) {
    
    
            return msgBean.getCode();
        } else if (id == RETURNMSG) {
    
    
            return msgBean.getText();
        } else if (id == SHEETCOUNT) {
    
    
            return String.valueOf(sheetCount);
        } else if (id == ROWCOUNT) {
    
    
            return String.valueOf(rowCount);
        } else if (id == SHEETNUM) {
    
    
            return String.valueOf(sheetNum);
        } else if (id == SQLSTATMENT) {
    
    
            return sqlStatment;
        } else if (id == VALUESTATMENT) {
    
    
            return valueStatment;
        } else if (id == RELEASE) {
    
    
            releaseResource();
        } else {
    
    
            return super.getProperty(id);
        }
        return "";
    }

    /**
     * 打开对话框选择文件
     *
     * @param filepath
     * @throws FException
     */
    private boolean selectFile(String filepath) throws FException {
    
    
        msgBean.setCode("S");
        msgBean.setText("");
        FileDialog filedialog = new FileDialog(WindowUtils.getSharedOwnerFrame(), "打开", FileDialog.LOAD);
        //路径为空则打开上次的路径
        if (filepath.equals(ORACLENULL)) {
    
    
            filedialog.setDirectory(fileLastDir);
        } else {
    
    
            filedialog.setDirectory(filepath);
        }
        //filedialog.show(); //已过时
        filedialog.setVisible(true);

        fileToRead = filedialog.getFile();
        fileLastDir = filedialog.getDirectory();

        if (fileLastDir != null && fileToRead != null) {
    
    
            fileToRead = (fileToRead.equals("null") ? NULLSTRING : fileLastDir.concat(fileToRead));
            //System.out.println("filetoread:" + this.fileToRead);
            //System.out.println("filelastdir:" + this.fileLastDir);

            //自定义事件,事件发布后触发from上bean区域组件的when-custom-item-event
            CustomEvent customevent = new CustomEvent(mHandler, OPENDIALOG); //自定义事件句柄
            mHandler.setProperty(FILETOREAD, fileToRead);
            mHandler.setProperty(LASTDIR, fileLastDir);
            mHandler.setProperty(RETURNCODE, msgBean.getCode());
            mHandler.setProperty(RETURNMSG, "OPENDIALOG: " + msgBean.getText());
            dispatchCustomEvent(customevent);
        }
        return true;
    }

    /**
     * 读取Excel文件
     *
     * @throws FException
     */
    private void creatWorkbook() throws FException {
    
    
        try {
    
    
            workbook = WorkbookFactory.create(new File(fileToRead), null, true); //仅读方式打开文件
            sheetCount = workbook.getNumberOfSheets();
        } catch (IOException e) {
    
    
            msgBean.setCode("E");
            msgBean.setText(e.getMessage());
            e.printStackTrace();
        }
        CustomEvent customevent = new CustomEvent(mHandler, CREATEWORKBOOK);
        mHandler.setProperty(RETURNCODE, msgBean.getCode());
        mHandler.setProperty(RETURNMSG, "CREATEWORKBOOK: " + msgBean.getText());
        dispatchCustomEvent(customevent);
    }

    /**
     * 创建Sheet对象
     *
     * @param sheetIndex
     * @throws FException
     */
    private void createSheet(String sheetIndex) throws FException {
    
    
        try {
    
    
            if (sheetIndex.trim().equals(ORACLENULL)) {
    
    
                sheetNum = workbook.getActiveSheetIndex();
            } else {
    
    
                sheetNum = Integer.parseInt(sheetIndex);
            }
            sheet = workbook.getSheetAt(sheetNum);
            rowCount = sheet.getLastRowNum();
        } catch (Exception e) {
    
    
            msgBean.setCode("E");
            msgBean.setText(e.getMessage());
            e.printStackTrace();
        }
        CustomEvent customevent = new CustomEvent(mHandler, CREATESHEET);
        mHandler.setProperty(RETURNCODE, msgBean.getCode());
        mHandler.setProperty(RETURNMSG, "CREATESHEET: " + msgBean.getText());
        dispatchCustomEvent(customevent);
    }

    /**
     * 读取指定Excel行数据
     *
     * @param rownum
     * @throws FException
     */
    private void readRow(int rownum) throws FException {
    
    
        Row row = sheet.getRow(rownum);
        if (row == null) {
    
    
            sqlStatment = "";
            valueStatment = "";
            return;
        }

        try {
    
    
            StringBuffer sqlStr = new StringBuffer("INSERT INTO BITC_UPLOAD_TMP(FILE_ID,SHEET_NUM,ROW_NUM");
            StringBuffer sqlStrPostfix = new StringBuffer(") VALUES (?,?,?");
            StringBuffer valueStr = new StringBuffer();
            boolean insertFlag = false;

            int columnCount = row.getLastCellNum();
            //System.out.println("columnCount:" + columnCount);
            for (int i = 0; i < columnCount; i++) {
    
    
                if (i == MAXCOLUMN) {
    
    
                    break;
                }

                sqlStr.append(",ATTRIBUTE" + (i + 1));
                sqlStrPostfix.append(",?");

                String cellValue;
                Cell cell = row.getCell(i);
                if (cell == null) {
    
    
                    cellValue = "";
                } else {
    
    
                    insertFlag = true;
                    cellValue = getCellValue(cell, cell.getCellType().getCode());
                }
                valueStr.append(splitStr + cellValue);
            }
            sqlStr.append(sqlStrPostfix).append(")");

            if (insertFlag) {
    
    
                sqlStatment = sqlStr.toString();
                valueStatment = valueStr.toString().replaceFirst(splitStr, "");
            } else {
    
    
                sqlStatment = "";
                valueStatment = "";
            }
        } catch (Exception e) {
    
    
            msgBean.setCode("E");
            msgBean.setText(e.getMessage());
            e.printStackTrace();
        }

        CustomEvent customevent = new CustomEvent(mHandler, READROW);
        mHandler.setProperty(RETURNCODE, msgBean.getCode());
        mHandler.setProperty(RETURNMSG, "READROW: " + msgBean.getText());
        dispatchCustomEvent(customevent);
    }

    private static String getCellValue(Cell cell, int cellType) {
    
    
        short f = cell.getCellStyle().getDataFormat();

        switch (cellType) {
    
    
            case 0: // NUMERIC 数值类型-整数、小数、日期
                DecimalFormat decimalFormat = new DecimalFormat("#.0000000000");
                if (HSSFDateUtil.isCellDateFormatted(cell) || f == 58 || f == 14
                        || f == 31 || f == 32) {
    
    
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    return simpleDateFormat.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                } else if (cell.getCellStyle().getDataFormatString().contains("%")) {
    
    
                    //数字要去掉后面多余的0
                    return BigDecimal.valueOf(Double.parseDouble(decimalFormat.format(cell.getNumericCellValue() * 100))).stripTrailingZeros().toPlainString() + "%";
                } else {
    
    
                    return BigDecimal.valueOf(Double.parseDouble(decimalFormat.format(cell.getNumericCellValue()))).stripTrailingZeros().toPlainString();
                }
            case 1: // String 字符串
                return cell.getStringCellValue();
            case 2: // FORMULA 公式
                return getCellValue(cell, cell.getCachedFormulaResultType().getCode());
            case 3: // blank 空值
                return "";
            case 4: // boolean
                return cell.getBooleanCellValue() + "";
            case 5: // error
                return cell.getErrorCellValue() + "";
            default:
                return "";
        }
    }


    private void releaseResource() {
    
    
        try {
    
    
            if (workbook != null) {
    
    
                workbook.close();
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
    
    

    }

}

return message Bean

package com.bitland.ebs.forms.beans;

/**
 * @author qiucheng.he
 * @version 1.0.0
 * @ClassName: MessageBean
 * @Description: TODO
 * @date 2020-11-26 16:46
 */
public class MessageBean {
    
    
    private String code;
    private String text;

    public MessageBean(String code, String text) {
    
    
        this.code = code;
        this.text = text;
    }

    public String getCode() {
    
    
        return code;
    }

    public void setCode(String code) {
    
    
        this.code = code;
    }

    public String getText() {
    
    
        return text;
    }

    public void setText(String text) {
    
    
        this.text = text;
    }
}

由于From调用JavaBean不能使用form同一session连接数据库,因此把插入到数据库的功能单独写一个java程序,加载到DB中(具体实现后面会介绍)。

package com.bitland.ebs;

import oracle.jdbc.OracleDriver;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @author qiucheng.he
 * @version 1.0.0
 * @ClassName: Load
 * @Description: 把数据插入数据库
 * @date 2020-12-02 8:53
 */
public class Load {
    
    
    private static String splitStr = "~#~";

    public static String loadRow(String sqlStatment, String valueStatment, int fileId, int sheetNum, int rowNum) {
    
    
        if (sqlStatment == null || valueStatment == null || sqlStatment.length() == 0 || valueStatment.length() == 0) {
    
    
            return "";
        }

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
    
    
            connection = new OracleDriver().defaultConnection(); //使用同一session最后不能关闭连接
            preparedStatement = connection.prepareStatement(sqlStatment);
            preparedStatement.setInt(1, fileId);
            preparedStatement.setInt(2, sheetNum);
            preparedStatement.setInt(3, rowNum + 1);

            String[] value = valueStatment.split(splitStr);
            for (int i = 0; i < value.length; i++) {
    
    
                if (value[i] == null || value[i].length() == 0) {
    
    
                    preparedStatement.setString(i + 4, "");
                } else {
    
    
                    preparedStatement.setString(i + 4, value[i]);
                }
            }
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
    
    
            System.out.println("bitcload.Load.loadRow occur unexpected error" + e.getMessage());
            e.printStackTrace();
            return ("[ERROR]Load.loadRow: " + e.getMessage());
        } finally {
    
    
            if (preparedStatement != null) {
    
    
                try {
    
    
                    preparedStatement.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

}

注意要点

  • Form的null值传到JavaBean变为”false”
    set_custom_property(g_bean_name,1,‘CREATESHEET’,null);
    在这里插入图片描述
  • 注意异常处理,若调用的java抛出空指针异常等就会导致整个session终止,form界面崩溃。

3、Idea打包成jar包

这里先打包好再上传到服务器发布比较方便,也可以直接把源码上传到服务器在编译、打包。
File>Project Structure>Artifacts
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Build>Build Artifacts…
在这里插入图片描述
在这里插入图片描述


二、Jar包部署到R12应用服务器

1、把打包好的bitcupload.jar上传至服务器$JAVA_TOP/oracle/forms/fd目录下,可以指定其他目录,方便管理即可。
2、创建keystore,密码设置为:123456

keytool -genkey -dname "cn=Qiucheng He, ou=Bitland, o= Bitland, c=CN" -alias bitcufkey -keystore bitcufkeystore -validity 720

在这里插入图片描述
3、检查keystore(可选)

keytool -list -v -keystore bitcufkeystore

在这里插入图片描述
4、输出keystore到文件(可选)命令

keytool -export -keystore bitcufkeystore -alias bitcufkey -file bitcufcert.cer

在这里插入图片描述
5、对JAR文件进行签名,并生成新的包bitcuf.jar

jarsigner -keystore bitcufkeystore -signedjar bitcuf.jar bitcupload.jar bitcufkey

在这里插入图片描述
检查生产的文件
在这里插入图片描述
6、修改系统配置文件,添加bitcuf.jar路径 ,/OA_JAVA/oracle/forms/fd/bitcuf.jar

vi $FORMS_WEB_CONFIG_FILE

实际上是修改appsweb.cfg文件,如果上面的命令无效可以用locate指令查找出该文件来修改,注意当运行autoconfig命令会将此文件恢复。
在这里插入图片描述


三、导入Load.class到数据库

1、把编译好的类Load.class上传至服务器$JAVA_TOP/oracle/forms/fd下
2、载入java类

loadjava -u apps/appsapps -v Load.class

在这里插入图片描述
在这里插入图片描述
3、编译plsql包

CREATE OR REPLACE PACKAGE BODY bitc_upload_pub IS
  -- insert_row
  FUNCTION insert_row(p_sql_str   VARCHAR2,
                      p_value_str VARCHAR2,
                      p_file_id   NUMBER,
                      p_sheet_num NUMBER,
                      p_row_num   NUMBER) RETURN VARCHAR2 AS
    LANGUAGE JAVA NAME 'com/bitland/ebs/Load.loadRow(java.lang.String,java.lang.String,int,int,int)return java.lang.String';
END bitc_upload_pub;


四、Form开发调用JavaBean

前期准备

  • 下载jar包bitcuf.jar复制到本地\DevSuiteHome_1\forms\java下
  • 修改注册表FORMS_BUILDER_CLASSPATH添加D:\DevSuiteHome_1\forms\java\ bitcuf.jar;
    不添加的话,后面Bean域组件设置class属性后,打开画布就会提示找不到Java类
    在这里插入图片描述

开发

这里的开发和普通的from开发一样,只是有一些需要特殊的地方,比如调用的bean组件、触发器等。

添加bean域组件

添加组件,项类型为“Bean 区域”,并且指定实施类(自己客制Bean的类名),组件必须部署在画布上并且设置为可见,否则调用bean时会报错“unable to communicate with bean”为了隐藏可以把宽度、高度设置为0。
在这里插入图片描述
在这里插入图片描述

主要代码

在这里插入图片描述
包头

PACKAGE UPLOAD IS
  g_bean_name varchar2(30) := 'MAIN.UPLOADBEAN';
  
  procedure init;
  procedure event_handler(event in varchar2);
  procedure summit(event in varchar2);
  procedure cancel(event in varchar2);
  procedure clear(event in varchar2);
END;

包体

PACKAGE BODY UPLOAD IS
  -- init()
  procedure init is
  begin
    copy(to_char(null), 'global.file_id');
    copy(to_char(null), 'global.file_name');
  end;
  
  --=====================
  -- event_handler()
  --=====================
  procedure event_handler(event in varchar2) is
    l_even_name       varchar2(30);
    l_parameter_list  paramlist;
    l_parameter_type  number;    
    l_file_to_read    varchar2(2000);
    l_file_path       varchar2(2000);    
    l_return_code     varchar2(100);
    l_return_msg      varchar2(4000);
    l_file_id         number;
    l_label_yes       varchar2(30);
    l_label_no        varchar2(30);
    l_label_cancel    varchar2(30);
  begin
    if event = 'WHEN-CUSTOM-ITEM-EVENT' then
      l_even_name := :system.custom_item_event;    
      --fnd_message.debug(l_even_name);
      if l_even_name = 'OPENDIALOG' then 
        l_parameter_list := get_parameter_list(:system.custom_item_event_parameters);
        
        get_parameter_attr(l_parameter_list,'RETURNCODE',l_parameter_type,l_return_code);
        get_parameter_attr(l_parameter_list,'RETURNMSG',l_parameter_type,l_return_msg);      
        --fnd_message.debug('l_return_code:'||l_return_code);
        if l_return_code <> 'S' then          
          fnd_message.set_name('FND','FND_GENERIC_MESSAGE');
          fnd_message.set_token('MESSAGE',l_return_msg);
          fnd_message.error;
          raise form_trigger_failure;
        end if;
        
        get_parameter_attr(l_parameter_list,'FILETOREAD',l_parameter_type,l_file_to_read);
        get_parameter_attr(l_parameter_list,'LASTDIR',l_parameter_type,l_file_path);
                
        select bitc_upload_s.nextval into l_file_id from dual;
        
        copy(l_file_id, 'global.file_id');
        copy(replace(l_file_to_read, l_file_path, ''), 'global.file_name');
        copy(name_in('global.file_name'),'main.file_name');
                
        set_custom_property(g_bean_name,1,'CREATEWORKBOOK',to_char(null));
                            
      elsif l_even_name in('CREATEWORKBOOK','CREATESHEET','READROW') then
        l_parameter_list := get_parameter_list(:system.custom_item_event_parameters);
        
        get_parameter_attr(l_parameter_list,'RETURNCODE',l_parameter_type,l_return_code);
        get_parameter_attr(l_parameter_list,'RETURNMSG',l_parameter_type,l_return_msg);
        --fnd_message.debug('l_return_code:'||l_return_code);
        --fnd_message.debug('l_return_msg:'||l_return_msg);
        if l_return_code <> 'S' then
          upload.clear('WHEN-BUTTON-PRESSED');
          
          fnd_message.set_name('FND','FND_GENERIC_MESSAGE');
          fnd_message.set_token('MESSAGE',l_return_msg);
          fnd_message.error;
          raise form_trigger_failure;
        end if;
      end if;
            
    elsif event = 'OPEN-DIALOG' then
      if name_in('global.file_name') is not null then
        fnd_message.set_name('FND','YES');
        l_label_yes := fnd_message.get;
        fnd_message.set_name('FND','NO');
        l_label_no := fnd_message.get;
        fnd_message.set_name('FND','CANCEL');
        l_label_cancel := fnd_message.get;
        
        fnd_message.set_name('BITC','BITC_FILE_ALREADY_EXISTS');        
        if fnd_message.question(l_label_yes,l_label_no,l_label_cancel,1,2,'question') <> 1 then
          raise form_trigger_failure;
        end if;        
      end if;
            
      upload.init;
      copy(to_char(null),'main.file_name');
      --clear current session data
      forms_ddl('truncate table bldsa.bitc_upload_tmp');
      
      set_custom_property(g_bean_name,1,'OPENDIALOG',to_char(null));
      
    else
      app_exception.invalid_argument(procname => 'event_handler',
                                     argument => 'event',
                                     value    => event);
    end if;
  end event_handler;

  --=====================
  -- summit()
  --=====================
  procedure summit(event in varchar2) is
    l_sheet_index   varchar2(10);
    l_sheet_count   number;
    l_row_count     number;    
    l_return_code   varchar2(100);
    l_return_msg    varchar2(4000); 
    l_message       varchar2(1000);
    l_sqlstatment   varchar2(1000);
    l_valuestatment VARCHAR2(32767, CHAR);
  begin
    
    if event = 'WHEN-BUTTON-PRESSED' then
      l_sheet_index := name_in('parameter.sheet_index');
      fnd_message.set_name('BITC','BITC_READING_FILE');
      l_message := fnd_message.get;
      
      if name_in('global.file_name') is null then
        fnd_message.set_name('BITC','BITC_NOT_SELECT_FILE');
        fnd_message.show;
        raise form_trigger_failure;
      end if;
      
      if l_sheet_index = 'ALL' then
        l_sheet_count := get_custom_property(g_bean_name,1,'SHEETCOUNT');               
        SET_APPLICATION_PROPERTY(CURSOR_STYLE, 'BUSY');
        APP_WINDOW.PROGRESS(0,l_message);        
        for i in 1..l_sheet_count loop
          set_custom_property(g_bean_name,1,'CREATESHEET',to_char(i-1));          
          l_row_count := get_custom_property(g_bean_name,1,'ROWCOUNT');
          for j in 1..l_row_count loop
            set_custom_property(g_bean_name,1,'READROW',to_char(j));
            l_sqlstatment   := get_custom_property(g_bean_name,1,'SQLSTATMENT');
            l_valuestatment := get_custom_property(g_bean_name,1,'VALUESTATMENT');
            --TODO call api to insert
            if l_sqlstatment is not null then
              l_return_msg := bitc_upload_pub.insert_row(p_sql_str   => l_sqlstatment,
                                                         p_value_str => l_valuestatment,
                                                         p_file_id   => name_in('global.file_id'),
                                                         p_sheet_num => i,
                                                         p_row_num   => j);
              if l_return_msg is not null then
                APP_WINDOW.PROGRESS(1,l_message); --close
                fnd_message.set_name('FND','FND_GENERIC_MESSAGE');
                fnd_message.set_token('MESSAGE',l_return_msg);
                fnd_message.error;
                raise form_trigger_failure;
              end if;
            end if;
          end loop;
          APP_WINDOW.PROGRESS(i/l_sheet_count,l_message);          
        end loop;
        SET_APPLICATION_PROPERTY(CURSOR_STYLE, 'DEFAULT');
        
      else          
        set_custom_property(g_bean_name,1,'CREATESHEET',to_char(l_sheet_index-1));
        l_sheet_index := get_custom_property(g_bean_name,1,'SHEETNUM');
        l_row_count   := get_custom_property(g_bean_name,1,'ROWCOUNT');
        --fnd_message.debug('l_row_count:'||l_row_count);
        SET_APPLICATION_PROPERTY(CURSOR_STYLE, 'BUSY');
        APP_WINDOW.PROGRESS(0,l_message);        
        for j in 1..l_row_count loop
          set_custom_property(g_bean_name,1,'READROW',to_char(j));
          l_sqlstatment   := get_custom_property(g_bean_name,1,'SQLSTATMENT');
          l_valuestatment := get_custom_property(g_bean_name,1,'VALUESTATMENT');
          --TODO call api to insert
          if l_sqlstatment is not null then
            l_return_msg := bitc_upload_pub.insert_row(p_sql_str   => l_sqlstatment,
                                                       p_value_str => l_valuestatment,
                                                       p_file_id   => name_in('global.file_id'),
                                                       p_sheet_num => to_number(l_sheet_index+1),
                                                       p_row_num   => j);
            if l_return_msg is not null then
              APP_WINDOW.PROGRESS(1,l_message); --close
              fnd_message.set_name('FND','FND_GENERIC_MESSAGE');
              fnd_message.set_token('MESSAGE',l_return_msg);
              fnd_message.error;
              raise form_trigger_failure;
            end if;
          end if;
          APP_WINDOW.PROGRESS(j/l_row_count,l_message);          
        end loop;        
        SET_APPLICATION_PROPERTY(CURSOR_STYLE, 'DEFAULT');        
      end if;
      --forms_ddl('commit');
      l_return_code := get_custom_property(g_bean_name,1,'RELEASE');
      app_custom.close_window('UPLOAD');
      
    else
      app_exception.invalid_argument(procname => 'summit',
                                     argument => 'event',
                                     value    => event);
    end if;
  end;
  
  --=====================
  -- cancel()
  --=====================
  procedure cancel(event in varchar2) is
  begin
    if event = 'WHEN-BUTTON-PRESSED' then
      upload.clear('WHEN-BUTTON-PRESSED');
      app_custom.close_window('UPLOAD');
      
    else
      app_exception.invalid_argument(procname => 'cancel',
                                     argument => 'event',
                                     value    => event);
    end if;
  end;
  
  --=====================
  -- clear()
  --=====================
  procedure clear(event in varchar2) is
    l_return_code varchar2(10);
  begin
    if event = 'WHEN-BUTTON-PRESSED' then
      copy(to_char(null),'global.file_name');
      copy(to_char(null),'global.file_id');
      copy(to_char(null),'main.file_name');
      l_return_code := get_custom_property(g_bean_name,1,'RELEASE');
            
    else
      app_exception.invalid_argument(procname => 'clear',
                                     argument => 'event',
                                     value    => event);
    end if;
  end;
END;

Form编译部署

效果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

查看日志

调用javabean报错日志:
cd $LOG_HOME/ora/10.1.3/Apache
在这里插入图片描述
或者打开java控制台查看日志
在这里插入图片描述


五、PLSQL调用Java

1、编写JAVA程序

程序方法必须是static类型的

public class sayhello {
public static String sayHello(String name){
    return "hello,"+name;
}
}

2、把java导入Oracle数据库

主要有两种方式:
1)、直接编写plsql执行,适合比较简单的情况;

create or replace and compile java source named JavaName as [Java代码]

2)、使用LoadJava指令,参数有
-u(用于输入用户名及密码)
-v(用于输出详细的反馈信息)
-resolve(对于没有编译的Java文件可以用resolve来编译)
-f(不管之前是否已经导入过该Java类,都强制再次导入)

当导入Class文件时,可以用如下命令:

loadjava –u username/userpassword –v filename.class

当删除Class文件时,可以用如下命令:

dropjava –u username/userpassword –v filename.class

当导入Java文件时,可以用如下命令:

loadjava –u username/userpassword –v -resolve filename.java

当删除Java文件时,可以用如下命令:

dropjava –u username/userpassword –v filename.java

当导入jar文件时,可以用如下命令:

loadjava –u username/userpassword –v -resolve filename.jar

当删除jar文件时,可以用如下命令:

dropjava –u username/userpassword –v -resolve filename.jar

3)、导入后查看对象是否可用,导入后状态是IVALID,第一次调用后状态才变为VALID

SELECT OBJECT_ID, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM USER_OBJECTS
WHERE OBJECT_TYPE LIKE 'JAVA%'

在这里插入图片描述

3、编写PLSQL程序

可用编写成function、procedure、trigger等

CREATE OR REPLACE PACKAGE BODY bitc_upload_pub IS
  -- insert_row
  FUNCTION insert_row(p_sql_str   VARCHAR2,
                      p_value_str VARCHAR2,
                      p_file_id   NUMBER,
                      p_sheet_num NUMBER,
                      p_row_num   NUMBER) RETURN VARCHAR2 AS
    LANGUAGE JAVA NAME 'com/bitland/ebs/Load.loadRow(java.lang.String,java.lang.String,int,int,int)return java.lang.String';

END bitc_upload_pub;

注意:

  • 这里的java类型如果不是基本类型则必须为全路径,例如java.lang.String
  • Java包名之间用’/’划分

4、调用测试

六、参考文献

1、黄建华《深入浅出 Oracle+EBS+Forms开发指南_中级》
2、https://blog.csdn.net/chenxianping/article/details/81173072
3、https://www.cnblogs.com/59nice/archive/2020/06/19/13164173.html

猜你喜欢

转载自blog.csdn.net/qingshimoon4/article/details/110554421