Java程序在eclipse中运行。作为可运行的Jar

时间:2018-05-09 20:58:57

标签: java eclipse executable-jar

我已经编写了一个从Eclipse运行时可以正常工作的Java应用程序 编译器JDK是1.8,JRE是jdk1.8.0_172附带的 Eclipse正在运行它的正常64位模式,JDK是64位版本

我需要能够从.bat或.cmd文件运行该应用程序:

jre8\bin\java.exe -jar ClientNavigator.jar
pause

该路径指的是JRE的副本,我将捆绑到一个带有runnable .Jar

的安装程序中。

运行.bat文件会导致此错误:

jre8\bin\java.exe -jar ClientNavigator.jar
java.lang.NullPointerException
        at ClientNavigator.<init>(ClientNavigator.java:50)
        at ClientNavigator.main(ClientNavigator.java:61)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)

当我使用eclipse将应用程序导出为可运行的.jar时,我选择&#34;将所需的库打包到生成的JAR&#34;

以下是我的大部分Java代码。

/*
 * Last edit: 5/9/2018 - Simon
*/

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Scanner;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.wb.swt.SWTResourceManager;

public class ClientNavigator {

    protected Shell shlClientNavigator; // This is the main window
    private Text nameBox;
    private Text serverBox;
    private Text portBox;
    private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
    private String dataPath = ClientNavigator.class.getResource("BMCliDat.csv").toString().substring(5);
    public String dataFile = dataPath; // this is the data file. It's .csv for
                                        // easy export and edit

    /**
     * Launch the application.
     * 
     * @param args
     */
    public static void main(String[] args) {
        try {
            ClientNavigator window = new ClientNavigator();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Open the window.
     */
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shlClientNavigator.open();
        shlClientNavigator.layout();
        while (!shlClientNavigator.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Create contents of the window.
     */
    protected void createContents() {
        shlClientNavigator = new Shell();
        String imgPath = ClientNavigator.class.getResource("BMInstaller.png").toString().substring(5);
        shlClientNavigator.setImage(SWTResourceManager.getImage(imgPath)); // non-essential
        shlClientNavigator.setMinimumSize(new Point(500, 500)); // prevent squishing
        shlClientNavigator.setSize(500, 500); // due to layout there is no benefit to stretching
        shlClientNavigator.setText("Client Navigator");
        // Style: try to keep all elements 10px apart
        Label lblName = new Label(shlClientNavigator, SWT.NONE);
        lblName.setBounds(10, 10, 60, 30);
        lblName.setText("Title:");

        Label lblName_1 = new Label(shlClientNavigator, SWT.NONE);
        lblName_1.setText("Server:");
        lblName_1.setBounds(10, 46, 60, 30);

        Label lblName_2 = new Label(shlClientNavigator, SWT.NONE);
        lblName_2.setText("Port:");
        lblName_2.setBounds(10, 81, 60, 30);

        final Label lblErrLabel = new Label(shlClientNavigator, SWT.WRAP | SWT.SHADOW_NONE);
        lblErrLabel.setTouchEnabled(true);
        lblErrLabel.setToolTipText("Error Bar");
        lblErrLabel.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED));
        lblErrLabel.setBounds(10, 365, 458, 27);
        formToolkit.adapt(lblErrLabel, true, true);

        nameBox = new Text(shlClientNavigator, SWT.BORDER);
        nameBox.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == 13) { // keyCode 13 on Windows is [Enter]. 9 is [Tab]
                    bmConnect(serverBox.getText().trim(), portBox.getText().trim(), nameBox.getText().trim());
                }
            }
        });
        nameBox.setToolTipText("Connection name");
        nameBox.setBounds(76, 10, 239, 30);

        serverBox = new Text(shlClientNavigator, SWT.BORDER);
        serverBox.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == 13) { // keyCode 13 on Windows is [Enter]
                    bmConnect(serverBox.getText().trim(), portBox.getText().trim(), nameBox.getText().trim());
                }
            }
        });
        serverBox.setToolTipText("Server name");
        serverBox.setBounds(76, 46, 239, 30);

        portBox = new Text(shlClientNavigator, SWT.BORDER);
        portBox.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) { // keyCode 13 on Windows is [Enter]
                if (e.keyCode == 13) {
                    bmConnect(serverBox.getText().trim(), portBox.getText().trim(), nameBox.getText().trim());
                }
            }
        });
        portBox.setToolTipText("Port number");
        portBox.setBounds(76, 82, 239, 30);
        // The list is merely a display and does not hold any connection info
        final List list = new List(shlClientNavigator, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        list.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == 13) { // keyCode 13 on Windows is [Enter]
                    bmConnect(serverBox.getText().trim(), portBox.getText().trim(), nameBox.getText().trim());
                } else if (e.keyCode == 127) { // keyCode 127 on Windows is [Delete]
                    // fast delete with delete key - bad idea?
                    deleteData(nameBox.getText());
                    // repopulate the list
                    fillList(list);
                }
            }
        });
        list.addSelectionListener(new SelectionAdapter() {
            /*
             * What happens here: The SelectionEvent does not contain the info we need to
             * populate the textBoxes However, due to how the list is populated - see
             * fillList() - the SelectionIndecies match perfectly with the line numbers in
             * the .csv
             * 
             * So, the bufferedReader cycles down until the index of the selected item ==
             * the current .csv line number being read the line is then parsed and used to
             * populate the textBoxes
             */
            @Override
            public void widgetSelected(SelectionEvent e) {
                int lineNum = 0;
                String currLine;
                try {
                    FileReader fileReader = new FileReader(dataFile);
                    BufferedReader bufferedReader = new BufferedReader(fileReader);
                    while ((currLine = bufferedReader.readLine()) != null) {
                        String[] record = currLine.split(",");
                        if (lineNum == list.getSelectionIndex()) {
                            serverBox.setText(record[0]);
                            portBox.setText(record[1]);
                            nameBox.setText(record[2]);
                        }
                        lineNum++;
                    }
                    bufferedReader.close();
                } catch (FileNotFoundException ex) {
                    makeErrBar("Unable to open file '" + dataFile + "'", lblErrLabel);
                } catch (IOException ex) {
                    makeErrBar("Error reading file '" + dataFile + "'", lblErrLabel);
                }
            }
        });
        list.setBounds(10, 125, 458, 234);
        // initial list population
        fillList(list);
        formToolkit.adapt(list, true, true);

        Button btnGo = new Button(shlClientNavigator, SWT.CENTER);
        btnGo.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDown(MouseEvent e) {
                if (hasMissing((serverBox.getText().trim() + "," + portBox.getText().trim() + ","
                        + nameBox.getText().trim()))) {
                    makeErrBar("All fields are required", lblErrLabel);
                    return;
                }
                bmConnect(serverBox.getText().trim(), portBox.getText().trim(), nameBox.getText().trim());
            }
        });
        btnGo.setToolTipText("Establish connection");
        btnGo.setBounds(321, 9, 147, 52);
        btnGo.setText("Connect");

        Button btnSave = new Button(shlClientNavigator, SWT.CENTER);
        btnSave.setToolTipText("Save by title");
        btnSave.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDown(MouseEvent e) {
                String recordSave = (serverBox.getText().trim() + "," + portBox.getText().trim() + ","
                        + nameBox.getText().trim());
                if (hasMissing(recordSave)) {
                    makeErrBar("All fields are required", lblErrLabel);
                } else {
                    // see saveData() for more info on how this works
                    saveData(recordSave);
                    // repopulate the list
                    fillList(list);
                }
            }
        });
        btnSave.setText("Save");
        btnSave.setBounds(321, 67, 147, 52);

        Button btnDelete = new Button(shlClientNavigator, SWT.CENTER);
        btnDelete.setToolTipText("Remove saved connection");
        btnDelete.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                // Clicking the delete button spawns a new shell with a prompt to prevent
                // accidental deletions
                if (nameBox.getText().trim().length() < 1) {
                    makeErrBar("Title required", lblErrLabel);
                    return;
                } else {
                    final Shell shlDelDiag = new Shell();
                    shlDelDiag.setText("Delete " + nameBox.getText() + "?");
                    shlDelDiag.setSize(300, 200);

                    Label lblDiagLabel = new Label(shlDelDiag, SWT.WRAP);
                    // has enough space for substantially sized names but may not be enough
                    lblDiagLabel.setBounds(10, 10, 258, 77);
                    lblDiagLabel.setText("Are you sure you want to delete: " + nameBox.getText());

                    Button btnYes = new Button(shlDelDiag, SWT.NONE);
                    btnYes.addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseDown(MouseEvent e) {
                            // see deleteData for more info
                            deleteData(nameBox.getText());
                            // repopulate the list
                            fillList(list);
                            // dialogue box no longer needed
                            shlDelDiag.dispose();
                        }
                    });
                    btnYes.setBounds(163, 99, 105, 35);
                    btnYes.setText("Yes");

                    Button btnNo = new Button(shlDelDiag, SWT.NONE);
                    btnNo.addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseDown(MouseEvent e) {
                            // dialogue box no longer needed
                            shlDelDiag.dispose();
                        }
                    });
                    btnNo.setBounds(10, 99, 105, 35);
                    btnNo.setText("No");
                    shlDelDiag.open();
                    shlDelDiag.layout();
                    // possibly redundant?
                    fillList(list);
                }
            }
        });
        btnDelete.setText("Delete");
        btnDelete.setBounds(367, 398, 101, 36);
    }

    private void fillList(List list) {
        // fill out list w/ info
        String currLine = null;
        list.removeAll();
        try {
            // FileReader reads text files in the default encoding.
            FileReader fileReader = new FileReader(dataFile);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            while ((currLine = bufferedReader.readLine()) != null) {
                // use comma as separator
                String[] record = currLine.split(",");
                if (hasMissing(currLine)) {
                    continue;
                }
                list.add(record[2].toString()); // save by title
            }
            // Close files.
            bufferedReader.close();
        } catch (FileNotFoundException ex) {
            makeErrBar("Unable to open file '" + dataFile + "'", null);
        } catch (IOException ex) {
            makeErrBar("Error reading file '" + dataFile + "'", null);
        }
    }

    // This method creates a label containing relevant error messages
    private void makeErrBar(String error, Label lblErrLabel) {
        // If the error message is too large to fit spawn a new window.
        // The general idea here is that the smaller messages should be meaningful to
        // the end users while the larger messages are for debugging or tech support
        if (error.length() > 40 || lblErrLabel == null) {
            final Shell shlErrDiag = new Shell();
            shlErrDiag.setText("Error");
            shlErrDiag.setSize(300, 200);
            shlErrDiag.setLayout(new FillLayout(SWT.HORIZONTAL));
            Label lblDErrLabel = new Label(shlErrDiag, SWT.WRAP | SWT.SHADOW_NONE);
            lblDErrLabel.setTouchEnabled(true);
            lblDErrLabel.setToolTipText("Error Bar");
            lblDErrLabel.setText(error);
            lblDErrLabel.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED));
            formToolkit.adapt(lblDErrLabel, true, true);
            shlErrDiag.open();
            shlErrDiag.layout();
        } else {
            lblErrLabel.setText(error);
            lblErrLabel.redraw();
            formToolkit.adapt(lblErrLabel, true, true);
            lblErrLabel.redraw();
        }
        // note that once the user triggers an error only another error will remove the
        // error label. Change?
    }

    private void saveData(String record) {
        String[] target = record.split(",");
        // This step is to prevent the creation of duplicates
        deleteData(target[2]); // 3rd index (target[2]) holds the name. delete by name
        try {
            FileWriter fileWriter = new FileWriter(dataFile, true);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(record);
            bufferedWriter.newLine();
            bufferedWriter.close();
        } catch (IOException ex) {
            makeErrBar("Error writing to file '" + dataFile + "'", null);
        }
    }

    // shortcut method to check for incomplete records in the .csv
    private boolean hasMissing(String rec) {
        if (rec.substring(0, 1).equals(",") || rec.substring(rec.length() - 1).equals(",") || rec.contains(",,")) {
            return true;
        }
        return false;
    }

    private void deleteData(String target) {
        File dFile = new File(dataFile);
        File tempFile = new File("temp.csv");
        try {
            // deletion is performed by writing a second file which excludes target
            BufferedReader reader = new BufferedReader(new FileReader(dFile));
            BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
            String currentLine;
            while ((currentLine = reader.readLine()) != null) {
                if (hasMissing(currentLine)) { // clean up blanks
                    continue;
                }
                String[] record = currentLine.split(",");
                if (record[2].equals(target))
                    continue;
                writer.write(record[0] + "," + record[1] + "," + record[2]);
                writer.newLine();
            }
            writer.close();
            reader.close();
            // delete original file
            dFile.delete();
            // temp takes it's name
            tempFile.renameTo(dFile);
            // temp file is deleted
            tempFile.delete();
        } catch (Exception e) {
            makeErrBar(e.toString(), null);
        }
    }

    @SuppressWarnings("resource")
    public void bmConnect(String server, String port, String title) {
        if (hasMissing(server + "," + port + "," + title)) {
            makeErrBar("All fields are required", null);
            return;
        } else {
            String bmConnectPath = ClientNavigator.class.getResource("bmConnect.bat").toString().substring(5);
            ProcessBuilder pb = new ProcessBuilder(bmConnectPath, title, server, port);
            Process process;
            try {
                process = pb.start();
                int errCode = process.waitFor();
                if (errCode != 0) {
                    InputStream errStream = process.getErrorStream();
                    Scanner errScan = new Scanner(errStream).useDelimiter("\\A");
                    String errMsg = errScan.hasNext() ? errScan.next() : "";
                    errScan.close();
                    errStream.close();
                    makeErrBar(errMsg, null);
                }
            } catch (IOException e) {
                makeErrBar(e.toString(), null);
            } catch (InterruptedException e) {
                makeErrBar(e.toString(), null);
            }
        }
    }
}

为了获得可运行的.Jar,我需要更改什么?我可以将其与jre打包在一起?

我的代码有问题吗?它在Eclipse中编译得很好。

我构建项目的方式可能有问题吗?

我意识到我的代码很大程度上依赖于org.eclipse库。这是问题吗?如果是这样,我应该怎么做才能解决它?

1 个答案:

答案 0 :(得分:0)

Eclipse的导出不会将其他文件打包到.Jar

正如一些用户指出的那样,错误是指

中的事实
var page = 1;

$(document).ready(function() {
// see if we're at the bottom of the page to potentially load more content
$(window).on('scroll', scrollProducts);

function scrollProducts() {
    var end = $("#footer").offset().top;
    var viewEnd = $(window).scrollTop() + $(window).height();
    var distance = end - viewEnd;

    // when we're almost at the bottom
    if (distance < 300)  {
        // unbind to prevent excessive firing
        $(window).off('scroll', scrollProducts);
        console.log('we reached the bottom');

        $.ajax({
            type: 'GET',
            url: "foo/bar/" + page,
            success: function(data) {
                console.log("success!");
                $('#container').append(data).fadeIn();
                // rebind after successful update
                $(window).on('scroll', scrollProducts);
                page++;
            }
        });
    }
}
});

BMCliDat.csv不存在。

解决方案是导出可运行的.Jar,然后手动将必要的附加文件添加到.Jar所在的目录中。直接将它们添加到.Jar中不起作用。

感谢Andres的帮助!