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:
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
operationselector/jaxrs/provider
provider
wireformat/json/provider
test/java/services/store
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue