Tag Archives: JAXRS

How to Get and Update Process Variable in jBPM 6 via REST API – Part 1

The GET part is fairly simple, you just need to form a URL with the right values.

So assuming you have a BPM process running on a remote server (business-central) and you would like to get/read the Process Variables, lets see how.

JBPM has published REST APIs to interact with it and get most of the information.

For our case, the REST URL to get the process variable information has this pattern:


It’s HTTP GET which returns the variable from a given process instance.

A complete URL may look like below:


The above would return the XML value of the variable (person), so if you had a POJO then this can be thought of as the XML version of the same. (JAXB at play).

Writing code to fetch the information can be in plain Java without any BPM libraries, after all its just a REST API which returns XML, the only complexity could be about BASIC AUTH.

Here’s a sample code for retrieving the variable value.

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.logging.Logger;

import org.apache.commons.codec.binary.Base64;

 * A general Helper class that once configured would return the XML value of a given Variable
 * under a process instance.
 * Sample URL used for REST API of JBPM 6:
 * http://localhost:8080/business-central/rest/runtime
 * /com.infibeam.sapphire:bpm-order-activation:0.3.9
 * /process/instance/4545
 * /variable/person
 * @author prashantp.org
public class BPMGetVariable {
	private Logger logger = Logger.getLogger(BPMGetVariable.class.getName());

	private String variableName;
	private String bpmUrl;
	private String username;
	private String password;

	public BPMGetVariable(long processId, String variableName, String bpmUrl,
			String username, String password, String deploymentId) {
		this.variableName = variableName;
		this.bpmUrl = bpmUrl + deploymentId + "/process/instance/" + processId + "/variable/" + variableName;
		this.username = username;
		this.password = password;

	public static void main(String[] args) throws Exception {
		long processId = 4545;
		String variableName = "person";
		String name = "bpmsAdmin";
		String password = "bpmspasswordhere";
		String deploymentId = "com.prashantp.demo:bpm-sample:0.1.0";

		BPMGetVariable bpmGetVariable = BPMGetVariable.builder()
				.credentials(name, password).addDeploymentId(deploymentId)
		//Save as XML
		Files.write(Paths.get("./" + processId + "_" + variableName + ".xml"),

	public String getValue()
			throws MalformedURLException, IOException {

		String variableValue = getFromSecureRESTUrl(bpmUrl, username, password);
		logger.info("Variable Name=" + variableName + ", value=" + variableValue);

		return variableValue;

	private String getFromSecureRESTUrl(String webpageUrl, String username,
			String password) throws MalformedURLException, IOException {
		URL url = new URL(webpageUrl);
		URLConnection urlConnection = url.openConnection();
		setSecurityCredentials(urlConnection, username, password);
		return readResponse(urlConnection);

	private void setSecurityCredentials(URLConnection toSecure,
			String username, String password) {
		String authString = username + ":" + password;
		byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());

		toSecure.setRequestProperty("Authorization", "Basic "
				+ new String(authEncBytes));

	private String readResponse(URLConnection urlConnection) throws IOException {
		InputStream is = urlConnection.getInputStream();
		InputStreamReader isr = new InputStreamReader(is);

		int numCharsRead;
		char[] charArray = new char[1024];
		StringBuffer sb = new StringBuffer();
		while ((numCharsRead = isr.read(charArray)) > 0) {
			sb.append(charArray, 0, numCharsRead);
		return sb.toString();

	public static BPMGetVariableBuilder builder() {
		return new BPMGetVariableBuilder();

	static class BPMGetVariableBuilder {
		private long processId;
		private String variableName;
		private String bpmUrl;
		private String username;
		private String password;
		private String deploymentId;

		public BPMGetVariableBuilder processId(long processId) {
			this.processId = processId;
			return this;

		public BPMGetVariableBuilder variableName(String variableName) {
			this.variableName = variableName;
			return this;

		public BPMGetVariableBuilder bpmUrl(String bpmUrl) {
			this.bpmUrl = bpmUrl;
			if (this.bpmUrl.endsWith("/")) {
				this.bpmUrl = this.bpmUrl + "rest/runtime/";
			} else {
				this.bpmUrl = this.bpmUrl + "/rest/runtime/";
			return this;

		public BPMGetVariableBuilder credentials(String name, String password) {
			this.username = name;
			this.password = password;
			return this;

		public BPMGetVariableBuilder addDeploymentId(String deploymentId) {
			this.deploymentId = deploymentId;
			return this;

		public BPMGetVariable build() {
			if (processId == 0 || Objects.isNull(variableName)
					|| Objects.isNull(bpmUrl) || Objects.isNull(username)
					|| Objects.isNull(password) || Objects.isNull(deploymentId)) {
				throw new IllegalStateException();
			return new BPMGetVariable(processId,variableName,bpmUrl,username,password,deploymentId);



Now that we have done the GET part how about updating the same Process Variable via the REST API, lets see how.

That’s coming in Part 2 soon.


REST API exception handling using JAX RS in JEE 6

It’s considered a good practice to use HTTP Status Codes in RESTful APIs for sharing the outcome of an API call.

There are plenty of HTTP Status codes to make use of. Unfortunately complex cases lead developers to returning custom errors rather than sticking to the HTTP standards. But there is a way to stick to the standard and still make use of custom errors as per the application needs. Let’s see an approach using JAXRS Exception mapping providers.

  • For simple requests the service may indeed return a single HTTP response code which makes sense.
  • But for complex requests which fail a more detailed error list (business specific) may be desired.

Let’s start building a JAXRS RESTful service to handle the simple case first and then see what we can do to handle the complex case later using the Exception mapping providers.

The code is available here https://github.com/prashantpro/jaxrs-movie-service


Consider a movie library service which returns the list of movies released on a given year.


Method: GET

URL: /movie/{year}

Parameters: Year

Response HTTP Status Code Description
Success 200 – Ok Movie list is returned
Input Invalid 400 – Bad Request The input year maybe invalid
Failure 500 – Internal Error Uncaught exception occurred such as RuntimeException

Setup a Web project

Create a dynamic web project in eclipse and name it jaxrs-movie-service. I have used a JEE 6 server i.e. JBoss 7.

Note: You can use maven and create a maven-archetype-webapp project as well. We won’t need any jars in our lib as JAXRS is part of JEE 6.

Deployment descriptor updates

Update web.xml to match the below

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">

Create an empty beans.xml under WEB-INF folder. (This will enable CDI capabilities which can be made use of if desired).

The source code

Let’s define a POJO which will hold the movie information.

package org.prashantpro.jaxrs.movie;

 * @author Prashant Padmanabhan <https://javaspecialist.wordpress.com>
public class Movie {

	private int year;
	private String title;
	private String genre;

	public Movie(int year, String title, String genre) {
		this.year = year;
		this.title = title;
		this.genre = genre;
	//Getters and setters left out for brevity.

Next, create the REST service which will expose the movie libraries movie list. Here we aren’t using any checked business exception handlers. This is a simple service which returns the HTTP Status code based on conditional constructs.

package org.prashantpro.jaxrs.movie;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

 * @author Prashant Padmanabhan <https://javaspecialist.wordpress.com>
public class MovieLibrary {
	//Store the in memory movie list as our repository.
	static final List MOVIE_LIST = new ArrayList();

	//Build a dummy list of movies to work with.
	static {
		MOVIE_LIST.add(new Movie(1971,"Dirty Harry","Action"));
		MOVIE_LIST.add(new Movie(2008,"Gran Torino","Drama"));
		MOVIE_LIST.add(new Movie(2012,"Argo","Drama"));

	public Response getMovies(@PathParam("year") int year) {
		if(year < 1880 || year > 9999) {
			//Invalid input for year so return HTTP Status 400
			return Response.status(Response.Status.BAD_REQUEST).build();
		List list = getMoviesByYear(year);
		return Response.status(Response.Status.OK).entity(list).build();

	private List getMoviesByYear(int targetYear) {
		List found = new ArrayList();
		for(Movie movie : MOVIE_LIST) {
			if(movie.getYear() == targetYear)
		return found;


Once the above code is deployed as a WAR file in a JEE 6 server such as JBoss 7, we can then hit the URL:



jaxrs-movie-service – Is the context name of our application

/movie – Is the REST resource identified by @Path(“/movie”)

1971 – Is the input which maps to the getMovies method via @Path(“/{year}”)

The above should result in the below response:

Response headers:

  • Status Code: 200 OK
  • Content-Type: application/json

Response body:

[{"year":1971,"title":"Dirty Harry","genre":"Action"}]

This was simple to begin with, but in real world we would have some facade or service layer which would do the processing. The facade may throw business exceptions which would then result in passing a different response code with an appropriate message.

The complex case discussed below explains the same.

Complex case

Consider the movie library service would also require to list out movies based on a genre in the given order of ASC or DESC.

For simplicity let’s say we have only two genres “Action” and “Drama“.

In case of any problem the detailed message must be returned by the REST Service. This means we need to return some error messages along with the right HTTP Status code.

We can start throwing business exceptions but these won’t get translated to an appropriate HTTP Response code.

Here, we make use of Exception Mapping providers. These map a checked or runtime exception to an instance of Response. An exception mapping provider implements the ExceptionMapper<T> interface and is annotated with @Provider.


Method: GET

URL: /movie/list

Parameters: order, genre

Response HTTP Status Code Description
Success 200 – Ok Movie list is returned
Input Invalid 400 – Bad Request Service must return the details of what went wrong.Example genre specified was wrong.Sort order related issue.

Let’s create a application exception which would contain the error details.

package org.prashantpro.jaxrs.movie;

import java.util.List;

 * @author Prashant Padmanabhan <https://javaspecialist.wordpress.com>
public class BusinessException extends Exception {

	private static final long serialVersionUID = 1L;

	private List messages;

	public BusinessException(List messages) {
		this.messages = messages;

	public List getMessages() {
		return messages;

Now, the Exception Mapper which will map our Business Exception to the correct Response code.

package org.prashantpro.jaxrs.movie;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

 * @author Prashant Padmanabhan <https://javaspecialist.wordpress.com>
public class ExceptionHttpStatusResolver implements
		ExceptionMapper {

	public Response toResponse(BusinessException exception) {
		Response.Status httpStatus = Response.Status.INTERNAL_SERVER_ERROR;

		if (exception instanceof BusinessException)
			httpStatus = Response.Status.BAD_REQUEST;

		return Response.status(httpStatus).entity(exception.getMessages())

The MovieLibrary.java gets a new method as shown below:

	public Response getMoviesByGenre(@QueryParam("order") String order,@QueryParam("genre") String genre) throws BusinessException {
		List errorMessages = new ArrayList();

		if(order == null || order.length() == 0) {
			errorMessages.add("order is required");

		if(genre == null || genre.length() == 0) {
			errorMessages.add("genre is required");

		if(!"ASC".equals(order) && !"DESC".equals(order)) {
			errorMessages.add("order of either ASC or DESC must be specified");

		if(!"Action".equals(genre) &&  !"Drama".equals(genre)) {
			errorMessages.add("genre of either Action or Drama must be specified");
		if(!errorMessages.isEmpty()) {
			throw new BusinessException(errorMessages);

		List list = listMoviesByGenre(genre,order);
		return Response.status(Response.Status.OK).entity(list).build();

	private List listMoviesByGenre(String genre, String order) {
		//Just return the list as is as this is a demo
		//We would use some logic to do the filtering and ordering in real world apps.
		return MOVIE_LIST;

If you invoke the service without any of the required parameters, it would return the HTTP status code of 400 along with the detailed messages. This works because our BusinessException thrown during validation checks is processed by the ExceptionHttpStatusResolver which translates the exception to the correct Response code.

When a resource method throws an exception for which there is an exception mapping provider, the matching provider is used to obtain a Response instance. The resulting Response is processed as if the method throwing the exception had instead returned the Response.

Example invocation URL:

The above should result in the below response:

Response headers:

  • Status Code: 400 Bad Request
  • Content-Type: application/json

Response body:

"genre is required",
"order of either ASC or DESC must be specified",
"genre of either Action or Drama must be specified"


Thus we can make use of JAXRS Exception Mapping providers for returning HTTP Status codes and add the needed error details in the response body as well.