...
This tutorial documents the steps to expose an ofbiz service using REST. The ofbiz ping service is exposed. The ping service returns a copy on the input message to the response. If the input message is null, ping returns PONG.
This is related: REST Service Implementation
The following steps show Apache wink was chosen as the REST implementation purely on the basis that it is an apache project. on base of Apache Wink.
Info | ||
---|---|---|
| ||
As of April 2017, Apache Wink is retired. For new REST implementations, it is not recommended to use it. This tutorial does not work with OFBIz Release 16.11 and above. This page will be either updated with an alternative or deprecated in the future. |
Assumptions
This tutorial assumes you have followed the ofbiz developer tutorial: http://cwiki.apache.org/confluence/x/cQFk
Step 1 - Create a new component
Code Block |
---|
ant create-component
Component name: restcomponent
Component resource name: RestComponent
Webapp name: restcomponent
Base permission: RESTCOMPONENT
|
Step 2 - Grab
...
Apache Wink*
Download apache wink . I used httpfrom here: https://wwwwink.apache.org/dyn/closer.cgi/incubator/wink/1.0-incubating/apache-wink-1.0-incubating.zipdownloads.html
Unzip and copy lib/* and dist/* to your ofbiz component restcomponent/lib
\* read this https://dzone.com/articles/apache-cxf-vs-apache-axis-vs for a comparison between 2 Apache solutions regarding REST and Spring WS
Step 3 - Create java files and update web.xml
The steps followed were taken from the wink user (i.e. developer) guide): http://incubator.apache.org/wink/1.0/Apache_Wink_User_Guide.pdf: apache-wink-developer-guide.html
In the folder restcomponent/src/restcomponent, create:
PingApplication.java
PingResource.java
Code Block |
---|
package restcomponent;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class PingApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(PingResource.class);
return classes;
}
}
|
Code Block |
---|
package restcomponent;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javolution.util.FastMap;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.entity.DelegatorFactory;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.service.GenericDispatcher;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceUtil;
@Path("/ping")
public class PingResource {
@GET
@Produces("text/plain")
@Path("{message}")
public Response sayHello(@PathParam("message") String message) {
GenericDelegator delegator = (GenericDelegator) DelegatorFactory.getDelegator("default");
LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher("default",delegator);
Map<String, String> paramMap = UtilMisc.toMap( "message", message );
Map<String, Object> result = FastMap.newInstance();
try {
result = dispatcher.runSync("ping", paramMap);
} catch (GenericServiceException e1) {
Debug.logError(e1, PingResource.class.getName());
return Response.serverError().entity(e1.toString()).build();
}
if (ServiceUtil.isSuccess(result)) {
return Response.ok("RESPONSE: *** " + result.get("message") + " ***").type("text/plain").build();
}
if (ServiceUtil.isError(result) || ServiceUtil.isFailure(result)) {
return Response.serverError().entity(ServiceUtil.getErrorMessage(result)).build();
}
// shouldn't ever get here ... should we?
throw new RuntimeException("Invalid ");
}
}
|
Update restcomponent/webapp/restcomponent/WEB-INF/web.xml:
Code Block |
---|
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>Open For Business - RestComponent Component</display-name>
<description>RestComponent Component of the Open For Business Project</description>
<servlet>
<servlet-name>restServlet</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>restcomponent.PingApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
|
...
Turn on auth="true" in framework/common/servicedef/services_test.xml
Code Block |
---|
<service name="ping" engine="java" export="true" require-new-transaction="true"
location="org.ofbiz.common.CommonServices" invoke="ping" auth="true">
|
Now change PingResource to take http headers with the login.username and login.password and pass the values to the service.
Code Block |
---|
package restcomponent;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javolution.util.FastMap;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.entity.DelegatorFactory;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.service.GenericDispatcher;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceUtil;
@Path("/ping")
public class PingResource {
@Context
HttpHeaders headers;
@GET
@Produces("text/plain")
@Path("{message}")
public Response sayHello(@PathParam("message") String message) {
String username = null;
String password = null;
try {
username = headers.getRequestHeader("login.username").get(0);
password = headers.getRequestHeader("login.password").get(0);
} catch (NullPointerException e) {
return Response.serverError().entity("Problem reading http header(s): login.username or login.password").build();
}
if (username == null || password == null) {
return Response.serverError().entity("Problem reading http header(s): login.username or login.password").build();
}
GenericDelegator delegator = (GenericDelegator) DelegatorFactory.getDelegator("default");
LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher("default",delegator);
Map<String, String> paramMap = UtilMisc.toMap(
"message", message,
"login.username", username,
"login.password", password
);
Map<String, Object> result = FastMap.newInstance();
try {
result = dispatcher.runSync("ping", paramMap);
} catch (GenericServiceException e1) {
Debug.logError(e1, PingResource.class.getName());
return Response.serverError().entity(e1.toString()).build();
}
if (ServiceUtil.isSuccess(result)) {
return Response.ok("RESPONSE: *** " + result.get("message") + " ***").type("text/plain").build();
}
if (ServiceUtil.isError(result) || ServiceUtil.isFailure(result)) {
return Response.serverError().entity(ServiceUtil.getErrorMessage(result)).build();
}
// shouldn't ever get here ... should we?
throw new RuntimeException("Invalid ");
}
}
|
Now trying accessing with web browser:
Code Block |
---|
Access to the specified resource () has been forbidden.
|
...