Google AppEngine Java限制(以及如何克服这些限制)

自Google的Java Java引擎启动以来,我一直试图创建一个小型但具有代表性的项目,并将其部署在Google的基础架构上。 我学到了很多东西,主要是犯了错误。 有趣的是,我取得了很多我不希望自己取得的成就。 相反,正如他们所说,魔鬼是细节,我发现那里是我无法想象的问题:对于某些问题,还有其他解决方案,对于某些问题则没有。

日食

Eclipse是我的第一个也是最重要的IDE。 我尝试过NetBeans,但是尽管我已通过NetBeans认证,但对我来说太奇怪了。 无论如何,Google为GAE提供了一个Eclipse插件。 当我尝试在更新站点上安装它时,出现了一个不太好的错误弹出窗口:

Cannot complete the install because one or more required items could not be found.
Software being installed: com.google.gdt.eclipse.suite.e34.feature.feature.group 1.0.0.v200904062334
Missing requirement: com.google.gdt.eclipse.suite.e34.feature.feature.group 1.0.0.v200904062334 requires \
    'org.eclipse.platform.feature.group [3.4.0,3.5.0)' but it could not be found

Google的插件仅适用于3.4版(Ganymede),而我具有3.5版(Galileo)。 对于Eclipse来说已经这么久了,但是Google似乎计划不迟于Galileo自己的版本发布与Galileo兼容的版本(感谢Rajeev )。

马文

像每个不那么年轻的Java开发人员一样,我曾经精通过Ant。 但是我无聊为每个项目编写相同的任务,所以我让Maven勾引我。 看来Google的人仍然只使用Ant(GAE文档中没有对Maven的引用),因此如果要使用Maven,则必须执行以下操作:

  • 参考DataNucleus存储库。 这是网址: http : //www.datanucleus.org/downloads/maven2
  • 将依赖项添加到:
    • org.datanucleus:datanucleus-core:1.1.0:jar
    • org.datanucleus:datanucleus-jpa:1.1.0:jar
    • org.datanucleus:datanucleus-enhancer:1.1.0:jar
  • datanucleus-corejavax.jta:transaction-api:1.1:jar有依赖性。 由于其POM引用了本地存储库(!),因此不会找到此工件。 您必须使用该名称手动安装JTA 1.1,
  • 手动安装并将依赖项添加到:
    • org.datanucleus:datanucleus-appengine:1.0.0.final:jar
    • com.google.appengine:appengine-api:1.0:jar

弹簧

在GAE中,Spring就像魅力一样。 GAE的文档说,反射已完全得到支持,因此这不足为奇。 我虽然没有使用AOP。

公共记录

Commons-logging是许多框架(包括Spring)的依赖项。 在本地服务器上,一切运行正常。 在云中,Google App Engine基础结构用其自身的JAR(具有不同的包结构)替换了commons-logging-1.1.1.jar。 实际上,这意味着即使您将JAR包含为依赖项,您也会在org.apache.commons.logging.LogFactory上看到有趣的NoClassDefFoundError 。 解决方案是仍然包括类,但给JAR重命名。

由于我使用Maven,因此使用Spring和MyFaces工件的exclusion标记从WAR中删除了commons-logging依赖性。 然后,我在运行时范围内添加了对commons-logging:commons-logging-api:1.1:jar的依赖。 这个罐子不会被更换。

JSP

JSP在页面中可以正常工作。 但是,XML格式JSP似乎没有得到翻译。 您需要创建“经典” JSP。

不过,您可能会遇到一些有趣的例外。 它看起来像这样:

java.lang.ClassCastException: SomeException cannot be cast to javax.servlet.ServletException
    at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:754)
    at org.apache.jsp.some_jsp._jspService(some_jsp.java:some_line)

似乎PageContextImpl类中存在一个错误,其中任何RuntimeException都将ServletExceptionServletException ,从而最终创建另一个异常。 这是非常困难的,因为ClassCastException堆栈跟踪将隐藏第一个堆栈跟踪。 为了进行调试,我建议您在内接的JSP中使用以下代码段:

<%try{%>
...yourJSPbody...
<%}catch(RuntimeExceptione){
    Loggerlog=Logger.getLogger(getClass().getName());
    StringWritersw=newStringWriter();
    e.printStackTrace(newPrintWriter(sw));
    log.severe(sw.toString());
    throwe;
}%>

EL

JSF标记(#)中的EL语法运行良好。 对于JSTL taglibs中的EL语法-例如核心($),一开始它不起作用。 多亏了Jim ,我知道您现在必须告诉App Engine不要在将EL与JSTL一起使用的每一页上使用代码<%@ page isELIgnored="false" %>忽略它。 恕我直言,这可能是默认行为,例如在Tomcat中。

JSF

Apache MyFaces v1.1可以很好地工作。 我的1.2版有问题:显然,某个地方有API不匹配。 因此,我暂时仍旧使用旧版本。

JPA

GAE选择的持久性API是JDO 。 来吧,伙计们,2009年的JDO? 尽管如此,GAE仍然接受JPA作为替代的持久性API,因此您在使用它时要格外小心。 在这两种情况下,GAE都使用DataNucleus框架(我第一次听说它-它似乎与JDO JPOX团队有关)。 与任何JDO框架一样,此框架使用自定义字节码增强了您的实体类:这在编译后的构建过程中进行。 DataNucleus令人惊讶的是,即使您选择JPA作为持久性API,也必须增强实体类。

由于增强过程依赖于某些工件,因此请检查这些工件是否被引用为依赖项(请参见上面的列表)。 要将增强功能绑定到编译阶段,请在您的POM中使用以下代码段(感谢Andy ):

<build>
...
    <plugin>
        <groupId> org.datanucleus </groupId>
        <artifactId> maven-datanucleus-plugin </artifactId>
        <version> 1.1.0 </version>
        <configuration>
            <mappingIncludes> net/frankel/hr/cra/model/*.class </mappingIncludes>
            <verbose> true </verbose>
            <api> JPA </api>
        </configuration>
        <executions>
            <execution>
                <phase> compile </phase>
                <goals>
                    <goal> enhance </goal>
                </goals>
            </execution>
        </executions>
    </plugin>
...
</build>

使用Datanucleus存在另一个限制,即如果使用JPA(或JDO)进行查询,则必须在结果List上显式调用size()方法。 否则,您的JSP将抛出一个不太好的NucleusUserException标记为“对象管理器已关闭”。 在datanucleus-appengine集成项目中提出了一个问题

本地AppEngine服务器

本地服务器运行良好。 我不禁要问,为什么翻译/编译过程会花费这么多时间(以分钟为单位)。 完成后,页面渲染非常Swift,因为我认为服务器可以优化缓存。

部署应用程序

最初的appcfg.cmd启动Java类。 我不知道为什么,但是应用程序只是忽略了JAVA_HOME环境变量,并不断检查java.home系统属性。 如果未找到后者,它将尝试使用C:\Program Files\Java\jre6\binC:\Program Files\Java\bin寻找javac 。 如果找不到,它将失败...我不得不修改appcfg.cmd来放置以下命令行:

java -Djava.home="%JAVA_HOME%" -cp "%~dp0\..\lib\appengine-tools-api.jar" com.google.appengine.tools.admin.AppCfg %*

无论如何,它无济于事,因为我收到以下SSL异常:

Unable to upload:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
  No trusted certificate found
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
    at com.google.appengine.tools.admin.ServerConnection.connect(ServerConnection.java:295)
    at com.google.appengine.tools.admin.ServerConnection.getAuthToken(ServerConnection.java:215)
    at com.google.appengine.tools.admin.ServerConnection.authenticate(ServerConnection.java:189)
    at com.google.appengine.tools.admin.ServerConnection.send(ServerConnection.java:116)
    at com.google.appengine.tools.admin.ServerConnection.post(ServerConnection.java:66)
    at com.google.appengine.tools.admin.AppVersionUpload.send(AppVersionUpload.java:345)
    at com.google.appengine.tools.admin.AppVersionUpload.beginTransaction(AppVersionUpload.java:159)
    at com.google.appengine.tools.admin.AppVersionUpload.doUpload(AppVersionUpload.java:68)
    at com.google.appengine.tools.admin.AppAdminImpl.update(AppAdminImpl.java:41)
    at com.google.appengine.tools.admin.AppCfg$UpdateAction.execute(AppCfg.java:469)
    at com.google.appengine.tools.admin.AppCfg.(AppCfg.java:114)
    at com.google.appengine.tools.admin.AppCfg.main(AppCfg.java:59)
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
    at sun.security.validator.SimpleValidator.buildTrustedChain(Unknown Source)
    at sun.security.validator.SimpleValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 24 more

解决方案是使用JDK中捆绑的JRE。 命令行因此变为:

java -Djava.home="%JAVA_HOME%/jre" -cp "%~dp0\..\lib\appengine-tools-api.jar" com.google.appengine.tools.admin.AppCfg %*

现在一切都应该从这里完美运行。 玩得开心!

翻译自: https://blog.frankel.ch/google-appengine-limitations/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值