Calling an external application (i.e. Windows Calculator) in a GWT web application
Asked Answered
M

4

1

I am trying to call an external windows application (i.e. calc.exe) when a user clicks on a button in a GWT web application. Is there a way on how to do it?

Below are what I have already tried so far:

1.) Tried Runtime.exec and ProcessBuilder but I end up having a GWT compile error

Runtime.exec Code:

Process winCalc;
try {
    winCalc = Runtime.getRuntime().exec("\"C:/Windows/System32/calc.exe\"");
    winCalc.waitFor();

} catch (IOException e) {
    e.printStackTrace();
} catch (InterruptedException e) {
    e.printStackTrace();
}

Runtime.exec Code - GWT Compile Error:

Rebinding dir.ClientGinjector
            Checking rule <generate-with class='org.jsonmaker.gwt.rebind.JsonizerGenerator'/>
               [ERROR] Errors in 'file:/C:/Users/blahblah/framework/Toolbar.java'
                  [ERROR] Line 962: No source code is available for type java.lang.Process; did you forget to inherit a required module?
                  [ERROR] Line 964: No source code is available for type java.lang.Runtime; did you forget to inherit a required module?
                  [ERROR] Line 969: No source code is available for type java.lang.InterruptedException; did you forget to inherit a required module?
               [ERROR] Unable to find type 'dir.ClientGinjector'
                  [ERROR] Hint: Previous compiler errors may have made this type unavailable
                  [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
   [ERROR] Errors in 'file:/C:/Users/blahblah/gin/ClientGinjector.java'
      [ERROR] Line 60:  Failed to resolve 'dir.ClientGinjector' via deferred binding

---

ProcessBuilder Code:

ProcessBuilder pbWinCalc = new ProcessBuilder ("C:/Windows/System32/calc.exe");

try {
    Process pWinCalc = pbWinCalc.start();
    System.out.println("[dan]: pWinCalc.exitValue() = " + pWinCalc.exitValue());

} catch (IOException e) {
    System.out.println("[dan]: stacktrace = " + e.getMessage().toString());
}

ProcessBuilder Code - GWT Compile Error:

Rebinding dir.ClientGinjector
            Checking rule <generate-with class='org.jsonmaker.gwt.rebind.JsonizerGenerator'/>
               [ERROR] Errors in 'file:/C:/Users/blahblah/framework/Toolbar.java'
                  [ERROR] Line 974: No source code is available for type java.lang.ProcessBuilder; did you forget to inherit a required module?
                  [ERROR] Line 977: No source code is available for type java.lang.Process; did you forget to inherit a required module?
               [ERROR] Unable to find type 'dir.ClientGinjector'
                  [ERROR] Hint: Previous compiler errors may have made this type unavailable
                  [ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
   [ERROR] Errors in 'file:/C:/Users/blahblah/gin/ClientGinjector.java'
      [ERROR] Line 60:  Failed to resolve 'dir.ClientGinjector' via deferred binding

2.) Tried calling ProcessBuilder in a separate class that extends RemoteServiceServlet as per suggestion in this link (GWT + ProcessBuilder).

ProcessBuilder Code:

import java.io.IOException;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class WinCalcServiceImpl extends RemoteServiceServlet {

    private static final long serialVersionUID = 7495421224005326634L;

    public void getWinCalculator(){
        //Dan - Using ProcessBuilder
        final ProcessBuilder pbWinCalc = new ProcessBuilder ("C:/Windows/System32/calc.exe");

        try {
            final Process pWinCalc = pbWinCalc.start();
            System.out.println("[dan]: pWinCalc.exitValue() = " + pWinCalc.exitValue());

        } catch (final IOException e) {
            System.out.println("[dan]: stacktrace = " + e.getMessage().toString());
        }
//      p.waitFor();
    }

}

ProcessBuilder - GWT Compile Error:

         Rebinding com.gwtplatform.dispatch.shared.DispatchService
            Invoking generator com.google.gwt.user.rebind.rpc.DlServiceInterfaceProxyGenerator
               Running DLProxyCreator
   [ERROR] An internal compiler exception occurred
com.google.gwt.dev.jjs.InternalCompilerException: Failed to get JNode
    at com.google.gwt.dev.jjs.impl.TypeMap.get(TypeMap.java:140)
    at com.google.gwt.dev.jjs.impl.TypeMap.get(TypeMap.java:71)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.getType(BuildTypeMap.java:730)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.process(BuildTypeMap.java:814)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.access$700(BuildTypeMap.java:99)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap$BuildDeclMapVisitor.process(BuildTypeMap.java:325)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap$BuildDeclMapVisitor.visit(BuildTypeMap.java:244)
    at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.traverse(TypeDeclaration.java:1198)
    at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.traverse(CompilationUnitDeclaration.java:687)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.createPeersForNonTypeDecls(BuildTypeMap.java:637)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.exec(BuildTypeMap.java:514)
    at com.google.gwt.dev.jjs.impl.BuildTypeMap.exec(BuildTypeMap.java:523)
    at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:599)
    at com.google.gwt.dev.jjs.JavaScriptCompiler.precompile(JavaScriptCompiler.java:33)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:284)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:233)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:145)
    at com.google.gwt.dev.Compiler.run(Compiler.java:232)
    at com.google.gwt.dev.Compiler.run(Compiler.java:198)
    at com.google.gwt.dev.Compiler$1.run(Compiler.java:170)
    at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:88)
    at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:82)
    at com.google.gwt.dev.Compiler.main(Compiler.java:177)
      [ERROR] <no source info>: public class com.google.gwt.user.server.rpc.RemoteServiceServlet
    extends com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet
    implements : com.google.gwt.user.server.rpc.SerializationPolicyProvider
/*   fields   */
private final [unresolved] java.lang.Object delegate
private final [unresolved] Map<java.lang.String,Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy> serializationPolicyCache
/*   methods   */
public void <init>() 
[unresolved] public void <init>(java.lang.Object) 
[unresolved] protected void checkPermutationStrongName() throws Unresolved type java.lang.SecurityException
[unresolved] protected Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy doGetSerializationPolicy(Unresolved type javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String) 
[unresolved] private Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy getCachedSerializationPolicy(java.lang.String, java.lang.String) 
[unresolved] public final Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy getSerializationPolicy(java.lang.String, java.lang.String) 
[unresolved] static Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy loadSerializationPolicy(Unresolved type javax.servlet.http.HttpServlet, Unresolved type javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String) 
[unresolved] protected void onAfterResponseSerialized(java.lang.String) 
[unresolved] protected void onBeforeRequestDeserialized(java.lang.String) 
[unresolved] public java.lang.String processCall(java.lang.String) throws Unresolved type com.google.gwt.user.client.rpc.SerializationException
public final void processPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) throws java.io.IOException, javax.servlet.ServletException, com.google.gwt.user.client.rpc.SerializationException
[unresolved] private void putCachedSerializationPolicy(java.lang.String, java.lang.String, Unresolved type com.google.gwt.user.server.rpc.SerializationPolicy) 
[unresolved] protected boolean shouldCompressResponse(Unresolved type javax.servlet.http.HttpServletRequest, Unresolved type javax.servlet.http.HttpServletResponse, java.lang.String) 
[unresolved] private void writeResponse(Unresolved type javax.servlet.http.HttpServletRequest, Unresolved type javax.servlet.http.HttpServletResponse, java.lang.String) throws java.io.IOException



         org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding
      [ERROR] at WinCalcServiceImpl.java(7): class WinCalcServiceImpl 
         com.google.gwt.dev.jjs.ast.JClassType
Melvamelvena answered 5/3, 2014 at 20:32 Comment(1)
I am trying to reuse the existing Windows calculator by calling it from my webapp. I'm just thinking that instead of creating an entirely new calculator program for my webapp, why not just reuse the existing application offered by Windows. Is there another way I could do that or do I have no choice but to create the calc function in my webapp?Melvamelvena
D
2

You cannot do it. Browsers do not allow access to executable files on a user's computer. It would have been a dream-come-true for every hacker out there.

Dilorenzo answered 5/3, 2014 at 20:45 Comment(0)
A
2

A webapp should not and can not call a local program..

GWT compiles client classes to javascript and there's no support for Runtime, so GWT doesn't know how to transform your Runtime usage to JS.

For a list of GWT supported classes (client side), see http://www.gwtproject.org/doc/latest/RefJreEmulation.html

Atiana answered 5/3, 2014 at 20:47 Comment(0)
H
0

Use Java Applet to call an external application in GWT using JSNI.

Please have a look at below links for sample code.

Invoking Applet Methods From JavaScript Code

Call Java Applet function from Javascript

How to call Applet method from javascript

Headward answered 5/3, 2014 at 22:36 Comment(0)
M
0

I see. Thanks for the answers guys. I'm still a newbie in GWT. Your answers helped me understand more about GWT and how it compiles classes to javascript as well as the idea behind why webapp should not be allowed access to local resources. However, I think there are still exceptions though depending on the need and scenarios; in my case, my webapp is only used and accessed in a closed group/network and not for public/anyone's use.

For anyone who is also interested, What I did is I created a javascript code that uses an ActiveXObject implementation to run the external apps, in my case a windows calculator. Then using this code, I run this in an IE browser since only IE fully supports ActiveX implementation.

I haven't tried Braj's suggestion above but I think it's also one alternative that will work. Maybe I'll try playing with that approach this weekend.

Melvamelvena answered 6/3, 2014 at 17:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.