Enhanced support for JAX-RS annotations allowing @Path({id}) to be mapped to an operation expecting a id paramenter. This gives basic support for get and delete operations on a given resource

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@939744 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
lresende 2010-04-30 17:15:53 +00:00
parent 80ca73f521
commit da0aff02c1
6 changed files with 116 additions and 37 deletions
sca-java-2.x/trunk/modules/binding-rest-runtime/src
main/java/org/apache/tuscany/sca/binding/rest
test/java/services/store

View file

@ -19,17 +19,22 @@
package org.apache.tuscany.sca.binding.rest.operationselector.jaxrs.provider;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.List;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import org.apache.tuscany.sca.common.http.HTTPContext;
import org.apache.tuscany.sca.common.http.HTTPUtil;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
import org.apache.tuscany.sca.invocation.Interceptor;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
@ -69,13 +74,34 @@ public class JAXRSOperationSelectorInterceptor implements Interceptor {
}
public Message invoke(Message msg) {
HTTPContext bindingContext = (HTTPContext) msg.getBindingContext();
Operation operation = findOperation(bindingContext.getHttpRequest().getMethod());
msg.setOperation(operation);
return getNext().invoke(msg);
try {
HTTPContext bindingContext = (HTTPContext) msg.getBindingContext();
String path = URLDecoder.decode(HTTPUtil.getRequestPath(bindingContext.getHttpRequest()), "UTF-8");
if(path.startsWith("/")) {
path = path.substring(1);
}
List<Operation> operations = filterOperationsByHttpMethod(interfaceContract, bindingContext.getHttpRequest().getMethod());
Operation operation = findOperation(path, operations);
final JavaOperation javaOperation = (JavaOperation) operation;
final Method method = javaOperation.getJavaMethod();
if(path != null && path.length() > 0) {
if(method.getAnnotation(Path.class) != null) {
msg.setBody(new Object[]{path});
}
}
msg.setOperation(operation);
return getNext().invoke(msg);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
/**
@ -84,7 +110,7 @@ public class JAXRSOperationSelectorInterceptor implements Interceptor {
* @param http_method
* @return
*/
private Operation findOperation(String http_method) {
private static List<Operation> filterOperationsByHttpMethod(InterfaceContract interfaceContract, String http_method) {
List<Operation> operations = null;
if(http_method.equalsIgnoreCase("get")) {
@ -97,13 +123,35 @@ public class JAXRSOperationSelectorInterceptor implements Interceptor {
operations = (List<Operation>) interfaceContract.getInterface().getAttributes().get(DELETE.class);
}
Operation result = null;
if(operations != null) {
if(! operations.isEmpty()) {
result = operations.get(0);
return operations;
}
/**
* Find the operation from the component service contract
* @param componentService
* @param http_method
* @return
*/
private Operation findOperation(String path, List<Operation> operations) {
Operation operation = null;
for(Operation op : operations) {
final JavaOperation javaOperation = (JavaOperation) op;
final Method method = javaOperation.getJavaMethod();
if(path != null && path.length() > 0) {
if(method.getAnnotation(Path.class) != null) {
operation = op;
break;
}
} else {
if(method.getAnnotation(Path.class) == null) {
operation = op;
break;
}
}
}
return result;
return operation;
}
}

View file

@ -55,6 +55,7 @@ public class RESTBindingListenerServlet extends HttpServlet {
transient private Binding binding;
transient private Invoker bindingInvoker;
private Invoker invoker;
private Invoker getInvoker;
private Invoker conditionalGetInvoker;
private Invoker putInvoker;
@ -421,6 +422,16 @@ public class RESTBindingListenerServlet extends HttpServlet {
}
}
public void setInvoker(Invoker invoker) {
this.invoker = invoker;
}
public Invoker getInvoker() {
return invoker;
}
/**
* @return the getInvoker
*/

View file

@ -98,7 +98,6 @@ public class RESTServiceBindingProvider implements EndpointProvider {
}
//clone the service contract to avoid databinding issues
try {
this.serviceContract = (InterfaceContract) service.getInterfaceContract().clone();
@ -119,45 +118,42 @@ public class RESTServiceBindingProvider implements EndpointProvider {
Invoker bindingInvoker = endpoint.getBindingInvocationChain().getHeadInvoker();
bindingListenerServlet = new RESTBindingListenerServlet(binding, bindingInvoker, messageFactory );
for (InvocationChain invocationChain : endpoint.getInvocationChains()) {
Operation operation = invocationChain.getTargetOperation();
Invoker serviceInvoker = invocationChain.getHeadInvoker();
String operationName = operation.getName();
if (operationName.equals("get")) {
Invoker getInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setGetInvoker(getInvoker);
if (binding.getOperationSelector() != null || binding.getRequestWireFormat() != null) {
bindingListenerServlet.setInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("get")) {
bindingListenerServlet.setGetInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalGet")) {
Invoker conditionalGetInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setConditionalGetInvoker(conditionalGetInvoker);
bindingListenerServlet.setConditionalGetInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("delete")) {
Invoker deleteInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setDeleteInvoker(deleteInvoker);
bindingListenerServlet.setDeleteInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalDelete")) {
Invoker conditionalDeleteInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setConditionalDeleteInvoker(conditionalDeleteInvoker);
bindingListenerServlet.setConditionalDeleteInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("put")) {
Invoker putInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setPutInvoker(putInvoker);
bindingListenerServlet.setPutInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalPut")) {
Invoker conditionalPutInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setConditionalPutInvoker(conditionalPutInvoker);
bindingListenerServlet.setConditionalPutInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("post")) {
Invoker postInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setPostInvoker(postInvoker);
bindingListenerServlet.setPostInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("conditionalPost")) {
Invoker conditionalPostInvoker = invocationChain.getHeadInvoker();
bindingListenerServlet.setConditionalPostInvoker(conditionalPostInvoker);
bindingListenerServlet.setConditionalPostInvoker(serviceInvoker);
servlet = bindingListenerServlet;
} else if (operationName.equals("service")) {
Invoker serviceInvoker = invocationChain.getHeadInvoker();
servlet = new RESTServiceListenerServlet(binding, serviceInvoker, messageFactory);
break;
}
}
}
if (servlet == null) {
throw new IllegalStateException("No get or service method found on the service");

View file

@ -21,6 +21,7 @@ package org.apache.tuscany.sca.binding.rest.wireformat.json.provider;
import java.io.CharArrayWriter;
import org.apache.tuscany.sca.common.http.HTTPContext;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.invocation.Interceptor;
import org.apache.tuscany.sca.invocation.Invoker;
@ -49,8 +50,10 @@ public class JSONWireFormatInterceptor implements Interceptor {
}
public Message invoke(Message msg) {
HTTPContext bindingContext = (HTTPContext) msg.getBindingContext();
try {
if(msg.getBody() != null) {
if(bindingContext.getHttpRequest().getMethod().equalsIgnoreCase("get") == false && bindingContext.getHttpRequest().getMethod().equalsIgnoreCase("delete") == false && msg.getBody() != null) {
Object[] args = msg.getBody();
CharArrayWriter data = (CharArrayWriter) args[0];

View file

@ -19,9 +19,12 @@
package services.store;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.oasisopen.sca.annotation.Remotable;
@ -30,11 +33,19 @@ import org.oasisopen.sca.annotation.Remotable;
public interface Catalog {
@GET
Item[] get();
Item[] getItem();
@GET
@Path("{id}")
Item getItemById(@PathParam("id") String itemId);
@POST
void addItem(Item item);
@PUT
void updateItem(Item item);
@DELETE
@Path("{id}")
void deleteItem(@PathParam("id") String itemId);
}

View file

@ -46,12 +46,16 @@ public class FruitsCatalogImpl implements Catalog {
catalog.put("Pear", new Item("Pear", currencySymbol + currencyConverter.getConversion("USD", currencyCode, 1.55)));
}
public Item[] get() {
public Item[] getItem() {
Item[] catalogArray = new Item[catalog.size()];
catalog.values().toArray(catalogArray);
return catalogArray;
}
public Item getItemById(String itemId) {
return catalog.get(itemId);
}
public void addItem(Item item) {
catalog.put(item.getName(),item);
}
@ -61,4 +65,10 @@ public class FruitsCatalogImpl implements Catalog {
catalog.put(item.getName(), item);
}
}
public void deleteItem(String itemId) {
if(catalog.get(itemId) != null) {
catalog.remove(itemId);
}
}
}