The step I was missing was adding the GAE Library into the project and then things were all happy.
Announcement
Collapse
No announcement yet.
X
-
The classpath settings have been updated and the next nightly build has the right ones (and has been verified to work). We've also verified that removing the classpath settings in a build that has them fixes the sample, so if you're having any trouble with that, try a re-import of the project - your IDE probably has some stale state around.
Comment
-
Disclaimer: This is my opinion based on 6 months of using SmartGWT.
jimmartens: If you are coding on App Engine I suggest you try out Objectify and write your own data store methods using Objectify. I suffered a lot of aggravation with the GAEJPADataSource. These problems are partly because I could not debug/see the code inside GAEJPADataSource and party because using JPA on app engine can be a pretty rough ride. Unless you have a large number of JPA classes that you are moving to App Engine (good luck to you!) JPA has a lot of headaches. Having a closed source JPA class made this pain even worse for me.
The following class is what I'm currently using. It implements the basic data operations but does not have any smart paging. This works great for me. I welcome to any suggestions on how to improve it. (I cut a few methods out but I think this will still compile).
Code:import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.persistence.Id; import com.google.appengine.api.NamespaceManager; import com.googlecode.objectify.Objectify; import com.googlecode.objectify.Query; import com.googlecode.objectify.impl.TypeUtils; import com.isomorphic.datasource.DSRequest; import com.isomorphic.datasource.DSResponse; import com.isomorphic.util.DataTools; public class ObjectService<T> { public enum OperationType { FETCH, ADD, UPDATE, DELETE } public ObjectService(Objectify ofy, Class<T> clazz) { this.ofy = ofy; this.clazz = clazz; findIdFieldName(); } public static interface Function { void apply(DSRequest request); } private Objectify ofy; private Class<T> clazz; private Field idField; private List<Function> criteriaFunctions = new ArrayList<Function>(); private boolean global; private void findIdFieldName() { // Check all the fields for (Field field : clazz.getDeclaredFields()) { if (!TypeUtils.isSaveable(field)) continue; boolean original = field.isAccessible(); field.setAccessible(true); if (field.isAnnotationPresent(Id.class)) { idField = field; } field.setAccessible(original); if (idField != null) break; } if (idField == null) throw new RuntimeException("Could not find ID field in class " + clazz.getSimpleName()); } public DSResponse fetch(DSRequest request) { for (Function f : criteriaFunctions) { f.apply(request); } DSResponse response = new DSResponse(); try { Map criteria = request.getCriteria(); List<T> list = fetch2(criteria); response.setData(list); response.setStartRow(0); response.setEndRow(list.size()); response.setSuccess(); } catch (Exception e) { e.printStackTrace(); response.setFailure(); } return response; } public List<T> fetch2(Map criteria) { Query<T> query = ofy.query(clazz); for (Object key : criteria.keySet()) { Object value = criteria.get(key); System.out.println("Filtering on criteria " + key + "=" + value); if (value != null && List.class.isAssignableFrom(value.getClass())) { if (((List) value).size() > 0) query.filter(key + " IN", value); else System.out.println("Ignoring criteria : " + key + " because it was an empty list"); } else query.filter((String) key, value); } List<T> list = query.list(); return list; } public DSResponse add(DSRequest request) { DSResponse response = new DSResponse(); try { T object = clazz.newInstance(); DataTools.setProperties(request.getValues(), object); ofy.put(object); response.setData(object); } catch (InstantiationException e) { e.printStackTrace(); response.setFailure(); } catch (IllegalAccessException e) { e.printStackTrace(); response.setFailure(); } catch (Exception e) { e.printStackTrace(); response.setFailure(); } return response; } public DSResponse update(DSRequest request) { DSResponse response = new DSResponse(); T object = findObject(request); try { DataTools.setProperties(request.getValues(), object); ofy.put(object); response.setData(object); } catch (Exception e) { e.printStackTrace(); response.setFailure(); } return response; } T findObject(DSRequest request) { T object = null; Class<?> class1 = idField.getType(); if (class1.equals(Long.class)) { Long id = (Long) request.getValues().get(idField.getName()); object = ofy.find(clazz, id); } if (class1.equals(String.class)) { String id = (String) request.getValues().get(idField.getName()); object = ofy.find(clazz, id); } return object; } public void remove(DSRequest request) { T object = findObject(request); ofy.delete(object); } public void addFetchCriteriaFunction(Function f) { criteriaFunctions.add(f); } }
I use this class with datasource definitions that include these bindings (there's probably a nicer way to do this - this seemed redundant to me)
Code:<operationBindings> <operationBinding operationType="fetch"> <serverObject className="com.sample.server.Service" targetXPath="employeeService" methodName="fetch" /> </operationBinding> <operationBinding operationType="add"> <serverObject className="com.sample.server.Service" targetXPath="employeeService" methodName="add" /> </operationBinding> <operationBinding operationType="update"> <serverObject className="com.sample.server.Service" targetXPath="employeeService" methodName="update" /> </operationBinding> <operationBinding operationType="remove"> <serverObject className="com.sample.server.Service" targetXPath="employeeService" methodName="remove" /> </operationBinding> <operationBindings>
finally com.sample.server.Service in the above binding definition must expose the method referred to in targetXPath
Code:public ObjectService<Employee> getEmployeeService() { return getObjectService(Employee.class); } /* oops forgot to add this one */ public <T> ObjectService<T> getObjectService(Class<T> class1) { //In my implementation I cache these classes -- note the ofy() returns an Objectify instance. return new ObjectService<T>(ofy(), class1)); }
Hope that helps.Last edited by atomatom; 13 Apr 2011, 17:49.
Comment
Comment