Project

General

Profile

« Previous | Next » 

Revision c46954e3

Added by Andreas Kohlbecker almost 7 years ago

ref #6169 RelatedEntityListSelect (ToOneRelatedEntityField) edit and select working, add blocked by #6673

View differences:

src/main/java/eu/etaxonomy/vaadin/mvp/AbstractCdmEditorPresenter.java
8 8
*/
9 9
package eu.etaxonomy.vaadin.mvp;
10 10

  
11
import org.apache.log4j.Logger;
11 12
import org.hibernate.Session;
13
import org.hibernate.engine.spi.SessionImplementor;
12 14
import org.springframework.context.event.EventListener;
13 15
import org.springframework.transaction.TransactionStatus;
14 16

  
......
19 21
import eu.etaxonomy.cdm.model.common.CdmBase;
20 22
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
21 23
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent.Type;
24
import eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent;
25
import eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent;
26
import eu.etaxonomy.vaadin.mvp.event.EditorViewEvent;
22 27

  
23 28
/**
29
 * Provides generic save operations of modified cdm entities.
30
 *
24 31
 * @author a.kohlbecker
25 32
 * @since Apr 5, 2017
26 33
 *
27 34
 */
28
public abstract class AbstractCdmEditorPresenter<DTO extends CdmBase> extends AbstractEditorPresenter<DTO> {
35
public abstract class AbstractCdmEditorPresenter<DTO extends CdmBase, V extends ApplicationView<?>> extends AbstractEditorPresenter<DTO, V> {
29 36

  
30 37
    private static final long serialVersionUID = 2218185546277084261L;
31 38

  
39
    private static final Logger logger = Logger.getLogger(AbstractCdmEditorPresenter.class);
40

  
32 41
    TransactionStatus tx = null;
33 42

  
43
    public AbstractCdmEditorPresenter() {
44
        super();
45
        logger.trace(this._toString() + " constructor");
46
    }
47

  
34 48
    @Override
35 49
    @EventListener
36 50
    public void onEditorPreSaveEvent(EditorPreSaveEvent preSaveEvent){
51
        if(!isResponsible(preSaveEvent)){
52
            return;
53
        }
54
        if(tx != null){
55
            // @formatter:off
56
            // holding the TransactionStatus as state is not good design. we should change the save operation
57
            // in the EditorView so that the presenter can process the save in one method call.
58
            // Problems:
59
            // 1. the fieldGroup needs a open session and read transaction during the validation, otherwise
60
            //    LazyInitialisationExceptions occur.
61
            // 2. passing the TransactionState to the view also doesn't seem like a good idea.
62
            // @formatter:on
63
            throw new RuntimeException("Can't process a second save operation while another one is in progress.");
64
        }
37 65
        super.onEditorPreSaveEvent(preSaveEvent);
66

  
67
        logger.trace(this._toString() + ".onEditorPreSaveEvent - starting transaction");
38 68
        tx = getRepo().startTransaction(true);
39 69
        // merge the bean and update the fieldGroup with the merged bean, so that updating
40 70
        // of field values in turn of the commit are can not cause LazyInitializationExeptions
41 71
        // the bean still has the original values at this point
72
        logger.trace(this._toString() + ".onEditorPreSaveEvent - merging bean into session");
42 73
        mergedBean(preSaveEvent.getCommitEvent());
43 74

  
44 75
    }
......
46 77
    @Override
47 78
    @EventListener
48 79
    public void onEditorSaveEvent(EditorSaveEvent saveEvent){
49
        if(!saveEvent.getView().equals(getView())){
80
        if(!isResponsible(saveEvent)){
50 81
            return;
51 82
        }
52 83
        // the bean is now updated with the changes made by the user
53 84
        // merge the bean into the session, ...
85
        logger.trace(this._toString() + ".onEditorSaveEvent - merging bean into session");
54 86
        DTO bean = mergedBean(saveEvent.getCommitEvent());
87

  
55 88
        Type changeEventType;
56 89
        if(bean.getId() > 1){
57 90
            changeEventType = Type.MODIFIED;
......
60 93
        }
61 94
        getRepo().getCommonService().saveOrUpdate(bean);
62 95
        getSession().flush();
96
        logger.trace(this._toString() + ".onEditorSaveEvent - session flushed");
63 97
        getRepo().commitTransaction(tx);
64 98
        tx = null;
99
        logger.trace(this._toString() + ".onEditorSaveEvent - transaction comitted");
65 100
        eventBus.publishEvent(new EntityChangeEvent(bean.getClass(), bean.getId(), changeEventType));
66 101
    }
67 102

  
68 103
    /**
69
     * Obtains the bean from the fieldGroup, merges the bean into the session and
70
     * updates the fieldGroup with the merged bean.
104
     * Obtains the bean from the fieldGroup. If the bean is contained in the session is being updated by
105
     * doing an evict and merge. The fieldGroup is updated with the merged bean.
106
     *
71 107
     *
72 108
     * @param CommitEvent
73
     * @return The bean merged to the session
109
     * @return The bean merged to the session or original bean in case a merge was not necessary.
74 110
     */
75 111
    private DTO mergedBean(CommitEvent commitEvent) {
76 112
        // using just some service to get hold of the session
......
78 114
        @SuppressWarnings("unchecked")
79 115
        BeanItem<DTO> itemDataSource = ((BeanFieldGroup<DTO>)commitEvent.getFieldBinder()).getItemDataSource();
80 116
        DTO bean = itemDataSource.getBean();
81
        if(session.isOpen()){
82
            // evict bean before merge to avoid duplicate beans in same session
83
            session.evict(bean);
84
        }
117
        if(session.contains(bean)){
85 118

  
86
        @SuppressWarnings("unchecked")
87
        DTO mergedBean = (DTO) session.merge(bean);
88
        itemDataSource.setBean(mergedBean);
89
        return mergedBean;
119
            if(session.isOpen()){
120
                // evict bean before merge to avoid duplicate beans in same session
121
                logger.trace(this._toString() + ".mergedBean() - evict " + bean.toString());
122
                session.evict(bean);
123
            }
124
            logger.trace(this._toString() + ".mergedBean() - doing merge of" + bean.toString());
125
            @SuppressWarnings("unchecked")
126
            DTO mergedBean = (DTO) session.merge(bean);
127
            logger.trace(this._toString() + ".mergedBean() - bean after merge " + bean.toString());
128
            itemDataSource.setBean(mergedBean);
129
            return mergedBean;
130
        }
131
        return bean;
90 132
    }
91 133

  
134

  
92 135
    /**
93 136
     * @return
94 137
     */
95 138
    private Session getSession() {
96
        return getRepo().getUserService().getSession();
139
        Session session = getRepo().getUserService().getSession();
140
        logger.trace(this._toString() + ".getSession() - session:" + session.hashCode() +", persistenceContext: " + ((SessionImplementor)session).getPersistenceContext() + " - " + session.toString());
141
        return session;
142
    }
143

  
144
    /**
145
     * see  #6673 (https://dev.e-taxonomy.eu/redmine/issues/6673)
146
     * @param event
147
     * @return
148
     */
149
    private boolean isResponsible(EditorViewEvent event){
150
        return event.getView().getClass().equals(getViewType());
97 151
    }
98 152

  
99 153
    @Override
......
101 155
        // blank implementation, since this is not needed in this or any sub class
102 156
    }
103 157

  
158
    private String _toString(){
159
        return this.getClass().getSimpleName() + "@" + this.hashCode();
160
    }
161

  
104 162
}

Also available in: Unified diff