This is an automated email from the ASF dual-hosted git repository.
grv pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-plugins.git
The following commit(s) were added to refs/heads/trunk by this push:
new 6ac1f28 Implemented: Add support to read and register resources
defined in XML DSL(OFBIZ-11995)
6ac1f28 is described below
commit 6ac1f284915ff1de659bda944e26b90bdab2f75c
Author: Girish Vasmatkar <[email protected]>
AuthorDate: Wed Sep 16 18:21:27 2020 +0530
Implemented: Add support to read and register resources defined in XML
DSL(OFBIZ-11995)
---
.../apache/ofbiz/ws/rs/core/OFBizApiConfig.java | 40 ++++
.../ofbiz/ws/rs/process/RestRequestHandler.java | 256 +++++++++++++++++++++
.../ofbiz/ws/rs/process/ServiceRequestHandler.java | 102 ++++++++
3 files changed, 398 insertions(+)
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
index 911c880..5a168fe 100644
---
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
@@ -21,19 +21,29 @@ package org.apache.ofbiz.ws.rs.core;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.ws.rs.core.MediaType;
+
import org.apache.ofbiz.base.component.ComponentConfig;
import org.apache.ofbiz.base.component.ComponentException;
import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.ws.rs.model.ModelApi;
import org.apache.ofbiz.ws.rs.model.ModelApiReader;
+import org.apache.ofbiz.ws.rs.model.ModelOperation;
+import org.apache.ofbiz.ws.rs.model.ModelResource;
+import org.apache.ofbiz.ws.rs.process.ServiceRequestHandler;
+import org.apache.ofbiz.ws.rs.security.Secured;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.model.Resource;
+import org.glassfish.jersey.server.model.ResourceMethod;
public class OFBizApiConfig extends ResourceConfig {
private static final String MODULE = OFBizApiConfig.class.getName();
@@ -58,6 +68,7 @@ public class OFBizApiConfig extends ResourceConfig {
private void registerDSLResources() {
loadApiDefinitions();
+ traverseAndRegisterApiDefinitions();
}
private void loadApiDefinitions() {
@@ -78,4 +89,33 @@ public class OFBizApiConfig extends ResourceConfig {
}
});
}
+
+ private void traverseAndRegisterApiDefinitions() {
+ if (UtilValidate.isEmpty(MICRO_APIS)) {
+ Debug.logInfo("No API defintion to process", MODULE);
+ return;
+ }
+ MICRO_APIS.forEach((k, v) -> {
+ Debug.logInfo("Registring Resource Definitions from API - " + k,
MODULE);
+ List<ModelResource> resources = v.getResources();
+ resources.forEach(modelResource -> {
+ Resource.Builder resourceBuilder =
Resource.builder(modelResource.getPath()).name(modelResource.getName());
+ for (ModelOperation op : modelResource.getOperations()) {
+ if (UtilValidate.isEmpty(op.getPath())) { // Add the
method to the parent resource
+ ResourceMethod.Builder methodBuilder =
resourceBuilder.addMethod(op.getVerb().toUpperCase());
+
methodBuilder.produces(MediaType.APPLICATION_JSON).nameBindings(Secured.class);
+ String serviceName = op.getService();
+ methodBuilder.handledBy(new
ServiceRequestHandler(serviceName));
+ } else {
+ Resource.Builder childResourceBuilder =
resourceBuilder.addChildResource(op.getPath());
+ ResourceMethod.Builder childResourceMethodBuilder =
childResourceBuilder.addMethod(op.getVerb().toUpperCase());
+
childResourceMethodBuilder.produces(MediaType.APPLICATION_JSON).nameBindings(Secured.class);
+ String serviceName = op.getService();
+ childResourceMethodBuilder.handledBy(new
ServiceRequestHandler(serviceName));
+ }
+ }
+ registerResources(resourceBuilder.build());
+ });
+ });
+ }
}
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java
new file mode 100644
index 0000000..0309cdf
--- /dev/null
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/RestRequestHandler.java
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.ofbiz.ws.rs.process;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.glassfish.jersey.message.internal.MediaTypes;
+import org.glassfish.jersey.process.Inflector;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.ExtendedUriInfo;
+
+public abstract class RestRequestHandler implements
Inflector<ContainerRequestContext, Response> {
+
+ @Inject
+ private HttpHeaders httpHeaders;
+
+ @Inject
+ private UriInfo uriInfo;
+
+ @Inject
+ private ExtendedUriInfo extendedUriInfo;
+
+ @Inject
+ private ResourceInfo resourceInfo;
+
+ @Inject
+ private ServletContext servletContext;
+
+ @Inject
+ private HttpServletRequest httpRequest;
+
+ /**
+ * @return the httpHeaders
+ */
+ protected HttpHeaders getHttpHeaders() {
+ return httpHeaders;
+ }
+
+ /**
+ * @return the uriInfo
+ */
+ protected UriInfo getUriInfo() {
+ return uriInfo;
+ }
+
+ /**
+ * @return the extendedUriInfo
+ */
+ protected ExtendedUriInfo getExtendedUriInfo() {
+ return extendedUriInfo;
+ }
+
+ /**
+ * @return the resourceInfo
+ */
+ protected ResourceInfo getResourceInfo() {
+ return resourceInfo;
+ }
+
+ /**
+ * @return the servletContext
+ */
+ protected ServletContext getServletContext() {
+ return servletContext;
+ }
+
+ /**
+ * @return the httpRequest
+ */
+ protected HttpServletRequest getHttpRequest() {
+ return httpRequest;
+ }
+
+ /**
+ * @param ctx
+ * @return
+ */
+ @Override
+ public Response apply(ContainerRequestContext ctx) {
+ // TODO Auto-generated method stub
+ String method = ctx.getMethod();
+ switch (method) {
+ case HttpMethod.POST:
+ return doPost(ctx);
+ case HttpMethod.GET:
+ return doGet(ctx);
+ case HttpMethod.DELETE:
+ return doDelete(ctx);
+ case HttpMethod.PUT:
+ return doPut(ctx);
+ case HttpMethod.PATCH:
+ return doPatch(ctx);
+ }
+ return null;
+ }
+
+ /**
+ * @param data
+ * @param arguments
+ * @return
+ */
+ protected abstract Response execute(ContainerRequestContext data,
Map<String, Object> arguments);
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ protected Map<String, Object> extractRequestBody(ContainerRequestContext
requestContext) {
+ if (requestContext instanceof ContainerRequest) {
+ ContainerRequest request = (ContainerRequest) requestContext;
+ if (requestContext.hasEntity()) {
+ request.bufferEntity();
+ if (isJson(requestContext)) {
+ Map<String, Object> entity = request.readEntity(Map.class);
+ if (entity == null) {
+ return Collections.emptyMap();
+ }
+ return entity;
+ }
+ }
+ }
+ return Collections.emptyMap();
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ protected Map<String, Object>
extractPathParameters(ContainerRequestContext requestContext) {
+ return extract(requestContext.getUriInfo().getPathParameters());
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ protected Map<String, Object>
extractQueryParameters(ContainerRequestContext requestContext) {
+ return extract(requestContext.getUriInfo().getQueryParameters());
+ }
+
+ /**
+ * @param multivaluedMap
+ * @return
+ */
+ protected Map<String, Object> extract(MultivaluedMap<String, String>
multivaluedMap) {
+ Map<String, Object> result = new HashMap<>();
+ multivaluedMap.forEach((name, values) -> {
+ if (UtilValidate.isNotEmpty(values)) {
+ result.put(name, (values.size() != 1) ? values :
values.get(0));
+ }
+ });
+ return result;
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ private boolean isJson(ContainerRequestContext requestContext) {
+ final MediaType mediaType = requestContext.getMediaType();
+ if (UtilValidate.isNotEmpty(mediaType) &&
MediaTypes.typeEqual(mediaType, MediaType.APPLICATION_JSON_TYPE)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ private Response doGet(ContainerRequestContext requestContext) {
+ Map<String, Object> arguments = new HashMap<>();
+ arguments.putAll(extractPathParameters(requestContext));
+ arguments.putAll(extractQueryParameters(requestContext));
+ return execute(requestContext, arguments);
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ private Response doPost(ContainerRequestContext requestContext) {
+ Map<String, Object> arguments = new HashMap<>();
+ arguments.putAll(extractRequestBody(requestContext));
+ arguments.putAll(extractPathParameters(requestContext));
+ arguments.putAll(extractQueryParameters(requestContext));
+ return execute(requestContext, arguments);
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ private Response doPut(ContainerRequestContext requestContext) {
+ Map<String, Object> arguments = new HashMap<>();
+ arguments.putAll(extractRequestBody(requestContext));
+ arguments.putAll(extractPathParameters(requestContext));
+ arguments.putAll(extractQueryParameters(requestContext));
+ return execute(requestContext, arguments);
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ private Response doPatch(ContainerRequestContext requestContext) {
+ Map<String, Object> arguments = new HashMap<>();
+ arguments.putAll(extractRequestBody(requestContext));
+ arguments.putAll(extractPathParameters(requestContext));
+ arguments.putAll(extractQueryParameters(requestContext));
+ return execute(requestContext, arguments);
+ }
+
+ /**
+ * @param requestContext
+ * @return
+ */
+ private Response doDelete(ContainerRequestContext requestContext) {
+ Map<String, Object> arguments = new HashMap<>();
+ arguments.putAll(extractPathParameters(requestContext));
+ arguments.putAll(extractQueryParameters(requestContext));
+ return execute(requestContext, arguments);
+ }
+}
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java
new file mode 100644
index 0000000..51ce63b
--- /dev/null
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/process/ServiceRequestHandler.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.ofbiz.ws.rs.process;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Response;
+
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.service.DispatchContext;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ModelParam;
+import org.apache.ofbiz.service.ModelService;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.apache.ofbiz.ws.rs.util.RestApiUtil;
+
+public final class ServiceRequestHandler extends RestRequestHandler {
+
+ private String service;
+
+ public ServiceRequestHandler(String service) {
+ this.service = service;
+ }
+
+ /**
+ * @param data
+ * @return
+ * @throws GenericServiceException
+ */
+ @Override
+ protected Response execute(ContainerRequestContext data, Map<String,
Object> arguments) {
+ LocalDispatcher dispatcher = (LocalDispatcher)
getServletContext().getAttribute("dispatcher");
+ Map<String, Object> serviceContext = null;
+ try {
+ serviceContext =
dispatcher.getDispatchContext().makeValidContext(service, ModelService.IN_PARAM,
+ arguments);
+ } catch (GenericServiceException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ ModelService svc = getModelService(dispatcher.getDispatchContext());
+ GenericValue userLogin = (GenericValue)
getHttpRequest().getAttribute("userLogin");
+ serviceContext.put("userLogin", userLogin);
+ Map<String, Object> result = null;
+ try {
+ result = dispatcher.runSync(service, serviceContext);
+ } catch (GenericServiceException e) {
+ throw new InternalServerErrorException(e.getMessage());
+ }
+ Map<String, Object> responseData = new LinkedHashMap<>();
+ if (ServiceUtil.isSuccess(result)) {
+ Set<String> outParams = svc.getOutParamNames();
+ for (String outParamName : outParams) {
+ ModelParam outParam = svc.getParam(outParamName);
+ if (!outParam.isInternal()) {
+ Object value = result.get(outParamName);
+ if (UtilValidate.isNotEmpty(value)) {
+ responseData.put(outParamName, value);
+ }
+ }
+ }
+ return RestApiUtil.success((String)
result.get(ModelService.SUCCESS_MESSAGE), responseData);
+ } else {
+ return
RestApiUtil.error(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
+ Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase(),
+ (String) result.get(ModelService.ERROR_MESSAGE));
+ }
+ }
+
+ private ModelService getModelService(DispatchContext dispatchContext) {
+ ModelService svc = null;
+ try {
+ svc = dispatchContext.getModelService(service);
+ } catch (GenericServiceException gse) {
+ throw new NotFoundException(gse.getMessage());
+ }
+ return svc;
+ }
+}