Since version 7.2 Camunda provides an optional library which is called Camunda Spin. Spin is a lightweight wrapper library which provides a easy to use API when working with text based data formats such as XML and JSON.
Example
<?xml version="1.0" encoding="UTF-8" ?>
<show>
<name>The Big Bang Theory</name>
<totalseasons>8</totalseasons>
<episodelist>
<season no="1">
<episode>
<epnum>1</epnum>
<seasonnum>01</seasonnum>
<prodnum>276023</prodnum>
<airdate>2007-09-24</airdate>
<link>https://www.tvrage.com/The_Big_Bang_Theory/episodes/550436</link>
<title>Pilot</title>
</episode>
<episode>
<epnum>2</epnum>
<seasonnum>02</seasonnum>
<prodnum>3T6601</prodnum>
<airdate>2007-10-01</airdate>
<link>https://www.tvrage.com/The_Big_Bang_Theory/episodes/603610</link>
<title>The Big Bran Hypothesis</title>
</episode>
...
As Output we want to obtain a JSON list of all episodes which aired after 2012:
[{
"name":"The Shiny Trinket Maneuver",
"air-date":"2012-01-12"
},
{
"name":"The Recombination Hypothesis",
"air-date":"2012-01-19"
}, ... ]
Enable Spin in your project
In order to enable Camunda Spin in your project,
1) add it to your maven dependencies:
<dependencymanagement>
<dependencies>
<dependency>
<groupid>org.camunda.bpm</groupid>
<artifactid>camunda-bom</artifactid>
<version>7.3.0-alpha1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencymanagement>
<dependencies>
<dependency>
<groupid>org.camunda.spin</groupid>
<artifactid>camunda-spin-core</artifactid>
</dependency>
<dependency>
<groupid>org.camunda.spin</groupid>
<artifactid>camunda-spin-dataformat-json-jackson</artifactid>
</dependency>
<dependency>
<groupid>org.camunda.spin</groupid>
<artifactid>camunda-spin-dataformat-xml-dom</artifactid>
</dependency>
</dependencies>
2) In your Java Code, add the following static import:
import static org.camunda.spin.Spin.*;
Parsing the Xml input with Spin
XML(xmlInput)
The Java 6/7 way
Using Spin’s xPath function to iterate through all episodes
for (SpinXmlElement element : XML(xmlInput).xPath("/Show/Episodelist/Season/episode").elementList()) {
// work with the element
}
Getting the production Year as Integer
for (SpinXmlElement element : XML(xmlInput).xPath("/Show/Episodelist/Season/episode").elementList()) {
int productionYear = Integer.parseInt(element.childElement("airdate").textContent().substring(0, 4));
}
Creating an empty JSON Document
SpinJsonNode resultJson = JSON("[]");
Transform the Episodes into JSON
Next we create a JSON object into which we copy the values from the xml source:
SpinJsonNode episodeJson = JSON("{}")
.prop("name", episode.childElement("title").textContent())
.prop("air-date", episode.childElement("airdate").textContent());
The complete Java 6/7 source code then looks like this:
SpinJsonNode resultJson = JSON("[]");
for (SpinXmlElement episode : XML(xmlInput).xPath("/Show/Episodelist/Season/episode").elementList()) {
int productionYear = Integer.parseInt(episode.childElement("airdate").textContent().substring(0, 4));
if(productionYear >= 2012) {
SpinJsonNode episodeJson = JSON("{}")
.prop("name", episode.childElement("title").textContent())
.prop("air-date", episode.childElement("airdate").textContent());
resultJson.append(episodeJson);
}
}
The Java 8 Way
Java 8 introduces the Stream API and lambdas. This allows us to write a very compact representation for obtaining the same thing:
final SpinJsonNode resultJson = JSON("[]");
XML(xmlInput)
.xPath("/Show/Episodelist/Season/episode").elementList()
.stream()
.filter(e -> Integer.parseInt(e.childElement("airdate").textContent().substring(0, 4)) >= 2012)
.map(e -> JSON("{}")
.prop("name", e.childElement("title").textContent())
.prop("air-date", e.childElement("airdate").textContent()))
.forEach(e -> resultJson.append(e));
What is missing?
The above example is not “purely” functional. In the forEach
method we collect the generated customers and append them to the resultJson
object.
A more functional approach would use a java.util.stream.Collector
:
SpinJsonNode resultJson = XML(xmlInput)
.xPath("/Show/Episodelist/Season/episode").elementList()
.stream()
.filter(e -> Integer.parseInt(e.childElement("airdate").textContent().substring(0, 4)) >= 2012)
.map(e -> JSON("{}")
.prop("name", e.childElement("title").textContent())
.prop("air-date", e.childElement("airdate").textContent()))
.collect(asJsonList());
The SpinCollectors.asJsonList()
method does not exist yet. This would be something the Spin library could provide. In case anybody would use this?
Camunda Developer Community
Join Camunda’s global community of developers sharing code, advice, and meaningful experiences