forked from seam2/jboss-seam
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Configuration.xml
executable file
·1258 lines (1029 loc) · 60.4 KB
/
Configuration.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"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
<chapter id="configuration">
<title>Configuring Seam and packaging Seam applications</title>
<para> Configuration is a very boring topic and an extremely tedious pastime. Unfortunately, several lines of XML
are required to integrate Seam into your JSF implementation and servlet container. There's no need to be too put
off by the following sections; you'll never need to type any of this stuff yourself, since you can just use
seam-gen to start your application or you can copy and paste from the example applications! </para>
<section>
<title>Basic Seam configuration</title>
<para> First, let's look at the basic configuration that is needed whenever we use Seam with JSF. </para>
<section>
<title>Integrating Seam with JSF and your servlet container</title>
<para> Of course, you need a faces servlet! </para>
<programlisting role="XML"><![CDATA[<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
</servlet-mapping>]]></programlisting>
<para> (You can adjust the URL pattern to suit your taste.) </para>
<para> In addition, Seam requires the following entry in your <literal>web.xml</literal> file: </para>
<programlisting role="XML"><![CDATA[<listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>]]></programlisting>
<para> This listener is responsible for bootstrapping Seam, and for destroying session and application
contexts. </para>
<!-- para> Some JSF implementations have a broken implementation of server-side state saving that interferes
with Seam's conversation propagation. If you have problems with conversation propagation during form
submissions, try switching to client-side state saving. You'll need this in <literal>web.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>]]></programlisting>
<warning>
<para>Setting of <literal>javax.faces.STATE_SAVING_METHOD</literal> to <literal>client</literal>
can lead to security issues and it should be set environment entry <literal>com.sun.faces.ClientStateSavingPassword</literal>
in <filename>web.xml</filename> like:
<programlisting><![CDATA[
<env-entry>
<env-entry-name>com.sun.faces.ClientStateSavingPassword</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>INSERT_YOUR_PASSWORD</env-entry-value>
</env-entry>]]></programlisting>
</para>
</warning-->
<para>
There is a minor gray area in the JSF specification regarding the mutability of view state values. Since
Seam uses the JSF view state to back its PAGE scope this can become an issue in some cases. If you're
using server side state saving with the JSF-RI and you want a PAGE scoped bean to keep its exact value
for a given view of a page you will need to specify the following context-param. Otherwise if a user
uses the "back" button a PAGE scoped component will have the latest value if it has changed not the
value of the "back" page. (see
<ulink url="http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1127">
Spec Issue
</ulink>
). This setting is not enabled by default because of the performance hit of serializing the JSF view
with every request.
</para>
<programlisting role="XML"><![CDATA[<context-param>
<param-name>com.sun.faces.serializeServerState</param-name>
<param-value>true</param-value>
</context-param>]]></programlisting>
</section>
<section>
<title>Seam Resource Servlet</title>
<para> The Seam Resource Servlet provides resources used by Seam Remoting, captchas (see the security
chapter) and some JSF UI controls. Configuring the Seam Resource Servlet requires the following entry in
<literal>web.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<servlet>
<servlet-name>Seam Resource Servlet</servlet-name>
<servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Seam Resource Servlet</servlet-name>
<url-pattern>/seam/resource/*</url-pattern>
</servlet-mapping>]]></programlisting>
</section>
<section>
<title>Seam servlet filters</title>
<para> Seam doesn't need any servlet filters for basic operation. However, there are several features which
depend upon the use of filters. To make things easier, Seam lets you add and configure
servlet filters just like you would configure other built-in Seam components. To take advantage of this
feature, we must first install a master filter in <literal>web.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<filter>
<filter-name>Seam Filter</filter-name>
<filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>]]></programlisting>
<para>The Seam master filter <emphasis>must</emphasis> be the first filter specified in
<literal>web.xml</literal>. This ensures it is run first. </para>
<para>
The Seam filters share a number of common attributes, you can set these in
<literal>components.xml</literal> in addition to any parameters discussed
below:
</para>
<itemizedlist>
<listitem>
<para>
<literal>url-pattern</literal> — Used to specify which requests are filtered, the
default is all requests. <literal>url-pattern</literal> is a Tomcat style pattern
which allows a wildcard suffix.
</para>
</listitem>
<listitem>
<para>
<literal>regex-url-pattern</literal> — Used to specify which requests are filtered, the
default is all requests. <literal>regex-url-pattern</literal> is a true regular expression
match for request path.
</para>
</listitem>
<listitem>
<para>
<literal>disabled</literal> — Used to disable a built in filter.
</para>
</listitem>
</itemizedlist>
<para>
Note that the patterns are matched against the URI path of the request (see
<literal>HttpServletRequest.getURIPath()</literal>) and that the name of the servlet context is
removed before matching.
</para>
<para> Adding the master filter enables the following built-in filters. </para>
<sect3 id="exception_handling">
<title>Exception handling</title>
<para> This filter provides the exception mapping functionality in <literal>pages.xml</literal> (almost
all applications will need this). It also takes care of rolling back uncommitted transactions when
uncaught exceptions occur. (According to the Java EE specification, the web container should do this
automatically, but we've found that this behavior cannot be relied upon in all application servers.
And it is certainly not required of plain servlet engines like Tomcat.) </para>
<para> By default, the exception handling filter will process all requests, however this behavior may be
adjusted by adding a <literal><web:exception-filter></literal> entry to
<literal>components.xml</literal>, as shown in this example: </para>
<programlisting role="XML"><![CDATA[<components xmlns="http://jboss.org/schema/seam/components"
xmlns:web="http://jboss.org/schema/seam/web">
<web:exception-filter url-pattern="*.seam"/>
</components>]]></programlisting>
</sect3>
<sect3>
<title>Conversation propagation with redirects</title>
<para> This filter allows Seam to propagate the conversation context across browser redirects. It
intercepts any browser redirects and adds a request parameter that specifies the Seam conversation
identifier. </para>
<para> The redirect filter will process all requests by default, but this behavior can also be adjusted
in <literal>components.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<web:redirect-filter url-pattern="*.seam"/>]]></programlisting>
</sect3>
<sect3 id="configuration.filters.rewrite">
<title>URL rewriting</title>
<para> This filter allows Seam to apply URL rewriting for views based on configuration in the
<literal>pages.xml</literal> file. This filter is not activate by default, but can be
activated
by adding the configuration to <literal>components.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<web:rewrite-filter view-mapping="*.seam"/>]]></programlisting>
<para>The <literal>view-mapping</literal> parameter must match the servlet mapping defined for the Faces Servlet
in the <literal>web.xml</literal> file. If ommitted, the rewrite filter assumes
the pattern <literal>*.seam</literal>.
</para>
</sect3>
<sect3>
<title>Multipart form submissions</title>
<para> This feature is necessary when using the Seam file upload JSF control. It detects multipart form
requests and processes them according to the multipart/form-data specification (RFC-2388). To
override the default settings, add the following entry to <literal>components.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<web:multipart-filter create-temp-files="true"
max-request-size="1000000"
url-pattern="*.seam"/>]]></programlisting>
<itemizedlist>
<listitem>
<para>
<literal>create-temp-files</literal> — If set to <literal>true</literal>, uploaded
files are written to a temporary file (instead of held in memory). This may be an important
consideration if large file uploads are expected. The default setting is
<literal>false</literal>. </para>
</listitem>
<listitem>
<para>
<literal>max-request-size</literal> — If the size of a file upload request
(determined by reading the <literal>Content-Length</literal> header in the request) exceeds
this value, the request will be aborted. The default setting is 0 (no size limit). </para>
</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Character encoding</title>
<para> Sets the character encoding of submitted form data. </para>
<para> This filter is not installed by default and requires an entry in
<literal>components.xml</literal> to enable it: </para>
<programlisting role="XML"><![CDATA[<web:character-encoding-filter encoding="UTF-16"
override-client="true"
url-pattern="*.seam"/>]]></programlisting>
<itemizedlist>
<listitem>
<para>
<literal>encoding</literal> — The encoding to use. </para>
</listitem>
<listitem>
<para>
<literal>override-client</literal> — If this is set to <literal>true</literal>,
the request encoding will be set to whatever is specified by <literal>encoding</literal> no
matter whether the request already specifies an encoding or not. If set to
<literal>false</literal>, the request encoding will only be set if the request doesn't
already specify an encoding. The default setting is <literal>false</literal>. </para>
</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>RichFaces</title>
<para>
If RichFaces is used in your project, Seam will install the
RichFaces Ajax filter for you, making sure to install it
before all other built-in filters. You don't need to install
the RichFaces Ajax filter in <literal>web.xml</literal>
yourself.
</para>
<para>
The RichFaces Ajax filter is only installed if the RichFaces
jars are present in your project.
</para>
<para> To override the default settings, add the following entry to <literal>components.xml</literal>.
The options are the same as those specified in the RichFaces Developer Guide: </para>
<programlisting role="XML"><![CDATA[<web:ajax4jsf-filter force-parser="true"
enable-cache="true"
log4j-init-file="custom-log4j.xml"
url-pattern="*.seam"/>]]></programlisting>
<itemizedlist>
<listitem>
<para>
<literal>force-parser</literal> — forces all JSF pages to be validated by
Richfaces's XML syntax checker. If <literal>false</literal>, only AJAX responses are
validated and converted to well-formed XML. Setting <literal>force-parser</literal> to
<literal>false</literal> improves performance, but can provide visual artifacts on AJAX
updates. </para>
</listitem>
<listitem>
<para>
<literal>enable-cache</literal> — enables caching of framework-generated resources
(e.g. javascript, CSS, images, etc). When developing custom javascript or CSS, setting to
true prevents the browser from caching the resource. </para>
</listitem>
<listitem>
<para>
<literal>log4j-init-file</literal> — is used to setup per-application logging. A
path, relative to web application context, to the log4j.xml configuration file should be
provided. </para>
</listitem>
</itemizedlist>
</sect3>
<sect3>
<title>Identity Logging</title>
<para>
This filter adds the authenticated user name to the log4j mapped diagnostic context so that it
can be included in formatted log output if desired, by adding %X{username} to the pattern.
</para>
<para> By default, the logging filter will process all requests, however this behavior may be
adjusted by adding a <literal><web:logging-filter></literal> entry to
<literal>components.xml</literal>, as shown in this example: </para>
<programlisting role="XML"><![CDATA[<components xmlns="http://jboss.org/schema/seam/components"
xmlns:web="http://jboss.org/schema/seam/web">
<web:logging-filter url-pattern="*.seam"/>
</components>]]></programlisting>
</sect3>
<sect3>
<title>Context management for custom servlets</title>
<para> Requests sent direct to some servlet other than the JSF servlet are not processed through the JSF
lifecycle, so Seam provides a servlet filter that can be applied to any other servlet that needs
access to Seam components. </para>
<para> This filter allows custom servlets to interact with the Seam contexts. It sets up the Seam
contexts at the beginning of each request, and tears them down at the end of the request. You should
make sure that this filter is <emphasis>never</emphasis> applied to the JSF
<literal>FacesServlet</literal>. Seam uses the phase listener for context management in a JSF
request. </para>
<para> This filter is not installed by default and requires an entry in
<literal>components.xml</literal> to enable it: </para>
<programlisting role="XML"><![CDATA[<web:context-filter url-pattern="/media/*"/>]]></programlisting>
<para> The context filter expects to find the conversation id of any conversation context in a request
parameter named <literal>conversationId</literal>. You are responsible for ensuring that it gets
sent in the request. </para>
<para> You are also responsible for ensuring propagation of any new conversation id back to the client.
Seam exposes the conversation id as a property of the built in component
<literal>conversation</literal>. </para>
</sect3>
<sect3>
<title>Enabling HTTP cache-control headers</title>
<para>
Seam does <emphasis>not</emphasis> automatically add <literal>cache-control</literal> HTTP headers to
any resources served by the Seam resource servlet, or directly from your view directory by the servlet
container. This means that your images, Javascript and CSS files, and resource representations from
Seam resource servlet such as Seam Remoting Javascript interfaces are usually not cached by the browser.
This is convenient in development but should be changed in production when optimizing the application.
</para>
<para>
You can configure a Seam filter to enable automatic addition of <literal>cache-control</literal> headers
depending on the requested URI in <literal>components.xml</literal>:
</para>
<programlisting role="XML"><![CDATA[<web:cache-control-filter name="commonTypesCacheControlFilter"
regex-url-pattern=".*(\.gif|\.png|\.jpg|\.jpeg|\.css|\.js)"
value="max-age=86400"/> <!-- 1 day -->
<web:cache-control-filter name="anotherCacheControlFilter"
url-pattern="/my/cachable/resources/*"
value="max-age=432000"/> <!-- 5 days -->]]></programlisting>
<para>
You do not have to name the filters unless you have more than one filter enabled.
</para>
</sect3>
<sect3>
<title>Adding custom filters</title>
<para> Seam can install your filters for you, allowing you to specify <emphasis>where</emphasis> in the
chain your filter is placed (the servlet specification doesn't provide a well defined order if you
specify your filters in a <literal>web.xml</literal>). Just add the <literal>@Filter</literal>
annotation to your Seam component (which must implement <literal>javax.servlet.Filter</literal>): </para>
<programlisting role="JAVA"><![CDATA[@Startup
@Scope(APPLICATION)
@Name("org.jboss.seam.web.multipartFilter")
@BypassInterceptors
@Filter(within="org.jboss.seam.web.ajax4jsfFilter")
public class MultipartFilter extends AbstractFilter {]]></programlisting>
<para> Adding the <literal>@Startup</literal> annotation means that the component is available during
Seam startup; bijection isn't available here (<literal>@BypassInterceptors</literal>); and the filter
should be further down the chain than the RichFaces filter
(<literal>@Filter(within="org.jboss.seam.web.ajax4jsfFilter")</literal>). </para>
</sect3>
</section>
<section id="config.integration.ejb.container">
<title>Integrating Seam with your EJB container</title>
<para> In a Seam application, EJB components have a certain duality, as they are managed by both the EJB
container and Seam. Actually, it's more that Seam resolves EJB component references, manages the
lifetime of stateful session bean components, and also participates in each method call via
interceptors. Let's start with the configuration of the Seam interceptor chain.</para>
<para> We need to apply the <literal>SeamInterceptor</literal> to our Seam EJB components. This interceptor
delegates to a set of built-in server-side interceptors that handle such concerns as bijection,
conversation demarcation, and business process signals. The simplest way to do this across an entire
application is to add the following interceptor configuration in <literal>ejb-jar.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<interceptors>
<interceptor>
<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
]]></programlisting>
<para> Seam needs to know where to go to find session beans in JNDI. One way to do this is specify the
<literal>@JndiName</literal> annotation on every session bean Seam component. However, this is quite
tedious. A better approach is to specify a pattern that Seam can use to calculate the JNDI name from the
EJB name. Fortunately, new portable JNDI Syntax was introduced in Java EE 6. There are three JNDI namespaces for
portable JNDI lookups - <literal>java:global</literal>, <literal>java:module</literal> and <literal>java:app</literal>.
More in <ulink url="http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html#girgn">Java EE 6 tutorial</ulink>
We usually specify this option in <literal>components.xml</literal>. </para>
<para> For JBoss AS 7, the following pattern is correct: </para>
<programlisting role="XML"><![CDATA[<core:init jndi-name="java:app/<ejb-module-name>/#{ejbName}" />]]></programlisting>
<para> In this case, <literal><ejb-module-name></literal> is the name of the EJB module (by default it is filename of ejb jar)
in which the bean is deployed, Seam replaces <literal>#{ejbName}</literal> with the name of the EJB. </para>
<para> How these JNDI names are resolved and somehow locate an EJB component might appear a bit like black
magic at this point, so let's dig into the details. First, let's talk about how the EJB components get
into JNDI.</para>
<para> EJB components would get assigned a global JNDI name automatically, using the pattern
described in <ulink url="http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html#girgn">Java EE 6 tutorial</ulink>.
The EJB name is the first non-empty value from the following list: </para>
<itemizedlist>
<listitem>
<para>The value of the <literal><ejb-name></literal> element in ejb-jar.xml</para>
</listitem>
<listitem>
<para>The value of the <literal>name</literal> attribute in the @Stateless or @Stateful annotation</para>
</listitem>
<listitem>
<para>The simple name of the bean class</para>
</listitem>
</itemizedlist>
<para> Let's look at an example. Assume that you have the following EJB bean and interface defined. </para>
<programlisting role="JAVA"><![CDATA[package com.example.myapp;
import javax.ejb.Local;
@Local
public interface Authenticator
{
boolean authenticate();
}
package com.example.myapp;
import javax.ejb.Stateless;
@Stateless
@Name("authenticator")
public class AuthenticatorBean implements Authenticator
{
public boolean authenticate() { ... }
}
]]></programlisting>
<para> Assuming your EJB bean class is deployed in an EAR named myapp, the global JNDI name
myapp/AuthenticatorBean/local will be assigned to it on JBoss AS. As you learned, you can reference this
EJB component as a Seam component with the name <literal>authenticator</literal> and Seam will take care
of finding it in JNDI according to the JNDI pattern (or <literal>@JndiName</literal> annotation).
</para>
<para>So what about the rest of the application servers? Well, according to the Java EE spec, which most
vendors try to adhere to religiously, you have to declare an EJB reference for your EJB in order for it
to be assigned a JNDI name. That requires some XML. It also means that it is up to you to establish a
JNDI naming convention so that you can leverage the Seam JNDI pattern. You might find the JBoss
convention a good one to follow.</para>
<para>There are two places you have to define the EJB reference when using Seam on non-JBoss application
servers. If you are going to be looking up the Seam EJB component through JSF (in a JSF view or as a JSF
action listener) or a Seam JavaBean component, then you must declare the EJB reference in web.xml. Here
is the EJB reference for the example component just shown: </para>
<programlisting role="XML"><![CDATA[<ejb-local-ref>
<ejb-ref-name>myapp/AuthenticatorBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>org.example.vehicles.action.Authenticator</local>
</ejb-local-ref>
]]></programlisting>
<para>This reference will cover most uses of the component in a Seam application. However, if you want to
be able to inject a Seam EJB component into another Seam EJB component using <literal>@In</literal>, you
need to define this EJB reference in another location. This time, it must be defined in ejb-jar.xml, and
it's a bit tricker. </para>
<para>Within the context of an EJB method call, you have to deal with a somewhat sheltered JNDI context.
When Seam attempts to find another Seam EJB component to satisfy an injection point defined using
<literal>@In</literal>, whether or not it finds it depends on whether an EJB reference exists in
JNDI. Strictly speaking, you cannot simply resolve JNDI names as you please. You have to define
the references explicitly. Fortunately, JBoss recognized how aggravating this would be for the
developer and all versions of JBoss automatically register EJBs so they are always available in
JNDI, both to the web container and the EJB container. So if you are using JBoss, you can skip the next
few paragraphs. However, if you are deploying to GlassFish, pay close attention.</para>
<para>For application servers that stubbornly adhere to the EJB specification, EJB references must always be
defined explicitly. But unlike with the web context, where a single resource reference covers all
uses of the EJB from the web environment, you cannot declare EJB references globally in the EJB container.
Instead, you have to specify the JNDI resources for a given EJB component one-by-one.</para>
<para> Let's assume that we have an EJB named RegisterAction (the name is resolved using the three steps
mentioned previously). That EJB has the following Seam injection:</para>
<programlisting role="JAVA"><![CDATA[@In(create = true)
Authenticator authenticator;
]]></programlisting>
<para> In order for this injection to work, the link must be established in the ejb-jar.xml file as follows: </para>
<programlisting role="XML"><![CDATA[<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>RegisterAction</ejb-name>
<ejb-local-ref>
<ejb-ref-name>myapp/AuthenticatorAction/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.example.myapp.Authenticator</local>
</ejb-local-ref>
</session>
</enterprise-beans>
...
</ejb-jar>
]]></programlisting>
<para> Notice that the contents of the <literal><ejb-local-ref></literal> are identical to what we
defined in web.xml. What we are doing is bringing the reference into the EJB context where it can be
used by the RegisterAction bean. You will need to add one of these references for any injection of a
Seam EJB component into another Seam EJB component using <literal>@In</literal>. (You can see an
example of this setup in the jee5/booking example).</para>
<para> But what about <literal>@EJB</literal>? It's true that you can inject one EJB into another using
<literal>@EJB</literal>. However, by doing so, you are injecting the actual EJB reference rather than the
Seam EJB component instance. In this case, some Seam features will work, while others won't. That's
because Seam's interceptor is invoked on any method call to an EJB component. But that only invokes
Seam's server-side interceptor chain. What you lose is Seam's state management and Seam's client-side
interceptor chain. Client-side interceptors handle concerns such as security and concurrency. Also, when
injecting a SFSB, there is no guarantee that you will get the SFSB bound to the active session or
conversation, whatever the case may be. Thus, you definitely want to inject the Seam EJB component using
<literal>@In</literal>.</para>
<!--
<para> That covers how JNDI names are defined and used. The lesson is that with some application servers,
such as GlassFish, you are going to have to specify JNDI names for all EJB components explicitly, and
sometimes twice! And even if you are following the same naming convention as JBoss AS, the JNDI pattern
in Seam may need to be altered. For instance, the global JNDI names are automatically prefixed with
java:comp/env on GlassFish, so you need to define the JNDI pattern as follows:</para>
<programlisting role="XML"><![CDATA[<core:init jndi-name="java:comp/env/earName/#{ejbName}/local" />]]></programlisting>
-->
<para>
Finally, let's talk about transactions. In an EJB environment, we recommend the use of a special
built-in component for transaction management, that is fully aware of container transactions, and can
correctly process transaction success events registered with the <literal>Events</literal> component. If
you don't add this line to your <literal>components.xml</literal> file, Seam won't know when
container-managed transactions end: </para>
<programlisting role="XML"><![CDATA[<transaction:ejb-transaction/>]]></programlisting>
</section>
<section>
<title>Don't forget!</title>
<para> There is one final item you need to know about. You must place a <literal>seam.properties</literal>,
<literal>META-INF/seam.properties</literal> or <literal>META-INF/components.xml</literal> file in
any archive in which your Seam components are deployed (even an empty properties file will do). At
startup, Seam will scan any archives with <literal>seam.properties</literal> files for seam components. </para>
<para> In a web archive (WAR) file, you must place a <literal>seam.properties</literal> file in the
<literal>WEB-INF/classes</literal> directory if you have any Seam components included here. </para>
<para> That's why all the Seam examples have an empty <literal>seam.properties</literal> file. You can't
just delete this file and expect everything to still work! </para>
<para> You might think this is silly and what kind of idiot framework designers would make an empty file
affect the behavior of their software?? Well, this is a workaround for a limitation of the
JVM — if we didn't use this mechanism, our next best option would be to force you to list every
component explicitly in <literal>components.xml</literal>, just like some other competing frameworks do!
I think you'll like our way better. </para>
</section>
</section>
<section id="alt-jpa-providers">
<title>Using Alternate JPA Providers</title>
<para> Seam comes packaged and configured with Hibernate as the default JPA provider.
If you require using a different JPA provider you must tell <literal>seam</literal>
about it.
</para>
<note>
<title>This is a workaround</title>
<para>
Configuration of the JPA provider will be easier in the future and will
not require configuration changes, unless you are adding a custom persistence provider
implementation.
</para>
</note>
<para>Telling seam about a different JPA provider can be done in one of two ways:</para>
<para>Update your application's <literal>components.xml</literal>
so that the generic <literal>PersistenceProvider</literal> takes
precedence over the hibernate version. Simply add the following
to the file:
</para>
<programlisting role="XML"><![CDATA[<component name="org.jboss.seam.persistence.persistenceProvider"
class="org.jboss.seam.persistence.PersistenceProvider"
scope="stateless">
</component>]]></programlisting>
<para>If you want to take advantage of your JPA provider's
non-standard features you will need to write you own implementation of
the <literal>PersistenceProvider</literal>. Use
<literal>HibernatePersistenceProvider</literal> as a starting
point (don't forget to give back to the community :). Then you
will need to tell <literal>seam</literal> to use it as before.
</para>
<programlisting role="XML"><![CDATA[<component name="org.jboss.seam.persistence.persistenceProvider"
class="org.your.package.YourPersistenceProvider">
</component>]]></programlisting>
<para>All that is left is updating the <literal>persistence.xml</literal>
file with the correct provider class, and what ever properties your
provider needs. Don't forget to package your new provider's jar files in the
application if they are needed.
</para>
</section>
<section>
<title>Configuring Seam in Java EE 6</title>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/ee6.png" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/ee6.png" align="center"/>
</imageobject>
</mediaobject>
<para> If you're running in a Java EE environment, this is all the configuration required to start using Seam! </para>
<section>
<title>Packaging</title>
<para> Once you've packaged all this stuff together into an EAR, the archive structure will look something
like this: </para>
<programlisting><![CDATA[my-application.ear/
jboss-seam.jar
lib/
jboss-el.jar
META-INF/
MANIFEST.MF
application.xml
jboss-deployment-structure.xml
my-application.war/
META-INF/
MANIFEST.MF
WEB-INF/
web.xml
components.xml
faces-config.xml
lib/
jboss-seam-ui.jar
login.jsp
register.jsp
...
my-application.jar/
META-INF/
MANIFEST.MF
persistence.xml
seam.properties
org/
jboss/
myapplication/
User.class
Login.class
LoginBean.class
Register.class
RegisterBean.class
...]]></programlisting>
<para>
You should declare <literal>jboss-seam.jar</literal> as an ejb module in <literal>META-INF/application.xml</literal>;
<literal>jboss-el.jar</literal> should be placed in the EAR's lib directory (putting it in the EAR classpath.
</para>
<para> If you want to use jBPM or Drools, you must include the needed jars in the EAR's lib directory.</para>
<para> If you want to use the Seam tag library (most Seam applications do), you must include
<literal>jboss-seam-ui.jar</literal> in the <literal>WEB-INF/lib</literal> directory of the WAR. If
you want to use the PDF or email tag libraries, you need to put <literal>jboss-seam-pdf.jar</literal> or
<literal>jboss-seam-mail.jar</literal> in <literal>WEB-INF/lib</literal>. </para>
<para> If you want to use the Seam debug page (only works for applications using facelets), you must include
<literal>jboss-seam-debug.jar</literal> in the <literal>WEB-INF/lib</literal> directory of the WAR. </para>
<para> Seam ships with several example applications that are deployable in any Java EE container that
supports EJB 3.1. </para>
<para><filename>faces-config.xml</filename> is not required in JSF 2, but if you want to set up something non-default
you need to place it in <filename>WAR/WEB-INF</filename>.</para>
<para> I really wish that was all there was to say on the topic of configuration but unfortunately we're
only about a third of the way there. If you're too overwhelmed by all this tedious configuration stuff,
feel free to skip over the rest of this section and come back to it later. </para>
</section>
</section>
<section>
<title>Configuring Seam without EJB</title>
<para> Seam is useful even if you're not yet ready to take the plunge into EJB 3.1. In this case you would use
Hibernate 4 instead of EJB 3.1 persistence, and plain JavaBeans instead of session beans. You'll miss
out on some of the nice features of session beans but it will be very easy to migrate to EJB 3.1 when you're
ready and, in the meantime, you'll be able to take advantage of Seam's unique declarative state management
architecture. </para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/hibernate-ee6.png" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/hibernate-ee6.png" align="center"/>
</imageobject>
</mediaobject>
<para> Seam JavaBean components do not provide declarative transaction demarcation like session beans do. You
<emphasis>could</emphasis> manage your transactions manually using the JTA
<literal>UserTransaction</literal> or declaratively using Seam's <literal>@Transactional</literal>
annotation. But most applications will just use Seam managed transactions when using Hibernate with
JavaBeans. </para>
<para> The Seam distribution includes a version of the booking example application that uses Hibernate and
JavaBeans instead of EJB, and another version that uses JPA and JavaBeans. These example applications are
ready to deploy into any Java EE application server. </para>
<section>
<title>Boostrapping Hibernate in Seam</title>
<para> Seam will bootstrap a Hibernate <literal>SessionFactory</literal> from your
<literal>hibernate.cfg.xml</literal> file if you install a built-in component: </para>
<programlisting role="XML"><![CDATA[<persistence:hibernate-session-factory name="hibernateSessionFactory"/>]]></programlisting>
<para> You will also need to configure a <emphasis>managed session</emphasis> if you want a Seam managed
Hibernate <literal>Session</literal> to be available via injection. </para>
<programlisting role="XML"><![CDATA[<persistence:managed-hibernate-session name="hibernateSession"
session-factory="#{hibernateSessionFactory}"/>]]></programlisting>
</section>
<section>
<title>Boostrapping JPA in Seam</title>
<para> Seam will bootstrap a JPA <literal>EntityManagerFactory</literal> from your
<literal>persistence.xml</literal> file if you install this built-in component: </para>
<programlisting role="XML"><![CDATA[<persistence:entity-manager-factory name="entityManagerFactory"/>]]></programlisting>
<para> You will also need to configure a <emphasis>managed persistence context</emphasis> if you want a
Seam managed JPA <literal>EntityManager</literal> to be available via injection. </para>
<programlisting role="XML"><![CDATA[<persistence:managed-persistence-context name="entityManager"
entity-manager-factory="#{entityManagerFactory}"/>]]></programlisting>
</section>
<section>
<title>Packaging</title>
<para> We can package our application as a WAR, in the following structure: </para>
<programlisting><![CDATA[my-application.war/
META-INF/
MANIFEST.MF
jboss-deployment-structure.xml
WEB-INF/
web.xml
components.xml
faces-config.xml
lib/
jboss-seam.jar
jboss-seam-ui.jar
jboss-el.jar
hibernate-core.jar
hibernate-annotations.jar
hibernate-validator.jar
...
my-application.jar/
META-INF/
MANIFEST.MF
seam.properties
hibernate.cfg.xml
org/
jboss/
myapplication/
User.class
Login.class
Register.class
...
login.jsp
register.jsp
...]]></programlisting>
<para> If we want to deploy Hibernate in a non-EE environment like Tomcat or TestNG, we need to do a little
bit more work. </para>
</section>
</section>
<section>
<title>Configuring Seam in Java SE</title>
<para> It is possible to use Seam completely outside of an EE environment. In this case, you need to tell Seam
how to manage transactions, since there will be no JTA available. If you're using JPA, you can tell
Seam to use JPA resource-local transactions, ie. <literal>EntityTransaction</literal>, like so: </para>
<programlisting role="XML"><![CDATA[<transaction:entity-transaction entity-manager="#{entityManager}"/>]]></programlisting>
<para> If you're using Hibernate, you can tell Seam to use the Hibernate transaction API like this: </para>
<programlisting role="XML"><![CDATA[<transaction:hibernate-transaction session="#{session}"/>]]></programlisting>
<para> Of course, you'll also need to define a datasource.</para>
</section>
<section>
<title>Configuring jBPM in Seam</title>
<para> Seam's jBPM integration is not installed by default, so you'll need to enable jBPM by installing a
built-in component. You'll also need to explicitly list your process and pageflow definitions. In
<literal>components.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<bpm:jbpm>
<bpm:pageflow-definitions>
<value>createDocument.jpdl.xml</value>
<value>editDocument.jpdl.xml</value>
<value>approveDocument.jpdl.xml</value>
</bpm:pageflow-definitions>
<bpm:process-definitions>
<value>documentLifecycle.jpdl.xml</value>
</bpm:process-definitions>
</bpm:jbpm>]]></programlisting>
<para> No further special configuration is needed if you only have pageflows. If you do have business process
definitions, you need to provide a jBPM configuration, and a Hibernate configuration for jBPM. The Seam DVD
Store demo includes example <literal>jbpm.cfg.xml</literal> and <literal>hibernate.cfg.xml</literal> files
that will work with Seam: </para>
<programlisting role="XML"><![CDATA[<jbpm-configuration>
<jbpm-context>
<service name="persistence">
<factory>
<bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory">
<field name="isTransactionEnabled"><false/></field>
</bean>
</factory>
</service>
<service name="tx" factory="org.jbpm.tx.TxServiceFactory" />
<service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />
<service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
<service name="logging" factory="org.jbpm.logging.db.DbLoggingServiceFactory" />
<service name="authentication"
factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />
</jbpm-context>
</jbpm-configuration>]]></programlisting>
<para> The most important thing to notice here is that jBPM transaction control is disabled. Seam or EJB3 should
control the JTA transactions. </para>
<section>
<title>Packaging</title>
<para> There is not yet any well-defined packaging format for jBPM configuration and process/pageflow
definition files. In the Seam examples we've decided to simply package all these files into the root of
the EAR. In future, we will probably design some other standard packaging format. So the EAR looks
something like this: </para>
<programlisting><![CDATA[my-application.ear/
jboss-seam.jar
lib/
jboss-el.jar
jbpm-jpdl.jar
META-INF/
MANIFEST.MF
application.xml
jboss-deployment-structure.xml
my-application.war/
META-INF/
MANIFEST.MF
WEB-INF/
web.xml
components.xml
faces-config.xml
lib/
jboss-seam-ui.jar
login.jsp
register.jsp
...
my-application.jar/
META-INF/
MANIFEST.MF
persistence.xml
seam.properties
org/
jboss/
myapplication/
User.class
Login.class
LoginBean.class
Register.class
RegisterBean.class
...
jbpm.cfg.xml
hibernate.cfg.xml
createDocument.jpdl.xml
editDocument.jpdl.xml
approveDocument.jpdl.xml
documentLifecycle.jpdl.xml]]></programlisting>
</section>
</section>
<section>
<title>Deployment in JBoss AS 7</title>
<para>JBoss AS 7 is default deployment target for all examples in Seam 2.3 distribution.</para>
<para>Seam 2.3 requires to have setup special deployment metada file <filename>jboss-deployment-structure.xml</filename>
for correct initialization. Minimal content for EAR is:
<example>
<title>jboss-deployment-structure.xml</title>
<programlisting><![CDATA[<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="org.dom4j" export="true"/>
<module name="org.apache.commons.collections" export="true"/>
<module name="javax.faces.api" export="true"/>
</dependencies>
</deployment>
</jboss-deployment-structure>]]></programlisting>
</example>
More details about new AS 7 classloading can be found at
<ulink url="https://docs.jboss.org/author/display/AS7/Developer+Guide#DeveloperGuide-ClassloadinginJBossAS7">https://docs.jboss.org/author/display/AS7/Developer+Guide#DeveloperGuide-ClassloadinginJBossAS7</ulink>
</para>
<warning>
<title>Deployment of multiple modules in one EAR</title>
<para>There is a significant enhancement for speed up the application deployment in AS 7. This unfortunatelly can
cause some issues while you have multiple war/ejb modules in your application.</para>
<para>
This situation requires to use and set up new Java EE 6 configuration parameter -
<emphasis>Module initialization order</emphasis>