I’m trying to get the smart-gwt-ee 2.3 GAEDS example running and it’s giving me grief. I believe I’ve followed the README.txt instructions, but it still keeps giving me problems. I am working through them, but I wonder why it does not work out of the box? (I’m still presuming I am doing something wrong).
First problem, the classpath in the samples points to hibernate-tools.jar which is not in the smart-gwt-ee lib folder. Easy fix, delete the inclusion (but why is it in the sample CP)
The WAR does not have smart-gwt lib jars in it’s class path (or I am doing something quite wrong). For example, Jetty blows up because it can’t find DataSourceLoader. I can fix this by copying in the appropriate jar to WAR/WEB-INF/lib folder (actually I dumped the whole SGWTEE lib folder in).
And finally, the sample worked. So, I am posting this for two reasons. 1 to find out if I am simply doing something wrong, and 2 to help improve the samples so that they run out of the box.
I had the same grief you’re talking about. Basically, just following the instructions in the README won’t help you if you’re using Eclipse. You need to look in the build.xml file (Ant) and see which libraries it’s expecting to be in the \war\WEB-INF\lib directory (it has an include of an entire directory of jars with a bunch of excludes directives). Or just do what I did. Copy all of the libraries that are in your build path into the \war\WEB-INF\lib directory and rebuild / deploy your project to GAE then it’ll work fine.
Or forget eclipse and use Ant. BTW, I couldn’t get the Ant build to work inside eclipse either but I don’t recall off hand what the error was.
As I said, I followed the readme.txt instructions and read over it several times. Adding SGWTEE_HOME helps eclipse compile, but when I “run as Web Application” from eclipse, it fails because of missing jars that it expects.
There is likely another way to add a classpath when running the war folder, rather than copying all the files in. But copying is probably good as the war is then a self contained executable.
I respectfully meant the above as questions and suggestions to improve the readme.txt file.
I am using Eclipse Galileo (3.5), GWT 2.0.0, App Engine 1.3.0, and Java 6 (1.6.0_21)
You’re right, that setting SGWTEE_HOME lets it build but doesn’t bring the libs down into the war where they need to be for the project to actually run once deployed to GAE. That’s why I manually copied the libraries. If someone has a way that automatically will bring these libs into the war on an Eclipse build, I’m all ears (no pun intended).
Eclipse will build Ant projects as well. Try building the ant project inside Eclipse (Right click on the build.xml - build - debug - repeat). It’ll copy the libraries into the proper directory for you. You’ll need to set environment variables of course and you might need to tweak it a little to get it working.
Greetings,
After following the readme and setting the SGWTEE_HOME variable I have gotten a few of the samples to run just fine, but the GAEDS example is still running into an error when it tries to include hibernate-tools.jar. I can’t find this jar anywhere and I’m wondering if it got deprecated or if I just failed to install something. All the other jars are where they are supposed to be.
Description Resource Path Location Type Project ‘GAEDS’ is missing required library: ‘C:\downloads\Google\smartgwtee-2.4\lib\hibernate-tools.jar’ GAEDS Build path Build Path Problem
First, a sanity check; if you don’t plan deployment to GAE (Google App Engine) don’t bother troubleshooting this.
Second, GAE doesn’t use/allow Hibernate, it uses DataNucleus. This is a spurious dependency which doesn’t come from the original sample project and may have something to do with resources you still have lying around from playing with other sample project.
Well I do plan on deploying to GAE. I have heard of others doing this and am very interested in any documentation that points to using SmartGWT within the GAE framework.
And the classpath for the ds-gae has hibernate links in it, so I may just go about removing those and see if it works.
Confirmed that when we upgraded to a new Hibernate version the Hibernate .jars were inadvertently added to the GAE sample, thanks for catching this, we’re removing them. You should be able to proceed by just deleting the entries as you suggested.
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.
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).
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)
finally com.sample.server.Service in the above binding definition must expose the method referred to in targetXPath
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));
}