Reputation: 20196
I am attempting to migrate a Java AppEngine from Cloud Endpoints to Cloud Endpoints Framework. Ie v1 to v2.
Migration goes fine, the endpoints are all accessible on the new instance. And discovery shows all the methods https://myapp.appspot.com/_ah/api/discovery/v1/apis
But when I use https://apis-explorer.appspot.com/apis-explorer for my appengine domain, while I can still see the API methods, when I drill down on them I can no longer provide params and execute them.
Looking at the AppEngine log I am seeing the following ClassCastException
Uncaught exception from servlet
javax.servlet.UnavailableException: java.lang.ClassCastException: com.google.api.server.spi.config.AnnotationBoolean cannot be cast to com.google.api.server.spi.config.AnnotationBoolean
at org.mortbay.jetty.servlet.ServletHolder.makeUnavailable(ServletHolder.java:415)
at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:458)
at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:58)
at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:48)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:37)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:48)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:257)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:145)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchServletRequest(JavaRuntime.java:559)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchRequest(JavaRuntime.java:519)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:489)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:453)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:460)
at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:293)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:319)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:311)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:457)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:238)
at java.lang.Thread.run(Thread.java:745)
Which seems to match up to the attempts to drill down on the methods in API Explorer. These errors don't occur with v1 of Cloud Endpoints.
The ClassCast implies that the AnnotationBoolen has been loaded into 2 different classloaders. I'm not playing with classloaders myself, so I presume this is something new for Endpoints v2. What do I change to avoid the ClassCast?
Does API Explorer not fully support Cloud Endpoints Framework?
Is there some extra step I need to take to enable method execution via API Explorer for Cloud Endpoints Framework?
Upvotes: 3
Views: 577
Reputation: 4784
The ClassCastException
that you experienced is due to loading the old SystemServiceServlet
instead of the new EndpointsServlet
. Configure your web.xml
to replace
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
...
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
with
<servlet>
<servlet-name>EndpointsServlet</servlet-name>
<servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
...
</servlet>
<servlet-mapping>
<servlet-name>EndpointsServlet</servlet-name>
<url-pattern>/_ah/api/*</url-pattern>
</servlet-mapping>
Upvotes: 0
Reputation: 20196
According to the Cloud EndPoints Frameworks migration guide these maven goals are no longer supported.
<goal>endpoints_get_discovery_doc</goal>
<goal>endpoints_get_client_lib</goal>
See https://cloud.google.com/appengine/docs/standard/java/endpoints/migrating
It also looks like you need to
Generate an API configuration file and deploy it PRIOR to deploying the app. See https://cloud.google.com/endpoints/docs/frameworks/java/test-deploy
Generate client libs using ...
See https://cloud.google.com/endpoints/docs/frameworks/java/quickstart-frameworks-java
Step 1 means adding something like the following to your web.xml:
<!--
EndPoints management API. See https://cloud.google.com/endpoints/docs/frameworks/java/adding-api-management
-->
<filter>
<filter-name>endpoints-api-configuration</filter-name>
<filter-class>com.google.api.control.ServiceManagementConfigFilter</filter-class>
</filter>
<!--
EndPoints management API. See https://cloud.google.com/endpoints/docs/frameworks/java/adding-api-management
-->
<filter>
<filter-name>endpoints-api-controller</filter-name>
<filter-class>com.google.api.control.extensions.appengine.GoogleAppEngineControlFilter</filter-class>
<init-param>
<param-name>endpoints.projectId</param-name>
<param-value>your-appengine-projectid</param-value>
</init-param>
<init-param>
<param-name>endpoints.serviceName</param-name>
<param-value>your-appengine-project-url.appspot.com</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>endpoints-api-configuration</filter-name>
<servlet-name>EndpointsServlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>endpoints-api-controller</filter-name>
<servlet-name>EndpointsServlet</servlet-name>
</filter-mapping>
Upvotes: 3