Sarah Clark, Program Manager, Google Developer Training
Front-end web developers face challenges when using common “asynchronous” requests. These requests, such as fetching a URL or reading a file, often lead to complicated code, especially when performing multiple actions in a row. How can we make this easier for developers?
Javascript Promises are a new tool that simplifies asynchronous code, converting a tangle of callbacks and event handlers into simple, straightforward code such as: fetch(url).then(decodeJSON).then(addToPage)...
fetch(url).then(decodeJSON).then(addToPage)...
Promises are used by many new web standards, including Service Worker, the Fetch API, Quota Management, Font Load Events,Web MIDI, and Streams.
We’ve just opened up a online course on Promises, built in collaboration with Udacity. This brief course, which you can finish in about a day, walks you through building an “Exoplanet Explorer” app that reads and displays live data using Promises. You’ll also learn to use the Fetch API and finally kiss XMLHttpRequest goodbye!
This short course is a prerequisite for most of the Senior Web Developer Nanodegree. Whether you are in the paid Nanodegree program or taking the course for free, won’t you come learn to make your code simpler and more reliable today?
Originally posted on Google Apps Developers blog
Posted by Matt Hessinger, Project Specialist, Google Apps Script
Welcome to our 100th blog post on Apps Script! It’s amazing how far we’ve come from our first post back in 2010. We started out highlighting some of the simple ways that you could develop with the Apps platform. Today, we’re sharing tips and best practices for developing more complex Apps Script solutions by pointing out some community contributions.
The Apps Script editor does not allow you to use your own source code management tool, making it a challenge to collaborate with other developers. Managing development, test, and production versions of a project becomes very tedious. What if you could have the best of both worlds — the powerful integration with Google’s platform that Apps Script offers, along with the development tooling and best practices that you use every day? Now, you can.
npm install -g node-google-apps-script
This project, “node-google-apps-script”, is a Node.js based command-line interface (CLI) that uses Google Drive API to update Apps Script project from the command line. You can view the node package on the NPM site, and also view the GitHub repo. Both links have usage instructions. This tool was created by Dan Thareja, with additional features added by Matt Condon.
Before using the tool, take a look at the Apps Script Importing and Exporting Projects page. There are a few things that you should be aware of as you plan out your development process. There are also a few best practices that you can employ to take full advantage of developing in this approach.
There is a sample project that demonstrates some of the practices described in this post: click here to view that code on GitHub. To get all of the Apps Script samples, including this import/export development example:
Your standalone Apps Script projects live in Google Drive. If you use a command-line interface (CLI) tool like the one linked above, you can work in your favorite editor, and commit and sync code to your chosen repository. You can add tasks in your task runner to push code up to one or more Apps Script projects, conditionally including or excluding code for different environments, checking coding style, linting, minifying, etc. You can more easily create and push UI-related files to a file host outside of Apps Script, which could be useful if those same files are used in other apps you are building.
In addition to the information on the Importing and Exporting Projects page, here are a few things to consider:
Over and above the editing experience, the biggest improvements you get by working outside the script editor is that you are no longer locked into working in just one Apps Script project. You can much more easily collaborate as a team, with individual developers having their own working Apps Script projects, while also having more controlled test, user acceptance and production versions, each with more process and security. Beyond just the consistency with other normal project practices, there are a few Apps Script specific ways you can leverage this multi-environment approach.
If you are going to use this approach, here are three best practices to consider:
The provided sample shows a simple example of how a base configuration class could allow a developer to inject their local values for their own debugging and testing. In this case, the developer also added the annotation @NotOnlyCurrentDoc, which tells Apps Script that they need the full scope for Drive API access. In this project, the “production” deployment has the annotation @OnlyCurrentDoc, which leads to the OAuth scope that is limited to the document associated with script running as Sheets, Docs, or Forms add-on. If you add a standard file pattern to the source project’s “ignore” file, these developer-specific files will never get into the actual codebase.
Benefits for your project — Production can have more limited OAuth scopes, while a developer can use broader access during development. Developers can also have their own personal configuration settings to support their individual development efforts.
While there is no current way to trigger tests in an automated way, you still may want to author unit tests that validate specific functions within your projects. You’ll also likely have specific configuration values for testing. Once again, none of these files should make it into a production deployment. You can even use the Apps Script Execution API to drive those tests from a test runner!
Benefits for your project — You can author test functions, and keep them separate from the production Apps Script file. This slims down your production Apps Script project, and keeps the correct OAuth scopes that are needed for production users.
If you are developing an add-on for Sheets or Docs, and you expect to have an “active” item on the SpreadsheetApp. However when you are developing or testing, you may be running your Apps Script without an “active” context. If you need to develop in this mode, you can wrap the call to get the current active item in a method that also can determine what mode you are running in. This would allow your development or test instance to inject the ID of an “active” document to use for testing, while delegating to the getActive* result when running in a real context.
Benefits for your project — You can integrate better unit testing methodologies into your projects, even if the end deployment state dependents on resources that aren’t typically available when debugging.
You now have the option to use your own development and source management tools. While you still do need to use the Apps Script editor in your application’s lifecycle — to publish as a web app or add-on, configure advanced services, etc. — taking this step will help you get the most out of the power of the Apps Script platform. Remember to check out Apps Script on the Google Developers site to get more information and samples for your Apps Script development.
If you happen to use python tools on the command line to facilitate your team’s build process, you can check out Joe Stump's python-gas-cli. You can view the package info here or the GitHub repo where you’ll also find usage instructions.
Here are some additional reference links related to this post:
Posted by Wouter van Oortmerssen, Fun Propulsion Labs at Google*
Originally posted to the Google Open Source blog
After months in development, the FlatBuffers 1.1 update is here. Originally released in June 2014, it’s a highly efficient open source cross-platform serialization library that allows you to read data without parsing/unpacking or allocating additional memory. It supports schema evolution (forwards/backwards compatibility) and optional JSON conversion. We primarily created it for games written in C++ where performance is critical, but it’s also useful more broadly. This update brings:
Download the latest release from our github page and join our discussion list for more details.
*Fun Propulsion Labs is a team within Google that's dedicated to advancing gaming on Android and other platforms.
public static void invokeExample() { String s; MethodType mt; MethodHandle mh; MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodType mt = MethodType.methodType(String.class, char.class, char.class); MethodHandle mh = lookup.findVirtual(String.class, "replace", mt); s = (String) mh.invokeExact("App Engine Java 6 runtime",'6','7'); System.out.println(s); }
public static void viewTable(Connection con, String query) throws SQLException { try ( Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query) ) { while (rs.next()) { // process results // } } catch (SQLException e) { // con resource is auto-closed, no need to do anything here! // } }
Map<String, List<String>> myMap = new HashMap<>();
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
public class SuperHeroes { public List listSuperHeroes() { List list = new ArrayList(); list.add(new SuperHero ("Champion of the Obvious", "Brad Abrams")); list.add(new SuperHero ("Mr. Justice", "Chris Ramsdale")); return list; } }
@Api(name = "superheroes", version = "v1") public class SuperHeroesV1 { ... }
$ curl http://localhost:8888/_ah/api/superheroes/v1/superheroes { "items": [ { "knownAs" : "Champion of the Obvious", "realName" : "Brad Abrams" }, { "knownAs" : "Mr. Justice", "realName" : "Chris Ramsdale" }
Real result = superheroes.list().execute();
GTLQuerySuperHeroesV1 *query = [GTLQuerySuperHeroesV1 queryForSuperHeroesList]; [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLSuperHeroes *object, NSError *error) { NSArray *items = [object items]; }];
// ... var ROOT = 'https://' + window.location.host + '/_ah/api'; gapi.client.load('superheroes', 'v1', loadSuperheroesCallback, ROOT); // Get the list of superheroes gapi.client.superheroes.superheroes.list().execute(function(resp) { displaySuperheroesList(resp); });
// Set up the HTTP transport and JSON factoryHttpTransport httpTransport = new NetHttpTransport();JsonFactory jsonFactory = new JacksonFactory();// Set up OAuth 2.0 access of protected resources // using the refresh and access tokens, automatically // refreshing the access token when it expiresGoogleAccessProtectedResource requestInitializer = new GoogleAccessProtectedResource(accessToken, httpTransport, jsonFactory, clientId, clientSecret, refreshToken);// Set up the main Google+ classPlus plus = new Plus(httpTransport, requestInitializer, jsonFactory);// Make a request to access your profile and display it to consolePerson profile = plus.people().get("me").execute();System.out.println("ID: " + profile.getId());System.out.println("Name: " + profile.getDisplayName());System.out.println("Image URL: " + profile.getImage().getUrl());System.out.println("Profile URL: " + profile.getUrl());
When Google acquired Instantiations in August 2010, everyone knew about our Java Eclipse products. Shortly after we joined, we talked about how best to help developers now that we are part of Google. We have always wanted to get these tools in more developers’ hands. So, back in September we decided to give them away for free! The community response has been fantastic. With that done, we asked ourselves, how could we make a good thing even better? How about by open sourcing the code and creating two new Eclipse projects!
Today we are announcing Google’s donation of the source code and IP for two of these products to the open source community through the Eclipse Foundation. This donation includes WindowBuilder, the leading Eclipse Java GUI Designer, and CodePro Profiler, which identifies Java code performance issues. Specifically, the WindowBuilder Engine and designers for SWT and Swing. All in all, this is a value of more than $5 million dollars worth of code and IP.
The Eclipse Foundation’s Executive Director, Mike Milinkovich, states that, “this is clearly a significant new project announcement, and very good news for Java developers using Eclipse. It has been impressive to see the continued growth and popularity of WindowBuilder, as this product has always filled a much needed gap in the Eclipse offerings. We look forward to it appearing in an Eclipse release soon. We’re very pleased with Google’s generous support of Eclipse, and the Java developer community around the world.”
One of the exciting aspects of innovating in the open source arena is that customers benefit from a full community. We are very excited to see the diverse collection of companies and individuals that have already expressed an interest in contributing to these projects. Commercial level support is important to many customers. Genuitec, makers of MyEclipse, intends to offer commercial support for the various WindowBuilder based products including the SWT, Swing Designer and even the GWT Designer from Google. Please sign up on the Genuitec site for more information. Similarly, OnPositive intends to offer commercial support for CodePro Profiler, as well as lead as the committers on the Eclipse Community Project. Sign up on the OnPositive site for more information.
"Genuitec is pleased to offer commercial support for WindowBuilder-based products - Swing, SWT and GWT - in early 2011 for companies who wish to continue a paid support contract once their Google support expires. We've been involved with the Eclipse Foundation since the beginning, so we are very familiar with these products. Thus, providing commercial support for this product line is a natural fit for us," said Maher Masri, President of Genuitec.
“Over the years OnPositive has built up unique experience with the CodePro Profiler and we are excited to offer commercial support for it. Google’s donation ensures that Java developers can build faster applications,” said Pavel Petrochenko, President of OnPositive.
WindowBuilderWindowBuilder is regarded as the leading GUI builder in the Java community (winning the award for Best Commercial Eclipse Tool in 2009). It includes powerful functionality for creating user interfaces based on the popular Swing, SWT (Standard Widget Toolkit), GWT (Google Web Toolkit), RCP and XWT UI frameworks.
CodePro ProfilerCodePro Profiler is an Eclipse-based Java application profiling tool that helps developers identify performance issues early in the development cycle and find CPU and algorithmic bottlenecks, memory leaks, threading issues, and other concurrency-related problems that can slow down an application or cause it to hang.
Both WindowBuilder and CodePro Profiler will become Eclipse projects in the first half of 2011. Once each one is set up as a project and available for download from the Eclipse site, the products will be accessible to use as open source code under the the standard Eclipse license. I am looking forward to leading the WindowBuilder project.
If you have any questions, you can learn more at this FAQ or we look forward to hearing from you on the forums.
(Cross-posted from the Google Web Toolkit blog)
In early August, Google acquired Instantiations, a company known for its focus on Eclipse Java developer tools, including GWT Designer. We're happy to announce today that we're relaunching the following former Instantiations products under the Google name and making them available to all developers at no charge:
Now that these products are available again, we hope you’ll start using them within your GWT projects. Meanwhile, our next step is to more deeply unify them into the GWT family of tools by blending the fantastic Instantiations technology into the Google Plugin for Eclipse (GPE). So, there’s much more to come, including things we’re pretty sure you’ll like, such as UiBinder support in GWT Designer.
You can download any of the tools from the GWT download page. If you have questions or comments we’d love to hear from you. The best place to discuss the tools above is at http://forums.instantiations.com. As always, continue to discuss GWT and GPE at the main GWT Group.
We would love to stay in better touch with you as we have more news about how we are integrating the Instantiations products into the Google Web Toolkit suite. Sign up if you’d like to receive email updates on these products and other developer tools.
CreateAlbumTx createAlbum = albumsFactory.createAlbum( "College Days", "The best days of my life!");Album album = createAlbum.getAlbum();albumsFactory.shareAlbumWithFriends(album);byte[] photo = captureImage();photosFactory.uploadPhoto(album, photo, ImageType.JPG, "My Best Buddies");
GetScrapsTx scraps = scrapFactory.getSelfScraps();for(int i = 0; i < scraps.getScrapCount(); ++i) { ScrapEntry scrap = scraps.getScrap(i); if(myFriends.contains(scrap.getFromUserId())) { scrapFactory.replyToScrap(scrap, "hey, thanks for remembering me!"); } else { scrapFactory.replyToScrap(scrap, "wanna be friends? [:)]"); friendsFactory.sendFriendRequest(scrap.getFromUserId()); }}
package com.blogpost.client;import com.google.gwt.core.client.EntryPoint;import com.google.gwt.user.client.Window;import com.google.gwt.user.client.ui.RootPanel;import com.google.gwt.visualization.client.AjaxLoader;import com.google.gwt.visualization.client.DataTable;import com.google.gwt.visualization.client.Query;import com.google.gwt.visualization.client.QueryResponse;import com.google.gwt.visualization.client.Query.Callback;import com.google.gwt.visualization.client.visualizations.AnnotatedTimeLine;public class BlogPost implements EntryPoint { public void onModuleLoad() { AjaxLoader.loadVisualizationApi(new Runnable(){ public void run() { Query query = Query.create("http://spreadsheets.google.com/pub?key=pCQbetd-CptH5QNY89vLtAg"); query.send(new Callback(){ public void onResponse(QueryResponse response) { if (response.isError()) { Window.alert("An error occured: " + response.getDetailedMessage()); } DataTable data = response.getDataTable(); AnnotatedTimeLine.Options options = AnnotatedTimeLine.Options.create(); options.setDisplayAnnotations(true); RootPanel.get().add(new AnnotatedTimeLine(data, options, "800px", "400px")); } }); }}, AnnotatedTimeLine.PACKAGE); }}