Quantcast
Channel: SCN : All Content - SAP Business Process Management
Viewing all articles
Browse latest Browse all 887

How to Start a BPM Process using BPM API as a RESTful service.

$
0
0

This guide provides instructions on how to start SAP BPM Process using BPM API as a Restful Service.

 

Applies to:

This Document Holds good for all CE 7.3 SP05 onward. This service can be called from UI5 Screen as an Ajax call.

Please note that from 7.31 SP11 onward you can also use the standard BPM OData service to starting processes as mentioned byChristian Loos.

 

Special Thanks to Christian Loos  for commenting & Andre Backofen for the telling me about the Exact SP form which Starting Process is possible.


Summary:

This guide describes step-by-step how to Start a BPM Process using BPM API as a rest full service.


About Me:

Piyas Kumar Das

As a Sr. Netweaver Consultant, I've been undertaking consulting assignments leveraging on my undermentioned NetWeaver skills.

  • Business Process Management (SAP NW BPM)
  • Restful Services using BPM api to be used in UI5 Screens.
  • SAP Web Dynpro Java (SAP WD4J)
  • SAP Business Rules Management (SAP BRMS)
  • SAP Composit Application Framework (SAP CAF)
  • Master Data Management (SAP NW MDM)
  • Enterprise Portal (SAP EP)
  • Services creation using NWDS (SAP EJB)
  • Enterprise SOA


We will be discussing following points in detail in this document -


  1. Adding Libraries.
  2. Setting up the foundation for using Libraries.
  3. Creating Deploy-able Object.
  4. Accessing the methods exposed.
  5. Testing your REST services


Adding Libraries:


Step 1 : Download the Libraries using the below link:

Download Jars.


Step 2 : Create a new DC of type “External Library” and paste the jars into the “libraries” folder of the DC.

1.jpg

Step 3 : Expose the added libraries as public parts of type “Compilation” and “Assembly”. To do that, go to "Component Properties" go to "Public Parts" and right click and select "Manage Entities". Expand the Archive and select all the Jar's for both the public parts.

1.jpg

1.jpg

Step 4 : Create an Enterprise Application DC and add the External library DC as a dependency.

1.jpg

Step 5 : In the Enterprise Application DC, create a public part of type “Compilation” and add the compilation type public part from the External library DC as the referenced entity using the “Referenced entities” option in the right click context menu of the public part as shown below. Finally build the DC.

1.jpg

Setting up the foundation for using Library:

Step 1 : Create a new DC of type "Web Module".

1.jpg

Step 2 : Define a dependency between the Web Module and the library DC. Add only the “api” public part from the External library DC to the Web module DC.

1.jpg

Step 3 : Create 2 packages (1 for Business Objects, 1 for the Restful Services)

1.jpg

Step 4 : Create Business Objects as shown below:

import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Material {  protected String material;  protected String industrySector;  protected String materialType;  protected String description;
public String getMaterial() {  return material;  }  public void setMaterial(String material) {  this.material = material;  }  public String getIndustrySector() {  return industrySector;  }  public void setIndustrySector(String industrySector) {  this.industrySector = industrySector;  }  public String getMaterialType() {  return materialType;  }  public void setMaterialType(String materialType) {  this.materialType = materialType;  }  public String getDescription() {  return description;  }
}

Step 5 : Create a restful service class file and write a code as shown below:

import java.io.StringReader;
import java.net.URI;
import java.util.Iterator;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import bo.Material;
import com.sap.bpm.api.BPMFactory;
import com.sap.bpm.exception.api.BPMException;
import com.sap.bpm.pm.api.ProcessDefinition;
import com.sap.bpm.pm.api.ProcessDefinitionManager;
import com.sap.bpm.pm.api.ProcessStartEvent;
import com.sap.bpm.pm.api.ProcessStartManager;
import com.sap.bpm.tm.api.Status;
import com.sap.bpm.tm.api.TaskAbstract;
import com.sap.bpm.tm.api.TaskDetail;
import com.sap.bpm.tm.api.TaskInstanceManager;
import com.sap.tc.logging.Location;
import commonj.sdo.DataObject;
@Path("/MaterialCreationService")
@Produces({MediaType.APPLICATION_XML})
public class MaterialCreationToRestService {  private static final Location location = Location.getLocation(MaterialCreationToRestService.class);  private final String PRE_TASK_URI = "bpm://bpm.sap.com/task-instance/";  @Path("/startMaterialCreationProcess")  @POST  @Produces( { MediaType.APPLICATION_JSON })  @Consumes( { MediaType.APPLICATION_JSON })  public String startMaterialCreationProcess(MaterialCreation materialCreation) throws Exception {  try {  ProcessDefinitionManager processDefinitionManager = BPMFactory.getProcessDefinitionManager();  ProcessDefinition processDefinition = processDefinitionManager.getActiveProcessDefinition("demo.sap.com", "mat~create~bpm", "Material_Creation");  ProcessStartManager processStartManager = BPMFactory.getProcessStartManager();  Set<ProcessStartEvent> processStartEvents = processStartManager.getProcessStartEvents(processDefinition.getId());  ProcessStartEvent processStartEvent = processStartEvents.iterator().next();  DataObject processStartDataObject = processStartManager.createDataObjectForStartEvent(processStartEvent);  setMaterialCreationToDataObject(materialCreation, processStartDataObject);  URI processInstanceId = processStartManager.startProcess(processStartEvent, processStartDataObject);  return processInstanceId +" process successfully started";  } catch (Exception e) {  location.debugT("Error while Starting BPM process"+e);  throw e;  }  }  private void setMaterialCreationToDataObject(MaterialCreation materialCreation, DataObject pDataObject)  {  if(materialCreation == null || pDataObject == null)  return;  pDataObject.set("Material", materialCreation.getMaterial());  pDataObject.set("IndustrySector", materialCreation.getIndustrySector());  pDataObject.set("MaterialType", materialCreation.getMaterialType());  pDataObject.set("Description", materialCreation.getDescription());  }
}
  • The Following code is very important as the "vendor name" , "deploy dc name" and "process name" is set in the BPM API.1.jpg
  • The "deploy dc name" / "deploy-able DC Name" can be got from:1.jpg


Note : Key points to be noted in this class.

  1. All Plain Old Java objects (POJOs) used as a part of method signature in this class must be annotated with @XMLRootElement
  2. @Path annotation at the class level is used to indicate the URL identifier in which you would like to expose the class
  3. Use the @GET and @POST annotations at the class level to define which methods needs to be exposed how. Typically, @GET is used when the method in the class has to get an existing data from a data source (ex: get details of a customer from DB) and @POST is used when the given data has to be posted / saved to the data source (ex: DB level create, update, delete).
  4. @Path annotation at the method level with the value placed inside “{value}/” is used to either specify the query parameter in the REST service (for ex: Say you need to pass the customer id to the service to get the customer details). Refer method getObjectDetails in the sample class given above.
  5. @Path annotation at the method level with a plain value is used to expose the method name in the REST service (for ex: Say you need to expose an update method to get the object data from UI.) Refer method changeObjectDetails in the sample class given above.
  6. @Produces and @Consumes annotations are used specify what content types the methods in the REST service would produce and consume respectively. Typically for UI5, it can be set to MediaType.APPLICATION_JSON.

 

 

Step 6 : open the web.xml file and fill in the relevant sections as shown below.

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  <display-name>mat_create_rest_web</display-name>  <welcome-file-list>    <welcome-file>index.html</welcome-file>    <welcome-file>index.htm</welcome-file>    <welcome-file>index.jsp</welcome-file>    <welcome-file>default.html</welcome-file>    <welcome-file>default.htm</welcome-file>    <welcome-file>default.jsp</welcome-file>  </welcome-file-list>  <servlet>    <servlet-name>Mat_Create_Rest_Servlet</servlet-name>    <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>    <init-param>      <param-name>jaxrs.serviceClasses</param-name>      <param-value>rest.converter.MaterialCreationToRestService</param-value>    </init-param>    <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>    <servlet-name>Mat_Create_Rest_Servlet</servlet-name>    <url-pattern>/rest/*</url-pattern>  </servlet-mapping>  <security-role>    <description>Everyone</description>    <role-name>Everyone</role-name>  </security-role>  <security-constraint>    <web-resource-collection>      <web-resource-name>Mat_Create_Rest_Servlet</web-resource-name>      <url-pattern>*</url-pattern>    </web-resource-collection>    <auth-constraint>      <role-name>Everyone</role-name>    </auth-constraint>    <user-data-constraint>      <transport-guarantee>NONE</transport-guarantee>    </user-data-constraint>  </security-constraint>  <login-config>    <auth-method>BASIC</auth-method>    <realm-name>Demo</realm-name>  </login-config></web-app>
  • <display-name> - Provide the display name you need for the Web Module DC
  • <servlet-name> - any name. For ex: “Vendor “for Vendor master process.
  • <servlet-class> - set it to com.sun.jersey.spi.container.servlet.ServletContainer
  • <param-name> - set it to com.sun.jersey.config.property.packages
  • <param-value> - set it to the package in which you’ve placed the EJBInjectableProvide.java
  • <load-on-startup> - set it to 1
  • <servlet-name> - same name as specified for <servlet-name> under the tag <servlet>
  • <url-pattern> - identifier that you need in the URL of the REST service. Can be any string with a “/” before and after the identifier and a * in the end. Ex: “/rest/*”
  • <description> - set it to Everyone
  • <role-name> - set it to Everyone
  • <web-resource-name> - same name as specified for <servlet-name> under the tag <servlet>
  • <url-pattern> - set it to *
  • <role-name> - set it to Everyone
  • <transport-guarantee> - set it to NONE
  • <auth-method> - set it to BASIC
  • <realm-name> - set it to Demo


Step 7 : Open web-j2ee-engine.xml file and fill in the relevant sections as shown below.

<?xml version="1.0" encoding="UTF-8"?><web-j2ee-engine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="web-j2ee-engine.xsd">  <spec-version>2.4</spec-version>  <security-role-map>            <role-name>Everyone</role-name>            <server-role-name>Everyone</server-role-name>      </security-role-map>      <login-module-configuration>            <login-module-stack>                  <login-module>                        <login-module-name>EvaluateTicketLoginModule</login-module-name>                        <flag>SUFFICIENT</flag>                  </login-module>                  <login-module>                        <login-module-name>EvaluateAssertionTicketLoginModule</login-module-name>                        <flag>SUFFICIENT</flag>                  </login-module>                  <login-module>                        <login-module-name>BasicPasswordLoginModule</login-module-name>                        <flag>REQUISITE</flag>                  </login-module>                  <login-module>                        <login-module-name>CreateTicketLoginModule</login-module-name>                        <flag>OPTIONAL</flag>                  </login-module>            </login-module-stack>      </login-module-configuration></web-j2ee-engine>

Creating Deploy-able Object

Step 1 : Create a DC of type Enterprise Application and add the Web Module DC.

Step 2 : Add the External library wrapper Application DC as a dependency to this Enterprise Application DC as shown below.

1.jpg


Accessing the methods exposed.

You can access the deployed REST services by constructing the URL as per the format given below.

http://<server_name>:<http_port>/<context_root_given_in_application_xml>/<url_pattern_in_web_xml>/<value_of_@Path_in_class>/<value_of_@Path_in_method>

  1. <context_root_given_in_application_xml> is the war file name can be found inside gen folder as shown below:1.jpg
  2. <url_pattern_in_web_xml> is defined inside web.xml as shown below:1.jpg
  3. <value_of_@Path_in_class> is defined inside the java class just above the class definition as shown below: 1.jpg
  4. <value_of_@Path_in_method> is defined inside the java class just above the method definition as shown below: 1.jpg

 

Testing your REST services

You can test the created REST services using the POSTMAN for Chrome or Advanced REST client for Chrome.

 

1.jpg


Viewing all articles
Browse latest Browse all 887

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>