-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeed.xml
More file actions
655 lines (514 loc) · 95.1 KB
/
feed.xml
File metadata and controls
655 lines (514 loc) · 95.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>RMPader</title>
<description>This blog is by no means a source of "absolute truth". It's simply a guide to those who wants them. I hope that you find the contents of this site helpful and may the undying light of learning guide you.
</description>
<link>http://reypader.github.io/</link>
<atom:link href="http://reypader.github.io/feed.xml" rel="self" type="application/rss+xml"/>
<pubDate>Tue, 19 Jan 2016 18:44:09 +0800</pubDate>
<lastBuildDate>Tue, 19 Jan 2016 18:44:09 +0800</lastBuildDate>
<generator>Jekyll v2.4.0</generator>
<item>
<title>How to: Secure your RESTful Application for Google App Engine</title>
<description><h2 id="the-configuration">The Configuration</h2>
<h3 id="the-explanation">The Explanation</h3>
</description>
<pubDate>Wed, 27 Jan 2016 18:53:00 +0800</pubDate>
<link>http://reypader.github.io/2016/01/27/spring-security-rest-gae.html</link>
<guid isPermaLink="true">http://reypader.github.io/2016/01/27/spring-security-rest-gae.html</guid>
<category>java</category>
<category>spring</category>
<category>spring-rest</category>
<category>google-app-engine</category>
</item>
<item>
<title>How to: Secure your RESTful Application - Part 3</title>
<description><h2 id="the-configuration">The Configuration</h2>
<h3 id="the-explanation">The Explanation</h3>
</description>
<pubDate>Mon, 25 Jan 2016 18:53:00 +0800</pubDate>
<link>http://reypader.github.io/2016/01/25/spring-security-rest-3.html</link>
<guid isPermaLink="true">http://reypader.github.io/2016/01/25/spring-security-rest-3.html</guid>
<category>java</category>
<category>spring</category>
<category>spring-rest</category>
</item>
<item>
<title>How to: Secure your RESTful Application - Part 2</title>
<description><h2 id="the-configuration">The Configuration</h2>
<h3 id="the-explanation">The Explanation</h3>
</description>
<pubDate>Fri, 22 Jan 2016 18:53:00 +0800</pubDate>
<link>http://reypader.github.io/2016/01/22/spring-security-rest-2.html</link>
<guid isPermaLink="true">http://reypader.github.io/2016/01/22/spring-security-rest-2.html</guid>
<category>java</category>
<category>spring</category>
<category>spring-rest</category>
</item>
<item>
<title>How to: Secure your RESTful Application - Part 1</title>
<description><h2 id="setup-basic-authentication">Setup Basic Authentication</h2>
<h2 id="use-a-custom-quot-user-class-quot">Use a custom &quot;User Class&quot;</h2>
</description>
<pubDate>Wed, 20 Jan 2016 18:53:00 +0800</pubDate>
<link>http://reypader.github.io/2016/01/20/spring-security-rest-1.html</link>
<guid isPermaLink="true">http://reypader.github.io/2016/01/20/spring-security-rest-1.html</guid>
<category>java</category>
<category>spring</category>
<category>spring-rest</category>
</item>
<item>
<title>How to: Integrate Drools and Spring Framework</title>
<description><p>There are a few - very few - tutorials that show us how to integrate Spring and Drools. <a href="http://scattercode.co.uk/2015/02/06/a-minimal-spring-boot-drools-web-service/">This article in Scattercode</a> actually does a
great job and I highly suggest you have a look at that. <a href="http://mytechnorage.blogspot.com/2014/10/drools-6-integration-with-spring-mvc-4.html">Technorage also has a pretty good tutorial</a> but I found it
a bit hard to follow. I&#39;m not sure, maybe it&#39;s just the layout that makes it a bit intimidating - and the colors? IDK IDK. Anyway, I&#39;ll be building upon the tutorial from Scattercode and see where
we can get from there.</p>
<p>This article focuses on how to configure your <code>KieContainer</code> which serves as the root of all interactions with Drools. We&#39;ll be looking at how to configure a classpath-based rule and a remote-based rule.
The latter would be what you would be looking for if you wish to dynamically change rules without restarting the server, or redeploying.</p>
<p>We&#39;ll be creating a &quot;Course Suggestion&quot; application that would return a list of courses that would fit based on a user&#39;s ratings of subjects. See the table below:</p>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<table class="table">
<thead>
<tr>
<th><em>Course<em></th>
<th>math</th>
<th>software</th>
<th>electronics</th>
<th>physics</th>
<th>arts</th>
<th>social_studies</th>
<th>culinary</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Computer Science</th>
<td>6</td>
<td>9</td>
<td>3</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Theoretical Physics</th>
<td>9</td>
<td></td>
<td></td>
<td>9</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Theatrical Arts</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td>9</td>
<td>6</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Based on this table, if a user provides a rating of 9 in math, 9 in software, 5 in electronics, and 3 in physics, only the course Computer Science will be suggested. However, if the rating for physics is increased to 9, then
there will be two suggested courses - Theoretical Physics and Computer Science.</p>
<p>For simplicity, the only aspect that will change for each section is how the <code>KieContainer</code> is configured. The assumption is that you have an idea on how to use
the <code>KieContainer</code> to fire rules. If not, the Drools documentation has a <a href="http://docs.jboss.org/drools/release/6.3.0.Final/drools-docs/html_single/index.html#KIEExamplesSection">section</a> to show you how to do just that. You can find the source code <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools">here</a>.
You will also find a guide there on how to setup <a href="https://docs.jboss.org/drools/release/latest/drools-docs/html/pt05.html">Drools Workbench</a> and <a href="http://wildfly.org/">Wildfly</a> (an alternative to Tomcat which is more compatible with Drools Workbench) on your machine.</p>
<hr>
<h2 id="declaring-rules-within-the-classpath">Declaring Rules within the Classpath</h2>
<p>If you&#39;ve seen <a href="http://scattercode.co.uk/2015/02/06/a-minimal-spring-boot-drools-web-service/">the article in Scattercode</a>, you&#39;ll find that this section presents exactly the same configuration.
The first step is to create the DRL file corresponding to the table above. If you need a reference, the <a href="http://docs.jboss.org/drools/release/latest/drools-docs/html_single/index.html#DroolsLanguageReferenceChapter">official documentation</a> is still your best bet.
The DRL file needs to be in the <code>src/main/resources/</code> directory. Ideally you should place it in a folder whose name is similar to a package structure (e.g. <code>com.rmpader.springdrools</code>).</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="kr">package</span> <span class="nx">com</span><span class="p">.</span><span class="nx">rmpader</span><span class="p">.</span><span class="nx">springdrools</span>
<span class="kr">import</span> <span class="nx">com</span><span class="p">.</span><span class="nx">rmpader</span><span class="p">.</span><span class="nx">springdrools</span><span class="p">.</span><span class="nx">fact</span><span class="p">.</span><span class="nx">SubjectRating</span><span class="p">;</span>
<span class="nx">global</span> <span class="nx">com</span><span class="p">.</span><span class="nx">rmpader</span><span class="p">.</span><span class="nx">springdrools</span><span class="p">.</span><span class="nx">fact</span><span class="p">.</span><span class="nx">Suggestions</span> <span class="nx">suggestions</span><span class="p">;</span>
<span class="nx">rule</span> <span class="s2">&quot;Suggest Computer Science&quot;</span>
<span class="nx">when</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;math&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">6</span><span class="p">)</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;software&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">9</span><span class="p">)</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;electronics&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">)</span>
<span class="nx">then</span>
<span class="nx">suggestions</span><span class="p">.</span><span class="nx">addSuggestedCourseCode</span><span class="p">(</span><span class="s2">&quot;COMP-SCI&quot;</span><span class="p">);</span>
<span class="nx">end</span>
<span class="nx">rule</span> <span class="s2">&quot;Suggest Theoretical Physics&quot;</span>
<span class="nx">when</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;math&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">9</span><span class="p">)</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;physics&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">9</span><span class="p">)</span>
<span class="nx">then</span>
<span class="nx">suggestions</span><span class="p">.</span><span class="nx">addSuggestedCourseCode</span><span class="p">(</span><span class="s2">&quot;THEOR-PHYS&quot;</span><span class="p">);</span>
<span class="nx">end</span>
<span class="nx">rule</span> <span class="s2">&quot;Suggest Theatrical Arts&quot;</span>
<span class="nx">when</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;arts&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">9</span><span class="p">)</span>
<span class="nx">SubjectRating</span><span class="p">(</span> <span class="nx">subject</span><span class="o">==</span><span class="s2">&quot;social_studies&quot;</span><span class="p">,</span> <span class="nx">rating</span> <span class="o">&gt;=</span> <span class="mi">6</span><span class="p">)</span>
<span class="nx">then</span>
<span class="nx">suggestions</span><span class="p">.</span><span class="nx">addSuggestedCourseCode</span><span class="p">(</span><span class="s2">&quot;THEAT-ART&quot;</span><span class="p">);</span>
<span class="nx">end</span>
</code></pre></div>
<p>Notice the classes being used in this DRL file. <code>SubjectRating</code> and <code>Suggestions</code> are classes that exists in the classpath (i.e. they are either declared in the same project or in a dependency).
These are <em>facts</em>. <em>Facts</em> are objects that are passed into the rule engine as input. You&#39;ll notice that the concept of imports are the same in Drools as it is in Java. This should help you get an idea on how facts should be declared and used.
In the <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools">sample code</a>, those classes are <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools/drools-demo-facts/src/main/java/com/rmpader/springdrools/fact">defined</a> in the <code>drools-demo-facts</code> directory.
When writing your fact objects, I highly suggest that you place them in a separate maven artifact/project from your application. That artifact should only contain the fact objects and nothing else. It doesn&#39;t make sense to do it that way when you&#39;re doing the classpath rules configuration but you&#39;ll understand why once you use <a href="#fetching-rules-from-a-remote-location">remote artifacts</a>.</p>
<p>Now that we have rules in place, we need to be able do declare them in the rule engine. The rule engine identifies rules that are declared in a <code>kmodule.xml</code> file in the <code>src/main/resources/META-INF</code> directory.
To declare the rules, the <code>kmodule.xml</code> file needs to have the following content:</p>
<div class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;kmodule</span> <span class="na">xmlns=</span><span class="s">&quot;http://jboss.org/kie/6.0.0/kmodule&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;kbase</span> <span class="na">name=</span><span class="s">&quot;base&quot;</span> <span class="na">default=</span><span class="s">&quot;true&quot;</span> <span class="na">packages=</span><span class="s">&quot;com.rmpader.springdrools&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;ksession</span> <span class="na">name=</span><span class="s">&quot;session&quot;</span> <span class="na">default=</span><span class="s">&quot;true&quot;</span> <span class="na">type=</span><span class="s">&quot;stateless&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/kbase&gt;</span>
<span class="nt">&lt;/kmodule&gt;</span>
</code></pre></div>
<p>The <code>packages</code> attribute of the <code>&lt;kbase/&gt;</code> tag needs to be the same as the name of the directory where you&#39;ve placed the DRL file. In this case, the directory name is <code>com.rmpader.springdrools</code>.
I wouldn&#39;t go into detail about the other tags and attributes. I implore you to read the <a href="http://docs.jboss.org/drools/release/latest/drools-docs/html_single/index.html">official documentation</a> to learn more about Drools itself.</p>
<p>Now that we have the rules and the proper configuration for them to be recognized by the rules engine. We need only to tell the rules engine where to look for the configuration file <code>kmodule.xml</code>.
To do that, we need to tell the <code>KieContainer</code> to look in the classpath.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Bean</span>
<span class="kd">public</span> <span class="n">KieContainer</span> <span class="nf">kieContainer</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
<span class="n">KieServices</span> <span class="n">ks</span> <span class="o">=</span> <span class="n">KieServices</span><span class="o">.</span><span class="na">Factory</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
<span class="k">return</span> <span class="n">ks</span><span class="o">.</span><span class="na">getKieClasspathContainer</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div>
<p>With this, each time you fire rules, the DRL file declared in your classpath <code>kmodule.xml</code> will be used. You can see the complete source <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools/drools-demo-app-classpath">here</a>.</p>
<p>This is a very simple use-case. Actually, you&#39;ll rarely want this particular configuration. Why? The strength of rule engines is that they are decoupled from
your application. Which means that they could change independently from the application itself without disrupting service. With a classpath rule, evertime you need
to change the rules, you&#39;ll need to rebuild and re-deploy the application which needs a certain amount of downtime. So, how do you change the rules without
stopping the server? You should be...</p>
<hr>
<h2 id="fetching-rules-from-a-remote-location">Fetching Rules from a Remote Location</h2>
<p>Fetching rules remotely is actually the most common use-case for Drools in my opinion. Strangely enough, I&#39;ve yet to find a tutorial on how to do this. Hopefully, this section
does a decent enough job to show you how.</p>
<h3 id="drools-workbench">Drools Workbench</h3>
<p><img class="img-rounded img-responsive center-block" src="https://docs.jboss.org/drools/release/6.2.0.Final/drools-docs/html_single/images/Workbench/ReleaseNotes/kie-drools-wb.png">
<div style="margin:auto; text-align:center"><em>Taken from the Drools Documentation</em></div></p>
<p>Before diving into the configuration, let me introduce you first to the <a href="https://docs.jboss.org/drools/release/latest/drools-docs/html/pt05.html">Drools Workbench</a>. This application
is where we will be authoring and serving rules. To those who use <a href="https://maven.apache.org/">Maven</a>, it&#39;s very similar to <a href="http://books.sonatype.com/nexus-book/reference/intro-sect-intro.html">Nexus</a>. In fact, it also serves rules as JAR artifacts. Basically
the rules themselves are also Maven Artifacts. Aside from serving as a repository, the Drools Workbench can also serve as your IDE for authoring projects/rules.</p>
<p>The README of the sample source code contains guides on how to <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools#setup-a-drools-project">author rules</a> as well as setting up your <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools#setup-wildfly">Drools Workbench and Wildfly</a>.
Wildfly was used over Tomcat due to compatibility issues.</p>
<h3 id="the-facts-artifact">The Facts Artifact</h3>
<p>Earlier, I&#39;ve mentioned that you should place your facts in a separate maven artifact. Also, if you&#39;ve gone through the guide on how to author rules, you&#39;ll also see that the first thing needed
is to have a facts artifact ready to be imported. The reason for this is that since your application and the rules project are two different projects that use the same fact objects, there needs to be a uniform
definition of the classes being used. By now you&#39;ve probably realized that the same is true with API artifacts of certain libraries (e.g. <a href="http://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api">log4j-api</a>, <a href="http://mvnrepository.com/artifact/javax.persistence/persistence-api">JPA</a>).
Hence, separating the fact objects artifact becomes mandatory when doing remote rules. You could see how it&#39;s done in the <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools/drools-demo-facts">sample code repository</a> (drools-demo-facts)</p>
<h3 id="retrieving-a-rule-from-drools-workbench">Retrieving a rule from Drools Workbench</h3>
<p>Alright! Now that we&#39;ve cleared up some things needed to be able to fetch rules remotely, we can jump right in to how the configuration of the <code>KieContainer</code> looks like.</p>
<p>The idea of fetching the rules remotely is that your application will download the JAR file of the rules from the Drools Workbench and include its contents into the classpath.
To be able to do this, you need to add the artifact as a <code>KieModule</code> into your application&#39;s <code>KieRepository</code>. The &quot;source&quot; of the <code>KieModule</code> will come from the data contained in the
downloaded rule artifact which is declared as a <code>org.drools.core.io.impl.UrlResource</code> (not to be confused with Spring&#39;s own <code>UrlResource</code>).
Feeling lost? Hopefully this snippet could clear things up a bit.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Bean</span>
<span class="kd">public</span> <span class="n">KieContainer</span> <span class="nf">kieContainer</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
<span class="n">KieServices</span> <span class="n">ks</span> <span class="o">=</span> <span class="n">KieServices</span><span class="o">.</span><span class="na">Factory</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
<span class="n">KieResources</span> <span class="n">resources</span> <span class="o">=</span> <span class="n">ks</span><span class="o">.</span><span class="na">getResources</span><span class="o">();</span>
<span class="n">String</span> <span class="n">url</span> <span class="o">=</span> <span class="s">&quot;http://localhost:8080/kie-drools-wb-6.3.0.Final-wildfly8/maven2/com/rmpader/course-suggestion/1.0/course-suggestion-1.0.jar&quot;</span><span class="o">;</span>
<span class="n">UrlResource</span> <span class="n">urlResource</span> <span class="o">=</span> <span class="o">(</span><span class="n">UrlResource</span><span class="o">)</span> <span class="n">resources</span><span class="o">.</span><span class="na">newUrlResource</span><span class="o">(</span><span class="n">url</span><span class="o">);</span>
<span class="n">urlResource</span><span class="o">.</span><span class="na">setUsername</span><span class="o">(</span><span class="s">&quot;drools-user&quot;</span><span class="o">);</span>
<span class="n">urlResource</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="s">&quot;password&quot;</span><span class="o">);</span>
<span class="n">urlResource</span><span class="o">.</span><span class="na">setBasicAuthentication</span><span class="o">(</span><span class="s">&quot;enabled&quot;</span><span class="o">);</span>
<span class="n">InputStream</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">urlResource</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">();</span>
<span class="n">KieRepository</span> <span class="n">repo</span> <span class="o">=</span> <span class="n">ks</span><span class="o">.</span><span class="na">getRepository</span><span class="o">();</span>
<span class="n">KieModule</span> <span class="n">k</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="na">addKieModule</span><span class="o">(</span><span class="n">resources</span><span class="o">.</span><span class="na">newInputStreamResource</span><span class="o">(</span><span class="n">stream</span><span class="o">));</span>
<span class="k">return</span> <span class="n">ks</span><span class="o">.</span><span class="na">newKieContainer</span><span class="o">(</span><span class="n">k</span><span class="o">.</span><span class="na">getReleaseId</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div>
<p>As you can see here, the authentication parameters need to always be present because Drools Workbench requires authentication details for any form of
interaction. Of course, it would be best if you could externalize the values into a properties file. You can see the complete source <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools/drools-demo-app-remote">here</a>.</p>
<p>Great! So, now we are fetching rules remotely from the workbench. What does this mean, exactly? For one, you no longer need to declare a <code>kmodule.xml</code> in your
application&#39;s <code>src/main/resources</code> folder as well as declare DRL files. That&#39;s one less element that new developers in a project need to know about. However,
there is one piece left missing. How do we...</p>
<hr>
<h2 id="dynamically-change-rule-versions">Dynamically change rule versions</h2>
<p>At this point in the article, the goal to show you how to fetch rules remotely is already met. This section focuses on how to change the version which is basically
executing the same code in the configuration bean for <code>KieContainer</code> with a different artifact URL and executing <code>kieContainer.updateToVersion(...)</code>.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">KieServices</span> <span class="n">ks</span> <span class="o">=</span> <span class="n">KieServices</span><span class="o">.</span><span class="na">Factory</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
<span class="n">KieResources</span> <span class="n">resources</span> <span class="o">=</span> <span class="n">ks</span><span class="o">.</span><span class="na">getResources</span><span class="o">();</span>
<span class="n">String</span> <span class="n">url</span> <span class="o">=</span> <span class="s">&quot;http://localhost:8080/kie-drools-wb-6.3.0.Final-wildfly8/maven2/&quot;</span>
<span class="o">+</span> <span class="n">createPath</span><span class="o">(</span><span class="n">ruleArtifact</span><span class="o">.</span><span class="na">getGroupId</span><span class="o">(),</span>
<span class="n">ruleArtifact</span><span class="o">.</span><span class="na">getArtifactId</span><span class="o">(),</span>
<span class="n">ruleArtifact</span><span class="o">.</span><span class="na">getVersion</span><span class="o">());</span>
<span class="n">UrlResource</span> <span class="n">urlResource</span> <span class="o">=</span> <span class="o">(</span><span class="n">UrlResource</span><span class="o">)</span> <span class="n">resources</span><span class="o">.</span><span class="na">newUrlResource</span><span class="o">(</span><span class="n">url</span><span class="o">);</span>
<span class="n">urlResource</span><span class="o">.</span><span class="na">setUsername</span><span class="o">(</span><span class="s">&quot;drools-user&quot;</span><span class="o">);</span>
<span class="n">urlResource</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="s">&quot;password&quot;</span><span class="o">);</span>
<span class="n">urlResource</span><span class="o">.</span><span class="na">setBasicAuthentication</span><span class="o">(</span><span class="s">&quot;enabled&quot;</span><span class="o">);</span>
<span class="n">InputStream</span> <span class="n">is</span> <span class="o">=</span> <span class="n">urlResource</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">();</span>
<span class="n">KieRepository</span> <span class="n">repo</span> <span class="o">=</span> <span class="n">ks</span><span class="o">.</span><span class="na">getRepository</span><span class="o">();</span>
<span class="n">KieModule</span> <span class="n">k</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="na">addKieModule</span><span class="o">(</span><span class="n">resources</span><span class="o">.</span><span class="na">newInputStreamResource</span><span class="o">(</span><span class="n">is</span><span class="o">));</span>
<span class="n">kieContainer</span><span class="o">.</span><span class="na">updateToVersion</span><span class="o">(</span><span class="n">k</span><span class="o">.</span><span class="na">getReleaseId</span><span class="o">());</span>
</code></pre></div>
<ul>
<li><p><code>createPath()</code> transforms the group ID, artifact ID, and the version into its equivalent URL path. For Example:
<code>com.rmpader.groupid:artifactid:version</code> becomes <code>com/rmpader/groupid/artifactid/version/artifactid-version.jar</code></p></li>
<li><p><code>ruleArtifact</code> is an entity retrieved from the database.</p></li>
</ul>
<p>As with the configuration, you still need to declare the artifact as a <code>UrlResource</code> and add it as a <code>KieModule</code> in the <code>KieRepository</code>. The only new step for that
matter is to update the version that the <code>KieContainer</code> itself is using. Of course, there&#39;s still the matter of saving the activated version details somewhere (e.g. database).
I&#39;ll leave that part up to you but if you wish to see a sample application, you can find one <a href="https://github.com/reypader/blogstuff/tree/master/spring-drools/drools-demo-app-versioned">here</a>.
The sample application saves the group ID, artifact ID, and the version in the database. It also saves which one among all the saved versions is currently active so that
when the application starts up, the application first fetches the version details from the database and constructs the correct artifact URL from it.</p>
<p><strong>Note: The sample application does not take into account multiple instances. In the case that multiple instances are running, activating a version in one instance does not update the version used by the others. That part could be made into a separate article itself.</strong></p>
<hr>
<p>There you have it, a tutorial on how to fetch rules remotely from Drools Workbench.</p>
<p><em>Cheers!</em><br>
Rey</p>
</description>
<pubDate>Wed, 06 Jan 2016 18:06:00 +0800</pubDate>
<link>http://reypader.github.io/2016/01/06/spring-drools.html</link>
<guid isPermaLink="true">http://reypader.github.io/2016/01/06/spring-drools.html</guid>
<category>java</category>
<category>spring</category>
<category>drools</category>
</item>
<item>
<title>How to: Integrate Google Cloud Endpoints into the Spring Container</title>
<description><p>Before we go through this article, I just need to make one thing clear. If you have the freedom to choose other REST frameworks such as Jersey or Spring REST, I urge you to use them instead.
Google Cloud endpoints is okay, but it&#39;s not as flexible as those that I&#39;ve mentioned. I&#39;ll list down some of the limitations I&#39;ve encountered while using Google Cloud Endpoints:</p>
<ul>
<li><strong>You&#39;re pretty much stuck with its authentication mechanism.</strong> - Cloud Endpoints rely on Google&#39;s OAuth to authenticate users. There is a way to <a href="https://cloud.google.com/appengine/docs/java/endpoints/javadoc/com/google/api/server/spi/config/Authenticator">implement your own Authenticator</a> but its documentation is virtually non-existent. You can follow this <a href="http://stackoverflow.com/a/25390994">stackoverflow answer</a>, though.</li>
<li><strong>The default security implementation is not meant for inter-server communication.</strong> - As with the previous item, unless you create your own Authenticator, the default authentication (Google Login) is meant for end-users.</li>
<li><strong>Custom exception-to-error-response handling doesn&#39;t seem to exist.</strong> - I&#39;ve yet to see a similar feature to Spring&#39;s <code>@ExceptionHandler / @ResponseStatus</code> or Jersey&#39;s <code>WebApplicationException / ExceptionMapper</code>. You can extend Cloud Endpoint&#39;s existing exceptions but you&#39;re stuck with how it appears in JSON.</li>
<li><strong>Does not support FileUpload.</strong> - This is understandable because you really can&#39;t write files in GAE. However, there are times when you wish to capture the file in memory and write it somewhere else (Google Cloud Storage). There is a way to do this using servlets but why not do it with a uniform syntax (i.e. the same way you handle other requests).</li>
</ul>
<p>Anyway, that&#39;s just what I was able to gather while using it. If any of the above points are no longer valid, please feel free to message me or write a comment.</p>
<p>On to the article!</p>
<hr>
<h2 id="the-systemserviceservlet">The SystemServiceServlet</h2>
<p>Google Cloud Endpoint instances are created by the <code>SystemServiceServlet</code> class from the App Engine SDK. It uses the <code>newInstance()</code> method to create instances. This is fine unless you&#39;re using IoC frameworks such as Spring.
The problem with how <code>SystemServiceServlet</code> creates instances is that those instances are not &quot;tracked&quot; by Spring. The instances themselves need to exist in a <a href="http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/beans/factory/support/BeanDefinitionRegistry.html">Bean Registry</a>.
You can do this by annotating the Endpoints with <code>@Component</code>. However, you&#39;ll soon find out that if the endpoint has dependencies to other beans, a <code>NullPointerException</code> will be thrown. This is because the instance that Cloud Endpoints used was not able to wire its dependencies.
Recall that <code>SystemServiceServlet</code> uses <code>newInstance()</code> to create the endpoints as shown in the snippet below:</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">SystemServiceServlet</span> <span class="kd">extends</span> <span class="n">HttpServlet</span> <span class="o">{</span>
<span class="o">...</span>
<span class="kd">protected</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">T</span> <span class="nf">createService</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">serviceClass</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">serviceClass</span><span class="o">.</span><span class="na">newInstance</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">InstantiationException</span> <span class="n">var3</span><span class="o">)</span> <span class="o">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">RuntimeException</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">&quot;Cannot instantiate service class: %s&quot;</span><span class="o">,</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">serviceClass</span><span class="o">.</span><span class="na">getName</span><span class="o">()}),</span> <span class="n">var3</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">IllegalAccessException</span> <span class="n">var4</span><span class="o">)</span> <span class="o">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">RuntimeException</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">&quot;Cannot access service class: %s&quot;</span><span class="o">,</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">serviceClass</span><span class="o">.</span><span class="na">getName</span><span class="o">()}),</span> <span class="n">var4</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">...</span>
<span class="o">}</span>
</code></pre></div>
<p>This means that there will be two instances of an endpoint (Cloud Endpoints call them &quot;service&quot;). The instances created by Spring will never be used because <code>SystemServiceServlet</code> does not know about it.
We need to be able to create the instances as beans in Spring and at the same time, make the <code>SystemServiceServlet</code> use them.</p>
<hr>
<h2 id="customizing-systemserviceservlet-createservice">Customizing SystemServiceServlet.createService()</h2>
<p>To ensure that only one instance is created that is both recognized by Spring and used by the servlet, we need to override the implementation of the <code>createService()</code> method with the code below:</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">protected</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">T</span> <span class="nf">createService</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">serviceClass</span><span class="o">)</span> <span class="o">{</span>
<span class="n">ApplicationContext</span> <span class="n">context</span> <span class="o">=</span> <span class="n">WebApplicationContextUtils</span>
<span class="o">.</span><span class="na">getRequiredWebApplicationContext</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">getServletContext</span><span class="o">());</span>
<span class="n">AutowireCapableBeanFactory</span> <span class="n">beanFactory</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getAutowireCapableBeanFactory</span><span class="o">();</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">beanFactory</span><span class="o">.</span><span class="na">getBean</span><span class="o">(</span><span class="n">serviceClass</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">BeansException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">beanName</span> <span class="o">=</span> <span class="n">StringUtils</span><span class="o">.</span><span class="na">uncapitalize</span><span class="o">(</span><span class="n">serviceClass</span><span class="o">.</span><span class="na">getSimpleName</span><span class="o">());</span>
<span class="n">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">&quot;No bean of type&#39;&quot;</span> <span class="o">+</span> <span class="n">serviceClass</span><span class="o">.</span><span class="na">getName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&quot;&#39;.&quot;</span> <span class="o">+</span>
<span class="s">&quot; Creating a new bean named &#39;&quot;</span> <span class="o">+</span> <span class="n">beanName</span> <span class="o">+</span> <span class="s">&quot;&#39;&quot;</span><span class="o">);</span>
<span class="n">T</span> <span class="n">bean</span> <span class="o">=</span> <span class="o">(</span><span class="n">T</span><span class="o">)</span> <span class="n">beanFactory</span><span class="o">.</span><span class="na">createBean</span><span class="o">(</span><span class="n">serviceClass</span><span class="o">,</span> <span class="n">AutowireCapableBeanFactory</span><span class="o">.</span><span class="na">AUTOWIRE_BY_TYPE</span><span class="o">,</span> <span class="kc">true</span><span class="o">);</span>
<span class="k">return</span> <span class="o">(</span><span class="n">T</span><span class="o">)</span> <span class="n">beanFactory</span><span class="o">.</span><span class="na">initializeBean</span><span class="o">(</span><span class="n">bean</span><span class="o">,</span> <span class="n">beanName</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div>
<p>Instead of returning the result of <code>serviceClass.newInstance()</code>, we now return an instance from Spring&#39;s bean registry or create one if it&#39;s not yet there.
Afterwards, make sure to update your <code>web.xml</code> to use the new class as shown below:</p>
<div class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;servlet&gt;</span>
<span class="nt">&lt;servlet-name&gt;</span>SystemServiceServlet<span class="nt">&lt;/servlet-name&gt;</span>
<span class="nt">&lt;servlet-class&gt;</span>
com.rmpader.cloudendpointsspring.compatibility.AutowireSupportSystemServiceServlet
<span class="nt">&lt;/servlet-class&gt;</span>
<span class="nt">&lt;init-param&gt;</span>
<span class="nt">&lt;param-name&gt;</span>services<span class="nt">&lt;/param-name&gt;</span>
<span class="nt">&lt;param-value&gt;</span>
com.rmpader.cloudendpointsspring.api.endpoint.HelloEndpoint
<span class="nt">&lt;/param-value&gt;</span>
<span class="nt">&lt;/init-param&gt;</span>
<span class="nt">&lt;/servlet&gt;</span>
</code></pre></div>
<p>Voila! Your Cloud Endpoints are now officially Spring beans.</p>
<hr>
<p>If you wish to see a sample application, you can find it <a href="https://github.com/reypader/blogstuff/tree/master/cloud-endpoints-spring">here</a>.</p>
<p><em>Cheers!</em><br>
Rey</p>
</description>
<pubDate>Fri, 25 Dec 2015 18:53:00 +0800</pubDate>
<link>http://reypader.github.io/2015/12/25/cloud-endpoints-spring.html</link>
<guid isPermaLink="true">http://reypader.github.io/2015/12/25/cloud-endpoints-spring.html</guid>
<category>java</category>
<category>spring</category>
<category>google-app-engine</category>
<category>google-cloud-endpoints</category>
</item>
<item>
<title>How to: Declare more complex request mappings in Spring</title>
<description><p>There&#39;s a lot of how-to&#39;s out there that could teach you how to create a REST API server with <a href="http://projects.spring.io/spring-boot/">Spring Boot</a>. Actually, spring already has a pretty good <a href="https://spring.io/guides/gs/rest-service/">example</a>. However, most of those found out there are pretty simplistic - the usual &quot;Hello World&quot; application. Of course, if that already showed you what you wanted, you wouldn&#39;t still be looking and stumble upon my humble blog. So, I would show you instead how to make a REST API with <em>the common stuff and use cases</em> that I think you&#39;re probably looking for.</p>
<p><br>
<strong>NOTE: All of the methods shown here assume that they are declared within the following controller:</strong></p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RestController</span>
<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/sample&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SampleController</span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
</code></pre></div>
<p>You can find the source code <a href="https://github.com/reypader/blogstuff/tree/master/spring-request-mapping">here</a>.</p>
<p><br>
Here we go...</p>
<hr>
<h2 id="the-basics">The Basics</h2>
<p>Before I show you how to do the more complex request mappings, I&#39;d like to refresh your memory a bit by showing you the most basic way of declaring request handlers in your controller.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sampleGet</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;This is the &#39;/sample&#39; handler for GET requests&quot;</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">samplePost</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;This is the &#39;/sample&#39; handler for POST requests&quot;</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div>
<p>Notice that these mappings do not declare their own <code>value</code>, which means that they will match the same URL as the containing class. In this case, it would be &quot;/sample&quot;.</p>
<hr>
<h2 id="handling-query-params">Handling Query Params</h2>
<p>One of the most usual case for handling requests are consuming query parameters. For those of you that might call it differently, query parameters are the ones that come after the question mark (<code>?</code>) in the URL. For example, in the URL <code>http://localhost:8080?foo=bar&amp;cat=meow</code>, the query parameters are <code>foo</code> and <code>cat</code> with values <code>bar</code> and <code>meow</code>, respectively.</p>
<p>In the snippet below, the query parameters are automatically parsed into a <code>Map</code> object. From what I know, older versions of Spring does not have this transformation.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/get-with-params&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sampleQueryParam</span><span class="o">(</span><span class="nd">@RequestParam</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">params</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/get-with-params&#39; request handler with the following query params:\n&quot;</span> <span class="o">+</span> <span class="n">params</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div>
<p>There are times when you simply want to do different logic based on certain parameters. For example, if the user passes a query param <code>foo=bar</code> you will create a new database record, otherwise you will do some other logic.</p>
<p>You can do this by placing an <code>if-else</code> block in your handler or in your service but that could lead to some cluttering. Spring has an option that could help you separate your business logic better by allowing you to declare a separate handler when <code>foo</code> is <code>bar</code>. See the snippet below.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/get&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">,</span>
<span class="n">params</span> <span class="o">=</span> <span class="s">&quot;foo=bar&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sampleForFooBar</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/get&#39; request handler where foo MUST be bar&quot;</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div>
<p>With this in place, whenever the query parameters contain the key <code>foo</code> and its value is <code>baz</code>, the <code>sampleForFooBar()</code> will be the one to handle the request.</p>
<p>Be careful, though. Spring executes request handlers that match the same request based on the &quot;best&quot; match which <em>may</em> be the same as the &quot;more strict&quot; match. Consider the two request handlers below.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/get&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">unreachable</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You will never hit this request handler. Why? Because sampleForFooNotBar() has a more strict &#39;criteria&#39;. See RequestMappingInfo.compareTo()&quot;</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/get&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">,</span>
<span class="n">params</span> <span class="o">=</span> <span class="s">&quot;foo!=bar&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sampleForFooNotBar</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/get&#39; request handler where foo should not be bar&quot;</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div>
<p>The second method declares that it would handle any <code>GET</code> request to <code>/get</code> where <code>foo</code> is not assigned to <code>bar</code>. The first method on the other hand simply matches any <code>GET</code> request to <code>/get</code>. The problem will come to light once you try doing a <code>GET</code> to <code>/get</code> without any query parameters. You may expect that the method <code>unreachable()</code> will be executed but you&#39;ll be surprised that it does not. The method <code>sampleForFooNotBar()</code> was matched simply because <code>foo</code> is technically <code>null</code> which is, logically, not <code>bar</code>.</p>
<hr>
<h2 id="handling-path-variables">Handling Path Variables</h2>
<p>There are times when you&#39;d prefer to have some values embedded into the URL itself and not use query parameters. These embedded values are called &quot;path variables&quot;. Including path variables into your request handler is pretty straight forward.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/get/{var}&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">samplePathVariable</span><span class="o">(</span><span class="nd">@PathVariable</span><span class="o">(</span><span class="s">&quot;var&quot;</span><span class="o">)</span> <span class="n">String</span> <span class="n">var</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/get/{var}&#39; request handler with var=&quot;</span> <span class="o">+</span> <span class="n">var</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div>
<hr>
<h2 id="receiving-the-request-body-payload">Receiving the Request Body / Payload</h2>
<p>Have you ever been in the situation where you&#39;ve declared an object parameter in the request handler and expected Spring to deserialize the payload correctly - but it always ends up <code>null</code>?</p>
<p>You&#39;ve probably forgotten to add the <code>@RequestBody</code> annotation.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/post-with-body&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">samplePostBody</span><span class="o">(</span><span class="nd">@RequestBody</span> <span class="n">PostRequest</span> <span class="n">request</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">JsonProcessingException</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/post-with-body&#39; request handler with the following body:\n&quot;</span>
<span class="o">+</span> <span class="n">objectMapper</span><span class="o">.</span><span class="na">writeValueAsString</span><span class="o">(</span><span class="n">request</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div>
<p>Without going into too much details, <code>@RequestBody</code> tells Spring that the body of the request payload/body should be mapped to the annotated parameter. This is important because you can mix and match various parameter types that have been shown in previous sections.</p>
<hr>
<h2 id="responding-with-a-json-object">Responding with a (JSON) Object</h2>
<p>So far, we have only been responding with Strings. Of course, this is not the common use-case. Usually, you&#39;d want to respond with a complex JSON or XML object. Strictly speaking, you have to annotate the method or class with <code>@ResponseBody</code> to declare an object response. However, since this is such a common annotation, you can make do without it. See the snippet below.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/post-with-body&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">,</span>
<span class="n">params</span> <span class="o">=</span> <span class="s">&quot;json=true&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">SampleResponse</span> <span class="nf">sampleJsonResponse</span><span class="o">(</span><span class="nd">@RequestBody</span> <span class="n">PostRequest</span> <span class="n">request</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">JsonProcessingException</span> <span class="o">{</span>
<span class="n">SampleResponse</span> <span class="n">response</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">SampleResponse</span><span class="o">();</span>
<span class="n">response</span><span class="o">.</span><span class="na">setMessage</span><span class="o">(</span><span class="n">samplePostBody</span><span class="o">(</span><span class="n">request</span><span class="o">));</span>
<span class="k">return</span> <span class="n">response</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div>
<hr>
<h2 id="file-uploads">File Uploads</h2>
<p>File uploads in Spring are pretty straightforward. You simply declare a parameter of the type <code>MultipartFile</code> and annotate it with <code>@RequestParam</code> so that Spring knows where to read the data from.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/upload&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">handleFileUpload</span><span class="o">(</span><span class="nd">@RequestParam</span><span class="o">(</span><span class="s">&quot;file&quot;</span><span class="o">)</span> <span class="n">MultipartFile</span> <span class="n">file</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">feile</span><span class="o">.</span><span class="na">getBytes</span><span class="o">();</span>
<span class="k">return</span> <span class="s">&quot;Contents: \n\n&quot;</span> <span class="o">+</span> <span class="k">new</span> <span class="nf">String</span><span class="o">(</span><span class="n">bytes</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div>
<p>One important thing to note here is that this creates a temporary file in the system and the reads from that. This is done for large file uploads where keeping them in memory is not a cost-effective option. However, there are times when you&#39;re not allowed to write to the file system such as when you&#39;re deploying to <a href="https://cloud.google.com/appengine/docs/java/">Google App Engine</a>. </p>
<p>To work around this, you must simply create a bean of the type <code>org.springframework.web.multipart.commons.CommonsMultipartResolver</code> and set the <code>maxInMemorySize</code> property to an appropriate value.</p>
<hr>
<h2 id="handling-different-content-types">Handling Different Content Types</h2>
<p>We&#39;ve covered a lot of variations in handling requests. I&#39;d dare say that these are the most common types that you will encounter in your development. However, there are rare cases when you want to handle request differently simply based on the <code>content-type</code> of the request. Doing so is as simple as declaring the <code>consumes</code> parameter in the <code>@RequestMapping</code> annotation.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/post-strict&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">,</span>
<span class="n">consumes</span> <span class="o">=</span> <span class="n">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON_VALUE</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sampleStrictJson</span><span class="o">(</span><span class="nd">@RequestBody</span> <span class="n">PostRequest</span> <span class="n">request</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">JsonProcessingException</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/post-strict&#39; request handler for &#39;application/json&#39; with the following body:\n&quot;</span>
<span class="o">+</span> <span class="n">objectMapper</span><span class="o">.</span><span class="na">writeValueAsString</span><span class="o">(</span><span class="n">request</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">&quot;/post-strict&quot;</span><span class="o">,</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">,</span>
<span class="n">consumes</span> <span class="o">=</span> <span class="n">MediaType</span><span class="o">.</span><span class="na">APPLICATION_XML_VALUE</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sampleStrictXml</span><span class="o">(</span><span class="nd">@RequestBody</span> <span class="n">PostXMLRequest</span> <span class="n">request</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">JsonProcessingException</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;You&#39;ve hit the &#39;/sample/post-strict&#39; request handler for &#39;application/xml&#39; with the following body (in JSON):\n&quot;</span>
<span class="o">+</span> <span class="n">objectMapper</span><span class="o">.</span><span class="na">writeValueAsString</span><span class="o">(</span><span class="n">request</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div>
<hr>
<h2 id="adding-translatable-exceptions">Adding Translatable Exceptions</h2>
<p>You wouldn&#39;t want the raw exception stacktrace being returned to the clients. In previous versions of Spring you can present exceptions in a more presentable manner by catching all exceptions and constructing a <code>ResponseEntity</code> return type with its status and body set to appropriate values. Since Spring 3, we can annotate exceptions with <code>@ResponseStatus</code> to give Spring an idea on how to present this to the client. You can then throw this annotated exception as-is.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ResponseStatus</span><span class="o">(</span><span class="n">code</span> <span class="o">=</span> <span class="n">HttpStatus</span><span class="o">.</span><span class="na">EXPECTATION_FAILED</span><span class="o">,</span>
<span class="n">reason</span> <span class="o">=</span> <span class="s">&quot;A sample annotated exception.&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SampleTranslatedException</span> <span class="kd">extends</span> <span class="n">RuntimeException</span> <span class="o">{</span>
<span class="o">}</span>
</code></pre></div>
<p>The downside to this is that the description is static. If you&#39;d want a dynamic error description, you should try...</p>
<hr>
<h2 id="writing-an-exception-handler">Writing an Exception Handler</h2>
<p>Setting up your own exception handler is ideal for those cases when you want to assign different descriptions depending on certain parameters. Another benefit to this is that you can do additional tasks such as audit logging, error dumping, or calling other services when an exception is raised.</p>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@ExceptionHandler</span><span class="o">({</span><span class="n">JsonProcessingException</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">IOException</span><span class="o">.</span><span class="na">class</span><span class="o">})</span>
<span class="kd">public</span> <span class="n">ResponseEntity</span><span class="o">&lt;</span><span class="n">ErrorResponse</span><span class="o">&gt;</span> <span class="nf">handleAllExceptions</span><span class="o">(</span><span class="n">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">ErrorResponse</span> <span class="n">errorResponse</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">ErrorResponse</span><span class="o">();</span>
<span class="n">errorResponse</span><span class="o">.</span><span class="na">setMessage</span><span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="k">return</span> <span class="n">ResponseEntity</span><span class="o">.</span><span class="na">status</span><span class="o">(</span><span class="n">HttpStatus</span><span class="o">.</span><span class="na">BAD_REQUEST</span><span class="o">)</span>
<span class="o">.</span><span class="na">body</span><span class="o">(</span><span class="n">errorResponse</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div>
<hr>
<h2 id="other-notes">Other notes</h2>
<p>If you&#39;re not using Spring Boot (which packages a lot of dependencies for you), you might have problems trying to receive or respond JSON objects. If that&#39;s the case, you might be missing the following dependency:</p>
<div class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>com.fasterxml.jackson.core<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>jackson-databind<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
</code></pre></div>
<hr>
<p>That concludes this article. Hopefully, you&#39;ve found the information I&#39;ve presented here useful to your REST API development. If you have questions, feel free to <a href="https://github.com/reypader/reypader.github.io/issues/new?title=How%20to:%20Declare%20more%20complex%20request%20mappings%20in%20Spring">comment/file an issue</a> or if you feel like reading, I suggest you read the <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/">Core Spring Framework documentation</a> or the <a href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/">Spring Boot Documentation</a>.</p>
<p><em>Cheers!</em><br>
Rey</p>
</description>
<pubDate>Mon, 21 Dec 2015 18:53:00 +0800</pubDate>
<link>http://reypader.github.io/2015/12/21/spring-request-mapping.html</link>
<guid isPermaLink="true">http://reypader.github.io/2015/12/21/spring-request-mapping.html</guid>
<category>java</category>
<category>spring</category>
<category>spring-rest</category>
</item>
</channel>
</rss>