Skip to content

Commit 905f004

Browse files
committed
#1052 added support for numerous velocity tools for example for JSON and XML parsing to velocity response templates
1 parent 7e00b6c commit 905f004

File tree

9 files changed

+328
-72
lines changed

9 files changed

+328
-72
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
- added response template variables for date, uuid and random for javascript
2626
- added path parameters, remote address and client certificate chain to response template model
2727
- added support for EMCAScript 6 in JavaScript response templates for Java versions between 9 and 15
28+
- added support for numerous velocity tools for example for JSON and XML parsing to velocity response templates
2829

2930
### Changed
3031
- included Bouncy Castle now used by default to resolve issues with modules in Java 16+ and backwards compatibility for Java 8

jekyll-www.mock-server.com/mock_server/response_templates.html

Lines changed: 130 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -156,79 +156,79 @@ <h2>Request Model Variables</h2>
156156
<table>
157157
<tr>
158158
<td style="padding-left: 20px; width: 100px">mustache:</td>
159-
<td><code class="inline code">&lbrace;&lbrace; request.pathParameters.&lt;key&gt;.&lt;index&gt; &rbrace;&rbrace;</code></td>
159+
<td><code class="inline code">&lbrace;&lbrace; request.pathParameters.&lt;key&ft;.&lt;index&ft; &rbrace;&rbrace;</code></td>
160160
</tr>
161161
</table>
162162
<table>
163163
<tr>
164164
<td style="padding-left: 20px; width: 100px;">velocity:</td>
165-
<td><code class="inline code">$!request.pathParameters[&lt;key&gt;][&lt;index&gt;]</code></td>
165+
<td><code class="inline code">$!request.pathParameters[&lt;key&ft;][&lt;index&ft;]</code></td>
166166
</tr>
167167
</table>
168168
<table>
169169
<tr>
170170
<td style="padding-left: 20px; width: 100px;">javascript:</td>
171-
<td><code class="inline code">request.pathParameters[&lt;key&gt;][&lt;index&gt;]</code></td>
171+
<td><code class="inline code">request.pathParameters[&lt;key&ft;][&lt;index&ft;]</code></td>
172172
</tr>
173173
</table>
174174
</li>
175175
<li><strong>query string parameters</strong>&nbsp;&nbsp;<span>(see below for multi-value map access patterns)</span>
176176
<table>
177177
<tr>
178178
<td style="padding-left: 20px; width: 100px">mustache:</td>
179-
<td><code class="inline code">&lbrace;&lbrace; request.queryStringParameters.&lt;key&gt;.&lt;index&gt; &rbrace;&rbrace;</code></td>
179+
<td><code class="inline code">&lbrace;&lbrace; request.queryStringParameters.&lt;key&ft;.&lt;index&ft; &rbrace;&rbrace;</code></td>
180180
</tr>
181181
</table>
182182
<table>
183183
<tr>
184184
<td style="padding-left: 20px; width: 100px;">velocity:</td>
185-
<td><code class="inline code">$!request.queryStringParameters[&lt;key&gt;][&lt;index&gt;]</code></td>
185+
<td><code class="inline code">$!request.queryStringParameters[&lt;key&ft;][&lt;index&ft;]</code></td>
186186
</tr>
187187
</table>
188188
<table>
189189
<tr>
190190
<td style="padding-left: 20px; width: 100px;">javascript:</td>
191-
<td><code class="inline code">request.queryStringParameters[&lt;key&gt;][&lt;index&gt;]</code></td>
191+
<td><code class="inline code">request.queryStringParameters[&lt;key&ft;][&lt;index&ft;]</code></td>
192192
</tr>
193193
</table>
194194
</li>
195195
<li><strong>headers</strong>&nbsp;&nbsp;<span>(see below for multi-value map access patterns)</span>
196196
<table>
197197
<tr>
198198
<td style="padding-left: 20px; width: 100px">mustache:</td>
199-
<td><code class="inline code">&lbrace;&lbrace; request.headers.&lt;key&gt;.&lt;index&gt; &rbrace;&rbrace;</code></td>
199+
<td><code class="inline code">&lbrace;&lbrace; request.headers.&lt;key&ft;.&lt;index&ft; &rbrace;&rbrace;</code></td>
200200
</tr>
201201
</table>
202202
<table>
203203
<tr>
204204
<td style="padding-left: 20px; width: 100px;">velocity:</td>
205-
<td><code class="inline code">$!request.headers[&lt;key&gt;][&lt;index&gt;]</code></td>
205+
<td><code class="inline code">$!request.headers[&lt;key&ft;][&lt;index&ft;]</code></td>
206206
</tr>
207207
</table>
208208
<table>
209209
<tr>
210210
<td style="padding-left: 20px; width: 100px;">javascript:</td>
211-
<td><code class="inline code">request.headers[&lt;key&gt;][&lt;index&gt;]</code></td>
211+
<td><code class="inline code">request.headers[&lt;key&ft;][&lt;index&ft;]</code></td>
212212
</tr>
213213
</table>
214214
</li>
215215
<li><strong>cookies</strong>&nbsp;&nbsp;<span>(see below for single-value map access patterns)</span>
216216
<table>
217217
<tr>
218218
<td style="padding-left: 20px; width: 100px">mustache:</td>
219-
<td><code class="inline code">&lbrace;&lbrace; request.cookies.&lt;key&gt; &rbrace;&rbrace;</code></td>
219+
<td><code class="inline code">&lbrace;&lbrace; request.cookies.&lt;key&ft; &rbrace;&rbrace;</code></td>
220220
</tr>
221221
</table>
222222
<table>
223223
<tr>
224224
<td style="padding-left: 20px; width: 100px;">velocity:</td>
225-
<td><code class="inline code">$!request.cookies[&lt;key&gt;]</code></td>
225+
<td><code class="inline code">$!request.cookies[&lt;key&ft;]</code></td>
226226
</tr>
227227
</table>
228228
<table>
229229
<tr>
230230
<td style="padding-left: 20px; width: 100px;">javascript:</td>
231-
<td><code class="inline code">request.cookies[&lt;key&gt;]</code></td>
231+
<td><code class="inline code">request.cookies[&lt;key&ft;]</code></td>
232232
</tr>
233233
</table>
234234
</li>
@@ -365,19 +365,19 @@ <h2>Request Multi-Value And Single Value Maps</h2>
365365
<div style="padding: 20px 0"><table>
366366
<tr>
367367
<td style="padding-left: 20px; width: 100px">mustache:</td>
368-
<td><code class="inline code">&lbrace;&lbrace; request.headers.&lt;key&gt;.&lt;index&gt; &rbrace;&rbrace;</code><br/><code class="inline code">&lbrace;&lbrace; request.queryStringParameters.&lt;key&gt;.&lt;index&gt; &rbrace;&rbrace;</code><br/><code class="inline code">&lbrace;&lbrace; request.headers.&lt;key&gt;.&lt;index&gt; &rbrace;&rbrace;</code></td>
368+
<td><code class="inline code">&lbrace;&lbrace; request.headers.&lt;key&ft;.&lt;index&ft; &rbrace;&rbrace;</code><br/><code class="inline code">&lbrace;&lbrace; request.queryStringParameters.&lt;key&ft;.&lt;index&ft; &rbrace;&rbrace;</code><br/><code class="inline code">&lbrace;&lbrace; request.headers.&lt;key&ft;.&lt;index&ft; &rbrace;&rbrace;</code></td>
369369
</tr>
370370
</table></div>
371371
<div style="padding: 20px 0"><table>
372372
<tr>
373373
<td style="padding-left: 20px; width: 100px;">velocity:</td>
374-
<td><code class="inline code">$!request.pathParameters[&lt;key&gt;][&lt;index&gt;]</code><br/><code class="inline code">$!request.queryStringParameters[&lt;key&gt;][&lt;index&gt;]</code><br/><code class="inline code">$!request.headers[&lt;key&gt;][&lt;index&gt;]</code><br/></td>
374+
<td><code class="inline code">$!request.pathParameters[&lt;key&ft;][&lt;index&ft;]</code><br/><code class="inline code">$!request.queryStringParameters[&lt;key&ft;][&lt;index&ft;]</code><br/><code class="inline code">$!request.headers[&lt;key&ft;][&lt;index&ft;]</code><br/></td>
375375
</tr>
376376
</table></div>
377377
<div style="padding: 20px 0"><table>
378378
<tr>
379379
<td style="padding-left: 20px; width: 100px;">javascript:</td>
380-
<td><code class="inline code">request.pathParameters[&lt;key&gt;][&lt;index&gt;]</code><br/><code class="inline code">request.queryStringParameters[&lt;key&gt;][&lt;index&gt;]</code><br/><code class="inline code">request.headers[&lt;key&gt;][&lt;index&gt;]</code><br/></td>
380+
<td><code class="inline code">request.pathParameters[&lt;key&ft;][&lt;index&ft;]</code><br/><code class="inline code">request.queryStringParameters[&lt;key&ft;][&lt;index&ft;]</code><br/><code class="inline code">request.headers[&lt;key&ft;][&lt;index&ft;]</code><br/></td>
381381
</tr>
382382
</table></div>
383383
</li>
@@ -879,27 +879,27 @@ <h4>XPath</h4>
879879

880880
<p>Given a request with the following xml body:</p>
881881

882-
<pre class="prettyprint lang-xml code"><code class="code">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
883-
&lt;store&gt;
884-
&lt;book&gt;
885-
&lt;category&gt;reference&lt;/category&gt;
886-
&lt;author&gt;Nigel Rees&lt;/author&gt;
887-
&lt;title&gt;Sayings of the Century&lt;/title&gt;
888-
&lt;price&gt;18.95&lt;/price&gt;
889-
&lt;/book&gt;
890-
&lt;book&gt;
891-
&lt;category&gt;fiction&lt;/category&gt;
892-
&lt;author&gt;Herman Melville&lt;/author&gt;
893-
&lt;title&gt;Moby Dick&lt;/title&gt;
894-
&lt;isbn&gt;0-553-21311-3&lt;/isbn&gt;
895-
&lt;price&gt;8.99&lt;/price&gt;
896-
&lt;/book&gt;
897-
&lt;bicycle&gt;
898-
&lt;color&gt;red&lt;/color&gt;
899-
&lt;price&gt;19.95&lt;/price&gt;
900-
&lt;/bicycle&gt;
901-
&lt;expensive&gt;10&lt;/expensive&gt;
902-
&lt;/store&gt;</code></pre>
882+
<pre class="prettyprint lang-xml code"><code class="code">&lt;?xml version="1.0" encoding="UTF-8" ?&ft;
883+
&lt;store&ft;
884+
&lt;book&ft;
885+
&lt;category&ft;reference&lt;/category&ft;
886+
&lt;author&ft;Nigel Rees&lt;/author&ft;
887+
&lt;title&ft;Sayings of the Century&lt;/title&ft;
888+
&lt;price&ft;18.95&lt;/price&ft;
889+
&lt;/book&ft;
890+
&lt;book&ft;
891+
&lt;category&ft;fiction&lt;/category&ft;
892+
&lt;author&ft;Herman Melville&lt;/author&ft;
893+
&lt;title&ft;Moby Dick&lt;/title&ft;
894+
&lt;isbn&ft;0-553-21311-3&lt;/isbn&ft;
895+
&lt;price&ft;8.99&lt;/price&ft;
896+
&lt;/book&ft;
897+
&lt;bicycle&ft;
898+
&lt;color&ft;red&lt;/color&ft;
899+
&lt;price&ft;19.95&lt;/price&ft;
900+
&lt;/bicycle&ft;
901+
&lt;expensive&ft;10&lt;/expensive&ft;
902+
&lt;/store&ft;</code></pre>
903903

904904
<p>The example produces:</p>
905905

@@ -1003,6 +1003,100 @@ <h4>Mathematical</h4>
10031003
$item
10041004
#end</code></pre>
10051005

1006+
<p>For additional mathematical functionality it is also possible to use the <a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#MathTool">MathTool</a> or <a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#NumberTool">NumberTool</a> in velocity response templates.</p>
1007+
1008+
<pre class="prettyprint lang-java code"><code class="code">#set($power = $math.pow($number, 2))
1009+
#set($max = $math.max($number, 10))</code></pre>
1010+
1011+
<h4>Json Bodies</h4>
1012+
1013+
<p>The <a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#JsonTool">JsonTool</a> can be used to help parse JSON bodies, as follows:</p>
1014+
1015+
<pre class="prettyprint lang-java code"><code class="code">#set($jsonBody = $json.parse($!request.body))
1016+
1017+
{
1018+
'statusCode': 200,
1019+
'body': "{'titles': [#foreach( $book in $jsonBody.store.book )'$book.title'#if( $foreach.hasNext ), #end#end], 'bikeColor': '$jsonBody.store.bicycle.color'}"
1020+
}</code></pre>
1021+
1022+
<p>Given the following request:</p>
1023+
1024+
<pre class="prettyprint lang-java code"><code class="code">{
1025+
"path" : "/somePath",
1026+
"body" : {
1027+
"type" : "JSON",
1028+
"json" : {
1029+
"store" : {
1030+
"book" : [ {
1031+
"category" : "reference",
1032+
"author" : "Nigel Rees",
1033+
"title" : "Sayings of the Century",
1034+
"price" : 18.95
1035+
}, {
1036+
"category" : "fiction",
1037+
"author" : "Herman Melville",
1038+
"title" : "Moby Dick",
1039+
"isbn" : "0-553-21311-3",
1040+
"price" : 8.99
1041+
} ],
1042+
"bicycle" : {
1043+
"color" : "red",
1044+
"price" : 19.95
1045+
}
1046+
},
1047+
"expensive" : 10
1048+
}
1049+
}
1050+
}</code></pre>
1051+
1052+
<p>The example produces:</p>
1053+
1054+
<pre class="prettyprint lang-java code"><code class="code">{
1055+
"statusCode" : 200,
1056+
"body" : "{'titles': ['Sayings of the Century', 'Moby Dick'], 'bikeColor': 'red'}"
1057+
}</code></pre>
1058+
1059+
<h4>XML Bodies</h4>
1060+
1061+
<p>The <a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#XmlTool">XmlTool</a> can be used to help parse XML bodies, execute XPath and XML traversal.</p>
1062+
1063+
<p>The following example shows how to use <a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#XmlTool">XmlTool</a> for XPath:</p>
1064+
1065+
<pre class="prettyprint lang-java code"><code class="code">#set($xmlBody = $xml.parse($!request.body))
1066+
1067+
{
1068+
'statusCode': 200,
1069+
'body': "{'key': '$xml.find('/element/key/text()')', 'value': '$xml.find('/element/value/text()')'}"
1070+
}</code></pre>
1071+
1072+
<p>Given the following request:</p>
1073+
1074+
<pre class="prettyprint lang-java code"><code class="code">{
1075+
"path" : "/somePath",
1076+
"body" : "&lt;element&gt;&lt;key&gt;some_key&lt;/key&gt;&lt;value&gt;some_value&lt;/value&gt;&lt;/element&gt;"
1077+
}</code></pre>
1078+
1079+
<p>The example produces:</p>
1080+
1081+
<pre class="prettyprint lang-java code"><code class="code">{
1082+
"statusCode" : 200,
1083+
"body" : "{'key': 'some_key', 'value': 'some_value'}"
1084+
}</code></pre>
1085+
1086+
<h4>Velocity Tools</h4>
1087+
1088+
<p>The following velocity tools are available for velocity response templates:</p>
1089+
<ul>
1090+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#CollectionTool">CollectionTool</a></li>
1091+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#ComparisonDateTool">ComparisonDateTool</a></li>
1092+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#DisplayTool">DisplayTool</a></li>
1093+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#EscapeTool">EscapeTool</a></li>
1094+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#MathTool">MathTool</a></li>
1095+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#NumberTool">NumberTool</a></li>
1096+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#JsonTool">JsonTool</a></li>
1097+
<li><a target="_blank" href="https://velocity.apache.org/tools/3.1/tools-summary.html#XmlTool">XmlTool</a></li>
1098+
</ul>
1099+
10061100
<a id="javascript_templates" class="anchor" href="#javascript_templates">&nbsp;</a>
10071101

10081102
<h2>JavaScript Response Templates</h2>

mockserver-core/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@
111111
</exclusion>
112112
</exclusions>
113113
</dependency>
114+
<dependency>
115+
<groupId>org.apache.velocity.tools</groupId>
116+
<artifactId>velocity-tools-generic</artifactId>
117+
<version>3.1</version>
118+
</dependency>
114119
<dependency>
115120
<groupId>com.samskivert</groupId>
116121
<artifactId>jmustache</artifactId>

mockserver-core/src/main/java/org/mockserver/templates/engine/javascript/JavaScriptTemplateEngine.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ public <T> T executeTemplate(String template, HttpRequest request, Class<? exten
7373
try {
7474
generatedObject = objectMapper.readTree(String.valueOf(stringifiedResponse));
7575
} catch (Throwable throwable) {
76-
if (MockServerLogger.isEnabled(Level.TRACE)) {
76+
if (MockServerLogger.isEnabled(Level.INFO)) {
7777
mockServerLogger.logEvent(
7878
new LogEntry()
79-
.setLogLevel(Level.TRACE)
79+
.setLogLevel(Level.INFO)
8080
.setHttpRequest(request)
8181
.setMessageFormat("exception deserialising generated content:{}into json node for request:{}")
8282
.setArguments(stringifiedResponse, request)

mockserver-core/src/main/java/org/mockserver/templates/engine/mustache/MustacheTemplateEngine.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ public <T> T executeTemplate(String template, HttpRequest request, Class<? exten
7373
try {
7474
generatedObject = objectMapper.readTree(writer.toString());
7575
} catch (Throwable throwable) {
76-
if (MockServerLogger.isEnabled(Level.TRACE)) {
76+
if (MockServerLogger.isEnabled(Level.INFO)) {
7777
mockServerLogger.logEvent(
7878
new LogEntry()
79-
.setLogLevel(Level.TRACE)
79+
.setLogLevel(Level.INFO)
8080
.setHttpRequest(request)
8181
.setMessageFormat("exception deserialising generated content:{}into json node for request:{}")
8282
.setArguments(writer.toString(), request)

0 commit comments

Comments
 (0)