    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 }