GWT服务器端反射

3
我正在尝试仅在GWT应用程序的服务器端使用反射。我已经在非GWT示例中实现了一个基本示例,可以在下面看到。
package com.xyz.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class EntryPoint {

/**
 * @param args
 */
public static void main(String[] args) {

    ClassLoader dynClassLoader = ClassLoader.getSystemClassLoader();

    Class<?> dynClass = null;
    try {
        dynClass = dynClassLoader.loadClass("com.xyz.reflection.RunMe");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    Object dynInstance = null;
    try {
        dynInstance = dynClass.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

    Method dynMethod = null;
    try {
        try {
            dynMethod = dynInstance.getClass().getMethod("returnSid",
                    new Class[] { PassMe.class });

        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        String returnValue = (String) dynMethod.invoke(dynInstance,
                new Object[] { new PassMe() });

        System.out.println("Return Value: " + returnValue.toString());

    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

使用恰如其名的:

    package com.xyz.reflection;

public class PassMe {

private String sid = "DEFAULT_SID";

public PassMe() {
    this.sid = "INITIATED_SID";
}

public String getSid() {
    return sid;
}

public void setSid(String sid) {
    this.sid = sid;
}

}

and:

    package com.xyz.reflection;


public class RunMe {

    public String returnSid(PassMe s) {
        return s.getSid();
    }
}

这段代码在本地运行正常。但是当我尝试在GWT服务器端类中运行它时,它不起作用,而是返回错误信息。
 java.lang.NoSuchMethodException: com.xyz.reflection.RunMe.returnSid(com.xyz.reflection.PassMe)

如果我将参数更改为字符串(而不是'PassMe'类),它可以正常工作。为什么不能传递我的'PassMe'类?我认为这可能与序列化有关,尽管是100%的服务器代码,但我也没有成功过。
非常感谢您提前给予的任何帮助。

你在使用什么来运行GWT服务器(GWT托管模式?独立还是嵌入式WAR容器(例如Jetty)? - Syntax
4个回答

1

我认为这可能与类加载有关 - 但这只是我的猜测,因为我无法在类似于您的上下文中进行实验。

以下是一些建议:

您使用:

ClassLoader dynClassLoader = ClassLoader.getSystemClassLoader();

dynClass = dynClassLoader.loadClass("com.xyz.reflection.RunMe");

加载RunMe类。

然而,要加载PassMe类,您需要使用:

PassMe.class

尝试通过动态类加载器加载PassMe类,并在getMethod()中使用该实例,而不是PassMe.class。 我想知道,您是否需要使用dynClassLoader?

这个让我很好奇,所以我试了一下。如果你使用相同的加载器来实例化PassMe,它就可以正常工作。可能与GWT的秘密RPC机制有很大关系。 - j flemm

1

除了finrod的解决方案,你也可以将你的类加载器更改为以下内容:

ClassLoader dynClassLoader = PassMe.class.getClassLoader();

你可以再次使用PassMe.class样式查找。用于查找加载器的类似乎并不重要。只是不能使用系统加载器。

奇怪的事情。我不会怀疑GWT正在与类加载器做一些奇怪的事情。

编辑:是的。在开发模式下,GWT将系统类加载器设置为com.google.appengine.tools.development.IsolatedAppClassLoader


太完美了!我只需要更改你标记的那一行,它就像梦想成真一样工作。感谢你和finrod的帮助,你们两个都加1分 :o) 抱歉回复晚了,我去度假了。关于类路径的进一步阅读,我发现这篇古老但信息丰富的文章:http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html?page=1 - specialtrevor

0

这基本上是一次尝试,但如果您将

dynMethod = dynInstance.getClass().getMethod("returnSid", new Class[] { PassMe.class });

替换为

dynMethod = dynInstance.getClass().getMethod("returnSid", PassMe.class );

在GWT服务器之外没有区别,但它可能会以不同的方式激活容器的VM。


很不错的尝试,但并没有实现。不过非常感谢你花时间尝试帮助解决问题。 - specialtrevor

0
你把反射文件放到服务器端的包里了吗? 例如:
org.myproject.client - 你的 GWT 客户端包(将能编译成 JavaScript 的 java 文件放在这里,不包括反射)
org.myproject.server - 将任何包括反射的 java 文件放在这里
org.myproject.shared - 将能编译成 JavaScript 的 java 类放在这里


我已经尝试过将反射代码放在'org.myproject.server'和'org.external.reflection'中(包括在构建路径中添加外部项目/包),但两者都没有任何区别。 为了确认,这两个路径都不在客户端源路径的*.gwt.xml文件中。该文件仍然是这样的: <source path='client'/> <source path='shared'/>感谢您的时间。 - specialtrevor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接