Google AppEngine – kolejne schody…
Ech. Nie jest łatwo zaprzyjaźnić się z GAE. Ciągle jakieś schody…
Przed momentem odkryłem problem z dostępem za pomocą refleksji do java.util.TimeZone, chcąc wyświetlić listę stref czasowych.
Wszystko zaczęło się niewinnie, od atrybutu modelu, zawierającego przefiltrowane listy:
@ModelAttribute("timeZones") public List<TimeZone> getTimeZones() { return TimeTools.TIME_ZONES; }
i kodu jsp:
<form:select path="timeZoneID">
<form:options items="${timeZones}" itemValue="id" itemLabel="displayName"/>
</form:select>Po otwarciu tego JSP AppEngine wyrzuca błąd:
HTTP ERROR: 500
access denied (java.lang.RuntimePermission accessClassInPackage.sun.util.calendar)
RequestURI=/product/add.htm
Caused by:
java.security.AccessControlException: access denied (java.lang.RuntimePermission accessClassInPackage.sun.util.calendar)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at com.google.appengine.tools.development.DevAppServerFactory
$CustomSecurityManager.checkPermission(DevAppServerFactory.java:139)
…
Problem tkwi w tym, że form:options używa refleksji do pobrania pól id dla itemValue oraz displayName dla itemLabel. Więc jak potwierdza niniejszy bug powstaje problem…
Rozwiązanie?
Użyć wrappera dla TimeZone:
public class MyTimeZone { private String id; private String displayName; public MyTimeZone(String id, String displayName) { this.id = id; this.displayName = displayName; } public MyTimeZone(TimeZone timeZone) { id = timeZone.getID(); displayName = timeZone.getDisplayName(); } public String getId() { return id; } public String getDisplayName() { return displayName; } }
i zmienić atrybut modelu na:
@ModelAttribute("timeZones") public List<MyTimeZone> getTimeZones() { return TimeTools.TIME_ZONES; }
A funkcja tworząca listę stref czasowych będzie wyglądać następująco:
public class TimeTools { private static final String TIMEZONE_ID_PREFIXES = "^(Africa|America|Asia|Atlantic|Australia|Europe|Indian|Pacific)/.*"; public static final List TIME_ZONES = new ArrayList(); static { String[] timeZoneIds = TimeZone.getAvailableIDs(); for (final String id : timeZoneIds) if (id.matches(TIMEZONE_ID_PREFIXES)) { TimeZone timeZone = TimeZone.getTimeZone(id); TIME_ZONES.add(new MyTimeZone(timeZone)); } Collections.sort(TIME_ZONES, new Comparator() { public int compare(final MyTimeZone a, final MyTimeZone b) { return a.getId().compareTo(b.getId()); } }); } }
Co jeszcze czeka mnie w walce z GAE? Zobaczymy niebawem











Zostaw odpowiedź!
Musisz się zalogować aby móc komentować.