GWT Client for App Engine Endpoints

190 views
Skip to first unread message

Matthew Rubenstein

unread,
Jan 11, 2017, 10:22:07 AM1/11/17
to GWT Users
Hello. I'm trying to add a Google Endpoints client to a LibGDX project. Adding one to the GWT module is causing me a lot of problems. Is there a demo GWT project that includes an Endpoints client, deployable to Google App Engine? A project I can open in Android Studio, so either a Gradle project or a (working) Eclipse project that can be imported by AS?

The LibGDX project setup application generates as an Android Studio Gradle project, like this game demo:

including Android, desktop, GWT ("html" module) and even Ios modules. The platform-nonspecific code (most of the clients application code) is implemented in the "core" module. I've added a simple HTTP XML client to a LigGDX GWT module. But it's not really an Endpoints client; it doesn't share the API from the rest of the project as an API, just as a component of a URL string. Is there a direct way to add an Endpoints client to that GWT module that can share the API with the backend and the other client modules? I'd rather not tack on yet another programming environment in a Javascript phase (ie. JsInterop) after GWT just to add the Endpoints client to what is otherwise a Java project. Thanks for your insights.


...

FWIW, I tried to get help in the Google App Engine group:

But the "Cloud Platform Support" guidance sent me into days of trying various GWT tutorials and demos all of which are broken. My final attempt was the GWT Project's "Build a GWT app" whose sample project executed but rendered a client webpage with no UI widgets.
"Deploy to GAE / Set up a project (without Eclipse)":

"Alternatively, If you would like to skip the Build a Sample GWT Application tutorial, then download and unzip this file."

BTW like all of the GWT instructional projects documentation I tried, that one's link is broken as its target project has been archived. But the file is still available from:

I edited the tutorial project's various config files according to the tutorial's instructions, and fixed some defects not mentioned in the instructions (like increasing the javac heap size to 512M, and adding <threadsafe>true</threadsafe> to appengine-web.xml , and removing old lib/ JARs that have substitute JARs downloaded by Ant, etc). Only to find the project launches in a browser in ant devmode but the browser app fails to include any actual UI widgets.

Michael Joyner (NewsRx)

unread,
Jan 11, 2017, 11:59:44 AM1/11/17
to google-we...@googlegroups.com

I don't know how much it will help, but RestyGWT could be used for the GWT client to access JSON data via a predefined and share-able json rest interface definition.

Then you could use the builts, (a bit manaully), of libGDX net to to http/json calls to the end point.

The end point I would think would need to be a separate project, just use a predefined endpoint API in your clients to access it as a 3rd party service.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

Matthew Rubenstein

unread,
Jan 11, 2017, 2:24:00 PM1/11/17
to GWT Users
I currently have the project's GWT module send data to the backend API
// Build API request URL.
backendMethodURLStr= "https://api-backend.appspot.com/_ah/api/endpointsApi/v1/sayHi
endpointRequestURLStr = backendMethodURLStr + "/" + URL.encode(dataStr);


// Ping Endpoint with value REST request.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, endpointRequestURLStr);
HttpRequestCallback httpReqClbk = new HttpRequestCallback();
try
{ builder.sendRequest(null, httpReqClbk); }
catch(RequestException exception)
{ httpReqClbk.onError(null, exception); }

[...]

class HttpRequestCallback implements RequestCallback
{
   
@Override
    public void onResponseReceived(Request request, Response response)
    {
        String responseStr = response.getText();
        log(
"HtmlLauncher.onSuccess() response:\n", responseStr);

       
// Parse data field from JSON response object.
        JSONValue responseJSONVal = JSONParser.parseStrict(responseStr);
[...]

So the backendMethodURLStr must be maintained to represent the Endpoints API. Are you saying RestyGWT can be used instead of a crude request string + RequestBuilder, with RestyGWT referencing the shared API that only has to be mainained in one place in the project? Ie. RestyGWT will automatically (after its configured by my code) to reference the class EndpointsApi that's generated by the Endpoints @Api and @ApiMethod annotations.

Paul Mazzuca

unread,
Jan 11, 2017, 4:39:15 PM1/11/17
to GWT Users
GAE Endpoints makes available REST EndPoints for your various clients.  If GWT is being used in your client, then you need to make an HTTP request from that client in order to communicate with GAE Endpoints.   So the question is how do you create an HTTP async request from a GWT client?

You could create a HTTP request using the GWT RequestBuilder API, which allows you to create a request from the ground up.  Or, you could use a higher level abstraction like RestyGWT which will do a lot of the heavy lifting for you.  I generally stick to RestyGWT for my REST API requests from a GWT client.  I would read through the documentation of RestyGWT and see if that is a good fit. 

Matthew Rubenstein

unread,
Jan 11, 2017, 7:28:56 PM1/11/17
to GWT Users
Well, I am making an async HTTP request using the GWT RequestBuilder API, as illustrated in the code snippet in my previous message. RestyGWT might offer better management of requests than my basic RequestBuilder code.

But what that doesn't do is allow me to call the API from GWT code, as I do in my Android AsyncTask:
try
{ resultDataStr = endpointsApiService.sayHi(name).execute().getData(); }
catch(IOException e)
{ return e.getMessage(); }

I can recode EndpointsApiService.sayHi(String) elsewhere in my code, change its name, and otherwise change both the API and its implementation - as Java. But in the GWT Endpoints client I have to separately maintain the REST URL strings. There are old (broken) tools like Google's apis-client-generator (generate_library) tool that supposedly generate GWT code from the Java API code (annotated). Are there any that actually work, so "just code in Java" gets maintainable Endpoints in GWT?

Matthew Rubenstein

unread,
Jan 12, 2017, 8:35:23 AM1/12/17
to GWT Users
The hitch seems to be getting the GWT compiler to find the API Java code generated by the annotation processor. That  generated API code is not under the project/html/src/ tree (html=GWT), but rather under the project/backend/build/generated-source/endpoints/java/ tree (eg. java/com/blue_green_group/gdxendpoints/backend/endpointsApi/EndpointsApi.java ). Failure of the GWT compiler to find the generated API code results in eg.
...html/src/com/blue_green_group/gdxendpoints/backend/api/gwt/services/endpointsApi/shared/EndpointsApi.java:45: error: cannot find symbol
 
public enum EndpointsApiAuthScope implements AuthScope {
                                               
^
  symbol
:   class AuthScope
  location
: interface EndpointsApi
...html/src/com/blue_green_group/gdxendpoints/backend/api/gwt/services/endpointsApi/shared/EndpointsApi.java:56: error: method does not override or implement a method from a supertype
   
@Override
   
^

Possibly the GWT compiler is not looking for the source code in that path, even though I tried adding project/backend/build/generated-source to eg. sourceSets.main.java.srcDirs (which fails because it's not a subdir of the GWT html/ module dir). Possibly because the generated API code is generated by the annotation processors only after the GWT compiles (though it's still in place when starting superdev after the last Android/backend build). Possibly both.

I could have the build process copy the generated API code from the backend module to a src/ dir under the html (GWT) module, but the Endoints pattern is for that code to be shared from a single source dir, not copied to other modules. But maybe that's the only way if GWT cannot share code from a dir outside the GWT module's tree.

Paul Mazzuca

unread,
Jan 13, 2017, 10:37:53 AM1/13/17
to GWT Users
I am not quite sure, but what might be the issue is that you are trying to add jar's that are not compatible with GWT.  GWT implements a subset of the Java 8 API. That's why GWT modules are usually written specifically for GWT, because they cannot leverage all of the Java API.  Furthermore, GWT modules require special xml files that specify details about how the module is supposed to be used.  

Usually, if you are using a third party library, it will most often be a javascript library that you would need to wrap using JsInterop. JsInterop becomes a powerful tool because in many cases it negates the need for third party GWT libraries.   For example, the Google Maps Javascript API enables developers to use Google Maps in their web apps.  A third party GWT jar is not required because GWT can wrap the API using JsInterop.  Though this requires some work, it is not that considerable, given that you are only wrapping the JsObjects and functions that you need.  Furthermore, as a developer, you are now less reliant on a another developers GWT-specifc library for Google Maps, making it easier to stay up-to-date with the most recent Google Maps updates.

So, if you are using a client library intended to connect to Google Endpoints, make sure it is Javascript (so that you can wrap it), or specifically intended for GWT. 

Matthew Rubenstein

unread,
Jan 13, 2017, 11:08:40 AM1/13/17
to GWT Users
Thanks for the clarification. JsInterop looks like a good "last resort" if I must write (and maintain) JS source in addition to Java. The limited set of Java classes that GWT can compile to JS makes JsInterop necessary and important (and better than JSNI).

The compilation error I get looks more like the GWT compiler just can't find the API class sources (since they're outside the GWT module source tree), before the GWT compiler even gets a chance to see if those classes are valid for compilation. The API classes are mostly simple Javascript, but refer to other Java classes, recursively, so some underlying classes might not be compilable by the GWT compiler. Do you know if there's a way to point the GWT compiler at an arbitrary source tree root, to validate whether it can compile the sources in that arbitrary source tree? If invalid then there's no point trying to get the GWT compiler to find them.
Reply all
Reply to author
Forward
0 new messages