#htmlunit #runtime.exec
#htmlunit #runtime.exec
Вопрос:
Я пишу приложение, которому необходимо периодически загружать jar. Jar извлекает содержимое веб-сайта, использующего HtmlUnit.Когда этот jar запускается из командной строки commond, он выполняется как ожидалось. Но когда я запускаю его с использованием Java-кода с использованием среды выполнения, он блокируется в месте, страница= WebClient.getPage(locationToPing); и не выполняется дальше.
Jar содержит только один класс Java, как указано ниже,
package tempproj2;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Fetcher {
String locationToPing;
volatile WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
HtmlPage page ;
public static final long SLEEP_TIME_IF_CONNECTION_WAS_REFUSED=10000; //SECS
public long connectionRefusedTime=0;
private static Fetcher theOnlyInstanceOfThisClass=new Fetcher();
public static Fetcher getInstance(){
return theOnlyInstanceOfThisClass;
}
private Fetcher(){
init();
fetchUsingGet();
}
private void init(){
locationToPing="http://www.mail.yahoo.com";
}
private void fetchUsingGet(){
try {
System.out.println("-----------Start 1 --------------") ;
webClient.setUseInsecureSSL(true);
webClient.setThrowExceptionOnScriptError(false);
System.out.println("-----------Start 2 --------------") ;
webClient.setJavaScriptEnabled(true);
System.out.println("-----------Start 3 --------------") ;
webClient.setTimeout(5000); //30 secs - its int n not long be careful abt it.
System.out.println("-----------Start 4 --------------locationToPing=" locationToPing) ;
page= webClient.getPage(locationToPing);
System.out.println("-----------Start 5 --------------" page.asXml()) ;
} catch (Exception ex) {
System.out.println("-----------IC Fetecher Error here --------------" ex.getMessage()) ;
connectionRefusedTime=System.currentTimeMillis();
ex.printStackTrace();
}
}
private void reload(){
if(page==null){
fetchUsingGet();
return;
}
try {
page=(HtmlPage)page.refresh();
} catch (java.net.SocketTimeoutException ex) {
fetchUsingGet();
ex.printStackTrace();
}catch(IOException ex){
ex.printStackTrace();
}
}
public static void main(String ar[]){
Fetcher fetcher=new Fetcher();
while(true){
try {
Thread.sleep(4*1000);
} catch (InterruptedException ex) {
Logger.getLogger(Fetcher.class.getName()).log(Level.SEVERE, null, ex);
}
fetcher.reload();
}
}
}
Ниже приведены различные способы, которыми я пытался запустить приведенный выше код
- Запустите класс как есть — работает нормально.
- Создайте Jar указанного выше класса и запустите из командной строки, используя java -jar , command — выполняется нормально.
-
Создайте Jar указанного выше класса и запустите его из другого класса Java, используя следующий код,
try { String execCmd="java -jar " downloadApplicationJarLocation.getAbsolutePath(); Process pr=Runtime.getRuntime().exec(execCmd) ; InputStreamReader is = new InputStreamReader(pr.getInputStream()); BufferedReader br = new BufferedReader(is); String line = null; String processMessage=""; while ((line = br.readLine()) != null) { System.err.println("Line 1 " line) ; processMessage =line; } System.out.println("Finished "); is.close(); br.close(); } catch (IOException ex) { ex.printStackTrace(); }
Но когда я пытаюсь использовать приведенный выше код, выполняется только код до page= WebClient.getPage(locationToPing); и блокируется. «Start 5» никогда не выводится на экран.
- Я изменил приведенный выше код и вместо прямого вызова команды e Java -jar в Runtime.exec() поместил ее в пакетный файл и вызвал этот пакетный файл. Process pr=Runtime.getRuntime().exec(batchFileLocation) ; Теперь он выполняется как ожидалось и не блокирует код.Также на экране выводится надпись «Start 5».
Моему приложению необходимо периодически вызывать jar из Java и уничтожать предыдущий процесс, если таковой имеется. Поэтому вариант 4 мне не подходит, поскольку подпроцесс все еще работает, и уничтожить подпроцесс не очень просто.
Вариант 3 — идеальный способ для меня, но я совершенно не в состоянии понять, почему он блокируется и больше не выполняется? Это как-то связано с потоковой обработкой? Использую ли я HtmlUnit так, как он должен использоваться?
Заранее спасибо
Комментарии:
1. Я заставил код работать. Ранее я читал только входной поток запускаемого процесса. Я изменил код для чтения как InutStream, так и ErrorStream создаваемого процесса, и это решило проблему.
2. Есть хорошая статья о подводных камнях создания процесса на Java javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1