简体   繁体   English

仅当从Runtime.exec()运行程序时,SQL异常

[英]SQL Exception only when program is run from Runtime.exec()

I am having some problems understanding the following issue. 我在理解以下问题时遇到了一些问题。 For reasons I will not (and cannot) tell here, I had to write an external JAR to be executed inside a Java web application, using a Process bound to a Runtime.exec() method call. 由于我不会(也无法)告诉我的原因,我不得不使用绑定到Runtime.exec()方法调用的Process编写要在Java Web应用程序内部执行的外部JAR。 This external JAR executes a query inside a database and prints its results inside an Excel file, using the Apache POI libraries. 此外部JAR使用Apache POI库在数据库内部执行查询,并将结果打印在Excel文件中。 This is its code: 这是它的代码:

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);
}

Inside the archive are also packed the external libraries (Apache POI and the SQL Server Driver in jar format). 归档文件内部还打包了外部库(Apache POI和jar格式的SQL Server驱动程序)。

When I try to execute the program directly from the terminal (either cmd or bash), using the command java -jar executable.jar "param1" "param2" ... everything works fine. 当我尝试直接从终端(cmd或bash)执行程序时,使用命令java -jar executable.jar "param1" "param2" ...一切正常。

The problem occurs when I try to launch the same command using the method mentioned above. 当我尝试使用上述方法启动同一命令时,会出现问题。

Following you will find the code responsible for the call: 接下来,您将找到负责调用的代码:

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());

In this second case, I obtain the following Exception: java.sql.SQLException: No suitable driver found for "jdbc:sqlserver://remoteServer:1433;databaseName=dbName" . 在第二种情况下,我获得以下异常: java.sql.SQLException: No suitable driver found for "jdbc:sqlserver://remoteServer:1433;databaseName=dbName"

The web application is currently running on Wildfly 10.0.0-Final on CentOS7 server. 该Web应用程序当前正在CentOS7服务器上的Wildfly 10.0.0-Final上运行。

Thank you for your time. 感谢您的时间。

EDIT: I thought it could be a good idea to add the JAR manifest, since it may contain some mistakes (the JAR file was generated by Eclipse export): MANIFEST.MF . 编辑:我认为添加JAR清单可能是一个好主意,因为它可能包含一些错误(JAR文件是由Eclipse导出生成的): MANIFEST.MF

Also, this is the JAR internal structure: JAR Structure . 同样,这是JAR内部结构: JAR Structure

I finally managed to solve the issue, but in a very inefficient (and really ugly) way. 我终于设法解决了这个问题,但是效率很低(而且非常丑陋)。

I had to create a shell script to parse the external JAR arguments, because there were some problems converting the quote (") character from the web application method calling the JAR and the actual terminal. Once I did that, the JAR application worked like a charm. 我必须创建一个shell脚本来解析外部JAR参数,因为从调用JAR和实际终端的Web应用程序方法转换引号(“)字符时会遇到一些问题。一旦完成此操作,JAR应用程序就可以像魅力。

I do not intend to provide the shell script source (unless explicitly requested) because I am bit ashamed of myself. 我无意提供shell脚本源(除非明确要求),因为我为自己感到羞耻。 Not about the code itself, but about this "workaround". 与代码本身无关,而与这种“解决方法”有关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM