At the client side I have angular code calling PUT:
$http.put('organization', {name: $scope.name}).success(
function(data){
alert('Success');
});
the GET, POST and DELETE will be more or less the same. $http.get(), $http.post(), $http.delete().One thing I found interesting about slim3 is the URL rewrite with AppRouter.java. Here is what I do (with evil smile):
addRouting(
"/secured/{entity}",
"/secured/rest?entity={entity}");
addRouting(
"/secured/{entity}/{resourceId}",
"/secured/rest?entity={entity}&resourceId={resourceId}");
I route both URL to the same Controller. So here is my Controller. My root package is "smis". (I know, I know...)
package smis.controller.secured;
import java.io.BufferedReader;
import java.lang.reflect.Method;
import java.util.List;
import org.apache.log4j.Logger;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.datastore.Datastore;
import org.slim3.datastore.ModelMeta;
import com.google.appengine.api.datastore.Key;
public class RestController extends Controller {
private Logger logger = Logger.getLogger(getClass());
@Override
public Navigation run() throws Exception {
String entityName = asString("entity");
String resourceId = asString("resourceId");
// hack class name. :p
entityName = entityName.substring(0, 1).toUpperCase()
+ entityName.substring(1);
Class entityClass = Class.forName("smis.model." + entityName);
Class modelMetaClass = Class.forName("smis.meta." + entityName
+ "Meta");
Method method = modelMetaClass.getMethod("get");
Object modelMetaInstance = method.invoke(null);
logger.debug(entityClass);
logger.debug(modelMetaClass);
logger.debug(modelMetaInstance);
logger.debug("Method = " + request.getMethod());
if (isGet()) {
if (resourceId == null) {
return handleList((ModelMeta) modelMetaInstance);
} else {
return handleDetail(entityClass,
(ModelMeta) modelMetaInstance);
}
} else if (isPost()) {
return handleCreate((ModelMeta) modelMetaInstance);
} else if (isPut()) {
return handleCreate((ModelMeta) modelMetaInstance);
} else if (isDelete()) {
return handleDelete(entityClass);
}
return null;
}
private Navigation handleDelete(Class entityClass) throws Exception {
Key key = asKey("resourceId");
Datastore.delete(key);
Object t = Datastore.get(entityClass, key);
logger.debug(t == null);
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(t == null);
response.flushBuffer();
return null;
}
private Navigation handleCreate(ModelMeta modelMeta) throws Exception {
StringBuffer jb = new StringBuffer();
String line = null;
try {
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
} catch (Exception e) { /* report an error */
e.printStackTrace();
}
String json = jb.toString();
logger.debug(json);
Object t = modelMeta.jsonToModel(json);
boolean isComplete = Datastore.put(t).isComplete();
logger.debug(isComplete);
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(isComplete);
response.flushBuffer();
return null;
}
private Navigation handleDetail(Class entityClass, ModelMeta modelMeta)
throws Exception {
Key key = asKey("resourceId");
logger.debug(key);
Object t = Datastore.get(entityClass, key);
String json = modelMeta.modelToJson(t);
logger.debug(json);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(json);
response.flushBuffer();
return null;
}
private Navigation handleList(ModelMeta modelMeta) throws Exception {
List list = Datastore.query(modelMeta).asList();
String json = modelMeta.modelsToJson(list);
logger.debug(json);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().print(json);
response.flushBuffer();
return null;
}
}
Because my lazy nature, I use reflection to create the Class for my entity and also the instance of the Meta class. Thanks to how slim3 name the model and meta class. There is a high security risk here! Not recommended for production, OK?Then based on the isXXX() functions I call the handleXXXXX() accordingly. The implementation explains itself.
Some more interesting would be the asKey("my_key"), it does the same thing like:
request.getParameter("my_key") + parse it into a Key.
Very handy.
Last thing to point out is how to digest the request data:
StringBuffer jb = new StringBuffer();
String line = null;
try {
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
} catch (Exception e) { /* report an error */
e.printStackTrace();
}
The experiment was fun. I enjoy writing and playing with it. Hope it is the same for you too.






































