Permalink
Browse files

Handle unsuccessful responses from http://ws.geonames.org/ more reaso…

…nably
  • Loading branch information...
1 parent 4581a63 commit bfd1c1bb61069206c44d33bf4b9fee15a3728871 @hlship committed Oct 12, 2011
@@ -14,8 +14,7 @@
package com.howardlewisship.tapx.datefield;
-public class DateFieldSymbols
-{
+public class DateFieldSymbols {
/**
* Path to the JSCalendar scripts and support files.
*/
@@ -31,4 +30,12 @@
* "win2k-cold-2"). Defaults to "". If a theme is configured, then the {@link #SKIN} is ignored.
*/
public static final String THEME = "tapx.datefield.theme";
+
+ /**
+ * Symbol that defines the base URL for accessing the GeoNames database. This can be overridden just for
+ * testing purposes.
+ *
+ * @since 1.2
+ */
+ public static final String GEONAMES_URL = "tapx.geonames.url";
}
@@ -14,13 +14,10 @@
package com.howardlewisship.tapx.datefield.services;
-import java.util.List;
-
-import org.apache.tapestry5.ioc.Configuration;
-import org.apache.tapestry5.ioc.MappedConfiguration;
-import org.apache.tapestry5.ioc.OrderedConfiguration;
-import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.ioc.ServiceBinder;
+import com.howardlewisship.tapx.datefield.DateFieldSymbols;
+import com.howardlewisship.tapx.datefield.TimeZoneVisibility;
+import com.howardlewisship.tapx.internal.datefield.services.*;
+import org.apache.tapestry5.ioc.*;
import org.apache.tapestry5.ioc.annotations.Contribute;
import org.apache.tapestry5.ioc.annotations.Marker;
import org.apache.tapestry5.ioc.annotations.Primary;
@@ -33,14 +30,7 @@
import org.apache.tapestry5.services.javascript.JavaScriptStack;
import org.apache.tapestry5.util.StringToEnumCoercion;
-import com.howardlewisship.tapx.datefield.DateFieldSymbols;
-import com.howardlewisship.tapx.datefield.TimeZoneVisibility;
-import com.howardlewisship.tapx.internal.datefield.services.BestGuessTimeZoneAnalyzer;
-import com.howardlewisship.tapx.internal.datefield.services.ClientTimeZoneTrackerImpl;
-import com.howardlewisship.tapx.internal.datefield.services.DateFieldFormatConverterImpl;
-import com.howardlewisship.tapx.internal.datefield.services.GeonameTimeZoneResolver;
-import com.howardlewisship.tapx.internal.datefield.services.LatLongTimeZoneAnalyzer;
-import com.howardlewisship.tapx.internal.datefield.services.SystemTimeZoneAnalyzer;
+import java.util.List;
public class DateFieldModule
{
@@ -57,6 +47,7 @@ public static void contributeFactoryDefaults(MappedConfiguration<String, String>
"classpath:/com/howardlewisship/tapx/datefield/jscalendar-1.0");
configuration.add(DateFieldSymbols.SKIN, "aqua");
configuration.add(DateFieldSymbols.THEME, "");
+ configuration.add(DateFieldSymbols.GEONAMES_URL, "http://ws.geonames.org/timezoneJSON");
}
public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
@@ -14,59 +14,72 @@
package com.howardlewisship.tapx.internal.datefield.services;
+import com.howardlewisship.tapx.datefield.DateFieldSymbols;
+import com.howardlewisship.tapx.datefield.services.LatLongToTimeZoneResolver;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.json.JSONObject;
+import org.slf4j.Logger;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.TimeZone;
-import org.apache.tapestry5.ioc.annotations.InjectResource;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.json.JSONObject;
-import org.slf4j.Logger;
-
-import com.howardlewisship.tapx.datefield.services.LatLongToTimeZoneResolver;
-
/**
* Makes use of the web service at http://ws.geonames.org/timezoneJSON to convert a latitude and
* longitude into TimeZone.
*/
-public class GeonameTimeZoneResolver implements LatLongToTimeZoneResolver
-{
- @InjectResource
- private Logger logger;
-
- public TimeZone resolveTimeZone(double latitude, double longitude)
- {
- try
- {
+public class GeonameTimeZoneResolver implements LatLongToTimeZoneResolver {
+ private final Logger logger;
+
+ private final String geonamesURL;
+
+ public GeonameTimeZoneResolver(Logger logger, @Symbol(DateFieldSymbols.GEONAMES_URL) String geonamesURL) {
+ this.logger = logger;
+ this.geonamesURL = geonamesURL;
+ }
+
+ public TimeZone resolveTimeZone(double latitude, double longitude) {
+ try {
String content = readContent(latitude, longitude);
+ if (content == null) {
+ return null;
+ }
+
JSONObject response = new JSONObject(content);
String timeZoneId = response.getString("timezoneId");
return TimeZone.getTimeZone(timeZoneId);
- }
- catch (Exception ex)
- {
- logger.error(String.format("Unable to use geonames.org to resolve time zone for %f, %f: %s", latitude,
+ } catch (Exception ex) {
+ logger.error(String.format("Unable to use %s to resolve time zone for %f, %f: %s", geonamesURL, latitude,
longitude, InternalUtils.toMessage(ex)), ex);
return null;
}
}
- private String readContent(double latitude, double longitude) throws IOException
- {
- URL url = new URL(String.format("http://ws.geonames.org/timezoneJSON?lat=%f&lng=%f", latitude, longitude));
+ private String readContent(double latitude, double longitude) throws IOException {
+ URL url = new URL(String.format("%s?lat=%f&lng=%f", geonamesURL, latitude, longitude));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ logger.info(String.format("Attempt to resolve location to time zone got %d result from %s",
+ connection.getResponseCode(), url));
+
+ connection.disconnect();
+
+ return null;
+ }
+
String content = readContentFromConnection(connection);
connection.disconnect();
@@ -75,28 +88,23 @@ private String readContent(double latitude, double longitude) throws IOException
}
- private String readContentFromConnection(HttpURLConnection connection) throws IOException
- {
+ private String readContentFromConnection(HttpURLConnection connection) throws IOException {
StringBuilder result = new StringBuilder(200);
BufferedReader reader = null;
- try
- {
+ try {
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = null;
- while (true)
- {
+ while (true) {
line = reader.readLine();
if (line == null)
break;
result.append(line).append('\n');
}
- }
- finally
- {
+ } finally {
InternalUtils.close(reader);
}
@@ -14,13 +14,12 @@
package com.howardlewisship.tapx.internal.datefield.services;
-import java.util.TimeZone;
-
-import org.apache.tapestry5.ioc.annotations.Inject;
-
import com.howardlewisship.tapx.datefield.services.ClientTimeZoneAnalyzer;
import com.howardlewisship.tapx.datefield.services.ClientTimeZoneData;
import com.howardlewisship.tapx.datefield.services.LatLongToTimeZoneResolver;
+import org.apache.tapestry5.ioc.annotations.Inject;
+
+import java.util.TimeZone;
public class LatLongTimeZoneAnalyzer implements ClientTimeZoneAnalyzer
{
@@ -29,8 +28,9 @@
public TimeZone extractTimeZone(ClientTimeZoneData data)
{
- if (data.latitude != null && data.longitude != null)
+ if (data.latitude != null && data.longitude != null) {
return resolver.resolveTimeZone(data.latitude, data.longitude);
+ }
return null;
}
@@ -0,0 +1,14 @@
+/* Used to simulate what happens when http://ws.geonames.org/ returns a 503. */
+
+var http = require("http");
+
+http.createServer(function(request, response) {
+
+ console.log("Sending 503 response for request " + request.url)
+
+ response.statusCode = 503;
+ response.end();
+
+}).listen(8888);
+
+console.log("Listening on port 8888")

0 comments on commit bfd1c1b

Please sign in to comment.