Skip to content

Commit 92ff07d

Browse files
author
Micha Kiener
committed
SPR-6420, refactoring conversation scope for more simplicity
1 parent 5bfb99a commit 92ff07d

File tree

6 files changed

+253
-321
lines changed

6 files changed

+253
-321
lines changed

org.springframework.context/src/main/java/org/springframework/conversation/Conversation.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@
2020
import java.util.Map;
2121

2222
import org.springframework.conversation.manager.ConversationManager;
23-
import org.springframework.conversation.scope.ConversationScope;
2423

2524
/**
2625
* The interface for a conversation, the instance behind the
27-
* {@link ConversationScope}.<br/>
26+
* {@link org.springframework.conversation.scope.ConversationScope}.<br/>
2827
* Conversations are created through the {@link ConversationManager} which is
2928
* the main API for conversation management unless the annotations are used. See
3029
* {@link ConversationManager} for a more detailed description on how the

org.springframework.context/src/main/java/org/springframework/conversation/manager/ConversationManager.java

+61-98
Original file line numberDiff line numberDiff line change
@@ -26,113 +26,76 @@
2626
import org.springframework.conversation.annotation.BeginConversation;
2727
import org.springframework.conversation.annotation.Conversational;
2828
import org.springframework.conversation.annotation.EndConversation;
29-
import org.springframework.conversation.scope.ConversationScope;
3029

3130
/**
32-
* <p>
33-
* The interface to be implemented by any conversation manager. It is used by
34-
* the advice behind the conversational annotations like
35-
* {@link BeginConversation}, {@link EndConversation} and {@link Conversational}
36-
* but might be used for even fine grained access to the underlying conversation
37-
* management, if a initializer callback is needed for instance or if
38-
* conversation switching should be used. If used directly, the conversation
39-
* manager can be injected into any bean to be used as it is a singleton and
40-
* thread safe.<br/>
41-
*
42-
* Conversations are a good way to scope beans and attributes depending on
43-
* business logic boundary rather than a technical boundary of a scope like
44-
* session, request etc. Usually a conversation boundary is defined by the
45-
* starting point of a use case and ended accordingly or in other words a
46-
* conversation defines the boundary for a unit of work.<br/>
47-
* <br/>
48-
*
49-
* Here is a short description on how to use the conversation management:<br/>
50-
* <br/>
51-
* <b>Starting a conversation</b><br/>
52-
* A conversation can be started in two different ways, either by placing the
53-
* {@link BeginConversation} annotation on a method defining the starting point
54-
* of the conversation (use case) or by invoking
55-
* {@link ConversationManager#beginConversation(boolean, JoinMode)} manually
56-
* through the conversation manager. The {@link JoinMode} declares on how a new
57-
* conversation is created (see its javadoc for more details on the different
58-
* join modes).<br/>
59-
* <br/>
60-
*
61-
* <b>Ending a conversation</b><br/>
62-
* A current conversation is ended by either placing the {@link EndConversation}
63-
* annotation on the ending method or by manually invoke the
64-
* {@link ConversationManager#endCurrentConversation(ConversationEndingType)}
65-
* method. A current conversation might also be ended, if a new conversation is
66-
* started having {@link JoinMode#NEW} being declared where the current
67-
* conversation is ended silently and a new one is created. This might be the
68-
* obvious way to end a conversation, if the end of a use case is not always
69-
* forced to be invoked by a user.<br/>
70-
* <br/>
71-
*
72-
* <b>Temporary conversations</b><br/>
73-
* A temporary conversation is automatically created, if the container is about
74-
* to create a bean having conversation scope but there is no current
75-
* conversation in progress, hence a new, temporary conversation is created. A
76-
* temporary conversation might be turned into a long running one by joining it
77-
* or manually invoke {@link Conversation#begin()}.<br/>
78-
* <br/>
79-
*
80-
* <b>Initializing the conversation</b><br/>
81-
* If there is any need to initialize beans or entities while starting a new
82-
* conversation, the {@link ConversationInitializationCallback} might be used to
83-
* be invoked if the new conversation was started in order to initialize it.
84-
* This is done by providing such a callback to the
85-
* {@link ConversationManager#beginConversation(JoinMode, ConversationType, ConversationInitializationCallback...)}
86-
* method. The callback feature is not available through the annotation support
87-
* and hence is only available through the conversation manager API. Here is an
88-
* example on such an initializing feature; if a conversation is used in
89-
* conjunction of a JPA entity manager or Hibernate session, there might be
90-
* entity beans already loaded, cached or referenced within backing beans which
91-
* have to be merged into the entity manager or session in order to be used
92-
* within the conversation's work. So it would be possible to implement the
93-
* callback, merging the necessary entities used within the conversation into
94-
* the entity manager.<br/>
95-
* <br/>
96-
*
97-
* <b>Listening to conversation events</b><br/>
98-
* If there is a need to listening to events of a conversation, add yourself as
99-
* a {@link ConversationListener} to a new {@link Conversation} as being
100-
* returned by this {@link ConversationManager}. The same goal can be achieved
101-
* by implementing the {@link ConversationListener} interface on a conversation
102-
* scoped bean which will be registered automatically to receive events.<br/>
103-
* <br/>
104-
*
105-
* <b>Nesting conversations</b><br/>
106-
* Conversations might be nested either by inheriting the state of the parent (
107-
* {@link JoinMode#NESTED}) or by isolating its state from the parent (
108-
* {@link JoinMode#ISOLATED}). Ending a nested conversation automatically
109-
* switches back to its parent making it the current conversation.<br/>
110-
* <br/>
111-
*
112-
* <b>Where are conversations stored?</b><br/>
113-
* Conversations are created by the {@link ConversationManager} and registered
114-
* within the {@link ConversationScope}. The scope handler is injected into the
115-
* manager by Spring (statically as both beans are singletons) and registered as
116-
* a custom scope. As the scope handler is a singleton, it needs a store where
117-
* conversations are stored within which is usually bound to the current session
118-
* or window of a user and represented by the {@link ConversationStore}
119-
* interface. The store is usually being injected into the scope handler using
120-
* method injection as the store has a narrower scope than the scope handler. In
121-
* a web environment, the store would typically live in session scope to
122-
* separate the conversations from each of the sessions. There is always one
123-
* current conversation either stored within the session or as a request
124-
* parameter passed along every request to set the current conversation and is
125-
* accessed by the manager using a {@link ConversationResolver}.
126-
* </p>
127-
*
31+
* <p> The interface to be implemented by any conversation manager. It is used by the advice behind the conversational
32+
* annotations like {@link BeginConversation}, {@link EndConversation} and {@link Conversational} but might be used for
33+
* even fine grained access to the underlying conversation management, if a initializer callback is needed for instance
34+
* or if conversation switching should be used. If used directly, the conversation manager can be injected into any bean
35+
* to be used as it is a singleton and thread safe.<br/>
36+
*
37+
* Conversations are a good way to scope beans and attributes depending on business logic boundary rather than a
38+
* technical boundary of a scope like session, request etc. Usually a conversation boundary is defined by the starting
39+
* point of a use case and ended accordingly or in other words a conversation defines the boundary for a unit of
40+
* work.<br/> <br/>
41+
*
42+
* Here is a short description on how to use the conversation management:<br/> <br/> <b>Starting a conversation</b><br/>
43+
* A conversation can be started in two different ways, either by placing the {@link BeginConversation} annotation on a
44+
* method defining the starting point of the conversation (use case) or by invoking {@link
45+
* ConversationManager#beginConversation(boolean, JoinMode)} manually through the conversation manager. The {@link
46+
* JoinMode} declares on how a new conversation is created (see its javadoc for more details on the different join
47+
* modes).<br/> <br/>
48+
*
49+
* <b>Ending a conversation</b><br/> A current conversation is ended by either placing the {@link EndConversation}
50+
* annotation on the ending method or by manually invoke the {@link ConversationManager#endCurrentConversation(ConversationEndingType)}
51+
* method. A current conversation might also be ended, if a new conversation is started having {@link JoinMode#NEW}
52+
* being declared where the current conversation is ended silently and a new one is created. This might be the obvious
53+
* way to end a conversation, if the end of a use case is not always forced to be invoked by a user.<br/> <br/>
54+
*
55+
* <b>Temporary conversations</b><br/> A temporary conversation is automatically created, if the container is about to
56+
* create a bean having conversation scope but there is no current conversation in progress, hence a new, temporary
57+
* conversation is created. A temporary conversation might be turned into a long running one by joining it or manually
58+
* invoke {@link Conversation#begin()}.<br/> <br/>
59+
*
60+
* <b>Initializing the conversation</b><br/> If there is any need to initialize beans or entities while starting a new
61+
* conversation, the {@link ConversationInitializationCallback} might be used to be invoked if the new conversation was
62+
* started in order to initialize it. This is done by providing such a callback to the {@link
63+
* ConversationManager#beginConversation(JoinMode, ConversationType, ConversationInitializationCallback...)} method. The
64+
* callback feature is not available through the annotation support and hence is only available through the conversation
65+
* manager API. Here is an example on such an initializing feature; if a conversation is used in conjunction of a JPA
66+
* entity manager or Hibernate session, there might be entity beans already loaded, cached or referenced within backing
67+
* beans which have to be merged into the entity manager or session in order to be used within the conversation's work.
68+
* So it would be possible to implement the callback, merging the necessary entities used within the conversation into
69+
* the entity manager.<br/> <br/>
70+
*
71+
* <b>Listening to conversation events</b><br/> If there is a need to listening to events of a conversation, add
72+
* yourself as a {@link ConversationListener} to a new {@link Conversation} as being returned by this {@link
73+
* ConversationManager}. The same goal can be achieved by implementing the {@link ConversationListener} interface on a
74+
* conversation scoped bean which will be registered automatically to receive events.<br/> <br/>
75+
*
76+
* <b>Nesting conversations</b><br/> Conversations might be nested either by inheriting the state of the parent ( {@link
77+
* JoinMode#NESTED}) or by isolating its state from the parent ( {@link JoinMode#ISOLATED}). Ending a nested
78+
* conversation automatically switches back to its parent making it the current conversation.<br/> <br/>
79+
*
80+
* <b>Where are conversations stored?</b><br/> Conversations are created by the {@link ConversationManager} and
81+
* registered within the {@link org.springframework.conversation.scope.ConversationScope}. The scope handler is
82+
* injected into the manager by Spring (statically as both beans are singletons) and registered as a custom scope. As
83+
* the scope handler is a singleton, it needs a store where conversations are stored within which is usually bound to
84+
* the current session or window of a user and represented by the {@link ConversationStore} interface. The store is
85+
* usually being injected into the scope handler using method injection as the store has a narrower scope than the scope
86+
* handler. In a web environment, the store would typically live in session scope to separate the conversations from
87+
* each of the sessions. There is always one current conversation either stored within the session or as a request
88+
* parameter passed along every request to set the current conversation and is accessed by the manager using a {@link
89+
* ConversationResolver}. </p>
90+
*
12891
* @author Micha Kiener
12992
* @since 3.1
13093
*/
13194
public interface ConversationManager {
13295

13396
/**
13497
* This method starts a new {@link Conversation} and registers it within the
135-
* {@link ConversationScope} to be exposed as the current conversation.
98+
* {@link org.springframework.conversation.scope.ConversationScope} to be exposed as the current conversation.
13699
*
137100
* @param temporary flag indicating whether this new conversation is
138101
* temporary (if invoked from elsewhere as the scope, it should always be

0 commit comments

Comments
 (0)