This repository has been archived by the owner on Nov 10, 2017. It is now read-only.
forked from VaclavDedik/jboss-seam
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Spring.xml
executable file
·405 lines (319 loc) · 22.8 KB
/
Spring.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
<?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="spring">
<title>Spring Framework integration</title>
<para>The Spring integration (part of the Seam IoC module) allows easy migration of Spring-based projects to Seam and allows Spring
applications to take advantage of key Seam features like conversations and Seam's more sophisticated persistence
context management.</para>
<para>Note! The Spring integration code is included in the jboss-seam-ioc library. This dependency is required for
all seam-spring integration techniques covered in this chapter.</para>
<para>Seam's support for Spring provides the ability to: </para>
<itemizedlist>
<listitem>
<para>inject Seam component instances into Spring beans</para>
</listitem>
<listitem>
<para>inject Spring beans into Seam components</para>
</listitem>
<listitem>
<para>turn Spring beans into Seam components</para>
</listitem>
<listitem>
<para>allow Spring beans to live in any Seam context</para>
</listitem>
<listitem>
<para>start a spring WebApplicationContext with a Seam component</para>
</listitem>
<listitem>
<para>Support for Spring PlatformTransactionManagement</para>
</listitem>
<listitem>
<para>provides a Seam managed replacement for Spring's <literal>OpenEntityManagerInViewFilter</literal> and <literal>OpenSessionInViewFilter</literal></para>
</listitem>
<listitem>
<para>Support for Spring <literal>TaskExecutors</literal> to back <literal>@Asynchronous</literal> calls</para>
</listitem>
</itemizedlist>
<section>
<title>Injecting Seam components into Spring beans</title>
<para> Injecting Seam component instances into Spring beans is accomplished using the
<literal><seam:instance/></literal> namespace handler. To enable the Seam namespace
handler, the Seam namespace must be added to the Spring beans definition file:</para>
<programlisting role="XML"><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:seam="http://jboss.org/schema/seam/spring-seam"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://jboss.org/schema/seam/spring-seam
http://jboss.org/schema/seam/spring-seam-2.3.xsd">]]></programlisting>
<para> Now any Seam component may be injected into any Spring bean: </para>
<programlisting role="XML"><![CDATA[<bean id="someSpringBean" class="SomeSpringBeanClass" scope="prototype">
<property name="someProperty">
<seam:instance name="someComponent"/>
</property>
</bean>]]></programlisting>
<para> An EL expression may be used instead of a component name: </para>
<programlisting role="XML"><![CDATA[<bean id="someSpringBean" class="SomeSpringBeanClass" scope="prototype">
<property name="someProperty">
<seam:instance name="#{someExpression}"/>
</property>
</bean>]]></programlisting>
<para> Seam component instances may even be made available for injection into Spring beans by a Spring bean id. </para>
<programlisting role="XML"><![CDATA[<seam:instance name="someComponent" id="someSeamComponentInstance"/>
<bean id="someSpringBean" class="SomeSpringBeanClass" scope="prototype">
<property name="someProperty" ref="someSeamComponentInstance">
</bean>
]]></programlisting>
<para>Now for the caveat!</para>
<para> Seam was designed from the ground up to support a stateful component model with multiple contexts. Spring
was not. Unlike Seam bijection, Spring injection does not occur at method invocation time. Instead,
injection happens only when the Spring bean is instantiated. So the instance available when the bean is
instantiated will be the same instance that the bean uses for the entire life of the bean. For example, if a
Seam <literal>CONVERSATION</literal>-scoped component instance is directly injected into a singleton Spring
bean, that singleton will hold a reference to the same instance long after the conversation is over! We call
this problem <emphasis>scope impedance</emphasis>. Seam bijection ensures that scope impedance is maintained
naturally as an invocation flows through the system. In Spring, we need to inject a proxy of the Seam
component, and resolve the reference when the proxy is invoked.</para>
<para>The <literal><seam:instance/></literal> tag lets us automatically proxy the Seam component.</para>
<programlisting role="XML"><![CDATA[<seam:instance id="seamManagedEM" name="someManagedEMComponent" proxy="true"/>
<bean id="someSpringBean" class="SomeSpringBeanClass">
<property name="entityManager" ref="seamManagedEM">
</bean>]]></programlisting>
<para> This example shows one way to use a Seam-managed persistence context from a Spring bean. (For a more robust
way to use Seam-managed persistence contexts as a replacement for the Spring
<literal>OpenEntityManagerInView</literal> filter see section on
<link linkend="spring-persistence">Using a Seam Managed Persistence Context in Spring</link>)</para>
</section>
<section>
<title>Injecting Spring beans into Seam components</title>
<para> It is even easier to inject Spring beans into Seam component instances. Actually, there are two possible
approaches: </para>
<itemizedlist>
<listitem>
<para> inject a Spring bean using an EL expression </para>
</listitem>
<listitem>
<para> make the Spring bean a Seam component </para>
</listitem>
</itemizedlist>
<para> We'll discuss the second option in the next section. The easiest approach is to access the Spring beans
via EL. </para>
<para> The Spring <literal>DelegatingVariableResolver</literal> is an integration point Spring provides for
integrating Spring with JSF. This <literal>VariableResolver</literal> makes all Spring beans available in EL
by their bean id. You'll need to add the <literal>DelegatingVariableResolver</literal> to
<literal>faces-config.xml</literal>: </para>
<programlisting role="XML"><![CDATA[<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>]]></programlisting>
<para> Then you can inject Spring beans using <literal>@In</literal>: </para>
<programlisting role="JAVA"><![CDATA[@In("#{bookingService}")
private BookingService bookingService;]]></programlisting>
<para>The use of Spring beans in EL is not limited to injection. Spring beans may be used anywhere that EL
expressions are used in Seam: process and pageflow definitions, working memory assertions, etc... </para>
</section>
<section>
<title>Making a Spring bean into a Seam component</title>
<para> The <literal><seam:component/></literal> namespace handler can be used to make any Spring
bean a Seam component. Just place the <literal><seam:component/></literal> tag within the
declaration of the bean that you wish to be a Seam component: </para>
<programlisting role="XML"><![CDATA[<bean id="someSpringBean" class="SomeSpringBeanClass" scope="prototype">
<seam:component/>
</bean>]]></programlisting>
<para> By default, <literal><seam:component/></literal> will create a <literal>STATELESS</literal>
Seam component with class and name provided in the bean definition. Occasionally, such as when a
<literal>FactoryBean</literal> is used, the class of the Spring bean may not be the class appearing in
the bean definition. In such cases the <literal>class</literal> should be explicitly specified. A Seam
component name may be explicitly specified in cases where there is potential for a naming conflict. </para>
<para> The <literal>scope</literal> attribute of <literal><seam:component/></literal> may be used
if you wish the Spring bean to be managed in a particular Seam scope. The Spring bean must be scoped to
<literal>prototype</literal> if the Seam scope specified is anything other than
<literal>STATELESS</literal>. Pre-existing Spring beans usually have a fundamentally stateless character, so
this attribute is not usually needed. </para>
</section>
<section>
<title>Seam-scoped Spring beans</title>
<para> The Seam integration package also lets you use Seam's contexts as Spring 2.0 style custom scopes. This
lets you declare any Spring bean in any of Seam's contexts. However, note once again that Spring's component
model was never architected to support statefulness, so please use this feature with great care. In
particular, clustering of session or conversation scoped Spring beans is deeply problematic, and care must
be taken when injecting a bean or component from a wider scope into a bean of a narrower scope.</para>
<para> By specifying <literal><seam:configure-scopes/></literal> once in a Spring bean factory
configuration, all of the Seam scopes will be available to Spring beans as custom scopes. To associate a
Spring bean with a particular Seam scope, specify the Seam scope in the <literal>scope</literal> attribute
of the bean definition. </para>
<programlisting role="XML"><![CDATA[<!-- Only needs to be specified once per bean factory-->
<seam:configure-scopes/>
...
<bean id="someSpringBean" class="SomeSpringBeanClass" scope="seam.CONVERSATION"/>]]></programlisting>
<para> The prefix of the scope name may be changed by specifying the <literal>prefix</literal> attribute in the
<literal>configure-scopes</literal> definition. (The default prefix is <literal>seam.</literal>) </para>
<para> By default an instance of a Spring Component registered in this way is not automatically created when
referenced using <literal>@In</literal>. To have an instance auto-created you must either specify <literal>@In(create=true)</literal>
at the injection point to identify a specific bean to be auto created or you can use the <literal>default-auto-create</literal>
attribute of <literal>configure-scopes</literal> to make all spring beans who use a seam scope auto created.</para>
<para> Seam-scoped Spring beans defined this way can be injected into other Spring beans without the use of
<literal><seam:instance/></literal>. However, care must be taken to ensure scope impedance
is maintained. The normal approach used in Spring is to specify
<literal><aop:scoped-proxy/></literal> in the bean definition. However, Seam-scoped Spring
beans are <emphasis>not</emphasis> compatible with <literal><aop:scoped-proxy/></literal>. So
if you need to inject a Seam-scoped Spring bean into a singleton,
<literal><seam:instance/></literal> must be used: </para>
<programlisting role="XML"><![CDATA[<bean id="someSpringBean" class="SomeSpringBeanClass" scope="seam.CONVERSATION"/>
...
<bean id="someSingleton">
<property name="someSeamScopedSpringBean">
<seam:instance name="someSpringBean" proxy="true"/>
</property>
</bean>]]></programlisting>
</section>
<section id="spring-transactions">
<title>Using Spring PlatformTransactionManagement</title>
<para>Spring provides an extensible transaction management abstraction with support for many
transaction APIs (JPA, Hibernate, JDO, and JTA) Spring also provides tight integrations with many application
server TransactionManagers such as Websphere and Weblogic. Spring
transaction management exposes support for many advanced features such as nested
transactions and supports full Java EE transaction propagation rules like REQUIRES_NEW and NOT_SUPPORTED. For more
information see the spring documentation
<ulink url="http://static.springframework.org/spring/docs/2.0.x/reference/transaction.html">here</ulink>.</para>
<para>To configure Seam to use Spring transactions enable the SpringTransaction component like so:</para>
<programlisting role="XML"><![CDATA[<spring:spring-transaction platform-transaction-manager="#{transactionManager}"/>]]></programlisting>
<para>
The <literal>spring:spring-transaction</literal> component will utilize Springs transaction synchronization
capabilities for synchronization callbacks.
</para>
</section>
<section id="spring-persistence">
<title>Using a Seam Managed Persistence Context in Spring</title>
<para>One of the most powerful features of Seam is its conversation scope and the ability to
have an EntityManager open for the life of a conversation. This eliminates many
of the problems associated with the detachment and re-attachment of entities as well as mitigates occurrences
of the dreaded <literal>LazyInitializationException</literal>. Spring does not provide a way to manage
an persistence context beyond the scope of a single web request
(<literal>OpenEntityManagerInViewFilter</literal>). So, it would be nice if Spring developers
could have access to a Seam managed persistence context using all of the same tools Spring provides
for integration with JPA(e.g. <literal>PersistenceAnnotationBeanPostProcessor</literal>,
<literal>JpaTemplate</literal>, etc.)</para>
<para>Seam provides a way for Spring to access a Seam managed persistence context with
Spring's provided JPA tools bringing conversation scoped persistence context capabilities to
Spring applications.</para>
<para>This integration work provides the following functionality:</para>
<itemizedlist>
<listitem>
<para>transparent access to a Seam managed persistence context using Spring provided tools</para>
</listitem>
<listitem>
<para>access to Seam conversation scoped persistence contexts in a non web request
(e.g. asynchronous quartz job)</para>
</listitem>
<listitem>
<para>allows for using Seam managed persistence contexts with Spring managed transactions (will need to
flush the persistence context manually)</para>
</listitem>
</itemizedlist>
<para>Spring's persistence context propagation model allows only one open EntityManager per EntityManagerFactory
so the Seam integration works by wrapping an EntityManagerFactory around a Seam managed persistence
context.</para>
<programlisting role="XML"><![CDATA[<bean id="seamEntityManagerFactory" class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
<property name="persistenceContextName" value="entityManager"/>
</bean>]]></programlisting>
<para>Where 'persistenceContextName' is the name of the Seam managed persistence context component. By default
this EntityManagerFactory has a unitName equal to the Seam component name or in this case 'entityManager'.
If you wish to provide a different unitName you can do so by providing a persistenceUnitName like so:
</para>
<programlisting role="XML"><![CDATA[<bean id="seamEntityManagerFactory" class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
<property name="persistenceContextName" value="entityManager"/>
<property name="persistenceUnitName" value="bookingDatabase:extended"/>
</bean>]]></programlisting>
<para>This EntityManagerFactory can then be used in any Spring provided tools. For example,
using Spring's <literal>PersistenceAnnotationBeanPostProcessor</literal> is the exact same as before.</para>
<programlisting role="XML"><![CDATA[<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>]]></programlisting>
<para>If you define your real EntityManagerFactory in Spring but wish to use a Seam managed persistence context
you can tell the <literal>PersistenceAnnotationBeanPostProcessor</literal> which persistenctUnitName you wish
to use by default by specifying the <literal>defaultPersistenceUnitName</literal> property.
</para>
<para>The <literal>applicationContext.xml</literal> might look like:</para>
<programlisting role="XML"><![CDATA[<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="bookingDatabase"/>
</bean>
<bean id="seamEntityManagerFactory" class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean">
<property name="persistenceContextName" value="entityManager"/>
<property name="persistenceUnitName" value="bookingDatabase:extended"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="defaultPersistenceUnitName" value="bookingDatabase:extended"/>
</bean>]]></programlisting>
<para>The <literal>component.xml</literal> might look like:</para>
<programlisting role="XML"><![CDATA[<persistence:managed-persistence-context name="entityManager"
auto-create="true" entity-manager-factory="#{entityManagerFactory}"/>]]></programlisting>
<para><literal>JpaTemplate</literal> and <literal>JpaDaoSupport</literal> are configured the same way for a
Seam managed persistence context as they would be fore a Seam managed persistence context.</para>
<programlisting role="XML"><![CDATA[<bean id="bookingService" class="org.jboss.seam.example.spring.BookingService">
<property name="entityManagerFactory" ref="seamEntityManagerFactory"/>
</bean>]]></programlisting>
</section>
<section id="spring-hibernate">
<title>Using a Seam Managed Hibernate Session in Spring</title>
<para>The Seam Spring integration also provides support for complete access to a Seam managed Hibernate session
using spring's tools. This integration is very similar to the <link linkend="spring-persistence">JPA integration</link>.</para>
<para>Like Spring's JPA integration spring's propagation model allows only one open EntityManager per
EntityManagerFactory per transaction??? to be available to spring tools. So, the Seam Session integration works
by wrapping a proxy SessionFactory around a Seam managed Hibernate session
context.</para>
<programlisting role="XML"><![CDATA[<bean id="seamSessionFactory" class="org.jboss.seam.ioc.spring.SeamManagedSessionFactoryBean">
<property name="sessionName" value="hibernateSession"/>
</bean>]]></programlisting>
<para>Where 'sessionName' is the name of the <literal>persistence:managed-hibernate-session</literal> component.
This SessionFactory can then be used in any Spring provided tools. The integration
also provides support for calls to <literal>SessionFactory.getCurrentInstance()</literal> as long as you call
getCurrentInstance() on the <literal>SeamManagedSessionFactory</literal>.</para>
</section>
<section>
<title>Spring Application Context as a Seam Component</title>
<para> Although it is possible to use the Spring <literal>ContextLoaderListener</literal> to start your
application's Spring ApplicationContext there are a couple of limitations.</para>
<itemizedlist>
<listitem>
<para> the Spring ApplicationContext must be started <emphasis>after</emphasis> the
<literal>SeamListener</literal> </para>
</listitem>
<listitem>
<para> it can be tricky starting a Spring ApplicationContext for use in Seam unit and integration
tests </para>
</listitem>
</itemizedlist>
<para> To overcome these two limitations the Spring integration includes a Seam component that will start a
Spring ApplicationContext. To use this Seam component place the
<literal><spring:context-loader/></literal> definition in the <literal>components.xml</literal>.
Specify your Spring context file location in the <literal>config-locations</literal> attribute. If more
than one config file is needed you can place them in the nested
<literal><spring:config-locations/></literal> element following standard
<literal>components.xml</literal> multi value practices. </para>
<programlisting role="XML"><![CDATA[<components xmlns="http://jboss.org/schema/seam/components"
xmlns:spring="http://jboss.org/schema/seam/spring"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/seam/components
http://jboss.org/schema/seam/components-2.3.xsd
http://jboss.org/schema/seam/spring
http://jboss.org/schema/seam/spring-2.3.xsd">
<spring:context-loader config-locations="/WEB-INF/applicationContext.xml"/>
</components>]]></programlisting>
</section>
<section>
<title>Using a Spring TaskExecutor for @Asynchronous</title>
<para>Spring provides an abstraction for executing code asynchronously called a <literal>TaskExecutor</literal>.
The Spring Seam integration allows for the use of a Spring <literal>TaskExecutor</literal> for executing
immediate <literal>@Asynchronous</literal> method calls. To enable this functionality install the
<literal>SpringTaskExecutorDispatchor</literal> and provide a spring bean defined taskExecutor like so:</para>
<programlisting role="XML"><![CDATA[<spring:task-executor-dispatcher task-executor="#{springThreadPoolTaskExecutor}"/>]]></programlisting>
<para>Because a Spring <literal>TaskExecutor</literal> does not support scheduling of an asynchronous event
a fallback Seam <literal>Dispatcher</literal> can be provided to handle scheduled asynchronous event like so:</para>
<programlisting role="XML">
<![CDATA[<!-- Install a ThreadPoolDispatcher to handle scheduled asynchronous event -->
<core:thread-pool-dispatcher name="threadPoolDispatcher"/>
<!-- Install the SpringDispatcher as default -->
<spring:task-executor-dispatcher task-executor="#{springThreadPoolTaskExecutor}" schedule-dispatcher="#{threadPoolDispatcher}"/>]]>
</programlisting>
</section>
</chapter>