Added server-side dispatchers for REST and procedural calls
Implemented the REST dispatcher.
This commit is contained in:
parent
f1e278c4c0
commit
54ba11210f
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.gson.example.service;
|
||||
|
||||
import com.google.gson.webservice.definition.CallPath;
|
||||
|
||||
/**
|
||||
* An enum describing all paths for this service
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
public enum ServicePaths {
|
||||
NULL_REQUEST(null),
|
||||
CART("/rest/cart"),
|
||||
ORDER("/rest/order");
|
||||
|
||||
private final CallPath path;
|
||||
|
||||
private ServicePaths(String pathInfo) {
|
||||
this.path = new CallPath(pathInfo);
|
||||
}
|
||||
|
||||
public CallPath getCallPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public static CallPath getCallPath(CallPath invokedPath) {
|
||||
for (ServicePaths path : values()) {
|
||||
CallPath callPath = path.path;
|
||||
String callPathInfo = callPath.get();
|
||||
// A rest path can end with a resource-id too.
|
||||
// For example, /rest/cart/1234 should match with /rest/cart
|
||||
if (callPathInfo != null && invokedPath.matches(callPath)) {
|
||||
return callPath;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -15,29 +15,12 @@
|
||||
*/
|
||||
package com.google.gson.wsexample.server;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.example.model.Cart;
|
||||
import com.google.gson.example.model.Order;
|
||||
import com.google.gson.example.model.TypedKeys;
|
||||
import com.google.gson.example.service.SampleJsonService;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.procedural.RequestBody;
|
||||
import com.google.gson.webservice.definition.procedural.RequestBodyGsonConverter;
|
||||
import com.google.gson.webservice.definition.procedural.RequestSpec;
|
||||
import com.google.gson.webservice.definition.procedural.ResponseBody;
|
||||
import com.google.gson.webservice.definition.procedural.ResponseBodyGsonConverter;
|
||||
import com.google.gson.webservice.definition.procedural.ResponseSpec;
|
||||
import com.google.gson.webservice.definition.procedural.WebServiceCallSpec;
|
||||
import com.google.gson.webservice.definition.procedural.WebServiceRequest;
|
||||
import com.google.gson.webservice.definition.procedural.WebServiceResponse;
|
||||
import com.google.gson.wsf.server.procedural.RequestReceiver;
|
||||
import com.google.gson.wsf.server.procedural.ResponseSender;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.google.gson.webservice.definition.CallPath;
|
||||
|
||||
/**
|
||||
* An example servlet that receives JSON web-service requests
|
||||
*
|
||||
@ -45,37 +28,24 @@ import javax.servlet.http.HttpServletResponse;
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MainServlet extends HttpServlet {
|
||||
private final RestDispatcher restDispatcher;
|
||||
private final ProcedureDispatcher procedureDispatcher;
|
||||
|
||||
public MainServlet() {
|
||||
this.restDispatcher = new RestDispatcher();
|
||||
this.procedureDispatcher = new ProcedureDispatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest req, HttpServletResponse res) {
|
||||
WebServiceCallSpec spec = SampleJsonService.PLACE_ORDER;
|
||||
RequestSpec requestSpec = spec.getRequestSpec();
|
||||
ResponseSpec responseSpec = spec.getResponseSpec();
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(RequestBody.class,
|
||||
new RequestBodyGsonConverter(requestSpec.getBodySpec()))
|
||||
.registerTypeAdapter(ResponseBody.class,
|
||||
new ResponseBodyGsonConverter(responseSpec.getBodySpec()))
|
||||
.create();
|
||||
RequestReceiver requestReceiver = new RequestReceiver(gson, requestSpec);
|
||||
WebServiceRequest webServiceRequest = requestReceiver.receive(req);
|
||||
|
||||
Cart cart = webServiceRequest.getBody().get(TypedKeys.RequestBody.CART);
|
||||
String authToken = webServiceRequest.getHeader(TypedKeys.Request.AUTH_TOKEN);
|
||||
|
||||
Order order = placeOrder(cart, authToken);
|
||||
|
||||
// Empty headers per the spec
|
||||
HeaderMap responseHeaders = new HeaderMap.Builder(responseSpec.getHeadersSpec()).build();
|
||||
ResponseBody responseBody = new ResponseBody.Builder(responseSpec.getBodySpec())
|
||||
.put(TypedKeys.ResponseBody.ORDER, order)
|
||||
.build();
|
||||
WebServiceResponse response = new WebServiceResponse(responseHeaders, responseBody);
|
||||
ResponseSender responseSender = new ResponseSender(gson);
|
||||
responseSender.send(res, response);
|
||||
}
|
||||
|
||||
private Order placeOrder(Cart cart, String authToken) {
|
||||
// Create an order, in this case a dummy one.
|
||||
return new Order(cart, "Order123");
|
||||
String servletPath = req.getServletPath();
|
||||
int index = "/wsexampleserver".length();
|
||||
CallPath callPath = new CallPath(servletPath.substring(index));
|
||||
String path = callPath.get();
|
||||
if (path.startsWith("/rest")) {
|
||||
restDispatcher.service(req, res, callPath);
|
||||
} else if (path.startsWith("/procedure")) {
|
||||
procedureDispatcher.service(req, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.gson.wsexample.server;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.example.model.Cart;
|
||||
import com.google.gson.example.model.Order;
|
||||
import com.google.gson.example.model.TypedKeys;
|
||||
import com.google.gson.example.service.SampleJsonService;
|
||||
import com.google.gson.webservice.definition.HeaderMap;
|
||||
import com.google.gson.webservice.definition.procedural.RequestBody;
|
||||
import com.google.gson.webservice.definition.procedural.RequestBodyGsonConverter;
|
||||
import com.google.gson.webservice.definition.procedural.RequestSpec;
|
||||
import com.google.gson.webservice.definition.procedural.ResponseBody;
|
||||
import com.google.gson.webservice.definition.procedural.ResponseBodyGsonConverter;
|
||||
import com.google.gson.webservice.definition.procedural.ResponseSpec;
|
||||
import com.google.gson.webservice.definition.procedural.WebServiceCallSpec;
|
||||
import com.google.gson.webservice.definition.procedural.WebServiceRequest;
|
||||
import com.google.gson.webservice.definition.procedural.WebServiceResponse;
|
||||
import com.google.gson.wsf.server.procedural.RequestReceiver;
|
||||
import com.google.gson.wsf.server.procedural.ResponseSender;
|
||||
|
||||
/**
|
||||
* A dispatcher for all the procedural calls
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
public final class ProcedureDispatcher {
|
||||
public void service(HttpServletRequest req, HttpServletResponse res) {
|
||||
WebServiceCallSpec spec = SampleJsonService.PLACE_ORDER;
|
||||
RequestSpec requestSpec = spec.getRequestSpec();
|
||||
ResponseSpec responseSpec = spec.getResponseSpec();
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(RequestBody.class,
|
||||
new RequestBodyGsonConverter(requestSpec.getBodySpec()))
|
||||
.registerTypeAdapter(ResponseBody.class,
|
||||
new ResponseBodyGsonConverter(responseSpec.getBodySpec()))
|
||||
.create();
|
||||
RequestReceiver requestReceiver = new RequestReceiver(gson, requestSpec);
|
||||
WebServiceRequest webServiceRequest = requestReceiver.receive(req);
|
||||
|
||||
Cart cart = webServiceRequest.getBody().get(TypedKeys.RequestBody.CART);
|
||||
String authToken = webServiceRequest.getHeader(TypedKeys.Request.AUTH_TOKEN);
|
||||
|
||||
Order order = placeOrder(cart, authToken);
|
||||
|
||||
// Empty headers per the spec
|
||||
HeaderMap responseHeaders = new HeaderMap.Builder(responseSpec.getHeadersSpec()).build();
|
||||
ResponseBody responseBody = new ResponseBody.Builder(responseSpec.getBodySpec())
|
||||
.put(TypedKeys.ResponseBody.ORDER, order)
|
||||
.build();
|
||||
WebServiceResponse response = new WebServiceResponse(responseHeaders, responseBody);
|
||||
ResponseSender responseSender = new ResponseSender(gson);
|
||||
responseSender.send(res, response);
|
||||
}
|
||||
|
||||
private Order placeOrder(Cart cart, String authToken) {
|
||||
// Create an order, in this case a dummy one.
|
||||
return new Order(cart, "Order123");
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.gson.wsexample.server;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.example.model.Cart;
|
||||
import com.google.gson.example.model.Order;
|
||||
import com.google.gson.example.service.ServicePaths;
|
||||
import com.google.gson.rest.definition.IDFactory;
|
||||
import com.google.gson.rest.definition.MetaData;
|
||||
import com.google.gson.rest.definition.ResourceMap;
|
||||
import com.google.gson.rest.definition.RestCallSpec;
|
||||
import com.google.gson.rest.definition.RestRequest;
|
||||
import com.google.gson.rest.definition.RestResponse;
|
||||
import com.google.gson.rest.definition.ValueBasedId;
|
||||
import com.google.gson.rest.server.Repository;
|
||||
import com.google.gson.rest.server.RepositoryInMemory;
|
||||
import com.google.gson.rest.server.ResponseBuilderMap;
|
||||
import com.google.gson.rest.server.RestRequestReceiver;
|
||||
import com.google.gson.rest.server.RestResponseBuilder;
|
||||
import com.google.gson.rest.server.RestResponseSender;
|
||||
import com.google.gson.webservice.definition.CallPath;
|
||||
|
||||
/**
|
||||
* A dispatcher for all the REST requests
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
public final class RestDispatcher {
|
||||
private static final double CURRENT_VERSION = 1D;
|
||||
private final ResourceMap resourceMap;
|
||||
private final ResponseBuilderMap responseBuilders;
|
||||
private final RestCallSpec cartSpec;
|
||||
private final RestCallSpec orderSpec;
|
||||
private final Gson gson;
|
||||
|
||||
public RestDispatcher() {
|
||||
this.cartSpec = new RestCallSpec.Builder(ServicePaths.CART.getCallPath(), Cart.class)
|
||||
.setVersion(CURRENT_VERSION)
|
||||
.build();
|
||||
this.orderSpec = new RestCallSpec.Builder(ServicePaths.CART.getCallPath(), Cart.class)
|
||||
.setVersion(CURRENT_VERSION)
|
||||
.build();
|
||||
this.resourceMap = new ResourceMap.Builder()
|
||||
.set(ServicePaths.CART.getCallPath(), cartSpec)
|
||||
.set(ServicePaths.ORDER.getCallPath(), orderSpec)
|
||||
.build();
|
||||
gson = new GsonBuilder()
|
||||
.setVersion(CURRENT_VERSION)
|
||||
.registerTypeAdapter(ValueBasedId.class, new ValueBasedId.GsonTypeAdapter())
|
||||
.registerTypeAdapter(MetaData.class, new MetaData.GsonTypeAdapter())
|
||||
.create();
|
||||
Repository<ValueBasedId<Cart>, Cart> carts =
|
||||
new RepositoryInMemory<ValueBasedId<Cart>, Cart>(ValueBasedId.class, Cart.class);
|
||||
Repository<ValueBasedId<Order>, Order> orders =
|
||||
new RepositoryInMemory<ValueBasedId<Order>, Order>(ValueBasedId.class, Order.class);
|
||||
responseBuilders = new ResponseBuilderMap.Builder()
|
||||
.set(cartSpec.getResourceType(), new RestResponseBuilder<ValueBasedId<Cart>, Cart>(carts))
|
||||
.set(orderSpec.getResourceType(), new RestResponseBuilder<ValueBasedId<Order>, Order>(orders))
|
||||
.build();
|
||||
}
|
||||
|
||||
public IDFactory<ValueBasedId<?>> getIDFactory(RestCallSpec callSpec) {
|
||||
return new IDFactory<ValueBasedId<?>>(ValueBasedId.class, callSpec.getResourceType());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public RestRequest getRestRequest(Gson gson, RestCallSpec callSpec, CallPath callPath,
|
||||
HttpServletRequest request, IDFactory<ValueBasedId<?>> idFactory) {
|
||||
RestRequestReceiver requestReceiver = new RestRequestReceiver(gson, callSpec.getRequestSpec());
|
||||
return requestReceiver.receive(request, idFactory.createId(callPath.getResourceId()));
|
||||
}
|
||||
|
||||
public void service(HttpServletRequest req, HttpServletResponse res, CallPath callPath) {
|
||||
RestCallSpec callSpec = resourceMap.get(callPath).createCopy(callPath);
|
||||
@SuppressWarnings("rawtypes")
|
||||
RestRequestReceiver requestReceiver = new RestRequestReceiver(gson, callSpec.getRequestSpec());
|
||||
IDFactory<ValueBasedId<?>> idFactory = getIDFactory(callSpec);
|
||||
RestRequest<?, ?> restRequest = getRestRequest(gson, callSpec, callPath, req, idFactory);
|
||||
RestResponse.Builder response = new RestResponse.Builder(callSpec.getResponseSpec());
|
||||
RestResponseBuilder responseBuilder = responseBuilders.get(callSpec.getResourceType());
|
||||
responseBuilder.buildResponse(callSpec, restRequest, response);
|
||||
RestResponse restResponse = response.build();
|
||||
RestResponseSender responseSender = new RestResponseSender(gson);
|
||||
responseSender.send(res, restResponse);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.gson.rest.server;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.rest.definition.ID;
|
||||
import com.google.gson.rest.definition.RestCallSpec;
|
||||
import com.google.gson.rest.definition.RestResource;
|
||||
|
||||
/**
|
||||
* A map of {@link RestCallSpec}, {@link RestResponseBuilder} to help figure out which
|
||||
* {@link RestResponseBuilder} to use for a {@link RestCallSpec}.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
public final class ResponseBuilderMap {
|
||||
public static final class Builder {
|
||||
private final Map<Type, RestResponseBuilder<?, ?>> map =
|
||||
new HashMap<Type, RestResponseBuilder<?, ?>>();
|
||||
|
||||
public <I extends ID, R extends RestResource<I, R>> Builder set(
|
||||
Type resourceType, RestResponseBuilder<I, R> responseBuilder) {
|
||||
map.put(resourceType, responseBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilderMap build() {
|
||||
return new ResponseBuilderMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<Type, RestResponseBuilder<?, ?>> map;
|
||||
|
||||
public ResponseBuilderMap(Map<Type, RestResponseBuilder<?, ?>> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public RestResponseBuilder<?, ?> get(Type resourceType) {
|
||||
return (RestResponseBuilder<?, ?>)map.get(resourceType);
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import com.google.gson.rest.definition.RestResource;
|
||||
import com.google.gson.rest.definition.RestResponse;
|
||||
import com.google.gson.webservice.definition.HttpMethod;
|
||||
|
||||
public abstract class RestResponseBuilder<I extends ID, R extends RestResource<I, R>> {
|
||||
public class RestResponseBuilder<I extends ID, R extends RestResource<I, R>> {
|
||||
protected final Repository<I, R> resources;
|
||||
|
||||
public RestResponseBuilder(Repository<I, R> resources) {
|
||||
|
Loading…
Reference in New Issue
Block a user