This post finishes with the tutorial about introducing Google Cloud Endpoints. As explained in the previous two parts, we plan to teach you how to construct a simple web backend storing data about posts and then expose it by means of a public REST-based API. We explained in the first post of the tutorial how to set up the environment. Then, we detailed how to create the core application with the endpoints to deal with posts objects. Finally, in this third post in the series we will explain how to interact with our application.
First, we want to locally test the endpoints operations created in the second part of the tutorial.
To do that, we right click the project name in the project explorer (see next screenshot), then select the Run As option in the contextual menu, and finally click on the Web Application option.
If everything worked fine now we see our local development time server up and running through Eclipse. Also, we obtain the right URL to use for opening the admin console where to manage the objects in the local datastore: http://localhost:8888/_ah/admin
Note that the URL we need to use to access Google Cloud Endpoints locally starts with the base URL http://localhost:8888. Then we use the _ah namespace which is the standard App Engine reserved namespace. This ensures there are not conflicts with any web pages in your app. Then we use the /api/myposts/v1 path. myposts comes from the @Api() attribute at the top of the PostEndpoint.java file. So we have the URL http://localhost:8888/_ah/api/myposts/v1. Then we access each endpoint operation by including the specific path we defined in the @ApiMethod() annotation at the top of each operation.
As an example, if we want to obtain the current list of posts the right URL is: http://localhost:8888/_ah/api/myposts/v1/post. To test the calls we use cURL. cURL provides a library and command-line tool for transferring data using various protocols. Basic use of cURL involves simply typing curl at the command line, followed by the URL of the output to retrieve. Also, almost every programming language provides an implementation of the cURL library. Therefore, you can easily adapt the calls shown here to your favorite piece of code.
The next screenshot shows 4 cURL calls to our endpoint operations. The first one obtains the list of posts with a GET call to the URL http://localhost:8888/_ah/api/myposts/v1/post. The result list is empty since no post was previously created. Then we want to create two posts. To do that, we need two HTTP POST calls passing a jSON encoded post object where we set the title, content, and author attributes of the post. The result is a jSON object of the post after it has been added to the datastore. Notice it has an id within the Key set which we can use to query for it later. The last call repeats the first GET call to obtain the list of posts. Now it obtains the two posts created.
Remember that visiting the local URL http://localhost:8888/_ah/admin you can explore and manage the entities created in the local datastore.
Next step is to deploy the current code to AppEngine in order to access the endpoints globally. We need to visit Google Cloud, log in, and then create a new Project. Next screenshot show you the way. Indicate the project name and the project ID. Note that the project ID must be unique.
Now we need to set up Eclipse to be ready to deploy the code. First of all, log in with your Google account in Eclipse by clicking in the bottom right corner, where you’ll find the Google logo. Once you are logged, right click on our myposts project and select Properties option. Within the Options panel, select Google, and inside it, App Engine (see next screenshot). Here you find a field named Application ID where you have to type the ID of the application you created before in Google Cloud (posts-example, in our case). Accept and then we are ready to deploy.
Select the project in the Project Explorer panel and then click on the Google icon (see next screenshot). Here we need to select Deploy to App Engine… to start the magic.
The Console shows the logs of the deployment (see next screenshot). Here you can find if something went wrong during this process. Once it finishes, we are ready to use our endpoints located at App Engine.
We can also use cURL calls. Note that the URL now has changed to a global URL starting with https://appid.appspot.com, where appid is the application ID we set before. Next screenshot shows the two POST calls to the URL to create a post. This way we can create two Post objects in Google’s App Engine Datastore.
To manage the characteristics of our Google Cloud Application, we can select our application in Google Cloud and then select App Engine. Here we find the App Engine dashboard with a Datastore Viewer where we can manage the entities of our application. We also can control the Instances that contain our code and answer the external calls, see their logs and set their characteristics. There are a lot of options that go beyond this tutorial and you can explore by yourself.
Remember that there is a free quota to test App Engine that includes (among others) several hours of running instances. If you need additional service, you can pay for it.
Thanks for reading! There is a lot more to do with Google Cloud Endpoints and Google’s AppEngine. I recommend you the tutorial by Ido Green from Google, the official documentation, and this book from Dan Sanderson. If you have any comment, I’ll be glad to answer you!
Great tutorial! Thanks!
Thank you for this awesome tutorial.
I wonder if you could help me out with the issue I have encountered.
On Windows 8 64 bits with Eclipse Luna, when I try to generate the endpoint class after annotating my entity, it fails and Eclipse says “There was a problem generating the API metadata for your Cloud Endpoints classes: unknown protocol: c ”
Do you know something about this please?
Hi Gannicus. I’ve never suffered the problem you indicated. Anyway, I searched stackoverflow and maybe the following links could help you:
http://stackoverflow.com/questions/23514301/generating-the-api-metadata-for-your-cloud-endpoints-classes-failed
http://stackoverflow.com/questions/23595180/google-app-engine-cloud-endpoints-prblem-marker-generate-app-engine-error-o
Hi Nelio and thank you for answering. Unfortunately I already checked stackoverflow, I even found someone who had the same issue (http://stackoverflow.com/questions/20773768/creating-app-engine-conected-android-project) but nobody answered.
You should open a new entry in the google group that discusses AppEngine: https://groups.google.com/forum/#!forum/google-appengine
Thank you Antonio, I will do that.
I would like to ask you another question about Cloud Endpoints. Is it possible to annotate the Entity for Objectify instead of JDO? I would like to use Objectify to interact with the datastore but I don’t know if I can use Cloud Endpoints with it. In particular, can it still generate the Endpoint class and the client library if I use Objectify annotations?
It seems that you can do it with Objectify: https://code.google.com/p/objectify-appengine/ Anyway, I never tried this. Good luck with it!
Thank you again.
This article was very useful to me, I must thank you. I don’t understand why but after doing this:
1)Create an web application project
2)create and annotate an entity
3)generate endpoint class
4)create a project on the google console and report the app id on the appengine-web.xml
5)deploy
I get 404 not found errors whereas it works perfectly on my local post. Eclipse keeps on saying the deployment was successful as well as the google console. Can you tell me if there is some step that I’m missing?
Thank you
Thanks, Rouge. Well, I cannot tell you why you get a 404 error without further information. Can you share some screenshots or a more detailed explanation in order to help you?
This is very helpful, but I want to do something a little more complicated. My application will have to handle users and allow them to send messages with a bunch of data.
Thus I would like to use two entities instead of one: a Member entity and a Post entity.
I figured there are two possibilities. The first one is to create two entities and generate one endpoint class for both. The second one is to write one endpoint class which could handle the two entities.
Do you know which solution is the best in my case? Thank you very much.
In my opinion (without knowing all the details of your particular case) I’d suggest creating two different endpoints, one for each entity. That’s the way I proceed in order to separate things. All the operations related to Member go to the MemberEndpoint, and all the operations related to Post, to the PostEndpoint.
Thank you very much Antonio
Hello, sorry for bothering you again. I would like to ask you one question (I got no answer on stack overflow) which you may be able to answer.
I have a Member entity which only has 2 fields: the Long id and String name.
I would like to use a getMemberByName(String name) method to retrieve easily a member instead of having to know its id. I am using JDO for persistence.
So I added this method to the Endpoint class generated:
@SuppressWarnings({“unchecked”})
@ApiMethod(name = “getMemberByName”,path=”/member/byname”)
public List getMemberByName(@Named(“name”) String name) {
PersistenceManager mgr = getPersistenceManager();
List candidates = null;
Query q=mgr.newQuery(Member.class);
q.setFilter(“name == nameParam”);
q.declareParameters(“String nameParam”);
q.setUnique(true);
try {
candidates = (List) q.execute(nom);
} finally {
mgr.close();
}
return candidates;
}
When I call this API method and give it a name parameter (which does exist in my datastore) it sends me nothing back. I thought maybe you could tell me if my code got any error, I’m not an expert with JDO.
Thank you
Amestris,
I see that candidates = (List) q.execute(nom); should be changed by candidates = (List) q.execute(name);
In addition to it, the “name” parameter should be used in the path (path=”/member/byname” -> path=”/member/byname/{name}”) and then the call for a name “John” should be /member/byname/John
Thank you Antonio.
I did apply your changes but that still doesn’t work. I think I read somewhere in Google’s documentation that I need to put an index on the name field. However for now I didn’t do anything like that, is it really necessary to query my database?
Hi Amestris,
Adding indexes depends on what you do inside the code of the method that responds to the endpoint. If that’s the problem, you should see it in the logs of your AppEngine application (in your AppEngine dashboard that you can find in appengine.google.com).
However, if the code you shared in a previous comment is the code you have (your query only filters one attribute) you won’t need any index.
As said, please check the logs in your Dashboard in order to get a clear idea of what’s happening.
Hi Antonio, since JDO doesn’t want to work for me I decided to use Objectify instead and it works perfectly.
Thank you very much.