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 }