Oracle APPS Shell Eş Zamanlı Programı İle Java Uygulaması
Merhaba,
Daha önceki yazımda Oracle Apps için Java Eş Zamanlı program yapımını anlatmıştım. Bu yazımda ise Shell eş zamanlı program ile bağımsız Java uygulamasını geliştirme ve çalıştırma yöntemini anlatacağım.
İki yöntem arasındaki temel farklar;
Java Eş Zamanlı Programı | Bağımsız Java Uygulaması |
---|---|
JDBC gerekliliği yoktur | JDBC elle yapılandırılmalıdır |
APPS_INIT hazır durumdadır | APPS_INIT elle yapılandırılmalıdır |
LOG yönetimi hazır durumdadır | LOG yönetimi elle yapılandırılmalıdır |
Kofigürasyon zordur | Konfigürasyon kolaydır |
Veritabanı bağlantı bilgileri gizlidir | Veritabanı bağlantı bilgileri açıktır |
Yazıda xlsx Excel üreten basit bir Java uygulaması yapılacaktır.
1.Öncelikle JDBC bağlantısı elle konfigüre edileceği için DRIVER’ın uygun versyonunun bulunması gerekiyor. Bunun için öncelikle veritabanı versyonu aşağıdaki SQL ile öğrenilir.
1 2 3 |
select * from v$version |
Sonuç:
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 – 64bit Production
PL/SQL Release 11.1.0.7.0 – Production
CORE 11.1.0.7.0 Production
TNS for Linux: Version 11.1.0.7.0 – Production
NLSRTL Version 11.1.0.7.0 – Production
2. Aşağıdaki linkten ilgili versyona ait driver (ojdbc6.jar) aşağıdaki bağlantıdan indirilir.
3. Aşağıdaki bağlantıdan Excel oluşturulmak için kullanılacak apache-poi API’si indirilir.
http://poi.apache.org/download.html
4. Netbeans açılır ve menüden New Project seçilir.
5. Java Application seçilerek devam edilir.
6. Proje Adı ve Main Class belirlenir.
7. Veritabanı bağlantı işlemleri için yeni bir java sınıfı yaratılır.
8. Sınıf adı ve paketi belirlenir.
9. Projeye sağ tıklanır ve proje özellikleri açılır.
10. Libaries bölümüne geçiş yapılır. Bu adımda kullanacağımız POI ve jdbc jar dosyalarının proje CLASSPATH yani Libary altına eklenmesi gerekmektedir. “Add Jar/Folder” butonuna tıklanır.
11. POI ile ilgili bütün JAR dosyaları ve ek olarak ojdbc6.jar dosyası eklenir.
12. Excel yönetimi için yeni bir sınıf daha yaratılır.
13. Sınıf adı ve paketi belirlenir.
XXConnection: Bu sınıf Connection ve OracleConnection döndüren iki adet fonksiyondan oluşmaktadır. 21. satırda yer alan bağlantı bilgisinin host, port ve sid bilgilerini kendi veritabanı bilgilerinize göre güncelleyiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package src.xx; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import oracle.jdbc.OracleConnection; /** * * @author Anil */ public class XXConnection { private String conString = "jdbc:oracle:thin:@<host_name>:<port>:<sid>"; private String userName = "apps"; private String password = "apps"; public Connection getConnection() { try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException ex) { System.out.println(ex.getMessage()); return null; } Connection connection = null; System.out.println("Trying connection for:"+conString+", "+userName+", "+password); try { connection = DriverManager.getConnection(conString, userName, password); } catch (SQLException e) { System.out.println(e.getMessage()); } if (connection != null) { System.out.println("Connected to database!"); } else { System.out.println("Failed to make connection!"); } return connection; } public OracleConnection getOracleConnection() { try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException ex) { System.out.println(ex.getMessage()); return null; } OracleConnection connection = null; System.out.println("Trying connection for:"+conString+", "+userName+", "+password); try { connection = (OracleConnection) DriverManager.getConnection(conString, userName, password); } catch (SQLException e) { System.out.println(e.getMessage()); } if (connection != null) { System.out.println("Connected to database!"); } else { System.out.println("Failed to make connection!"); } return connection; } } |
14. Bu adımda bağlantıyı test etmek için Main sınıf içerisinden XXConnection objesi oluşturulur ve bağlantı test edilir.
1 2 3 4 5 6 7 |
public static void main(String[] args) { // TODO code application logic here XXConnection c = new XXConnection(); OracleConnection con = c.getOracleConnection(); } |
Sonuç:
1 2 3 4 5 6 |
run: Trying connection for:jdbc:oracle:thin:@<host_name>:<port>:<sid>, apps, apps Connected to database! BUILD SUCCESSFUL (total time: 1 second) |
15. Excel oluştuktan sonra dosya adı, dizin ve talep numarası gibi bilgilerin veritabanında bir tabloya yazılması takip açısından daha sağlıklıdır. Aşağıdaki SQL Scripti ile veritabanında tablo oluşturulur.
1 2 3 4 5 6 7 |
create table hr.xx_excel_sh_result ( request_id number, file_name varchar2(100), path_file_name varchar2(300) ); |
16.
ExcelOperations: Bu sınıf excel’i oluşturan sınıftır. createExcel fonksiyonu Main sınıftan gönderilen SQL sorgusunu çalıştırıp, yine Main sınıftan gönderilen dosya adı ve sheet adı ile Excel’i dinamik olarak oluşturur. Dikkat edilmesi gereken noktalardan biri POI’nin Workbook dosyasının her durumda çalışacak olan finally bloğu içerisinde kapatılmasıdır. Aksi takdirde hatalı veya başarılı biten çalıştırmalarda ana makine /tmp dizini üzerinde SQL sorgunuzdan dönen satır sayısına da bağlı olarak yüklü yer kaplayan XML dosyaları oluşup, tmp dizininin dolmasına ve ERP sisteminin beklendiği gibi çalışmamasına neden olabilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package src.xx; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; import oracle.jdbc.OracleConnection; import oracle.jdbc.OraclePreparedStatement; import oracle.jdbc.OracleResultSet; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFDataFormat; import org.apache.poi.xssf.usermodel.XSSFFont; /** * * @author Anil */ public class ExcelOperations { public final static String OA_HTML = System.getenv("OA_HTML"); public void createExcel (String sql, String fileName, String sheetName, String requestId) { FileOutputStream out = null; SXSSFWorkbook wb = null; XXConnection c = new XXConnection(); OracleConnection con = c.getOracleConnection(); OraclePreparedStatement ps = null; OracleResultSet rs= null; String fullFilePath = null; int rowCount = 1; if (OA_HTML != null) { fullFilePath = OA_HTML + "/" + fileName + ".xlsx"; } else { fullFilePath = fileName+".xlsx"; } try { out = new FileOutputStream(fullFilePath); //workbook oluşturulur. //Constructor'ın aldığı parametre rowAccessWindowSize parametresidir. POI'nin kaç satırda bir flush işlemi yapacağını belirtir. //Flush işlemi yapılan satırlarda tekrar erişim kapalıdır. //Dolayısıyla önceden oluşturulan satırlara tekrar erişim gerektirdiği yerlerde yükek tutulmalıdır ancak performans handikabı yaratabilir. //Bu örnekte bu tarz bir ihtyaç olmadığından dolayı, 1 yeterlidir. -1 ise sınırsız erişim anlamına gelir. wb = new SXSSFWorkbook(1); //tarih formatının düzgün çıkması için Cell Stil objesi oluşturulur. XSSFCellStyle dateStyle = (XSSFCellStyle) wb.createCellStyle(); XSSFDataFormat dateFormat = (XSSFDataFormat) wb.createDataFormat(); dateStyle.setDataFormat(dateFormat.getFormat("[$-809]dd.mm.yyyy;@")); Sheet sh = wb.createSheet(sheetName); ps = (OraclePreparedStatement) con.prepareStatement(sql); rs = (OracleResultSet) ps.executeQuery(); ResultSetMetaData metaData = ps.getMetaData(); Row headerRow = sh.createRow(0); setHeaderRow(headerRow, metaData, wb); while (rs.next()) { Row row = sh.createRow(rowCount); int colCount = 1; while (metaData.getColumnCount() != colCount - 1) { Cell cell = row.createCell(colCount-1); String colType = metaData.getColumnTypeName(colCount); String colName = metaData.getColumnLabel(colCount); if ("VARCHAR2".equals(colType)) { cell.setCellValue(rs.getString(colName)); } else if ("NUMBER".equals(colType)) { cell.setCellValue(rs.getDouble(colName)); } else if ("DATE".equals(colType)) { if (rs.getDate(colName) != null) { cell.setCellValue(rs.getDate(colName)); cell.setCellStyle(dateStyle); } } else { System.out.println("Bilinmeyen verip tipi!"); } colCount++; } rowCount++; } wb.write(out); out.close(); wb.dispose(); insertResult(fileName, fullFilePath, Integer.parseInt(requestId)); } catch (SQLException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } catch (FileNotFoundException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(ExcelOperations.class.getName()).log(Level.SEVERE, null, ex); } finally { try { if (ps != null) { ps.close(); } if (rs != null) { rs.close(); } if (wb != null) { wb.dispose(); } if (out != null) { out.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(ExcelOperations.class.getName()).log(Level.SEVERE, null, ex); } } } private void setHeaderRow(Row headerRow, ResultSetMetaData metaData, SXSSFWorkbook wb) throws SQLException { int colCount = metaData.getColumnCount(); XSSFFont font = (XSSFFont) wb.createFont(); font.setBold(true); XSSFCellStyle style = (XSSFCellStyle) wb.createCellStyle(); style.setFont(font); for (int i = 1; i <= colCount; i++) { Cell headerCell = headerRow.createCell(i-1); headerCell.setCellValue(metaData.getColumnLabel(i)); headerCell.setCellStyle(style); } } private void insertResult(String fileName, String pathFileName, int requestId) { XXConnection c = new XXConnection(); Connection con = c.getConnection(); String sql = "INSERT into hr.xx_excel_sh_result (request_id, file_name, path_file_name) values (?, ?, ?)"; PreparedStatement ps = null; try { ps = con.prepareStatement(sql); ps.setInt(1, requestId); ps.setString(2, fileName); ps.setString(3, pathFileName); ps.execute(); } catch (SQLException ex) { Logger.getLogger(ExcelOperations.class.getName()).log(Level.SEVERE, null, ex); } finally { try { if (ps != null) { ps.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger.getLogger(ExcelOperations.class.getName()).log(Level.SEVERE, null, ex); } } } } |
17. Main sınıf aşağıdaki gibi düzenlenir. Dikkat edilmesi gereken nokta parametrelerin main sınıfa argüman aracılığı ile ulaşacağıdır. Bu argümanlar SH Scriptinden gönderilecektir. Dolayısıyla sırası önem arz etmektedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package src.xx; /** * * @author Anil */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here //arg[0] = SQL sorgusu //arg[1] = Dosya Adı //arg[2] = Sheet Adı //arg[3] = request_id ExcelOperations excel = new ExcelOperations(); excel.createExcel(args[0], args[1], args[2], args[3]); } } |
18. Program derlendikten sonra klasörüyle beraber FTP programı ile $PER_TOP/bin altına yüklenir. Projenin tamamının yüklenmesi önem arz etmektedir.
19. Bu adımdan sonra bir adet .prog uzantılı Shell Scripti hazırlanır. Dikkat edilmesi gereken noktalardan biri ilk 4 parametrenin otomatik olarak eş zamanlı tarafından sağlanmasıdır. Bunlar aşağıdaki gibidir;
$0: The shell script to be executed
$1: Oracle user/password
$2: Applications user_id
$3: Application user_name
$4: Concurrent program request_id
$5 ve sonrası parametreler eş zamanlı programda belirlenen sıraya göre devam etmektedir.
14. satırda içeri yüklediğimiz java uygulamasının jar dosyasına çağrıda bulunuyoruz.
Shell programın hatalı tamamlanması engellemek için SQLPLUS ile ilgili talebi normal tamamlandı durumuna çekiyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#!/bin/sh echo 'Printing parameters....' echo '0:'$0 echo '1:'$1 echo '2:'$2 echo '3:'$3 echo '4:'$4 echo '5:'$5 echo '6:'$6 echo '7:'$7 java -jar /u01/data_appl/apps/apps_st/appl/per/12.0.0/bin/XXJavaExcelShApp/dist/XXJavaExcelShApp.jar "$5" "$6" "$7" "$4" MYSTATUS=`sqlplus -s $1 <<! SET HEADING FEEDBACK OFF PAGESIZE 0 declare l_result boolean; l_session_id number; begin fnd_global.INITIALIZE(l_session_id, null, null, null,null, -1, null, null, null, null, $4, null,null,null,null,null,null,-1); l_result := fnd_concurrent.set_completion_status('WARNING','Review log file for details.'); commit; end; / exit; !` echo 'FCPLOGIN:'$FCP_LOGIN echo 'Finished printing parameters.' |
20. prog dosyası ve java uygulaması içeri atıldıktan sonra prog dosyasının link’lenmesi gerekmektedir. Bunun için ssh programından aşağıdaki komut ana makine unix ortamda çalıştırılır. Linkleme işleminden sonra aynı dizinde bir adet dosya oluşması gerekmektedir.
1 2 3 |
ln -s $FND_TOP/bin/fndcpesr /u01/data_appl/apps/apps_st/appl/per/12.0.0/bin/XxAnilShProg |
21. Çalıştırma yetkisi yok ise CHMOD ile yetkilerin tamamlanması gerekmektedir.
22. Bütün bu işlemler bittikten sonra son durumda bin klasörü görünümü aşağıdaki gibi olmalıdır.
23. Yürütülür dosya tanımı:
24. Eş zamanlı program tanımı:
25. Program çalıştırılır;
Not: Eğer program “Dosya Bulunamadı” hatası ile bitiyorsa, prog dosyasını FTP üzerinden BINARY modu kullanarak yükleyin.
26. Sonuç:
1 2 3 |
select * from hr.xx_excel_sh_result where request_id = 5858410; |
Kaynak: http:/http://oracleappsnotes.wordpress.com/2012/02/21/all-about-host-concurrent-programs/