2017-03-22 11 views
0

다음 문제를 이해하는 데 몇 가지 문제가 있습니다. 여기서는 말할 것도 없으므로 Runtime.exec() 메서드 호출에 바인딩 된 Process를 사용하여 Java 웹 응용 프로그램 내에서 실행되도록 외부 JAR을 작성해야했습니다. 이 외부 JAR은 데이터베이스 내에서 쿼리를 실행하고 그 결과를 Apache POI 라이브러리를 사용하여 Excel 파일에 인쇄합니다. 이이 코드입니다 : 아카이브 내부Runtime.exec()에서 프로그램을 실행할 때만 SQL 예외가 발생합니다.

public static void main(String[] args) { 

    //Initializing error variable 
    boolean error = false; 

    //Initializing rownum variable 
    int rownum = 0; 

    //Initializing db connection parameters 
    String userName = args[0]; 
    String password = args[1]; 
    String dbUrl = args[2]; 

    //Initializing file path 
    String filePath = args[3]; 

    //Initializing query string 
    String query = args[4]; 
    if(!query.endsWith(";")) 
     query += ";"; 

    //Keep 100 rows in memory, exceeding rows will be flushed to disk 
    SXSSFWorkbook wb = new SXSSFWorkbook(SXSSFWorkbook.DEFAULT_WINDOW_SIZE); 

    //Temp files will be gzipped 
    wb.setCompressTempFiles(true); 

    //Initializing xlsx sheet 
    Sheet sh = wb.createSheet(); 
    wb.setSheetName(wb.getSheetIndex(sh), "DBExtraction"); 

    //Trying to connect to db and execute a query. 
    //If the previous operation succeeded, parse query results 
    //into an xlsx workbook 
    try { 
     Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 
     Connection conn = DriverManager.getConnection(dbUrl, userName, password); 
     Statement stmt = conn.createStatement(); 
     ResultSet rs = stmt.executeQuery(query); 
     ResultSetMetaData md = rs.getMetaData(); 
     int cols = md.getColumnCount(); 
     int cn = 0; 

     Row header = sh.createRow(rownum++); 
     for(int i = 0; i < cols; ++i) { 
      header.createCell(cn++).setCellValue(md.getColumnLabel(i + 1)); 
     } 

     while(rs.next()) { 
      Row row = sh.createRow(rownum++); 
      cn = 0; 
      for (int cellnum = 0; cellnum < cols; cellnum++) { 
       Cell cell = row.createCell(cellnum); 
       cell.setCellValue(rs.getString(++cn)); 
      } 
     } 

     for(int j = 0; j < cols; ++j) { 
      sh.setColumnWidth(j, 67*256); 
     } 

     FileOutputStream fos = new FileOutputStream(filePath); 

     //Writing workbook to file 
     wb.write(fos); 

     //Closing file 
     fos.flush(); 
     fos.close(); 

     //Dispose of temporary files backing this workbook on disk 
     wb.dispose(); 
     wb.close(); 

     //Closing db connection objects 
     rs.close(); 
     stmt.close(); 
     conn.close(); 

    } catch (Exception e) { 
     error = true; 
     e.printStackTrace(); 
    } 

    if(error) 
     System.exit(1); 
    else 
     System.exit(0); 
} 

또한 외부 라이브러리 (아파치 POI와 항아리 형식으로 SQL 서버 드라이버) 포장된다.

터미널 (cmd 또는 bash)에서 직접 프로그램을 실행하려고하면 java -jar executable.jar "param1" "param2" ... 명령을 사용하면 정상적으로 작동합니다.

위에서 언급 한 방법을 사용하여 동일한 명령을 실행하려고하면 문제가 발생합니다.

당신이 전화에 대한 책임의 코드를 발견 할 것이다 다음은

Process p = null; 
p = Runtime.getRuntime().exec("java -jar " + 
    jarDir + 
    File.separator + 
    "executable.jar " + 
    "\"" + param0 + "\" " + 
    "\"" + param1 + "\" " + 
    "\"" + param2 + "\" " + 
    "\"" + param3 + "\" " + 
    "\"" + param4 +"\""); 

p.waitFor(); 
String line; 

BufferedReader error = new BufferedReader(new 
    InputStreamReader(p.getErrorStream())); 
while((line = error.readLine()) != null){ 
    System.out.println(line); 
} 
error.close(); 

BufferedReader input = new BufferedReader(new 
    InputStreamReader(p.getInputStream())); 
while ((line = input.readLine()) != null) { 
    System.out.println(line); 
} 
input.close(); 

System.out.println("EXIT VALUE: " + p.exitValue()); 

을 두 번째 경우에, 나는 다음과 같은 예외를 얻을 : java.sql.SQLException: No suitable driver found for "jdbc:sqlserver://remoteServer:1433;databaseName=dbName".

웹 응용 프로그램은 현재 CentOS7 서버의 Wildfly 10.0.0-Final에서 실행됩니다.

감사합니다.

EDIT : JAR 매니페스트를 추가하는 것이 좋습니다. 몇 가지 실수가있을 수 있습니다 (JAR 파일은 Eclipse 내보내기에서 생성되었습니다) : MANIFEST.MF.

또한 JAR 내부 구조는 JAR Structure입니다.

+0

를 @ esprittn 첫 번째 질문 : "이유는 다음과 같이 말할 수 없습니다."... – Fildor

+1

@esprittn Erm, 나는 OP가 아닙니다. 다음 질문을주의 깊게 읽으십시오. "프로그램을 실행하려고하면 d 직접 터미널 (cmd 또는 bash)에서 ... " – Fildor

+0

(가능한 경우) java -jar 대신 java -cp를 사용하려고 시도 했습니까? 그래서 당신은 classpath를 지정할 수 있고 jdbc 드라이버가 그것에 있는지를 확인할 수있다. 구문은 java -cp "[your classpath]"처럼 보입니다. [your.java.main] args .... –

답변

0

마침내 문제를 해결할 수 있었지만 매우 비효율적이었습니다.

JAR 및 실제 터미널을 호출하는 웹 응용 프로그램 메서드에서 인용 부호 (") 문자를 변환하는 데 문제가 있었기 때문에 외부 JAR 인수를 구문 분석하기 위해 쉘 스크립트를 만들어야했습니다. 응용 프로그램은 마법처럼 일했다.

내가 (명시 적으로 요청하지 않는 한) 내가 아니 코드 자체에 대한,하지만 "해결 방법"에 대해. 자신의 비트 부끄러워이기 때문에 쉘 스크립트 소스를 제공하지 않을

.