1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.myfaces.orchestra.conversation;
21
22 import org.apache.myfaces.orchestra.conversation.model.UserData;
23 import org.springframework.transaction.annotation.Transactional;
24
25 import javax.persistence.EntityManager;
26 import javax.persistence.PersistenceContext;
27
28 /**
29 * A backing bean for a view (ie a "view controller") that has an associated
30 * persistence context.
31 * <p>
32 * In real applications, the PersistenceContext is more likely to be on a
33 * DAO bean referenced from the backing bean than directly on the backing
34 * bean class. However that doesn't change the principles.
35 */
36 public class PersistentBackingBean implements ConversationBindingListener
37 {
38 /**
39 * Inject a PersistenceContext that is associated with the conversation
40 * that this bean instance is in.
41 */
42 @PersistenceContext
43 private EntityManager entityManager;
44
45 /**
46 * A UserData instance read via the PersistenceContext object associated
47 * with this bean, ie one associated with the conversation that this bean
48 * is in.
49 */
50 private UserData restartedUser;
51
52 private UserData createdUser;
53
54 public PersistentBackingBean()
55 {
56 }
57
58 public void valueBound(ConversationBindingEvent event)
59 {
60 }
61
62 public void valueUnbound(ConversationBindingEvent event)
63 {
64 }
65
66 public UserData getRestartedUser()
67 {
68 return restartedUser;
69 }
70
71 /**
72 * Create a UserData object and commit it to the database.
73 * <p>
74 * Because this method is marked with the Transactional annotation, a
75 * commit will be performed when the method returns successfully
76 * (without exception), and a rollback will be performed when the
77 * method throws an exception.
78 */
79 @Transactional
80 public UserData createUser()
81 {
82 // Create an object that is not yet attached to a persistence context.
83 UserData userData = new UserData();
84 userData.setUsername("test");
85
86 // Attach the object to the persistence context. Note that nothing
87 // is written to the database at this point; that only happens when
88 // the persistence context is flushed and committed. Due to the
89 // Transactional annotation on this method, that happens when this
90 // method returns.
91 entityManager.persist(userData);
92
93 createdUser = userData;
94
95 return userData;
96 }
97
98 public UserData readUser(Long id)
99 {
100 return entityManager.find(UserData.class, id);
101 }
102
103 /**
104 * Invalidate the conversation in which this bean lives.
105 * <p>
106 * This means that the next attempt to dereference a proxy or
107 * EL expression will cause a new instance of this bean to
108 * be created. A new Conversation instance will be created to
109 * hold that bean, and a new PersistenceContext object will
110 * also be created (and then injected into this instance).
111 */
112 public void invalidateConversation()
113 {
114 Conversation.getCurrentInstance().invalidate();
115 }
116
117 /**
118 * Invalidate the conversation in which this bean lives, and
119 * then create a new bean instance (in a new conversation) and
120 * copy some data from the old to the new instance.
121 * <p>
122 * Using invalidateAndRestart allows information to be communicated
123 * between one instance of this bean and its replacement.
124 */
125 public void invalidateAndRestartConversation()
126 {
127 PersistentBackingBean conv = (PersistentBackingBean)
128 ConversationUtils.invalidateAndRestartCurrent();
129 conv.setRestartedUser(createdUser.getId());
130 }
131
132 public void setRestartedUser(Long id)
133 {
134 restartedUser = readUser(id);
135 }
136
137 public void updateUser(Long id, String username)
138 {
139 UserData user = readUser(id);
140 user.setUsername(username);
141 }
142 }