Skip to content

Commit 01c0188

Browse files
committed
Demonstrate template versions
Change-Id: I4a36b14ed10b52da3443f5074430841465a0d3e5
1 parent b75ae82 commit 01c0188

File tree

4 files changed

+136
-22
lines changed

4 files changed

+136
-22
lines changed

config/README.md

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Firebase Remote Config REST API Java Quickstart
22
===============================================
33

4-
The Firebase Remote Config Java quickstart app demonstrates retrieving and
4+
The [Firebase Remote Config](https://firebase.google.com/docs/remote-config/) Java quickstart app demonstrates retrieving and
55
updating the Firebase Remote Config template.
66

77
Introduction
@@ -21,10 +21,11 @@ Getting started
2121
Run
2222
---
2323

24-
- From the `config` directory run `./gradlew run -Paction=get` to retrieve the template.
25-
- The returned template is stored in a file named `config.json`.
26-
- Note the Etag printed to the console you will need to use it when publishing template updates.
27-
- Update the template.
24+
- Get active template
25+
- From the `config` directory run `./gradlew run -Paction=get` to retrieve the template.
26+
- The returned template is stored in a file named `config.json`.
27+
- Note the ETag printed to the console you will need to use it when publishing template updates.
28+
- Update the template
2829
- If your template already has parameters, adjust one or more of the values.
2930
- If your template is empty, update it to look like this:
3031

@@ -58,28 +59,50 @@ Run
5859
}
5960
}
6061

61-
- From the `config` directory run `./gradlew run -Paction=publish -Petag='<LATEST_ETAG>'` to update the template.
62-
- Be sure to set the etag to the one that was last printed in the console.
63-
- Confirm in the console that the template has been updated.
64-
- At this point mobile clients can fetch the updated values.
62+
- From the `config` directory run `./gradlew run -Paction=publish -Petag='<LATEST_ETAG>'` to update the template.
63+
- Be sure to set the etag to the one that was last printed in the console.
64+
- Confirm in the console that the template has been updated.
65+
- At this point mobile clients can fetch the updated values.
66+
- View existing versions
67+
- From the `config` directory run `./gradlew run -Paction=versions` to print the
68+
last 5 template versions.
69+
- Roll back to an existing template
70+
- From the `config` directory run `./gradlew run -Paction=rollback -Pversion=<TEMPLATE_VERSION_NUMBER>` to
71+
activate the template with the matching version number.
6572

6673
Best practices
6774
--------------
6875

6976
This section provides some additional information about how the Remote Config
7077
REST API should be used when retrieving and updating templates.
7178

72-
### Etags ###
79+
### [Versions](https://firebase.google.com/docs/remote-config/templates) ###
7380

74-
Each time the Remote Config template it retrieved an Etag is included. This Etag is a
81+
Each time you update parameters, {{remote_config}} creates a
82+
new versioned {{remote_config}} template and stores the previous template as
83+
a version that you can retrieve or roll back to as needed.
84+
85+
All non-active versions expire and are removed if they are older than 90 days or if
86+
there are more than 300 newer template versions. Since template versions expire, any
87+
versions that need to be retrieved later on should be persisted externally.
88+
89+
Use the `listVersions` [query parameters](https://firebase.google.com/docs/reference/remote-config/rest/v1/projects.remoteConfig/listVersions#query-parameters)
90+
to filter the versions that are returned.
91+
92+
### ETags ###
93+
94+
Each time the Remote Config template it retrieved an ETag is included. This ETag is a
7595
unique identifier of the current template on the server. When submitting updates
76-
to the template you must include the latest Etag to ensure that your updates are consistent.
96+
to the template you must include the latest ETag to ensure that your updates are consistent.
7797

7898
In the event that you want to completely overwrite the server's template use
79-
an Etag of "\*". Use this with caution since this operation cannot be undone.
99+
an ETag of "\*". Use this with caution since this operation cannot be undone.
100+
101+
**NOTE:** To get the ETag your request must accept the gzip encoding. Add the header
102+
`Accept-Encoding: gzip` to receive the ETag in the response header `ETag`.
80103

81104
Support
82105
-------
83106

84-
- [Stack Overflow](https://stackoverflow.com/questions/tagged/firebase-cloud-messaging)
107+
- [Stack Overflow](https://stackoverflow.com/questions/tagged/firebase-remote-config)
85108
- [Firebase Support](https://firebase.google.com/support/)

config/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ run {
1515
if (project.hasProperty("etag")) {
1616
args = args << "${etag}"
1717
}
18+
if (project.hasProperty("version") && !project.version.equals("unspecified")) {
19+
args = args << "${version}"
20+
}
1821
standardInput = System.in
1922
}
2023

config/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip

config/src/main/java/com/google/firebase/samples/config/Configure.java

Lines changed: 95 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import com.google.gson.Gson;
55
import com.google.gson.GsonBuilder;
66
import com.google.gson.JsonElement;
7+
import com.google.gson.JsonObject;
78
import com.google.gson.JsonParser;
9+
810
import java.io.File;
911
import java.io.FileInputStream;
1012
import java.io.FileNotFoundException;
@@ -25,7 +27,7 @@
2527
*/
2628
public class Configure {
2729

28-
private final static String PROJECT_ID = "<YOUR-PROJECT-ID>";
30+
private final static String PROJECT_ID = "PROJECT_ID";
2931
private final static String BASE_URL = "https://firebaseremoteconfig.googleapis.com";
3032
private final static String REMOTE_CONFIG_ENDPOINT = "/v1/projects/" + PROJECT_ID + "/remoteConfig";
3133
private final static String REMOTE_CONFIG_SCOPE = "https://www.googleapis.com/auth/firebase.remoteconfig";
@@ -51,7 +53,7 @@ private static String getAccessToken() throws IOException {
5153
* @throws IOException
5254
*/
5355
private static void getTemplate() throws IOException {
54-
HttpURLConnection httpURLConnection = getCommonConnection();
56+
HttpURLConnection httpURLConnection = getCommonConnection(BASE_URL + REMOTE_CONFIG_ENDPOINT);
5557
httpURLConnection.setRequestMethod("GET");
5658
httpURLConnection.setRequestProperty("Accept-Encoding", "gzip");
5759

@@ -83,6 +85,64 @@ private static void getTemplate() throws IOException {
8385

8486
}
8587

88+
/**
89+
* Print the last 5 available Firebase Remote Config template metadata from the server.
90+
*
91+
* @throws IOException
92+
*/
93+
private static void getVersions() throws IOException {
94+
HttpURLConnection httpURLConnection = getCommonConnection(BASE_URL + REMOTE_CONFIG_ENDPOINT
95+
+ ":listVersions?pageSize=5");
96+
httpURLConnection.setRequestMethod("GET");
97+
98+
int code = httpURLConnection.getResponseCode();
99+
if (code == 200) {
100+
String versions = inputstreamToPrettyString(httpURLConnection.getInputStream());
101+
102+
System.out.println("Versions:");
103+
System.out.println(versions);
104+
} else {
105+
System.out.println(inputstreamToString(httpURLConnection.getErrorStream()));
106+
}
107+
}
108+
109+
/**
110+
* Roll back to an available version of Firebase Remote Config template.
111+
*
112+
* @param version The version to roll back to.
113+
*
114+
* @throws IOException
115+
*/
116+
private static void rollback(int version) throws IOException {
117+
HttpURLConnection httpURLConnection = getCommonConnection(BASE_URL + REMOTE_CONFIG_ENDPOINT
118+
+ ":rollback");
119+
httpURLConnection.setDoOutput(true);
120+
httpURLConnection.setRequestMethod("POST");
121+
httpURLConnection.setRequestProperty("Accept-Encoding", "gzip");
122+
123+
JsonObject jsonObject = new JsonObject();
124+
jsonObject.addProperty("version_number", version);
125+
126+
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpURLConnection.getOutputStream());
127+
outputStreamWriter.write(jsonObject.toString());
128+
outputStreamWriter.flush();
129+
outputStreamWriter.close();
130+
131+
int code = httpURLConnection.getResponseCode();
132+
if (code == 200) {
133+
System.out.println("Rolled back to: " + version);
134+
InputStream inputStream = new GZIPInputStream(httpURLConnection.getInputStream());
135+
System.out.println(inputstreamToPrettyString(inputStream));
136+
137+
// Print ETag
138+
String etag = httpURLConnection.getHeaderField("ETag");
139+
System.out.println("ETag from server: " + etag);
140+
} else {
141+
System.out.println("Error:");
142+
System.out.println(inputstreamToString(httpURLConnection.getErrorStream()));
143+
}
144+
}
145+
86146
/**
87147
* Publish local template to Firebase server.
88148
*
@@ -100,7 +160,7 @@ private static void publishTemplate(String etag) throws IOException {
100160
}
101161

102162
System.out.println("Publishing template...");
103-
HttpURLConnection httpURLConnection = getCommonConnection();
163+
HttpURLConnection httpURLConnection = getCommonConnection(BASE_URL + REMOTE_CONFIG_ENDPOINT);
104164
httpURLConnection.setDoOutput(true);
105165
httpURLConnection.setRequestMethod("PUT");
106166
httpURLConnection.setRequestProperty("If-Match", etag);
@@ -140,6 +200,26 @@ private static String readConfig() throws FileNotFoundException {
140200
return stringBuilder.toString();
141201
}
142202

203+
/**
204+
* Format content from an InputStream as pretty JSON.
205+
*
206+
* @param inputStream Content to be formatted.
207+
* @return Pretty JSON formatted string.
208+
*
209+
* @throws IOException
210+
*/
211+
private static String inputstreamToPrettyString(InputStream inputStream) throws IOException {
212+
String response = inputstreamToString(inputStream);
213+
214+
JsonParser jsonParser = new JsonParser();
215+
JsonElement jsonElement = jsonParser.parse(response);
216+
217+
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
218+
String jsonStr = gson.toJson(jsonElement);
219+
220+
return jsonStr;
221+
}
222+
143223
/**
144224
* Read contents of InputStream into String.
145225
*
@@ -162,8 +242,8 @@ private static String inputstreamToString(InputStream inputStream) throws IOExce
162242
* @return Base HttpURLConnection.
163243
* @throws IOException
164244
*/
165-
private static HttpURLConnection getCommonConnection() throws IOException {
166-
URL url = new URL(BASE_URL + REMOTE_CONFIG_ENDPOINT);
245+
private static HttpURLConnection getCommonConnection(String endpoint) throws IOException {
246+
URL url = new URL(endpoint);
167247
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
168248
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getAccessToken());
169249
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
@@ -173,14 +253,22 @@ private static HttpURLConnection getCommonConnection() throws IOException {
173253
public static void main(String[] args) throws IOException {
174254
if (args.length > 1 && args[0].equals("publish")) {
175255
publishTemplate(args[1]);
176-
} else if (args.length == 1 && args[0].equals("get")){
256+
} else if (args.length == 1 && args[0].equals("get")) {
177257
getTemplate();
258+
} else if (args.length == 1 && args[0].equals("versions")) {
259+
getVersions();
260+
} else if (args.length > 1 && args[0].equals("rollback")) {
261+
rollback(Integer.parseInt(args[1]));
178262
} else {
179263
System.err.println("Invalid request. Please use one of the following commands:");
180264
// To get the current template from the server.
181265
System.err.println("./gradlew run -Paction=get");
182266
// To publish the template in config.json to the server.
183-
System.err.println("./gradlew run -Paction=publish -Petag='LATEST_ETAG'");
267+
System.err.println("./gradlew run -Paction=publish -Petag='<LATEST_ETAG>'");
268+
// To get the available template versions from the server.
269+
System.err.println("./gradlew run -Paction=versions");
270+
// To roll back to a particular version.
271+
System.err.println("./gradlew run -Paction=rollback -Pversion=<TEMPLATE_VERSION_NUMBER>");
184272
}
185273
}
186274

0 commit comments

Comments
 (0)