初次使用gwtent遇到的问题

64 views
Skip to first unread message

gerald

unread,
Aug 19, 2010, 1:10:01 AM8/19/10
to GWT-Ent Developer Forum
你好,我们在用gwt做项目,希望拥有动态取得类属性的功能。
本来项目经理让我用generator自己开发,但是我无意间发现了您的这个项目,不但能满足我们的需求,还提供了更多的功能。先对您说一生谢谢。但是
我们在使用的时候,遇到了一些问题
1.如果一个类的属性,没有getter方法,是不能取得此属性值的。
2.生成的代码太多了,我们现在的项目,功能很多,TypeOracle_Visitor最终达到了11万多行。生成这个文件大概需要20多秒钟,程序
员每次在调试的时候,一刷新页面,就要多等20秒。
3.将@Reflectable.relationTypes=设置为false,还是会生成类属性的类型,不知道是否我对relationTypes
的含义理解错了。
另外,如果有可能的话,我想参与您的项目,我对gwt与gwt-ext都很熟的,我们也在用gwt-ext做实际的项目,现在做的这个项目功能很多,最
终大概有5000个功能,所以我有很多的gwt实地使用经验。

James Luo

unread,
Aug 19, 2010, 1:37:01 AM8/19/10
to gwt...@googlegroups.com
你好,谢谢你的关注. 非常高兴如果你能够参与我们的项目, 特别是我现在正在做比较大的重构,从手实在是不够, 不知道你用不用GOOGLE Talk?我白天基本只能够Google Talk在线.

1, 是的,一定要有getter方法,因为在GWT里一点点反射的功能都没有,所以取field的值,实际上就是调用的getter 方法
2, 生成的代码是太多了,现在在重构计划里的一部分就是减少生成的代码,比如一个子类的父类也拥有反射信息,那这个子类应该只生成自己类的反射信息,而不是整个继承树
3, 这个应该是不会生成的,但是不排除有错误在里面.试一试@Reflect_Mini看看.也可以看看showcase里的control size部分.

2010/8/19 gerald <sunxuf...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "GWT-Ent Developer Forum" group.
To post to this group, send email to gwt...@googlegroups.com.
To unsubscribe from this group, send email to gwt-ent+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/gwt-ent?hl=en.




--
Regards
James Luo

gerald

unread,
Aug 19, 2010, 9:15:17 AM8/19/10
to GWT-Ent Developer Forum
1.关于直接给对象的属性赋值,
我觉得可以在 ClassType接口中,添加setFieldValue与getFieldValue函数
然后在生成类的时候,和生成invoke类似,生成 setFieldValue 与 getFieldValue ,里面通过很多if语句来实
现操作字段值
然后在com.gwtent.reflection.client.impl.FieldImpl.getFieldValue(Object
instance)中,
先判断有没有getter与setter,如果没有,就直接调用 enclosingType的setFieldValue 与
getFieldValue,
通过这种方式实现直接操作成员。
因为在gwt中使用反射的时候,大部分情况都是操作前台界面类,而界面类中的控件,都是界面类的成员变量,一般都没有get与set函数。
2.关于生成的类代码很多的问题,
a)可不可以将生成的每个类,分成不同的文件,放到原始类相同的包下面,这样就可以操作原始类的protected与package成员,
从而也避免所有的内容放到同一个文件里,导致文件过大。
b)这个可能会导致您现有的反射机制改动过大,只是我的一点想法,交流一下吧。
使用一个标注接口 DynaClass 来标注某个类是可以反射的
使用GWT.create(DynaClass的子类) 来得到一个 ClassType对象,从而可以使用ClassType进行反射操
作,这里需要一个Generator生成单个类的代码。
TypeOracle的 Generator 生成的java代码,也就是现在的TypeOracle_Visitor,可以搞成这样

if("aa.bbb.Class1".equals(className)){
return GWT.create(aa.bbb.Class1);
}
else if("aa.bbb.Class2".equals(className)){
return GWT.create(aa.bbb.Class2);
}
....

这样,虽然在编译的时候没有节省时间,但是在开发模式的时候,因为只会生成指定类的代码,
不会生成没有用到的代码,能节省一部分时间。因为我们发现,在使用gwt开发的时候,
很不好的一点就是dev mode太慢了,刷新一下页面要等好久,尤其是界面,没有可视化编辑器,每次修改了界面,
改了点代码,一刷新就等待半分钟才能看到效果,界面开发效率就很慢了。
如果再长时间的话,开发人员就更无法忍受了。
c)我的一点想法:relationTypes 好像实际用处不大,反而把整个结构搞的很复杂。

我可以使用google talk,我的邮件是sunxuf...@gmail.com

gerald

unread,
Aug 19, 2010, 9:14:38 AM8/19/10
to GWT-Ent Developer Forum

James Luo

unread,
Aug 19, 2010, 7:55:45 PM8/19/10
to gwt...@googlegroups.com
谢谢! 很久没有真正讨论过了.

1, 我明白你的意思了,实际上我们应该的场景不一样,我一般认为反射只用在domain里,而且domain也是系统里最简单的对象,界面因为涉及的类太多,所以一开始也没有考虑.在这里我一般假定Field是私有的.所以就没有可能来获取或者是设置字符值了. 比较想知道你们现在操作前台界面类主要是哪些方面会用到反射?谢谢.

2A) 我也很想生成多个类,准备把这个改动放在这次重构里, 但是我现在还不知道要怎么样在一个生成器里生成多个类, 囧

2B) 最开始的版本就是这样子实现的,你现在还能够看到这种实现的影子, "Reflection"接口就是用来干这个事情的,那个时候实现了"Reflection"接口,然后使用GWT.create()来生成反射信息,但是后来改了,最主要的原因是这种方式不仅仅逼迫客户实现一个标识接口,更加重要的是把GWT.create这样子很重要的操作给占用了,比如你写了一个你的生成器也要操作这个类,可是你发现这个宝贵的资源被Reflection给占用了

2C) RelationTypes 可能还是要看不同的应用场景,比如用户有一个字段是List类型的,可是用户不仅仅想要获取那个字符的值,还要能够遍历这个值,这个时候就很想要List的反射信息了,但是List在系统包里,用户是不可能改List让他实现一个"Reflection"接口的,这个时候RelationTypes就很有用了.

另外这一次我打算重构的几个部分:
1, 改变代码结构, com.gwtent.gen.reflection.ReflectAllInOneCreator 的代码不多,但是有够乱的,太不好理解了,这里应该会完全改掉
2, 生成多个文件,而不是一个文件,这里我还不知道要怎么返回多个文件,不知道你能不能帮我Research一下 :)
3, 使用GWT新提供的JavaScript延迟加载功能,尽量将所有生成的反射信息都只在使用的时候才加载,解决第一次加载的代码太大的问题
4, 会支持更加多的泛型支持,如果你看SVN你就会发现前些天已经加了ParameterizedType, 打算把整个泛型的支持都加进来
5, 对外的接口改动应该不多,只是新加一些类型,但是这些接口的实现类改动应该很大了
6, 打算把生成的代码改得更加紧凑,甚至会考虑使用某种二进制格式,让生成的类非常的小.

不知道老兄还有没有更多的补充.

2010/8/19 gerald <sunxuf...@gmail.com>
--
You received this message because you are subscribed to the Google Groups "GWT-Ent Developer Forum" group.
To post to this group, send email to gwt...@googlegroups.com.
To unsubscribe from this group, send email to gwt-ent+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/gwt-ent?hl=en.




--
Regards
James Luo

gerald

unread,
Aug 19, 2010, 9:41:27 PM8/19/10
to GWT-Ent Developer Forum
1.操作界面类的情况应该还是有的。我举一下我们现在的例子
主要的需求是希望通过注解的方式,来配置界面上控件的权限。
例如,界面上有新增,修改,删除3个按钮,不同的人进去,权限不同的话,
3个按钮的状态是不一样的,有的会被disable掉。
通过给按钮提供一个标识,来告诉计算机按钮的权限信息,例如
@OperationRef(operId = "append",deniedAction =
DeniedAction.Disable)
protected Button appendBtn;
这个说明按钮appendBtn在具有append操作的时候,按钮可用,否则disable
这个就是我们现在的场景。
实现的时候,原本是用generator做的,但是觉得不够灵活,所以想用反射的机制。
如果我们把不需要反射的控间用private限制,并且去掉relationship,
那么应该不会涉及太多的类了。

>2B) 更加重要的是把GWT.create这样子很重要的操作给占用了,比如你写了一个你的生成器也要操作这个类,可是你发现这个宝贵的资源被Reflection给占用了
这个我倒是没考虑过,多谢您的提醒,以后再作设计的时候我们也会考虑这一点的。
现在的 Deferred binding,我们看到的大概有3种模式
1.类继承接口(比如说标注接口DynaClass),
然后GWT.create(DynaClass的子类),
generate定义为
<generate-with ...>
<when-type-assignable class="DynaClass" />
</generate-with>
我之前说的就是这种方式
2.在jsonizer中看到的用法
比如说有一个对象叫Person,如果想生成关于Person的操作的类
那么就定一个接口 PersonJsonizer,放在同样的包下面,
这个接口是一个标注接口,
他从 Jsonizer 继承,主要用于Deferred binding识别
generate定义为
<generate-with ...>
<when-type-assignable class="Jsonizer" />
</generate-with>
然后GWT.create(PersonJsonizer)
这样,他就不需要改变原有的类,只需要在相同的包下面放一个
PersonJsonizer接口就可以了
3.在gwt2.0 ui binder中看到的用法
interface Binder extends UiBinder<Widget, Contacts> { }
private static final Binder binder = GWT.create(Binder.class);
通过泛形,在gerator中可以拿到那个类的泛形信息,从而可以生成对应的类
具体可以看他自带的例子
不知道我表达清楚了没有
后面两种方式,都可以在不改变原有类的基础上,实现Deferred binding
这样,我们使用第一种方式,结合后面两种,就基本可以解决
"你写了一个你的生成器也要操作这个类,可是你发现这个宝贵的资源被Reflection给占用了"
的问题

> 2A) 我也很想生成多个类,准备把这个改动放在这次重构里, 但是我现在还不知道要怎么样在一个生成器里生成多个类, 囧

一个生成器里生成多个类,我也没试过,不过一直以为,只要用他的那几个api,
应该和生成一个类没什么区别吧,找时间我试一下.
不过我说的和生成多个类没什么关系,
可能我之前没有说清楚,我之前说的是有2个generator
第1个generator,


使用一个标注接口 DynaClass 来标注某个类是可以反射的
使用GWT.create(DynaClass的子类) 来得到一个 ClassType对象,
从而可以使用ClassType进行反射操作

这个是和domain类对应的
第2个generator,
就是类似现在的TypeOracle的 Generator,
生成的java代码,也就是现在的 TypeOracle_Visitor ,
我们可以将它生成为如下的样子

if("aa.bbb.Class1".equals(className)){
//使用第1个generator


return GWT.create(aa.bbb.Class1);
}
else if("aa.bbb.Class2".equals(className)){

//使用第1个generator
return GWT.create(aa.bbb.Class2);
}
....
第2个generator,是一个总体的 generator,会枚举所有的类,
生成很多if语句
这种方式,不涉及到一个generator中,生成很多类的情况.
这种方式很重要,
因为在开发模式的时候,只会生成指定类的代码,
不会生成没有用到的代码,在类多的时候,能节省大量的时间。

另外,您提到的 GWT新提供的JavaScript延迟加载功能,
我上网搜了一下,都是在说Deferred binding,不知道您说的是不是这个.
或者能给我发个链接,我也学习一下

祝周末愉快


James Luo

unread,
Aug 19, 2010, 11:24:07 PM8/19/10
to gwt...@googlegroups.com
1, 这个场景挺好的.如果要控制最后生成的size, 现在最极端的就是使用ReflectableHasReflect注解, 可以看一看这个链接"http://code.google.com/p/gwt-ent/source/browse/trunk/gwtent_showcase/src/main/java//com/gwtent/showcase/client/reflection/ReflectControlSizePage.java",

在这里几乎关闭了所有的反射信息生成,最后只剩下HasReeflect注解了的内容了,可以看一看http://gwtent-showcase.appspot.com/ 里运行的结果.
        @Anno
        @Reflectable(classAnnotations = true, fields = false, methods = false, constructors = false)
        public static class Class_Custom1 {
                @Anno
                private String str;
                private Date date;
               
                @Anno
                @HasReflect(parameterTypes = true)
                public void setDate(Date date) {
                        this.date = date;
                }
                public Date getDate() {
                        return date;
                }
                public void setStr(String str) {
                        this.str = str;
                }
               
                @HasReflect(resultType = true)
                public String getStr() {
                        return str;
                }
        }
       
      
2B)非常精辟,特别是第三种方式非常的好,GWTENT里的数据绑定也是基于的这种, 但是这三种都需要用户做一些接口方面的工作,现在GWTENT里用的算是第一种的变体,但也不失为一种好办法.这几种中最主要的限制在于用户必须为每一个想生成反射信息的类提供额外的信息(实现一个接口或者是创建一个接口), 特别是在用户无法控制的场景,比如java包里的内容,可能会比较烦.

2A)非常感谢,很喜欢这个想法,甚至可以更加进一步,自动生成第三种需要的接口,最终看起来像这样:
                   private interface ClassType_aa_bbb extends ClassType<aa.bbb>{}

                   if("aa.bbb.Class1".equals(className)){
                   //使用第1个generator
                         return GWT.create(ClassType_aa_bbb.class);
                   }


3, 不好意思,我讲的应该叫代码分割, 可以看这个链接:
http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html



2010/8/20 gerald <sunxuf...@gmail.com>


--
You received this message because you are subscribed to the Google Groups "GWT-Ent Developer Forum" group.
To post to this group, send email to gwt...@googlegroups.com.
To unsubscribe from this group, send email to gwt-ent+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/gwt-ent?hl=en.




--
Regards
James Luo

sxf

unread,
Aug 20, 2010, 5:24:23 AM8/20/10
to gwt...@googlegroups.com
那个代码分割我之前没注意到,可能对我们很有用,我还要再想想该怎么用,先谢谢你啊。
那现在的生成代码的机制,是不是调整为
1.原有的注释机制Reflectable保持不变,也不需要加标注的接口。
2.TypeOracle的 Generator,生成的代码,就变成

private interface ClassType_aa_bbb extends ClassType<aa.bbb>{}

if("aa.bbb.Class1".equals(className)){
//使用第1个generator
return GWT.create(ClassType_aa_bbb.class);
}

3.然后,再写一个generator,生成每个类独立的代码,存放于类相同的包下面,对应上面的
return GWT.create(ClassType_aa_bbb.class);

还有,是不是可以加上直接存取属性的功能呢。
如果这两点满足的话,我们就可以直接使用这个项目了,就不用自己写了。
如果可以的话,我可以帮助实现这两个功能。
因为我们也急着用,呵呵

James Luo

unread,
Aug 20, 2010, 11:47:37 PM8/20/10
to gwt...@googlegroups.com
对,我想会改成这样。
直接存取属性的也可以加上,因为Java的反射本来也就支持直接存取的功能。
要是能够得到老兄的帮忙真是非常感谢。那我先调整一下结构,到时上传到SVN,不知道你什么时候会开始?

谢谢

2010/8/20 sxf <sunxuf...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "GWT-Ent Developer Forum" group.
To post to this group, send email to gwt...@googlegroups.com.
To unsubscribe from this group, send email to gwt-ent+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/gwt-ent?hl=en.




--
Regards
James Luo

sxf

unread,
Aug 21, 2010, 12:01:00 AM8/21/10
to gwt...@googlegroups.com
我就这几天可以开始,因为我们那个权限的功能下周要改好。
如果不用这个的话,我们会先写一个简单的generator,只针对我们的需求,实现我们的功能。
当然最好是能用您这个比较完善的框架,这样扩展性好一些。

还有您昨天说的code splitting,我大概看了一下,它也是异步的,所以,如果您以后要加的话,是不是
TypeOracle的
public ClassType getClassType(String name);
要改成 void getClassType(String name,AsyncCallback callback);
这样会影响到用户接口,是不是要提早作打算啊。

James Luo

unread,
Aug 22, 2010, 9:35:44 PM8/22/10
to gwt...@googlegroups.com
那好的,我明天晚上会把要改的上传到SVN,然后我们可以同时进行改代码了。

code splitting的可能会另外加一个方法之类的,这样子用户有得选择是要还是不要,现在还不清楚呢。

2010/8/21 sxf <sunxuf...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "GWT-Ent Developer Forum" group.
To post to this group, send email to gwt...@googlegroups.com.
To unsubscribe from this group, send email to gwt-ent+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/gwt-ent?hl=en.




--
Regards
James Luo

James Luo

unread,
Aug 24, 2010, 7:46:59 AM8/24/10
to gwt...@googlegroups.com
你好SXF,我已经将我修改的内容上传。

从这个版本起,TypeOracle_Visitor只放一些自动生成的接口声明和注解Annotation的实现,在我的机器上,这个类的代码行数从500,000减少到现在的60,000行,只剩下差不多以前的十分之一。

现有的测试代码都通过了,不过不是很清楚会不会有隐藏的其它bug.

我已经将老兄加为committer, 现在还少一下直接Field取值的功能 :)

2010/8/23 James Luo <james...@gmail.com>



--
Regards
James Luo

sxf

unread,
Aug 24, 2010, 8:17:32 AM8/24/10
to gwt...@googlegroups.com
好的,那我就来做直接存取field的功能
Reply all
Reply to author
Forward
0 new messages