2012-03-30 9 views
1

Ich habe interessante Setup. Ich habe eine Web-App, die einen Webservice registriert. Der Web-Dienst ist im Wesentlichen ein Front-End zu einem Buch von Klassen, die folgende tun:Start jvm Subprozess von War Web App

  1. Setup ein RMI-Server
  2. ein subprocess beginnen mit der Jvm mit der angegebenen Klasse, um einig Job
  3. zu tun

Um den Klassenpfad aufzulösen, lese ich normalerweise die System.getProperty ("java.class.path"); und ich habe dies für den Parameter -cp eingerichtet. Bei Kriegsdateien ist dies jedoch nutzlos.

Dies ist, wie meine Funktion, die eine bestimmte Klasse aus dem Klassenpfad aussieht startet:

public static Process launchClassProcess(@SuppressWarnings("rawtypes") Class c, String[] javaArgs, String[] programArgs) throws Exception { 
    String separator = System.getProperty("file.separator"); 
    String classpath = System.getProperty("java.class.path"); 
    String home = System.getProperty("java.home"); 
    String path = home + separator + "bin" + separator + "java"; 
    String[] jvmArgs = new String[] { path, "-cp", classpath }; 
    String[] classArgs = new String[] { c.getName() }; 
    String[] processBuilderArgs = new String[jvmArgs.length + javaArgs.length + classArgs.length + programArgs.length]; 
    int i = 0; 

    for (String arg:jvmArgs) { 
     processBuilderArgs[i++] = arg; 
    } 

    for (String arg:javaArgs) { 
     processBuilderArgs[i++] = arg; 
    } 

    for (String arg:classArgs) { 
     processBuilderArgs[i++] = arg; 
    } 

    for (String arg:programArgs) { 
     processBuilderArgs[i++] = arg; 
    } 

    ProcessBuilder processBuilder = new ProcessBuilder(processBuilderArgs); 
    StringBuilder command = new StringBuilder(); 
    int j = 0; 

    for (String part:processBuilder.command()) { 
     if (j++ != 0) { 
      command.append(" "); 
     } 

     command.append(part); 
    } 

    LogUtils.recordMessage("executing: " + command.toString()); 

    processBuilder.redirectErrorStream(true); 

    return (new ProcessBuilder(processBuilderArgs)).start(); 
} 

Wie kann ich diese Funktion verwenden zu können, aber mit Krieg-Dateien? Ich denke, dass ich irgendwie finden muss, wo meine Kriegsakte auf dem Dateisystem ausgepackt worden ist und den libs-Ordner finde, aus dem ich den kompletten Klassenpfad bauen kann.

+0

und kümmern sich um darunter liegende App Server Classloading-Richtlinien. Nette Frage, die sich darauf freut, etwas zu erleuchten! – BigMike

+0

Es ist möglich, die Datei-URL über die Ressourcen zu jeder Klasse zu finden. Von dort können wir zum obersten Punkt der Klasse zurückkehren, um herauszufinden, wo sich das jar befindet, und alles darunter als Klassenpfad registrieren. Dies ist jedoch ein wenig unsicher, wie man sich vorstellen kann. Wenn es möglich ist, irgendwie zu erkennen, wenn wir gerade in einer Web-App laufen, wird das Risiko erheblich minimiert. – Pass

Antwort

0

Sie können den Inhalt des lib Ordner von einem ServletContext erhalten:

ServletContext context = ....; 
Set<String> libs = context.getResourcePaths("/WEB-INF/lib"); 
1

Der beste Weg, dies zu tun, ist ein wenig Magie hinzuzufügen, die die Classpath, um die obige Funktion Arbeit zu machen modifiziert.

Wir benötigen folgende Servlet, machen sie es

public class InitServlet extends HttpServlet { 

    public void init() throws ServletException { 
     String libRealPath = getServletContext().getRealPath("/WEB-INF/lib/"); 

     if (libRealPath == null) { 
      throw new ServletException("cannot find web-inf lib path"); 
     } 

     ArrayList<String> libs = new ArrayList<String>(); 
     File libDir = new File(libRealPath); 

     for (String file:libDir.list(new FilenameFilter() { 

      public boolean accept(File dir, String file) { 
       return file.endsWith(".jar"); 
      } 

     })) { 
      libs.add(libRealPath + System.getProperty("file.separator") + file); 
     } 

     System.setProperty("java.class.path", System.getProperty("java.class.path") + System.getProperty("path.separator") + ProcessUtils.joinPaths(libs)); 
    } 

} 

Dann InitServlet nennen, müssen wir das Servlet in web.xml registrieren, um die Magie zu tun:

<servlet> 
    <servlet-name>init-servlet</servlet-name> 
    <servlet-class>InitServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet>