I am writing a web app to process a command line commands and display the out put.
I've tried using exec() but it doesn't seem to work.
Process process;
process = Runtime.getRuntime().exec(commands);
String line;
is = new BufferedReader(new InputStreamReader(process.getInputStream()));
while((line = is.readLine()) != null)
out.println(line);
added buffers and try cases, works great now.
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String[] commands = {"date"};
BufferedReader is = null;
BufferedReader es = null;
try
{
Process process;
process = Runtime.getRuntime().exec(commands);
String line;
is = new BufferedReader(new InputStreamReader(process.getInputStream()));
while((line = is.readLine()) != null)
out.println(line);
es = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while((line = es.readLine()) != null)
System.err.println(line);
int exitCode = process.waitFor();
if (exitCode == 0)
out.println("It worked");
else
out.println("Something bad happend. Exit code: " + exitCode);
} //try
catch(Exception e)
{
out.println("Something when wrong: " + e.getMessage());
e.printStackTrace();
} //catch
finally
{
if (is != null)
try { is.close(); } catch (IOException e) {}
if (es != null)
try { es.close(); } catch (IOException e) {}
} //finally
}
Related
From my Tomcat's servlet I execute an https connection to an external servlet.
This is the code:
HttpsURLConnection hpcon = null;
try {
URL url = new URL(surl);
hpcon = (HttpsURLConnection) url.openConnection();
hpcon.setRequestMethod("POST");
hpcon.setDoInput(true);
hpcon.setDoOutput(true);
hpcon.setUseCaches(false);
hpcon.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
OutputStreamWriter wr = new OutputStreamWriter(hpcon.getOutputStream());
String params = "user=" + URLEncoder.encode(user, "UTF-8");
params += "&psswd=" + URLEncoder.encode(pssw, "UTF-8");
params += "&metodo=" + URLEncoder.encode(metodo, "UTF-8");
wr.write(params);
wr.flush();
wr.close();
hpcon.connect();
int respCode = hpcon.getResponseCode();
if (respCode == 200) {
BufferedReader br = new BufferedReader(new InputStreamReader(hpcon.getInputStream()));
String response = "";
String output;
while ((output = br.readLine()) != null) {
response += output;
}
if (response.indexOf("-") > 0) {
response = "-12";
System.out.println("ret = -12 - response = " + response);
}
br.close();
} else {
ret = "-11";
System.out.println("ret = -11 - respCode = " + respCode);
}
} catch (Exception e) {
e.printStackTrace();
ret = "-10";
System.out.println("ret = -10");
} finally {
if (hpcon != null) {
hpcon.disconnect();
}
}
Where surl is the full url of a servlet present in a different domain and the three parameters are read from a db table (the third really is fixed and is the operation that is make by the external servlet).
The result is:
ret = -11 - respCode = 404
Before make the connection I turn off the certificate's verify using the above code:
try {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (Exception e) {
e.printStackTrace();
}
If I execute the same servlet manually from a browser with parameters in get mode all run correctly.
I tried to execute it on my code using the get mode and passing the three parameters in query string, but the result is the same.
How can I do to resolve the problem?
I have an ASP.net web app that spawns a process (in a thread). This thread calls a '.dll' to connect to another 'subsystem'.
Problem is, when there are errors connecting to the 'subsystem', it affects my main application (main UI) and I get a 'connection refused message'. I have already put in 'try-catch' error handling routines in my thread. FYI, I would like to treat the thread as a 'Fire and forget' thread.
The thread is spawned when btnSubmit is clicked.
Please refer to trimmed-down extract of code.
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
txt_hide.Value = sStatus;
if (sStatus == "")
{
//create thread for posting
id = Guid.NewGuid();
Thread th = new Thread(() => postXMLClass.PostXML(sSeqNo));
th.Start();
sStatus = "Transaction generated..please check posting status..";
lblMessage.Text = "Transaction Generated...";
}
else
{
FormView1.DataBind(); //refresh the form
clib.Show2("Error generating transaction : " + sStatus, sender);
lblMessage.Text = "Error generating transaction : " + sStatus;
}
}
catch (SqlException ex)
{
lblMessage.Text = "Error generating transaction ...: " + ex.Message;
}
catch (Exception ex)
{
//sqc.Transaction.Rollback();
lblMessage.Text = "Error encountered...: " + ex.Message;
throw;
}
finally
{
if (dbc != null) dbc.Dispose();
if (clib != null) clib.Dispose();
}
}
public static void PostXML(string inlinkcode)
{
string sToken = "", sXMLOut = "";
Xml.Router.XMLRouter cX = new Xml.Router.XMLRouter();
try
{
cX.set_Options("com.xml.router.nameServer", appSetArray[0]);
cX.set_Options("com.xml.router.nameServerPort", appSetArray[2]);
cX.set_Options("com.xml.router.logicalServerName", appSetArray[1]);
{
sLinkcode = inlinkcode;
if (sLinkcode != null && sLinkcode != "")
{
strxml = "<?xml version=\"1.0\" encoding='UTF-8' ?>";
strxml += "<TableLinkRequest version=\"1.0\"><DocumentLinkStart><Request><StartParams>";
strxml += "<CmpCode>X</CmpCode><DocCode></DocCode></TableLinkRequest>";
sXMLOut = cX.Send(sToken, strxml);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception {0}", ex.Message);
}
finally
{
if (cX != null) cX.Logoff(sToken);
}
}
Simple enough problem but it's been driving me crazy.
In my program I have a TextArea, defined as:
<TextArea fx:id="output" editable="false" prefHeight="300.0" prefWidth="200.0" text="Output" GridPane.columnSpan="2" GridPane.rowIndex="4" />
#FXML private TextArea output;
...
public void initialize(URL url, ResourceBundle rb) {
output.setText("Test"); //Test appears correctly in output
...
}
#FXML
public void download() {
String outputTemplate = templateField.getText();
String url = urlField.getText();
System.out.println("Downloading from " + url);
try {
Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); //Prints as expected
output.appendText(line + "\n"); //Has no effect
}
} catch (IOException e) {
e.printStackTrace();
}
}
Any ideas on how to get the text to appear would be great, I've done this before on different programs, just for some reason, this time it's being cantankerous
EDIT: Upon further tinkering, it actually will print out the results, but only after the Process ends and it exits the loop.
The text shown in the UI changes on a layout pulse. Layout pulses are done on the JavaFX application thread. Event handlers, like your download method run on the same thread effectively preventing it from doing any layouting or processing and other events until it completes. This is why you shouldn't block this thread with longrunning tasks, but execute them on a different thread.
Since updates to the UI should be done from the application thread, use Platform.runLater to append the text:
#FXML
public void download() {
String outputTemplate = templateField.getText();
String url = urlField.getText();
Runnable r = () -> {
System.out.println("Downloading from " + url);
try {
Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); //Prints as expected
final String printText = line + "\n";
// append the line on the application thread
Platform.runLater(() -> output.appendText(printText));
}
} catch (IOException e) {
e.printStackTrace();
}
};
// run task on different thread
Thread t = new Thread(r);
t.start();
}
The problem is that you're doing this in the main thread. So stage can not be updated, until the cycle is finished. Try it in new thread:
#FXML
public void download() {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() {
String outputTemplate = templateField.getText();
String url = urlField.getText();
System.out.println("Downloading from " + url);
try {
Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); // Prints as expected
output.appendText(line + "\n"); // Has no effect
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
new Thread(task).start();
}
Here is client code
public static void uploadFiles() {
try (DirectoryStream<Path> ds = Files.newDirectoryStream(Paths.get(Parameter.UPLOAD_FILES_DIR), "{*.dat}")) {
for (Path path : ds) {
System.out.println(path);
URL url = new URL(Parameter.UPLOAD_URL);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setConnectTimeout(1000 * 20);
conn.setReadTimeout(1000 * 20);
send(conn, path);
receive(conn);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void send(HttpURLConnection conn, Path path) throws Exception {
try (
BufferedOutputStream out = new BufferedOutputStream(conn.getOutputStream());
BufferedInputStream in = new BufferedInputStream(new FileInputStream(path.toFile()))
) {
byte[] buffer = new byte[1024];
int c = 0;
while ((c = in.read(buffer)) != -1) {
out.write(buffer, 0, c);
}
out.flush();
}
}
public static void receive(HttpURLConnection conn) throws Exception {
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
if (HttpURLConnection.HTTP_OK != conn.getResponseCode()) {
throw new Exception("Uploader response code: " + conn.getResponseCode());
}
}
}
Here is Servlet code:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Post request");
System.out.println(request.getContentLength());
try (BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
) {
String str;
while ((str = br.readLine()) != null) {
System.out.print(str);
}
} catch (Exception ex) {
ex.printStackTrace();
}
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()))) {
bw.write("Close connection!!!");
}
}
When i run client code in server console out appears
Post refquest
-1
request.getContentLength() always return -1
Why i cant send bytes to the servlet? Here is contains of file which bytes i am trying to send
["192","2","3","4","5","6","7","8","9","US"] ["194","2","3","4","5","6","7","8","9","US"]
Resovled. Problem was in "/" symbol in the end of url. it was absent. But in this case servlet has responded.
How to redirect Glassfish server output into HttpServletResponse.out? I am making servlet in NetBeans.
here is a working example, just expose this as a servlet
public class ReadLogs extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.append("<html>\n<head>\n\n");
out.append("<script>function toBottom()" + "{"
+ "window.scrollTo(0, document.body.scrollHeight);" + "}");
out.append("\n</script>");
out.append("\n</head>\n<body onload=\"toBottom();\">\n<pre>\n");
try {
File file = new File("C:\\pathToServerLogFile");
BufferedReader in = new BufferedReader(new FileReader(file));
StringBuilder sb = new StringBuilder();
while (in.ready()) {
String x = in.readLine();
sb.append(x).append("<br/>");
}
in.close();
out.append("\n</pre>\n</body>\n</html>");
out.close();
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
UPDATE
If you need to print only the last portion of the file use this after line "in.close();"
//print only 1MB Oof data
if(sb.length()>1000000){
out.append(sb.substring(sb.length()-1000000, sb.length()));
}else{
out.append(sb.toString());
}
So.. to print only lines which appeared after invoking script I've made such code:
BufferedReader reader = new BufferedReader(new FileReader("/path/to/server/log/server.log"));
int lines = 0;
while (reader.readLine() != null) {
lines++;
}
reader.close();
BufferedReader reader2 = new BufferedReader(new FileReader("/path/to/server/log/server.log"));
String strLine;
int i = 0;
while (i != lines) {
reader2.readLine();
i++;
}
while ((strLine = reader2.readLine()) != null) {
out.println(stringToHTMLString(strLine));
out.println("<br>");
}
reader2.close();
When servlet starts it counts lines in server log (saves it in variable i), then after clicking on action form it read lines which indexes are higher than i and displays it on html page. I've used function stringToHTMLString which I found somewhere on stackoverflow.
Greets.