forked from Zenika/Blogs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zenikablog.wordpress.2015.xml
12351 lines (11201 loc) · 919 KB
/
zenikablog.wordpress.2015.xml
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
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This is a WordPress eXtended RSS file generated by WordPress as an export of your site. -->
<!-- It contains information about your site's posts, pages, comments, categories, and other content. -->
<!-- You may use this file to transfer that content from one site to another. -->
<!-- This file is not intended to serve as a complete backup of your site. -->
<!-- To import this information into a WordPress site follow these steps: -->
<!-- 1. Log in to that site as an administrator. -->
<!-- 2. Go to Tools: Import in the WordPress admin panel. -->
<!-- 3. Install the "WordPress" importer from the list. -->
<!-- 4. Activate & Run Importer. -->
<!-- 5. Upload this file using the form provided on that page. -->
<!-- 6. You will first be asked to map the authors in this export file to users -->
<!-- on the site. For each author, you may choose to map to an -->
<!-- existing user on the site or to create a new user. -->
<!-- 7. WordPress will then import each of the posts, pages, comments, categories, etc. -->
<!-- contained in this file into your site. -->
<!-- generator="WordPress/4.9.10" created="2019-05-03 14:25" -->
<rss version="2.0"
xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:wp="http://wordpress.org/export/1.2/"
>
<channel>
<title>Zenika Blog</title>
<link>https://blog.zenika.com</link>
<description>IT Systems architecture, frameworks and random thoughts</description>
<pubDate>Fri, 03 May 2019 14:25:40 +0000</pubDate>
<language>fr-FR</language>
<wp:wxr_version>1.2</wp:wxr_version>
<wp:base_site_url>https://blog.zenika.com</wp:base_site_url>
<wp:base_blog_url>https://blog.zenika.com</wp:base_blog_url>
<wp:author><wp:author_id>8</wp:author_id><wp:author_login><![CDATA[alamineousman]]></wp:author_login><wp:author_email><![CDATA[al-amine.ousman@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Al Amine Ousman]]></wp:author_display_name><wp:author_first_name><![CDATA[Al Amine]]></wp:author_first_name><wp:author_last_name><![CDATA[OUSMAN]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>95</wp:author_id><wp:author_login><![CDATA[edemey]]></wp:author_login><wp:author_email><![CDATA[emmanuel.demey@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Emmanuel DEMEY]]></wp:author_display_name><wp:author_first_name><![CDATA[Emmanuel]]></wp:author_first_name><wp:author_last_name><![CDATA[DEMEY]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>35</wp:author_id><wp:author_login><![CDATA[lclaisse]]></wp:author_login><wp:author_email><![CDATA[laurent.claisse@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Laurent Claisse]]></wp:author_display_name><wp:author_first_name><![CDATA[Laurent]]></wp:author_first_name><wp:author_last_name><![CDATA[CLAISSE]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>27</wp:author_id><wp:author_login><![CDATA[gquintana]]></wp:author_login><wp:author_email><![CDATA[gerald.quintana@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Gérald Quintana]]></wp:author_display_name><wp:author_first_name><![CDATA[Gérald]]></wp:author_first_name><wp:author_last_name><![CDATA[QUINTANA]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>39</wp:author_id><wp:author_login><![CDATA[mloriedo]]></wp:author_login><wp:author_email><![CDATA[mario.loriedo@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Mario Loriedo]]></wp:author_display_name><wp:author_first_name><![CDATA[Mario]]></wp:author_first_name><wp:author_last_name><![CDATA[LORIEDO]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>60</wp:author_id><wp:author_login><![CDATA[Zenika-HashCode]]></wp:author_login><wp:author_email><![CDATA[]]></wp:author_email><wp:author_display_name><![CDATA[Zenika-HashCode]]></wp:author_display_name><wp:author_first_name><![CDATA[]]></wp:author_first_name><wp:author_last_name><![CDATA[Julien Landuré, Germain Potet & Hugo Wood]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>61</wp:author_id><wp:author_login><![CDATA[team-buchet-md]]></wp:author_login><wp:author_email><![CDATA[]]></wp:author_email><wp:author_display_name><![CDATA[team-buchet-md]]></wp:author_display_name><wp:author_first_name><![CDATA[]]></wp:author_first_name><wp:author_last_name><![CDATA[Martine Metzger-Douçot & Gwennael Buchet]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>12</wp:author_id><wp:author_login><![CDATA[acogoluegnes]]></wp:author_login><wp:author_email><![CDATA[arnaud.cogoluegnes@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Arnaud Cogoluègnes]]></wp:author_display_name><wp:author_first_name><![CDATA[Arnaud]]></wp:author_first_name><wp:author_last_name><![CDATA[COGOLUEGNES]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>62</wp:author_id><wp:author_login><![CDATA[npayot]]></wp:author_login><wp:author_email><![CDATA[nicolas.payot@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Nicolas Payot]]></wp:author_display_name><wp:author_first_name><![CDATA[Nicolas]]></wp:author_first_name><wp:author_last_name><![CDATA[PAYOT]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>53</wp:author_id><wp:author_login><![CDATA[jlandure]]></wp:author_login><wp:author_email><![CDATA[julien.landure@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Julien Landuré]]></wp:author_display_name><wp:author_first_name><![CDATA[Julien]]></wp:author_first_name><wp:author_last_name><![CDATA[LANDURE]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>70</wp:author_id><wp:author_login><![CDATA[mmouterde]]></wp:author_login><wp:author_email><![CDATA[martin.mouterde@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Martin Mouterde]]></wp:author_display_name><wp:author_first_name><![CDATA[Martin]]></wp:author_first_name><wp:author_last_name><![CDATA[MOUTERDE]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>73</wp:author_id><wp:author_login><![CDATA[ncuillery]]></wp:author_login><wp:author_email><![CDATA[nicolas.cuillery@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Nicolas Cuillery]]></wp:author_display_name><wp:author_first_name><![CDATA[Nicolas]]></wp:author_first_name><wp:author_last_name><![CDATA[CUILLERY]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>78</wp:author_id><wp:author_login><![CDATA[rroy]]></wp:author_login><wp:author_email><![CDATA[regis.roy@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Regis Roy]]></wp:author_display_name><wp:author_first_name><![CDATA[Régis]]></wp:author_first_name><wp:author_last_name><![CDATA[ROY]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>37</wp:author_id><wp:author_login><![CDATA[agarnier]]></wp:author_login><wp:author_email><![CDATA[alexandre.garnier@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Alexandre Garnier]]></wp:author_display_name><wp:author_first_name><![CDATA[Alexandre]]></wp:author_first_name><wp:author_last_name><![CDATA[Garnier]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>81</wp:author_id><wp:author_login><![CDATA[devopsday]]></wp:author_login><wp:author_email><![CDATA[devopsday@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Vincent Demeester & Youcef Yekhlef]]></wp:author_display_name><wp:author_first_name><![CDATA[]]></wp:author_first_name><wp:author_last_name><![CDATA[Vincent Demeester & Youcef Yekhlef]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>79</wp:author_id><wp:author_login><![CDATA[vdemeester]]></wp:author_login><wp:author_email><![CDATA[vincent.demeester@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Vincent Demeester]]></wp:author_display_name><wp:author_first_name><![CDATA[Vincent]]></wp:author_first_name><wp:author_last_name><![CDATA[DEMEESTER]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>82</wp:author_id><wp:author_login><![CDATA[team-legat-detant]]></wp:author_login><wp:author_email><![CDATA[]]></wp:author_email><wp:author_display_name><![CDATA[team-legat-detant]]></wp:author_display_name><wp:author_first_name><![CDATA[]]></wp:author_first_name><wp:author_last_name><![CDATA[Yohan Legat & Xavier Detant]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>33</wp:author_id><wp:author_login><![CDATA[Ksouf]]></wp:author_login><wp:author_email><![CDATA[khaled.souf@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Khaled Souf]]></wp:author_display_name><wp:author_first_name><![CDATA[Khaled]]></wp:author_first_name><wp:author_last_name><![CDATA[SOUF]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>92</wp:author_id><wp:author_login><![CDATA[pvauthier]]></wp:author_login><wp:author_email><![CDATA[paul-julien.vauthier@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Paul-Julien Vauthier]]></wp:author_display_name><wp:author_first_name><![CDATA[Paul-Julien]]></wp:author_first_name><wp:author_last_name><![CDATA[VAUTHIER]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>227</wp:author_id><wp:author_login><![CDATA[tmp-dsi]]></wp:author_login><wp:author_email><![CDATA[dsi-ext@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Tmp DSI]]></wp:author_display_name><wp:author_first_name><![CDATA[Tmp]]></wp:author_first_name><wp:author_last_name><![CDATA[DSI]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>98</wp:author_id><wp:author_login><![CDATA[mverriez]]></wp:author_login><wp:author_email><![CDATA[manuel.verriez@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Manuel VERRIEZ]]></wp:author_display_name><wp:author_first_name><![CDATA[Manuel]]></wp:author_first_name><wp:author_last_name><![CDATA[VERRIEZ]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>50</wp:author_id><wp:author_login><![CDATA[mlux]]></wp:author_login><wp:author_email><![CDATA[matthieu.lux@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Matthieu Lux]]></wp:author_display_name><wp:author_first_name><![CDATA[Matthieu]]></wp:author_first_name><wp:author_last_name><![CDATA[LUX]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>218</wp:author_id><wp:author_login><![CDATA[rcoffre]]></wp:author_login><wp:author_email><![CDATA[richard.coffre@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Richard COFFRE]]></wp:author_display_name><wp:author_first_name><![CDATA[Richard]]></wp:author_first_name><wp:author_last_name><![CDATA[COFFRE]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>59</wp:author_id><wp:author_login><![CDATA[avillenave]]></wp:author_login><wp:author_email><![CDATA[arnaud.villenave@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Arnaud Villenave]]></wp:author_display_name><wp:author_first_name><![CDATA[Arnaud]]></wp:author_first_name><wp:author_last_name><![CDATA[VILLENAVE]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>58</wp:author_id><wp:author_login><![CDATA[sdescamps]]></wp:author_login><wp:author_email><![CDATA[sebastien.descamps@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Sébastien Descamps]]></wp:author_display_name><wp:author_first_name><![CDATA[Sébastien]]></wp:author_first_name><wp:author_last_name><![CDATA[DESCAMPS]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>230</wp:author_id><wp:author_login><![CDATA[aboivin]]></wp:author_login><wp:author_email><![CDATA[arnaud.boivin@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Arnaud Boivin]]></wp:author_display_name><wp:author_first_name><![CDATA[Arnaud]]></wp:author_first_name><wp:author_last_name><![CDATA[Boivin]]></wp:author_last_name></wp:author>
<wp:author><wp:author_id>232</wp:author_id><wp:author_login><![CDATA[gmembre]]></wp:author_login><wp:author_email><![CDATA[guillaume.membre@zenika.com]]></wp:author_email><wp:author_display_name><![CDATA[Guillaume Membré]]></wp:author_display_name><wp:author_first_name><![CDATA[Guillaume]]></wp:author_first_name><wp:author_last_name><![CDATA[Membré]]></wp:author_last_name></wp:author>
<generator>https://wordpress.org/?v=4.9.10</generator>
<image>
<url>https://blog.zenika.com/wp-content/uploads/2019/03/cropped-LOGO-rond-ROUGE-1-32x32.png</url>
<title>Zenika Blog</title>
<link>https://blog.zenika.com</link>
<width>32</width>
<height>32</height>
</image>
<item>
<title>Nouvelle version de la formation "Enterprise Spring"</title>
<link>https://blog.zenika.com/2015/01/12/nouvelle-version-de-la-formation-enterprise-spring/</link>
<pubDate>Mon, 12 Jan 2015 14:37:00 +0000</pubDate>
<dc:creator><![CDATA[alamineousman]]></dc:creator>
<guid isPermaLink="false">http://znk.vibioh.fr/2015/01/12/20150112nouvelle-version-de-la-formation-enterprise-spring/</guid>
<description></description>
<content:encoded><![CDATA[Avec la formation "Enterprise Integration with Spring", Zenika a le plaisir depuis de nombreuses années de vous former avec succès sur la partie "enterprise" des technologies Spring (web services, messaging, batch). Cette formation vient d’être renommée en <a href="http://www.zenika.com/formation-enterprise-spring.html" target="_blank">"Enterprise Spring"</a> et ce renommage vient avec son lot de nouveautés !
<!--more-->
La formation "Enterprise Spring" vous permet de découvrir les meilleures techniques d’intégration et de les mettre immédiatement en pratique avec les différentes briques de Spring : Spring MVC REST, Spring Web Services pour SOAP, Spring JMS et AMPQ et enfin Spring Integration et Spring Batch. Les avantages et inconvénients de chaque technique sont clairement mis en évidence afin de vous permettre de choisir la solution la plus adaptée à vos applications.
Voici les principales nouveautés de cette mise à jour :
<ul>
<li>Nouveau module sur <a href="http://projects.spring.io/spring-amqp/" target="_blank">Spring AMQP</a>, pour utiliser des messages asynchrones avec Spring et <a href="http://www.rabbitmq.com/" target="_blank">RabbitMQ</a></li>
<li>Refonte du module REST</li>
<li>Un module supplémentaire sur Spring Integration</li>
<li>Nombreuses figures ajoutées dans les différents modules (Spring Integration, scaling et parallélisation avec Spring Batch)</li>
<li>Certification mise à jour en conséquence</li>
</ul>
Les technologies Spring ne cessent d’évoluer pour nous permettre d’écrire des applications encore plus sophistiquées et robustes, tout en conservant la simplicité qui a fait la force de Spring. La formation "Enterprise Spring" et Zenika sont là pour vous faire monter rapidement en compétences, nous <a href="http://www.zenika.com/formation-enterprise-spring.html" target="_blank">vous attendons avec impatience</a> !]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>50</wp:post_id>
<wp:post_date><![CDATA[2015-01-12 15:37:00]]></wp:post_date>
<wp:post_date_gmt><![CDATA[2015-01-12 14:37:00]]></wp:post_date_gmt>
<wp:comment_status><![CDATA[open]]></wp:comment_status>
<wp:ping_status><![CDATA[closed]]></wp:ping_status>
<wp:post_name><![CDATA[nouvelle-version-de-la-formation-enterprise-spring]]></wp:post_name>
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[post]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="formations"><![CDATA[Formations]]></category>
<wp:postmeta>
<wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[slide_template]]></wp:meta_key>
<wp:meta_value><![CDATA[default]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_post]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_cat_label]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_disable]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_reviews]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_pos]]></wp:meta_key>
<wp:meta_value><![CDATA[none]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_type]]></wp:meta_key>
<wp:meta_value><![CDATA[points]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_verdict]]></wp:meta_key>
<wp:meta_value><![CDATA[Awesome]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wp_old_slug]]></wp:meta_key>
<wp:meta_value><![CDATA[20150112nouvelle-version-de-la-formation-enterprise-spring]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_thumbnail_id]]></wp:meta_key>
<wp:meta_value><![CDATA[3128]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wpghs_github_path]]></wp:meta_key>
<wp:meta_value><![CDATA[_articles/2015-01-12-nouvelle-version-de-la-formation-enterprise-spring.md]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_sha]]></wp:meta_key>
<wp:meta_value><![CDATA[49d92093cec22d9d37a550ea1a93305c61bccfdb]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_jetpack_related_posts_cache]]></wp:meta_key>
<wp:meta_value><![CDATA[a:1:{s:32:"8f6677c9d6b0f903e98ad32ec61f8deb";a:2:{s:7:"expires";i:1479727669;s:7:"payload";a:3:{i:0;a:1:{s:2:"id";i:290;}i:1;a:1:{s:2:"id";i:82;}i:2;a:1:{s:2:"id";i:85;}}}}]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Relevez le challenge "The Great Escape" sur CodinGame</title>
<link>https://blog.zenika.com/2015/02/03/relevez-le-challenge-the-great-escape/</link>
<pubDate>Tue, 03 Feb 2015 17:11:00 +0000</pubDate>
<dc:creator><![CDATA[alamineousman]]></dc:creator>
<guid isPermaLink="false">http://znk.vibioh.fr/2015/02/03/20150203relevez-le-challenge-the-great-escape/</guid>
<description></description>
<content:encoded><![CDATA[En tant que partenaire de la plateforme CodinGame, Zenika vous propose de relever le défi “The Great Escape” qui commence le 6 février prochain.
<!--more-->
The Great Escape est un challenge d'intelligence artificielle multijoueurs. Vous aurez 2 semaines pour coder l'IA qui vous permettra de vous échapper d'un labyrinthe. Vous devrez essayer de bloquer vos ennemis et d'éviter leurs pièges si vous voulez vous en sortir sain et sauf.
<strong>Pour vous inscrire rendez vous sur <a href="http://www.codingame.com/challenge/the-great-escape">GodinGame</a></strong>
<h5>Informations pratiques :</h5>
<ul>
<li>Participation 100% en ligne et gratuite</li>
<li>20 langages de programmation disponibles</li>
<li>Des lots : GoPro 4, iPad Mini, et 25+ t-shirts</li>
<li>Des jobs / stages à décrocher auprès des différents sponsors</li>
<li>Leaderboard international avec classement par universités</li>
<li>Ouvert à tous les programmeurs, quel que soit leur niveau : pas besoin d'être un expert en IA pour passer un bon moment :)</li>
</ul>]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>51</wp:post_id>
<wp:post_date><![CDATA[2015-02-03 18:11:00]]></wp:post_date>
<wp:post_date_gmt><![CDATA[2015-02-03 17:11:00]]></wp:post_date_gmt>
<wp:comment_status><![CDATA[open]]></wp:comment_status>
<wp:ping_status><![CDATA[closed]]></wp:ping_status>
<wp:post_name><![CDATA[relevez-le-challenge-the-great-escape]]></wp:post_name>
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[post]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="flash-info"><![CDATA[Flash Info]]></category>
<wp:postmeta>
<wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[slide_template]]></wp:meta_key>
<wp:meta_value><![CDATA[]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_thumbnail_id]]></wp:meta_key>
<wp:meta_value><![CDATA[6005]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_post]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_cat_label]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_disable]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_reviews]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_pos]]></wp:meta_key>
<wp:meta_value><![CDATA[none]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_type]]></wp:meta_key>
<wp:meta_value><![CDATA[points]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_verdict]]></wp:meta_key>
<wp:meta_value><![CDATA[Awesome]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wp_old_slug]]></wp:meta_key>
<wp:meta_value><![CDATA[20150203relevez-le-challenge-the-great-escape]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wpghs_github_path]]></wp:meta_key>
<wp:meta_value><![CDATA[_articles/2015-02-03-relevez-le-challenge-the-great-escape.md]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_sha]]></wp:meta_key>
<wp:meta_value><![CDATA[220412a3950bed6b78aa84d3cce74d796ce11fa6]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_jetpack_related_posts_cache]]></wp:meta_key>
<wp:meta_value><![CDATA[a:1:{s:32:"8f6677c9d6b0f903e98ad32ec61f8deb";a:2:{s:7:"expires";i:1480034851;s:7:"payload";a:3:{i:0;a:1:{s:2:"id";i:8391;}i:1;a:1:{s:2:"id";i:59;}i:2;a:1:{s:2:"id";i:9080;}}}}]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Facilitation Graphique : rencontre autour d'un marqueur avec Roberta Faulhaber</title>
<link>https://blog.zenika.com/2015/03/16/facilitation-graphique-rencontre-avec-roberta-faulhaber/</link>
<pubDate>Mon, 16 Mar 2015 15:45:00 +0000</pubDate>
<dc:creator><![CDATA[alamineousman]]></dc:creator>
<guid isPermaLink="false">http://znk.vibioh.fr/2015/03/16/20150316facilitation-graphique-rencontre-avec-roberta-faulhaber/</guid>
<description></description>
<content:encoded><![CDATA[Zenika est heureux de vous annoncer l'ajout à son catalogue d'un cycle de formation autour de la « Facilitation Graphique ».
Ces sessions seront animées par <strong>Roberta Faulhaber</strong> et auront lieu à Paris :
<ul>
<li><a href="http://www.zenika.com/formation-facilitation-graphique.html">Facilitation Graphique Fondamentaux (niveau 1)</a> : 30 mars et 15 juin</li>
</ul>
<ul>
<li><a href="http://www.zenika.com/formation-facilitation-graphique-approfondissement.html">Facilitation Graphique Approfondissements (niveau 2)</a> : 27 avril et 09 juillet</li>
</ul>
<!--more-->
Roberta s’est prêtée au jeu de l’interview pour présenter les enjeux de la facilitation graphique, nous vous proposons d’en lire un extrait !
<h4>Qu'est-ce que la facilitation graphique en deux mots ?</h4>
<blockquote>En deux mots (et un peu plus !), il s'agit d'utiliser la pensée visuelle et le dessin pour animer, coacher, organiser, faciliter la création de sens au niveau individuel et collectif, dans un cadre personnel et professionnel.
Nous utilisons des dessins et des dispositifs visuels simples et claires en tant que contenu statique ou comme outil de facilitation de réunion ou de management, avec la prise de notes visuelles en plus.
Bien que le travail d'un facilitateur graphique soit un métier à part entière, tout le monde peut apprendre le langage visuel et des templates simples pour réfléchir, sentir et agir au niveau personnel et professionnel, seul ou en groupe.</blockquote>
<h4>Faut-il savoir dessiner pour faire de la facilitation graphique ?</h4>
<img style="margin: 0 1em 1em 0;" title="Facilitation Graphique2" src="/wp-content/uploads/2015/07/facilitation-graphique2.jpg" alt="Facilitation Graphique2" />
<blockquote>Oui et non. Il s’agit de découvrir qu'en fait, tout le monde a la capacité de dessiner, d'apprendre un langage visuel simple qui peut être utilisé efficacement et partout dans sa vie. C'est comme la danse : tout le monde "sait" danser, bouger son corps avec la musique.
Par la suite, on peut enrichir cette capacité naturelle avec un langage, un style, une tradition, des expériences sociales, en fonction des désirs et objectifs de chaque individu. Certaines personnes deviendront des danseurs pro, mais cela n'empêche pas chacun de profiter de sa propre capacité à danser.
Ainsi, dans la <strong>facilitation graphique</strong>, on peut réfléchir avec des flèches, carrés, cercles, mots, bonhommes simples, cartes heuristiques, diagrammes élémentaires ; on peut exprimer sa créativité et ses émotions, clarifier un dispositif visuel pédagogique avec couleurs, ombres simples, picto et idéogrammes, mais aussi utiliser un template simple.
Le <strong>template</strong> est un outil indispensable de la facilitation graphique. C’est une <strong>métaphore visuelle</strong> en petit ou grand format qui permet de comprendre une situation sous un autre angle, de répondre à des questions fondamentales, de se mettre d'accord sur une vision, une stratégie, un objectif, d’élaborer un plan d'actions, seul ou avec ses collègues, amis, et famille, quelque soit la profession de chacun. En gros, nous pouvons à la fois avoir une vue d’hélicoptère et garder les pieds bien sur terre en réfléchissant aux actions à entreprendre. C’est une carte qui permet de dépasser l’horizon.</blockquote>
<h4>Comment utiliser la facilitation graphique dans son travail au quotidien ?</h4>
La matrice ci-dessous montre différentes façons d’utiliser la facilitation graphique.
<img style="display: block; margin: 0 auto;" title="Facilitation Graphique4" src="/wp-content/uploads/2015/07/facilitation-graphique4.jpg" alt="Facilitation Graphique4" />
<blockquote>En haut à gauche, nous avons le <strong>reportage ou récolte graphique</strong>. C’est un vrai métier ou le facilitateur graphique, en tant que “partenaire silencieux”, utilise son écoute active et sa capacité de synthèse visuelle en temps réel pour modéliser la conversation et le process du groupe visuellement.
En haut à droite, il y a <strong>facilitation graphique</strong>, où le facilitateur graphique reste en interaction avec le groupe pour travailler visuellement, généralement avec un template adapté.
En bas à droite, <strong>avec la co-création</strong>, le facilitateur visuel co-crée le visuel avec le groupe en temps réel.
En bas à gauche, pour représenter un contenu statique à visé pédagogique ou dans le cadre d’une présentation, d’un séminaire, ou autre type de réunion, <strong>nous avons le storymap et le concept-mapping</strong>. Le facilitateur visuel crée un dispositif visuel pour le groupe, ou une carte métaphorique qui raconte une histoire. Le storymap peut émerger d’une récolte graphique, d’une réunion visuelle, ou d’un processus de co-création.</blockquote>
<h4>Quels sont les bénéfices de ce mode de communication ?</h4>
<blockquote>Ce n'est pas qu'un mode de communication dans le sens où il s'agit d'exposer une idée ou vendre quelque chose avec une campagne de publicité. Il s'agit de bénéfices par rapport au sens large de la communication, c'est-à-dire notre capacité à dialoguer efficacement et de travailler ensemble en bonne intelligence collective. L'arbre des bénéfices ci-dessous présente un certain nombre des avantages dans le cadre d’une réunion avec facilitation graphique.</blockquote>
<img style="display: block; margin: 0 auto;" title="Facilitation Graphique5" src="/wp-content/uploads/2015/07/Facilitation-graphique5.png" alt="Facilitation Graphique5" />
Certains collaborateurs de Zenika ont suivi cette formation. Découvrez leurs témoignages !
« On le voit avec les mails, sur twitter et les réseaux sociaux : la manière plus efficace de capturer notre attention et de faire passer un message c'est à travers les images. Et la formation facilitation graphique nous apprend à représenter rapidement, avec le minimum de trait, une idée, un process, une émotion. Ce qui nous aurait pris des heures nous prend désormais 5 minutes avec les techniques apprises au cours de la formation. »
<em>Mario LORIEDO, Consultant</em>
« J’ai pu constater grâce à cette formation, que le dessin permet de transmettre et rendre visibles des informations qui ne sont pas véhiculées par le verbal. Les chiffres et tableaux comptables que j’utilise dans ma fonction ne sont pas les outils de communications les plus attrayants ; je me suis rendue compte que l’on peut intéresser un public d’horizons différents et dégager des intérêts et synergies communs par la facilitation graphique. »
<em>Emilie WAUQUIER, Contrôleuse de gestion</em>
Si vous souhaitez plus d’informations, contactez-nous : <a href="mailto:training@zenika.com">training@zenika.com</a>
<h5>A propos de Roberta</h5>
<img style="float: left; margin: 0 1em 1em 0;" title="Roberta" src="/wp-content/uploads/2015/07/Roberta_Faulhaber.jpg" alt="Roberta" /> Roberta est d'origine américaine, une francophile enthousiaste qui habite Paris depuis plus de 30 ans. Elle est en France l’une des pionnières d’un nouveau type de facilitation, la facilitation visuelle ou graphique, au travers duquel elle traduit, graphiquement et sur de grandes fresques murales, les idées, les processus, et les émotions qui émergent d’un groupe de travail en temps réel.]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>53</wp:post_id>
<wp:post_date><![CDATA[2015-03-16 16:45:00]]></wp:post_date>
<wp:post_date_gmt><![CDATA[2015-03-16 15:45:00]]></wp:post_date_gmt>
<wp:comment_status><![CDATA[open]]></wp:comment_status>
<wp:ping_status><![CDATA[closed]]></wp:ping_status>
<wp:post_name><![CDATA[facilitation-graphique-rencontre-avec-roberta-faulhaber]]></wp:post_name>
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[post]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="flash-info"><![CDATA[Flash Info]]></category>
<wp:postmeta>
<wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[slide_template]]></wp:meta_key>
<wp:meta_value><![CDATA[]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_post]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_cat_label]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_disable]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_reviews]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_pos]]></wp:meta_key>
<wp:meta_value><![CDATA[none]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_type]]></wp:meta_key>
<wp:meta_value><![CDATA[points]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_verdict]]></wp:meta_key>
<wp:meta_value><![CDATA[Awesome]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_thumbnail_id]]></wp:meta_key>
<wp:meta_value><![CDATA[5989]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wp_old_slug]]></wp:meta_key>
<wp:meta_value><![CDATA[20150316facilitation-graphique-rencontre-avec-roberta-faulhaber]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wpghs_github_path]]></wp:meta_key>
<wp:meta_value><![CDATA[_articles/2015-03-16-facilitation-graphique-rencontre-avec-roberta-faulhaber.md]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_sha]]></wp:meta_key>
<wp:meta_value><![CDATA[72f876f82b490813caf929f53a23de60ace2b163]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_jetpack_related_posts_cache]]></wp:meta_key>
<wp:meta_value><![CDATA[a:1:{s:32:"8f6677c9d6b0f903e98ad32ec61f8deb";a:2:{s:7:"expires";i:1479977689;s:7:"payload";a:3:{i:0;a:1:{s:2:"id";i:8302;}i:1;a:1:{s:2:"id";i:26;}i:2;a:1:{s:2:"id";i:224;}}}}]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Book review: Mastering lambdas</title>
<link>https://blog.zenika.com/2015/02/05/book-review-mastering-lambdas/</link>
<pubDate>Thu, 05 Feb 2015 16:30:00 +0000</pubDate>
<dc:creator><![CDATA[lclaisse]]></dc:creator>
<guid isPermaLink="false">http://znk.vibioh.fr/2015/02/05/20150205book-review-mastering-lambdas/</guid>
<description></description>
<content:encoded><![CDATA[<img style="float: left; margin: 0 1em 1em 0;" src="/wp-content/uploads/2015/07/cover.jpg" alt="cover.jpg" /> <a href="http://www.amazon.fr/Mastering-Lambdas-Programming-Multicore-World/dp/0071829628/ref=sr_1_1_twi_1?s=english-books&ie=UTF8&qid=1422549092&sr=1-1&keywords=mastering+lambdas">Mastering lambdas</a> is the second book I've read about lambda. The first one, that i'll use for comparison, was "Java 8 in action" (which is about Java 8 in general, not only lambdas).
<!--more-->
This one is written in the same precise style as the very good (and relatively little known) "Java generics and collections", of which Naftalin is a co-author. Some of the content (exception management, performance considerations,...) can't be found anywhere else. On the other hand J8IA is not as well written, but it covers one important technique that "Mastering lambdas" doesn't (using CompletableFutures with Streams).
Overall it's a great book. Also because it's so concise, it's not too thick and can be read in a few days.
This review is based on the printed version, not the Kindle edition (that i didn't try).
<h3>CHAPTER 1: Taking Java to the Next Level</h3>
The book begins with the now usual explanation of how in a multi-core context, going from external to internal iteration lets the java runtime utilize new "degrees of freedom", particularly to enable parallelism.
<h4>A structured explanation of the main programming model changes</h4>
From anonymous inner classes to lambdas: All that can logically be inferred by the compiler is introduced step by step
From collections to streams: The old model of chaining transformations by creating a new Collection at every step is bad from performance (creating a lot of intermediary objects), and also pollutes the code with boilerplate. The solution is to use unix-like pipes and filters, which are lazy and compose into pipelines better than classes.
From sequential to parallel: Parallelism is explicit, but unobstrusive, using just <code>parallelStream()</code>.
Lazyness: The intermediate operations don't pull any data from the pipeline's source. Work is only done when it can't be delayed anymore, which is at the pipeline's terminal operation.
<h3>CHAPTER 2:The Basics of Java Lambda Expressions</h3>
<h4>The grammar of lambdas</h4>
This chapter goes in more detail into the grammar of lambdas. The compiler's inference engine is well explained, which makes lambdas feel less magical than in the usual presentations. The part on the different kinds of method handles is much better than what I read so far (i didn't get the difference between <em>instance bound</em> and <em>instance unbound</em> references before).
<h4>From basic stuff to more advanced topics</h4>
It goes progressively:
Expression lambdas and statement lambdas
Differences with anonymous classes (ex: doesn't have to be a new instance every time)
Syntax, scope, and capture rules (unlike Javascript the value, and the not the variable, is captured)
<code>java.util.function</code>: the starter kit of functional interfaces
Type inference rules
Method references kinds: static, instance bound, instance unbound (for those, invocation target is the first lambda argument)
Detailed rules: checked exceptions handling, overload resolution
<h3>CHAPTER 3:Introduction to Streams and Pipelines</h3>
<h4>Goals of pipelining operations</h4>
A pipeline fuses multiple logical operations into one single pass on the data, like with unix pipes. Pipelines are composed of:
<ol>
<li>a source</li>
<li>intermediate operations (composed from the API's Stream->Stream methods)</li>
<li>a terminal operation</li>
</ol>
The most common of each are listed in this chapter.
An important point is that composing stream operations into a pipeline is only a logical transformation, which doesn't pull any data from the pipeline's source yet.
Another advantage of streams related to lazy processing is <em>short-circuiting</em>: for some operations, if a result is found, the rest can be skipped (ex: if we want to check that a property is true for all elements, we can skip the rest of the stream if we find one element for which it's false).
<h5>One unclear point in this chapter</h5>
"As we saw in §3.1, calling the terminal operation of a pipeline results in the execution of a fusion of its intermediate operations. As a result, the usual debugging technique of stepping through operations is not available for streams<a title="..." href="...">...</a>" For sure, I can place a breakpoint in a lambda (tested with Eclipse and IntelliJ):
<pre class="lang:default decode:true java code java">Stream.of ("toto", "tata", "titi").map (s -> {
System.out.println ("STEP 1 Stream: " + s); //i can stop at this breakpoint
return s;
}).map (s -> {
System.out.println ("STEP 2 Stream: " + s); //i can stop at this breakpoint
return s;
}).forEach (s -> {
System.out.println ("STEP 3 Stream: " + s); //i can stop at this breakpoint
})
;</pre>
That's one advantage over .NET lambdas, where I can't stop at the same breakpoints (tested with C# 4.5 in Visual Studio). I think the author means that there is no breakpoint corresponding to completion of a single filter of the pipeline, because execution order is not the same as with external iteration. The previous code displays this:
<pre class="lang:default decode:true java code java">STEP 1 Stream: toto
STEP 2 Stream: toto
STEP 3 Stream: toto
STEP 1 Stream: tata
STEP 2 Stream: tata
STEP 3 Stream: tata
STEP 1 Stream: titi
STEP 2 Stream: titi
STEP 3 Stream: titi</pre>
Whereas the corresponding external iteration approach:
<pre class="lang:default decode:true java code java">List<String> input = Arrays.asList ("toto", "tata", "titi");
List<String> step1 = new ArrayList<String> (input);
for(String s : step1) System.out.println ("STEP 1 Iterator: " + s);
List<String> step2 = new ArrayList<String> (step1);
for(String s : step1) System.out.println ("STEP 2 Iterator: " + s);
List<String> step3 = new ArrayList<String> (step2);
for(String s : step1) System.out.println ("STEP 3 Iterator: " + s);</pre>
Displays that:
<pre class="lang:default decode:true java code java">STEP 1 Iterator: toto
STEP 1 Iterator: tata
STEP 1 Iterator: titi
STEP 2 Iterator: toto
STEP 2 Iterator: tata
STEP 2 Iterator: titi
STEP 3 Iterator: toto
STEP 3 Iterator: tata
STEP 3 Iterator: titi</pre>
So pipeline execution one element at a time prevents us from mentally slicing execution into individual steps during debug, but it is still possible to follow the steps of processing a single element through the pipeline. This could have been formulated more clearly, unless i'm missing the point (there is a limitation though, you can't see the lambda's outside variables ).
<h4>Pipelines and non-interference</h4>
Finally, the notion of <em>non-interference</em> is introduced: for a pipeline to be parallel-ready, it must have no side-effects, and especially not modify its source.
The next 2 chapters explore the pipeline's "extremities": its end in chapter 4 about collection and reduction, and its beginning in chapter 5 about Stream sources.
<h3>CHAPTER 4: Ending Streams: Collection and Reduction</h3>
<h4>Collectors: the pipeline terminal operation</h4>
A Collector is a pipeline terminal operation. When <code>stream.collect(collector)</code> is called, it accumulates elements into a mutable collection. It may also do a final post-processing operation on that collection, for instance producing an aggregate result.
<h4>The 3 kinds of Collectors</h4>
There are 3 kinds of collectors, starting with the basic out-of-the-box ones and continuing with the API's more and more general extension points:
<h5>The predefined collectors</h5>
They create a stream from a collection source: <code>Collectors.toSet</code>/<code>groupingBy</code>/<code>partitionningBy</code>, ...
<h5>Composed collectors</h5>
The predefined <code>partitionningBy()</code> returns a <code>Map<Boolean,List<T>></code> But the API can't possibly do that for every kind of end result! So instead it offers a more general <code>collect()</code> overload, to compose a base/upstream collector (<code>groupingBy</code>) with a user-specified downstream collector (<code>Collectors.toList</code>/<code>counting</code>/<code>maxBy</code>/...). The API has similar overloads for other collector factory methods (for instance <code>Collectors.mapping</code>)
<h5>Custom collectors</h5>
They are the most general construction. They are explained just below:
<h4>Creating custom Collectors</h4>
Custom collectors are instantiated by passing all the collector's parts to a factory method like so: <code>Collector.of(supplier, accumulator, combiner, finisher, characteristics)</code>:
the <code>supplier</code> creates the mutable collection
the <code>accumulator</code> accumulates value into that
the <code>combiner</code> is used in parallel mode to agregate partial aggregate results
the <code>finisher</code> applies a final transformation to the mutable collection
the <code>characteristics</code> are used by the framework (or custom implementations) to decide on possible optimizations.
This is more difficult than the chapters before and I had to read it twice, but I think I now have a better mental model of this large API. The part on collectors is concluded by explaining the contract demanded from custom Collector implementations (for instance thread-safety requirements).
<h4>Collector's little brother: Reduction</h4>
The second (and shorter) half of this chapter is about the other major kind of terminal operation, reduction.
Reduction summarizes a stream by an immutable value. Unlike collection, at each step a new temporary immutable value is produced. Reduction is a special case of collection, as it can be implemented by a collector that itself uses a downstream collector (see <em>Composed collectors</em>).
Since the pipeline may be empty by the time reduction is reached, the API provides both an overload of <code>redu
ce()</code> that takes a default value (the reduction's neutral element, like <code>0</code> for <code>+</code>), and another that doesn't take a default value but returns an <code>Optional<R></code> result.
<h4>In closing</h4>
Collection will probably be used more often than reduction. Both are essential components of the Stream API to understand (but if you understand the more general collection you understand reduction as well).
This is important especially for parallel streams because if done wrong, the terminal operation can be a bottleneck that prevents any parallel speedup.
<h3>CHAPTER 5: Starting Streams: Sources and Spliterators</h3>
After the pipeline's end, this chapter examines the pipeline's beginning (this order is justified by the fact that custom stream initiating is more complex).
<h4>JDK out-of-the-box stream starters</h4>
The easiest way is to use the new API methods that directly provide Streams from sources:
The JDK's collections have been augmented with the <code>Collection.stream()</code> method, which returns a stream whose source is that collection
The <code>Stream</code> interface has static factory methods: <code>Stream.of(...)</code>, <code>Stream.empty()</code>/<code>Stream.iterate/generate(lambda)</code>
The IO API has been augmented too: <code>BufferedReader.lines()</code> (lazy, unlike eager <code>readAllLines()</code>.
One restriction is that file reading is sequential in most (but not all, as we'll see) cases, in which case it can't be parallelized. The java 7 NIO2 API has been augmented too with <code>Files.walk</code>/<code>find</code>/<code>list</code> that take lambdas.
<h4>Custom streams</h4>
To implement custom streams, one must implement the new <code>Spliterator</code> core abstraction. Spliterators are explained much more clearly than in other sources I read so far. Spliterators are strongly linked to the java 7 fork-join framework for recursive decomposition (divide-and-conquer), so this begins with a reminder: considering a recursive task, at each recursive iteration the computation can either do the remaining work sequentially, or fork (then join) parallel subtasks.
<h5>Spliterators</h5>
The name <code>Spliterator</code> evokes this choice: "split" evokes the parallel divide-and-conquer part, while "iterator" evokes the "bottom" sequential iteration.
The 2 essential methods to implement are:
<code>tryAdvance(Consumer)</code> implements the "bottom" sequential iteration
<code>trySplit()</code> returns null if further splitting is not worth it, otherwise it returns another Spliterator AND "shortens" the current one so that the two don't overlap
Once your custom Spliterator is implemented, use <code>StreamSupport.stream(Spliterator)</code> to instantiate a custom Stream (an example is given at the end of the chapter).
<h4>A touchy subject: exception propagation</h4>
Another difficult topic that is often avoided by authors is exception propagation during stream processing; here an example using <code>IOException</code>/<code>UncheckedIOException</code> (the latter introduced by java 8) is included, illustrating the two alternatives.
The easiest alternative is to "do nothing": with lazy evaluation, the exception will be generated during the terminal operation, when it triggers execution of the exception-generating lambda, and that exception will completely stop the terminal operation.
This is OK in most cases as most errors are not recoverable.
On the other hand some errors ARE recoverable (ex: if one of the files is not readable, this must not stop processing of the other files). In this case recoverable errors must be notified by checked exceptions, thrown from eagerly evaluated operations (in other words: can't use lazyness in this case).
<h4>Example: IO parallelization</h4>
This chapter ends with an original example of a parallel stream that does non-blocking IO. It is constructed from a custom Spliterator that splits a NIO <code>MappedByteBuffer</code> (a native "direct" buffer that maps a file into memory, here in read-only mode).
I liked the fact that it's a rare example of using NIO as an example in a book, and in believable circumstances, and also it really helps to understand how spliterators work; the main point is that to achieve parallel gains in the stream starting stage of stream processing, the stream source must splittable without contention.
This is the case for the example's <code>MappedByteBuffer</code> (because it's loaded once and for all in read-only mode).
This is a necessary but not sufficient condition though - the problem to solve must be intrinsically non-sequential, which is also the case for the example's "line grep" functionnality. As the author says: "Cooperation with Java NIO enables the Stream API to process input from large files with a high parallel speedup."
<h4>In closing</h4>
To quote Naftalin again, "The main strength of the Stream API is that the solutions are straightforward, and respecifying the problem to simulate the different options required only small corresponding changes in the code."
<h3>CHAPTER 6: Stream performance</h3>
<h4>Measure, don't guess</h4>
The first step to improve performance is measuring it, which is often done with a micro-benchmark; after listing some of the most common microbenchmark pitfalls (lack of warmup, dead code elimination, ..), two frameworks that alleviate these problems are introduced (Java Microbenchmark Harness and Google Caliper).
<h4>Factors making parallelism worth it or not</h4>
After the bench harness is ready and performance requirements have been gathered, if the code has been made parallel-ready using Streams correctly, it is time to choose between sequential processing or actual parallel processing; the latter may yield a speedup or not, depending on different factors:
<h5>The execution context</h5>
<ul>
<li>Can this parallel stream use all the machine's cores, or even all the web server's cores?</li>
</ul>
This is not necessarily the case, and if concurrent requests or other running programs compete for cores the speedup will be much smaller. A possible pointer is setting the common fork-join pool size at VM startup time.
<h5>Task sizes</h5>
<ul>
<li>The stream's workload is defined as <strong>W = Q(individual task time) * N(number of elements)</strong>.</li>
</ul>
The bigger W, the likelier parallel speedup exceeds parallelization overhead
<ul>
<li>Stream extremities (Spliterator/Collector) performance: at high Q parallelizing the stream's intermediate operations is worth it, while at low Q splitting by sources and concurrent accumulation by collectors are likely to become bottlenecks</li>
<li>"More complex intermediate operations will usually involve some I/O or synchronization, resulting in fewer gains from going parallel"</li>
</ul>
<h5>The stream characteristics</h5>
Apart from the runtime context and workload, the stream intrinsic characteristics also have a big impact:
<code>SORTED</code>
<code>SIZED</code>
<code>DISTINCT</code>
<code>ORDERED</code> (most important)
These characteristics are a product of both the stream's source and modifications by intermediate operations. Some optimizations will be possible or not based on them.
<h5>The kinds of operations performed</h5>
Then some other factors are considered:
<ul>
<li>Stateful VS stateless operations</li>
<li>Boxing/Unboxing overhead</li>
<li>Spliterator and Collector performance in different cases</li>
</ul>
<h4>In closing</h4>
It concludes by saying that Stream creation and collection is not where big parallel speedups are achieved, but can be bottlenecks that need tuning. To achieve parallel speedup, key factors are:
<ul>
<li>doing most of the work in intermediate operations</li>
<li>sufficiently high data set size (at least 10_000/100_000 elements) and per-element processing cost (at least 40/200µS per element)</li>
</ul>
Optimiza
tion or not, "<em>investment in writing parallel-ready code will not be wasted, whatever the outcome of your performance analysis. Your code will be better and, when advances in technology change the cost-benefit balance of going parallel, it will—as the name suggests—be ready</em>"
<h4>A few omissions</h4>
So a very good chapter, but with some omissions:
The biggest one is that every call to <code>parallelStream()</code> uses the same singleton <code>ForkJoinPool</code>: <code>ForkJoinPool.commonPool()</code>.
This is a big trap imo (that Heinz Kabutz likes talking about), so don't ever do blocking IO or any blocking calls in a parallel stream. The author does insist that parallel streams are for CPU intensive tasks though.
Exception: a more obscure point is that if you call <code>parallelStream()</code> while already within a ForkJoinPool, that pool is used instead of <code>ForkJoinPool.commonPool()</code>.
Well it seems to be the case but it's unspecified as far as I know..
<code>CompletableFuture</code> is not mentionned.
While it is not related to streams, J8IA does talk about it and makes the very important point that: "Conversely, when dealing with concurrency instead of parallelism, or when your main goal is to perform several loosely related tasks on the same CPUs, keeping their cores as busy as possible to maximize the throughput of your application, <a title="..." href="...">...</a>". <code>CompletableFuture</code> is useful for max throughput, while <code>parallelStream()</code> is useful for max performance. Which is more important most of the time? Probably throughput and J8IA shows a possible way to go that direction using Streams and CompletableFutures together.
<h3>CHAPTER 7: API Evolution with Default Methods</h3>
<h4>Reasons for their introduction</h4>
Default methods are linked to lambdas, because they were added to interfaces so that the addition of methods such as <code>Iterable.forEach()</code> is not a breaking change.
<h4>A few implementation patterns</h4>
After presenting their syntax, this chapter lists their common points/differences with abstract classes, and presents some interesting implementation patterns.
<h4>More technical points</h4>
More technical points include:
While lambdas are restricted to implementing Single Abstract Method Interface/FunctionalInterface, within a <code>FunctionalInterface</code>, concrete default methods are legal, and useful for instance as auxiliary methods to compose lambdas (ex: <code>Predicate.and()</code>).
Inheritance and overload resolution rules
The reason why they can't be declared final (which can be annoying) is just that the inheritance rule "classes always win over interfaces" prevents it.
Static interface methods
<h3>CHAPTER 8: Conclusion</h3>
Java 8 brings concepts of functional programing, immutability, and lazy evaluation to the java language. Their integration in an old language like java is well done, and they enable more concise, readable, and performant code.
<h3>Overall: Recommended</h3>
A very polished book. My only regret is that it doesn't talk about mixing Streams and CompletableFuture for better throughput.]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>152</wp:post_id>
<wp:post_date><![CDATA[2015-02-05 17:30:00]]></wp:post_date>
<wp:post_date_gmt><![CDATA[2015-02-05 16:30:00]]></wp:post_date_gmt>
<wp:comment_status><![CDATA[open]]></wp:comment_status>
<wp:ping_status><![CDATA[closed]]></wp:ping_status>
<wp:post_name><![CDATA[book-review-mastering-lambdas]]></wp:post_name>
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[post]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="java"><![CDATA[Java]]></category>
<wp:postmeta>
<wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
<wp:meta_value><![CDATA[225]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[slide_template]]></wp:meta_key>
<wp:meta_value><![CDATA[default]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_post]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_cat_label]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_disable]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_reviews]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_pos]]></wp:meta_key>
<wp:meta_value><![CDATA[none]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_type]]></wp:meta_key>
<wp:meta_value><![CDATA[points]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_verdict]]></wp:meta_key>
<wp:meta_value><![CDATA[Awesome]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wp_old_slug]]></wp:meta_key>
<wp:meta_value><![CDATA[20150205book-review-mastering-lambdas]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wpghs_github_path]]></wp:meta_key>
<wp:meta_value><![CDATA[_articles/2015-02-05-book-review-mastering-lambdas.md]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_sha]]></wp:meta_key>
<wp:meta_value><![CDATA[a8f166abb2a123c7ad0128f3bb4204ecff1a9054]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_thumbnail_id]]></wp:meta_key>
<wp:meta_value><![CDATA[7439]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_jetpack_related_posts_cache]]></wp:meta_key>
<wp:meta_value><![CDATA[a:1:{s:32:"8f6677c9d6b0f903e98ad32ec61f8deb";a:2:{s:7:"expires";i:1479849468;s:7:"payload";a:3:{i:0;a:1:{s:2:"id";i:375;}i:1;a:1:{s:2:"id";i:372;}i:2;a:1:{s:2:"id";i:124;}}}}]]></wp:meta_value>
</wp:postmeta>
<wp:comment>
<wp:comment_id>3224</wp:comment_id>
<wp:comment_author><![CDATA[Visit My Website]]></wp:comment_author>
<wp:comment_author_email><![CDATA[MccannHochstedler41@aol.com]]></wp:comment_author_email>
<wp:comment_author_url>http://http://www.jasonpicks.com/2015/01/jason-bond-picks-review.html</wp:comment_author_url>
<wp:comment_author_IP><![CDATA[108.162.245.96]]></wp:comment_author_IP>
<wp:comment_date><![CDATA[2015-06-25 12:44:20]]></wp:comment_date>
<wp:comment_date_gmt><![CDATA[2015-06-25 12:44:20]]></wp:comment_date_gmt>
<wp:comment_content><![CDATA[<p>Pretty good post. I merely stumbled upon your weblog in addition to tried to claim that I have got genuinely relished surfing around your blog site blogposts. In any case My business is opt-in to your give food to that i'm praying you're writing just as before immediately!</p>]]></wp:comment_content>
<wp:comment_approved><![CDATA[-2]]></wp:comment_approved>
<wp:comment_type><![CDATA[]]></wp:comment_type>
<wp:comment_parent>0</wp:comment_parent>
<wp:comment_user_id>0</wp:comment_user_id>
</wp:comment>
</item>
<item>
<title>Spark et Cassandra</title>
<link>https://blog.zenika.com/2015/02/23/spark-et-cassandra/</link>
<pubDate>Mon, 23 Feb 2015 15:00:00 +0000</pubDate>
<dc:creator><![CDATA[gquintana]]></dc:creator>
<guid isPermaLink="false">http://znk.vibioh.fr/2015/02/23/20150223spark-et-cassandra/</guid>
<description></description>
<content:encoded><![CDATA[<a href="http://cassandra.apache.org">Cassandra</a> est une base de données distribuée capable de stocker de gros volumes de données. Si son modèle de données constitué de tables et de colonnes, et son langage de requêtage CQL imitent fortement les bases de données relationnelles, la ressemblance s'arrête là.
<!--more-->
Les possibilités de requêtage dépendent intrinsèquement de la manière dont sont stockées/modélisées les données.
Datastax fournit un <a href="https://github.com/datastax/spark-cassandra-connector">connecteur Spark</a> qui permet manipuler des tables Cassandra sous forme de RDD, concept que nous avons présenté lors du précédent article d'<a href="http://blog.zenika.com/index.php?post/2015/02/02/Introduction-a-Spark">introduction à Spark</a>. Par le biais de ce connecteur, Spark apporte à Cassandra des capacités de requêtage analytique.
D'une manière plus générale, nous étudierons l'intégration de Cassandra et Spark. Ce sera aussi l'occasion de découvrir les possibilités de Spark SQL et Spark Streaming.
<h3>Spark classique</h3>
Pour commencer avec le connecteur Cassandra Spark, les Jobs Spark doivent pouvoir se connecter à Cassandra. Pour cela on place dans la configuration les identifiants de connexion à Cassandra:
<pre class="lang:default decode:true java code java">SparkConf conf = new SparkConf(true)
.setMaster("local")
.setAppName("Zenika")
.set("spark.cassandra.connection.host", "node1")
.set("spark.cassandra.connection.username", "spark")
.set("spark.cassandra.connection.password", "spark");</pre>
Pour lire les données dans Cassandra, on décrit au moyen de la classe <code>CassandraJavaUtil</code> une requête de type <code>select</code> comme en CQL. On obtient ainsi un RDD de lignes Cassandra:
<pre class="lang:default decode:true java code java">CassandraJavaRDD<CassandraRow> metricRdd = javaFunctions(sparkContext)
.cassandraTable("metrics", "metric")
.select("host", "name", "date", "value");</pre>
Au passage, notez qu'en Scala, les conversions implicites auraient permis d'éviter l'appel à <code>javaFunctions</code>.
Le connecteur sait automatiser le mapping ligne/objet à la manière d'un ORM (voir <code>mapRowTo</code>), la <code>columnMap</code> contient la correspondance colonne/propriété:
<pre class="lang:default decode:true java code java">CassandraJavaRDD<Metric> metricRdd = javaFunctions(sparkContext)
.cassandraTable("metrics", "metric", mapRowTo(Metric.class, columnMap))
.select("host", "name", "date", "value");</pre>
Le chemin inverse, l'écriture d'un RDD dans Cassandra, est très similaire à la lecture. La méthode <code>saveToCassandra</code> est une action Spark tout comme <code>saveAsTextFile</code>:
<pre class="lang:default decode:true java code java">javaFunctions(metricStatRdd)
.writerBuilder("metrics", "metric_stat", mapToRow(MetricStat.class, columnMap))
.saveToCassandra();</pre>
De manière à optimiser les accès base, il est de bon ton de placer les esclaves Spark sur les mêmes machines que les noeuds Cassandra.
<img style="display: block; margin: 0 auto;" title="Spark & Cassandra Cluster" src="/wp-content/uploads/2015/07/spark-cassandra-cluster.png" alt="Spark & Cassandra Cluster" />
Le connecteur Cassandra-Spark amène chaque exécutant Spark à préférer lire les partitions Cassandra du noeud sur lequel il est, évitant ainsi de coûteux allers-retours. Autrement dit, le connecteur sait optimiser les lectures, dès lors que Spark et Cassandra cohabitent sur un même noeud.
<h3>Spark SQL</h3>
Pour mémoire, Spark SQL est une extension de Spark qui permet d'exprimer les traitements sur un RDD dans un langage inspiré de SQL. Sous le capot, Spark SQL utilise un type de RDD spécialisé, nommé <code>SchemaRDD</code>, dans lequel les données seront structurées sous forme d'un tableau. Le <code>SchemaRDD</code> est constitué de lignes (<code>Row</code>), toutes ayant les mêmes colonnes. Pour passer d'un <code>RDD</code> tout simple à un <code>SchemaRDD</code>, on décrit les colonnes, puis on lui affecte un nom de table:
<pre class="lang:default decode:true java code java">// Un RDD tout simple
List<Metric> metrics = ...
JavaRDD<Metric> simpleRdd = sparkContext.parallelize(metrics);
// Un SchemaRDD
JavaSQLContext sqlContext = new JavaSQLContext(sparkContext);
JavaSchemaRDD schemaRDD = sqlContext.applySchema(simpleRdd, Metric.class);
schemaRDD.registerTempTable("metric");
JavaSchemaRDD resultRDD = sqlContext.sql("select host, avg(value) from metric where name='cpu.total' group by host");</pre>
Une fois tables et colonnes déclarées dans le contexte, Spark SQL permet d'exécuter du pseudo-SQL sur n'importe quel RDD. En enregistrant plusieurs tables dans le context Spark SQL, on aurait pu faire faire des jointures entre elles.
Revenons à Cassandra, avec le connecteur Cassandra Spark, on peut utiliser Spark SQL pour requêter directement la base de données et produire des <code>SchemaRDD</code>s.
<pre class="lang:default decode:true java code java">JavaCassandraSQLContext cassandraSQLContext = new JavaCassandraSQLContext(sc);
JavaSchemaRDD metricRDD = cassandraSQLContext.sql("select name from metrics.metric where name like 'cpu%'");
long count = metricRDD
.map(row -> row.getString(0))
distinct().count();</pre>
On peut aussi appliquer des transformations habituelles (map, filter), du cache, etc., sur le résultat de la requête comme sur tout RDD qui se respecte.
Pourquoi utiliser Spark SQL alors qu'on dispose déjà de CQL? Spark SQL permet de:
<ul>
<li>De requêter les données même si le modèle de données ne si prête pas. En effet, en CQL, on ne pourra pas exprimer une requête si le modèle ne s'y prête pas.</li>
<li>De faire des jointures et d'utiliser de nombreux opérateurs comme <code>like</code> ou <code>group by</code> dans les exemples ci-dessous</li>
</ul>
Bien que plus riche et permissive, l'approche Spark SQL est aussi beaucoup plus coûteuse que du CQL. En effet, Spark va généralement balayer un gros volume de données à la façon d'un full scan. Pour limiter l'impact de Spark sur les performances de Cassandra, il est vivement conseillé de créer un datacenter logique au niveau de Cassandra de manière à isoler cette charge.
Au final, Spark SQL ne remplace pas CQL, mais le complète pour tout ce qui est requêtes analytiques.
<h3>Spark Streaming</h3>
Si le coeur de Spark est focalisé sur les traitements en masse de gros volumes de données, Spark Streaming propose une API similaire pour des traitements de données au fil de l'eau. On troque les forts volumes de données pour de forts débits, et les RDD pour des <code>DStreams</code> (Discrete Streams). Mais l'API reste très proche, <code>map</code>, <code>filter</code> sont toujours de la partie:
<pre class="lang:default decode:true java code java">JavaStreamingContext streamingContext = new JavaStreamingContext(sparkContext,
new Duration(10000));
JavaDStream<Metric> metricDStream = streamingContext
.socketTextStream("metric-source", 7075)
.map(Metric::parseStream)
.filter(metric -> metric.getValue() != null);</pre>
Ces DStreams seront alimentés par des systèmes orientés message/événement comme Kafka, ZeroMQ, Akka, etc. Cependant, les traitements seront effectués de manière périodique (toutes les 10 secondes dans l'exemple ci-dessus). Spark Streaming est un framework de <em>micro-batch</em>, il traite les données sous forme de petits RDDs toutes les N secondes (N entre 1 seconde et 1 minute):
<img style="display: block; margin: 0 auto;" title="Spark Streamin Microbatch" src="/wp-content/uploads/2015/07/spark-streaming-microbatch.png" alt="Spark Streamin Microbatch" />
Le fait d'avoir des RDDs ouvre pas mal de possibilités comme factoriser du code avec les traitements batch classiques, faire des jointures...
Et Cassandra dans tout ça? Et bien le connecteur permet de persister un <code>DStream</code> dans une table de la même manière qu'un RDD:
<pre class="lang:default decode:true java code java ">javaFunctions(metricDStream)
.writerBuilder("metrics", "metric", mapRowTo(Metric.class, columnMap))
.saveToCassandra();</pre>
Cassandra pour le stockage et le requêtage temps réel, Spark pour le requêtage analytique, les traitements de masse et l'intégration au fil de l'eau. Ce redoutable tandem est capable d'absorber des données en grande quantité et procéder à des analyses de données à grande échelle. Spark apporte à Cassandra des capacités de requêtage et de fouille des données, Cassandra apporte à Spark une solution pour persister
les RDDs de manière distribuée et structurée.]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>153</wp:post_id>
<wp:post_date><![CDATA[2015-02-23 16:00:00]]></wp:post_date>
<wp:post_date_gmt><![CDATA[2015-02-23 15:00:00]]></wp:post_date_gmt>
<wp:comment_status><![CDATA[open]]></wp:comment_status>
<wp:ping_status><![CDATA[closed]]></wp:ping_status>
<wp:post_name><![CDATA[spark-et-cassandra]]></wp:post_name>
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[post]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<category domain="category" nicename="bigdata-nosql"><![CDATA[BigData & NoSQL]]></category>
<wp:postmeta>
<wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[slide_template]]></wp:meta_key>
<wp:meta_value><![CDATA[default]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_post]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_cat_label]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_featured_disable]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_reviews]]></wp:meta_key>
<wp:meta_value><![CDATA[0]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_pos]]></wp:meta_key>
<wp:meta_value><![CDATA[none]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_type]]></wp:meta_key>
<wp:meta_value><![CDATA[points]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_bunyad_review_verdict]]></wp:meta_key>
<wp:meta_value><![CDATA[Awesome]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_thumbnail_id]]></wp:meta_key>
<wp:meta_value><![CDATA[5864]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wp_old_slug]]></wp:meta_key>
<wp:meta_value><![CDATA[20150223spark-et-cassandra]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_wpghs_github_path]]></wp:meta_key>
<wp:meta_value><![CDATA[_articles/2015-02-23-spark-et-cassandra.md]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_sha]]></wp:meta_key>
<wp:meta_value><![CDATA[4eef6c0f51e88930882df10fbb5b1bcd72576736]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_jetpack_related_posts_cache]]></wp:meta_key>
<wp:meta_value><![CDATA[a:1:{s:32:"8f6677c9d6b0f903e98ad32ec61f8deb";a:2:{s:7:"expires";i:1479959246;s:7:"payload";a:3:{i:0;a:1:{s:2:"id";i:509;}i:1;a:1:{s:2:"id";i:368;}i:2;a:1:{s:2:"id";i:8447;}}}}]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title>Microsoft Tech Days 2015 - Jour 1</title>
<link>https://blog.zenika.com/2015/02/18/microsoft-tech-days-2015-jour-1/</link>
<pubDate>Wed, 18 Feb 2015 13:30:00 +0000</pubDate>
<dc:creator><![CDATA[lclaisse]]></dc:creator>
<guid isPermaLink="false">http://znk.vibioh.fr/2015/02/18/201502183microsoft-tech-days-2015-jour-1/</guid>
<description></description>
<content:encoded><![CDATA[Les Tech Days 2015 se sont tenus au palais des congrés du 10 au 12 février, au même endroit que le Devoxx Paris de cette année. Pour ceux qui n'ont pas eu la chance d'y aller, je vous propose un petit aperçu des conférences qui m'ont semblés les plus intéressantes.
Ce post couvre la première journée, la suite arrive bientôt.
<!--more-->
<h3>Frameworks JS en environnement Microsoft: état des lieux</h3>
Tour d'horizon de l'intégration dans Visual Studio de quelques frameworks front (et de quelques évolutions entre la version actuelle 2013 et la future version 2015, actuellement en beta):
<ul>
<li>JQuery</li>
<li>Bootstrap</li>
<li>KnockoutJS</li>
<li>AngularJS</li>
<li>Typescript</li>
<li>Cordova</li>
</ul>
Visual Studio fournit un support de très bon niveau de support de ces frameworks front, illustré par la démo:
<ul>
<li>Génération automatique de la validation client-side pour un projet ASP.NET MVC</li>
<li>Gestionnaire de packages et dépendances avec Nuget(VS 2013) ou Bower(VS 2015)</li>
<li>IntelliSense. Ce terme MS désigne principalement l'autocomplétion.</li>
</ul>
Il permet par exemple l'autocomplétion sur les attributs de binding de KnockoutJS. Le bébé de Microsoft, Typescript, bénéficie évidemment d'une attention particulière et est embarqué dans VS par défaut.
A noter qu'il existe désormais une version Visual Studio Community, avec les mêmes fonctionnalités que la version Enterprise contrairement à Express (évidemment Community est restreint aux développements non-commerciaux).
<h3>Introduction à C#6</h3>
Ce n'est pas une version révolutionnaire mais plutôt un "project coin". A noter que le nouveau compilateur C# (Roslyn) est lui aussi open-sourcé dans cette version.
<h4>Améliorer le ratio signal/bruit:</h4>
Ces nouveautés sont illustrées par la sorte de refactor la plus sympathique, celle qui qui n'utilise que le bouton DEL.
<h5>Auto-property initializer</h5>
Cette nouvelle syntaxe permet d'inliner l'initialisation de la propriété, ce qui est un peu plus lisible que dans le constructeur:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> bool MyProperty <span style="color: #009900;">{</span> get<span style="color: #339933;">;</span> set<span style="color: #339933;">;</span> <span style="color: #009900;">}</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span></pre>
<h5>Getter only auto-properties</h5>
Permet de remplacer:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> bool MyProperty <span style="color: #009900;">{</span> get<span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">private</span> set<span style="color: #339933;">;</span> <span style="color: #009900;">}</span></pre>
qui est du code mort si le champ est read-only, par:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> bool MyProperty <span style="color: #009900;">{</span> get<span style="color: #339933;">;</span> <span style="color: #009900;">}</span></pre>
Ce changement peut être combiné au précédent pour une déclaration concise d'une propriété read-only:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> bool MyProperty <span style="color: #009900;">{</span> get<span style="color: #339933;">;</span> <span style="color: #009900;">}</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span></pre>
Pour une propriété calculée, on peut l'initialiser avec le constructeur même si elle n'a pas de setter:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> string <span style="color: #003399;">Name</span> <span style="color: #009900;">{</span> get<span style="color: #339933;">;</span> <span style="color: #009900;">}</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">public</span> Customer<span style="color: #009900;">(</span>string first, string last<span style="color: #009900;">)</span> <span style="color: #009900;">{</span> <span style="color: #003399;">Name</span> <span style="color: #339933;">=</span> first <span style="color: #339933;">+</span> <span style="color: #0000ff;">" "</span> <span style="color: #339933;">+</span> last<span style="color: #339933;">;</span> <span style="color: #009900;">}</span></pre>
<h5>Imports statiques</h5>
Jusqu'à présent, C# n'avait pas d'équivalent des static imports de Java, ce qui était un peu pénible en cas de répétition de System.Console.WriteLine() par exemple. Une fonctionnalité analogue mais un peu moins complète est ajoutée en C#6: le using statique
Avant:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> DoSomething<span style="color: #009900;">(</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span> Console.<span style="color: #006633;">WriteLine</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Line 1"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> Console.<span style="color: #006633;">WriteLine</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Line 2"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> Console.<span style="color: #006633;">WriteLine</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Line 3"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #009900;">}</span></pre>
<pre class="java code java" style="font-family: inherit;">using <span style="color: #003399;">System</span>.<span style="color: #006633;">Console</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> DoSomething<span style="color: #009900;">(</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span> WriteLine<span style="color: #009900;">(</span><span style="color: #0000ff;">"Line 1"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> WriteLine<span style="color: #009900;">(</span><span style="color: #0000ff;">"Line 2"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> WriteLine<span style="color: #009900;">(</span><span style="color: #0000ff;">"Line 3"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #009900;">}</span></pre>
Si vous vous demandez pourquoi le mot clef static n'apparaît pas, c'est parce que ceci ne fonctionne qu'avec une classe statique, comme Console. Contrairement à Java, une classe statique est une classe marquée comme telle et ne comprenant que des méthodes statiques. A noter qu'on importe toutes les méthodes de la classe statique.
<h5>Un litéral pour le "String interpolation"</h5>
Un très sympathique syntactic sugar pour remplacer l'appel à string.Format, avec une syntaxe proche des expression languages utilisés par les fichiers de configuration:
Avant:
<pre class="java code java" style="font-family: inherit;">var name <span style="color: #339933;">=</span> <span style="color: #0000ff;">"Dave"</span><span style="color: #339933;">;</span> WriteLine<span style="color: #009900;">(</span>string.<span style="color: #003399;">Format</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"My name is {0}"</span>, name<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
Après:
<pre class="java code java" style="font-family: inherit;">var name = <span style="color: #0000ff;">"Dave"</span><span style="color: #339933;">;</span> WriteLine<span style="color: #009900;">(</span>$<span style="color: #0000ff;">"My name is {name}"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
<h5>Expression-bodied methods and properties</h5>
L'idée est de diminuer le bruit syntaxique en déclarant les méthodes et les auto-properties avec une expression lambda:
Pour une méthode:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Point</span> Move<span style="color: #009900;">(</span><span style="color: #000066; font-weight: bold;">int</span> dx, <span style="color: #000066; font-weight: bold;">int</span> dy<span style="color: #009900;">)</span> <span style="color: #339933;">=></span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Point</span><span style="color: #009900;">(</span>x <span style="color: #339933;">+</span> dx, y <span style="color: #339933;">+</span> dy<span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
Pour un opérateur overloadé:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> Complex operator <span style="color: #339933;">+</span><span style="color: #009900;">(</span>Complex a, Complex b<span style="color: #009900;">)</span> <span style="color: #339933;">=></span> a.<span style="color: #006633;">Add</span><span style="color: #009900;">(</span>b<span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
Pour une propriété:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> string <span style="color: #003399;">Name</span> <span style="color: #339933;">=></span> First <span style="color: #339933;">+</span> <span style="color: #0000ff;">" "</span> <span style="color: #339933;">+</span> Last<span style="color: #339933;">;</span></pre>
Et même pour une propriété indexée (indexer):
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">public</span> Customer <span style="color: #000000; font-weight: bold;">this</span><span style="color: #009900;">[</span><span style="color: #000066; font-weight: bold;">long</span> id<span style="color: #009900;">]</span> <span style="color: #339933;">=></span> store.<span style="color: #006633;">LookupCustomer</span><span style="color: #009900;">(</span>id<span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
<h5>Index initializers</h5>
Un raccourci initialiser une propriété indexée:
<pre class="java code java" style="font-family: inherit;">var numbers <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Dictionary<span style="color: #339933;"><</span>int, string<span style="color: #339933;">></span> <span style="color: #009900;">{</span> <span style="color: #009900;">[</span><span style="color: #cc66cc;">7</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">"seven"</span>, <span style="color: #009900;">[</span><span style="color: #cc66cc;">9</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">"nine"</span>, <span style="color: #009900;">[</span><span style="color: #cc66cc;">13</span><span style="color: #009900;">]</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">"thirteen"</span> <span style="color: #009900;">}</span><span style="color: #339933;">;</span></pre>
<h5>Null conditional operators</h5>
Les amateurs de Groovy reconnaîtront l'"Elvis operator", qui permet d'éviter les contrôles de nullité.
Avant:
<pre class="java code java" style="font-family: inherit;">string str<span style="color: #339933;">=</span><span style="color: #0000ff;">""</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">(</span>records<span style="color: #339933;">!=</span><span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&&</span> records<span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span><span style="color: #339933;">!=</span><span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&&</span> records<span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span>.<span style="color: #006633;">Person</span><span style="color: #339933;">!=</span><span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span> str<span style="color: #339933;">=</span> records<span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span>.<span style="color: #006633;">Person</span>.<span style="color: #003399;">Name</span><span style="color: #339933;">;</span> <span style="color: #009900;">}</span></pre>
Après:
<pre class="java code java" style="font-family: inherit;">string str<span style="color: #339933;">=</span>records<span style="color: #339933;">?</span><span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span>.<span style="color: #006633;">Person</span><span style="color: #339933;">?</span>.<span style="color: #003399;">Name</span><span style="color: #339933;">;</span></pre>
Encore plus intéressant quand on le combine à l'opérateur (préexistant) ??
<pre class="java code java" style="font-family: inherit;">string str<span style="color: #339933;">=</span>records<span style="color: #339933;">?</span><span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span>.<span style="color: #006633;">Person</span><span style="color: #339933;">?</span>.<span style="color: #003399;">Name</span><span style="color: #339933;">??</span><span style="color: #0000ff;">"n/a"</span><span style="color: #339933;">;</span></pre>
<h4>Autres nouveautés diverses:</h4>
<h5>L'opérateur nameof</h5>
nameof permet de produire un String, à destination des APIs d'événements ou de reflexion, mais l'avantage est que le compilateur vérifie l'absence de typo, et qu'un refactor/rename changera le String produit. Exemple d'une propriété qui produit un événement lors de sa mise à jour
Avant:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">private</span> ProductInformation _info<span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">public</span> ProductInformation Info <span style="color: #009900;">{</span> get <span style="color: #009900;">{</span> <span style="color: #000000; font-weight: bold;">return</span> _info<span style="color: #339933;">;</span> <span style="color: #009900;">}</span> set <span style="color: #009900;">{</span> _info <span style="color: #339933;">=</span> value<span style="color: #339933;">;</span> OnPropertyChanged<span style="color: #009900;">(</span><span style="color: #0000ff;">"Info"</span><span style="color: #009900;">)</span> <span style="color: #009900;">}</span> <span style="color: #009900;">}</span></pre>
Après:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">private</span> ProductInformation _info<span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">public</span> ProductInformation Info <span style="color: #009900;">{</span> get <span style="color: #009900;">{</span> <span style="color: #000000; font-weight: bold;">return</span> _info<span style="color: #339933;">;</span> <span style="color: #009900;">}</span> set <span style="color: #009900;">{</span> _info <span style="color: #339933;">=</span> value<span style="color: #339933;">;</span> OnPropertyChanged<span style="color: #009900;">(</span>nameof<span style="color: #009900;">(</span>Info<span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">}</span> <span style="color: #009900;">}</span></pre>
<h5>Exception filters</h5>
Si on compare les blocs catch d'un traitement d'exception aux blocs match d'un pattern matching Scala, les exceptions filters sont l'analogue des "guard clauses" (qui permettent d'ajouter une condition pour rentrer dans le bloc): en plus du contrôle structurel fait par catch/match sur l'Exception/case class, l'exception filter/guard clause ajoute un contrôle sur la valeur:
<pre class="java code java" style="font-family: inherit;"><span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">{</span> <span style="color: #666666; font-style: italic;">// Accès BD</span> <span style="color: #009900;">}</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">(</span>DbException e<span style="color: #009900;">)</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">(</span>e.<span style="color: #006633;">Code</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">10999</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span> <span style="color: #666666; font-style: italic;">// Traitement particulier pour ce code d'erreur BD</span> <span style="color: #009900;">}</span></pre>
<h5>Await in catch and finally</h5>