我正在尝试为我的GAE端点项目生成一个Android客户端库,我遇到了一个奇怪的问题。当我生成一个iOS客户端库时,一切都很好,但对于Android GAE,它会生成一堆有错误的java文件(我在JDK 1.7,1.8上测试过)。 我尝试使用appcfg.sh和maven使用不同版本的GAE SDK但结果是一样的。
这是一个示例日志:
symbol: class Ranking
location: class MyApp
myApp-backend/myApp-backend-api-war/myApp/src/main/java/com/appspot/myAppserver/myApp/MyApp.java:1482: error: cannot find symbol
public Rating rating() {
symbol: class Rating
location: class MyApp
myApp-backend/myApp-backend-api- war/myApp/src/main/java/com/appspot/myAppserver/myApp/MyApp.java:1757: error: cannot find symbol
public User user() {
symbol: class User
location: class MyApp
myApp-backend-api- war/myApp/src/main/java/com/appspot/myAppserver/myApp/MyApp.java:2321: error: method category() is already defined in class MyApp
public Category category() throws java.io.IOException {
是否可能是由项目结构中的任何错误引起的?
答案 0 :(得分:0)
以下是Google Cloud Support对此案的回应,以回应我们的案例编号05478936:
2015年2月26日下午1:57的Google Cloud支持响应:
此时,我能够在运行mvn appengine:endpoints_get_client_lib时观察到您在初始故障单描述中描述的编译错误。我相信这些编译错误的原因与您如何构建/编写代码有关,特别是参考Guices注入功能。我会尽力提供有关如何解决这些编译错误的见解,但请注意,它们似乎不是由SDK引起的,而是由您使用Guice引起的,因此下一步是寻求来自渠道的支持Guice项目[1]定义了支持,例如github问题页面[2]或邮件列表[3] [4]。您可以在他们的wiki [5]中深入了解注入功能,此外还可以利用您自己目前对Guice工作方式的了解,以及在编写应用程序时使用其功能。
下面列出了按类别划分的各种错误,以及明显的原因。所有这些错误发生在target / endpoints-client-libs / uluvit / src / main / java / com / appspot / uluvitserver / uluvit / Uluvit.java中,它们似乎是Guice根据您的注入模式生成的生成文件,最终来自com.uluvit.backend.application.UluvitServletModule.java中给出的指示。行号将引用此结果文件Uluvit.java中发生编译错误的位置。
错误形式:方法_____已在类Uluvit(.. *)中定义? ...
相对于第2979行,第2389行,在编译器错误中可以观察到两次。我们可以在2979上看到方法category()已定义,返回类Category的对象,而已使用相同的方法签名第130行。
错误形式:类_____已在类Uluvit(.. *)中定义? ...
相对于第947行,第2396行,第2882行,第2985行,在编译器错误中可以观察到四次。我们可以在第947行看到已经定义了类讨论,而在第810行已经定义了相同的类,但是有不同的继承。
类_____中的构造函数_____不能应用于给定类型:
相对于第941行,第2876行,在编译器错误中可以观察到两次。我们可以在第941行看到代码返回新的Discussion();尝试,而在第827行,为讨论定义构造函数,我们看到它需要两个java.lang.Long参数,而不是没有参数。
无法找到符号:
对于类排名,评级和用户,此错误在maven编译阶段错误输出中出现三次。在线1293,1482和1757上,分别有一种方法试图返回这些类中的每一个,这些类在下面定义。可能是
没有为初始化找到合适的方法(Uluvit.Category)
在maven编译阶段错误输出中发生此错误一次。在第2980行,出现以下代码:
类别结果=新类别(); 初始化(结果); 返回结果;
问题是,使用函数Uluvit.initialize(),该函数来自第115行,并且具有不同的方法签名:
protected void initialize(com.google.api.client.googleapis.services.AbstractGoogleClientRequest httpClientRequest)抛出java.io.IOException
总结了对项目生成的编译器错误的分析。
我希望我的调查对你有所帮助。似乎错误不是SDK,而是你使用Guice来生成你的Api类。我没有资格深入谈论Guice或如何调试您的注射,但我很高兴我能够无论如何帮助确定这一点。也许你有多个类在其他文件中不会重叠,因为它们的名称冲突,因为注入模式产生了整体服务类Uluvit。
因为我们已经确定问题不是SDK,而是Guice,你可以通过github页面问题访问支持或者通过发布到邮件列表,除了guice标签上的stackoverflow,你会像我这样继续关闭这个案子呢?如果您对SDK有任何其他问题,请告诉我,我很乐意为您提供帮助。
祝福,
尼克 技术方案代表 云平台支持
[1] https://github.com/google/guice [2] https://github.com/google/guice/issues [3] https://groups.google.com/forum/#!forum/google-guice [4] https://groups.google.com/forum/#!forum/google-guice-dev [5] https://github.com/google/guice/wiki/Injections
2015年2月26日下午3:05的Google Cloud支持响应:
此时我不认为问题是Guice的版本和使用模式一样多。命名冲突似乎源于各种类中的众多@Inject注释,它们共同创建了Uluvit.java。您需要根据您对其工作原理的了解来调试您的Guice注射。与Guice的人们取得联系是向这个方向迈出的一大步。
现在,就推荐的DI库而言,我们不推荐任何特定的库,因为我们希望对开发人员的选择保持开放态度。最佳工具的定义是最符合您需求的工具,但是您可以解释它们。
我相信,根据我之前的消息分析,并与Guice人员取得联系,并查看注入和命名类,方法,您应该能够调试这些编译错误。生成客户端库操作失败的原因是由于Uluvit.java中的这些编译错误,而不是由于端点工具或SDK的任何问题。
答案 1 :(得分:0)
以下是Google云计算支持部门针对我们的案例编号05478936所说的内容。如果他们在Guice问题跟踪器上发布了我们的问题,他们指的是https://groups.google.com/forum/#!topic/google-guice/ou-ZUhCwJko:
2015年3月2日上午9:09的Google Cloud支持响应:
我已经阅读了你在Guice问题跟踪器中发布的帖子,我也一直在对Guice做一些深入的阅读,因为我想确保你在这里得到最好的解决方案,而且我可以准确理解您的应用中发生了什么。深入阅读您的源代码后,我可以看到Guice注入不是问题 - 我已经将Guice的注入系统作为Uluvit.java文件命名冲突的原因。
仔细检查您的API方法层次结构后,我可以看到它是导致该行为的API方法的命名。我会解释一下,所以你确切知道发生了什么,我还会列出你需要做的一些小改动才能获得成功的编译。此外,我提交了一个文档改进请求,以警告这个潜在的名称冲突,并开始在端点客户端库生成期间实现更有用的错误消息,在像您这样的情况下。
所以,这就是发生的事情:
Java端点客户端库生成代码通过读取代码来创建源文件,以查找带注释的Api类和方法。
然后尝试编译这些类并创建一个.jar,您可以将其作为依赖项加载到客户端。对于您的应用程序,所有多个* Endpoint.java类汇集在一起以构建将被编译的一个文件Uluvit.java。
当你有一个API方法“user.friends”时,它会在生成的Uluvit API服务类中创建一个User类,将所有“user。*”方法和User内部的Friends类组合起来处理那个方法请求。
User.Friends类已创建,因为它对应于API方法(作为层次结构中的最后一个符号,它是一种方法,而其他符号只是为了帮助提供命名上下文)。对于API中的每个方法,它将被分组在这样的子类中,表示方法层次结构,直到它到达实际方法,该方法将是一个扩展UluvitRequest的类,它扩展了AbstractGoogleJsonClientRequest,表示API的请求处理程序用于该方法,返回T类型的对象。
如果除了已经是方法之外还使用“朋友”作为方法层次结构的一部分,将导致命名冲突,因为“user.friends.acceptRequest”(以及其他此类方法)将需要在User类中创建另一个Friends类(以前是方法,而不是其中的类分组方法),以对所有“user.friends *”方法进行分组。
在这种情况下,根据其实际功能将“user.friends”更改为“user.friends.list”可以消除名称冲突,并进一步保持“user.friends”方法的统一级别层次结构。几种方法也出现了同样的问题,这就是所有需要改变的方法:
您是否可以尝试进行这4项更改,并让我知道客户端库生成是否适合您?此外,如果您有任何其他问题或疑问,请随时告诉我,我将非常乐意为您提供帮助。我希望尽管我最初确信我们已经找到了错误的原因,但是当我们发现Guice注射不是原因时,我认为你确保获得解决方案的承诺得到支持。
此致
尼克
技术解决方案代表
Google Cloud Platform