William
William

Reputation: 20196

Google APIs Explorer not allowing access to Cloud Endpoints V2 methods

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

Answers (2)

Tad
Tad

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

William
William

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

  1. Add Cloud Endpoints API management to your app. See https://cloud.google.com/endpoints/docs/frameworks/java/adding-api-management
  2. Generate an API configuration file and deploy it PRIOR to deploying the app. See https://cloud.google.com/endpoints/docs/frameworks/java/test-deploy

  3. 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

Related Questions