Project

General

Profile

« Previous | Next » 

Revision 2f02081c

Added by Andreas Kohlbecker over 6 years ago

ref #7046 completely removing open session per view implementation and adding init strategies for Name and Typedesignation editor

View differences:

src/main/java/eu/etaxonomy/cdm/service/CdmFilterablePagingProvider.java
19 19
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
20 20
import eu.etaxonomy.cdm.persistence.query.MatchMode;
21 21
import eu.etaxonomy.cdm.persistence.query.OrderHint;
22
import eu.etaxonomy.cdm.vaadin.session.ConversationDirector;
23 22

  
24 23
/**
25 24
 * @author a.kohlbecker
......
36 35

  
37 36
    private List<OrderHint> orderHints = OrderHint.ORDER_BY_TITLE_CACHE.asList();
38 37

  
39
    private ConversationDirector conversationDirector;
40

  
41 38

  
42 39
    /**
43 40
     * @return the matchMode
......
72 69
     *
73 70
     * @param service
74 71
     */
75
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, ConversationDirector conversationDirector) {
72
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service) {
76 73
        super();
77 74
        this.service = service;
78
        this.conversationDirector = conversationDirector;
79 75
    }
80 76

  
81 77
    /**
......
83 79
     * @param matchMode
84 80
     * @param orderHints
85 81
     */
86
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, MatchMode matchMode, List<OrderHint> orderHints, ConversationDirector conversationDirector) {
82
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, MatchMode matchMode, List<OrderHint> orderHints) {
87 83
        super();
88 84
        this.service = service;
89 85
        this.matchMode = matchMode;
90 86
        this.orderHints = orderHints;
91
        this.conversationDirector = conversationDirector;
92 87
    }
93 88

  
94 89
    /**
......
97 92
    @Override
98 93
    public List<T> findEntities(int firstRow, String filter) {
99 94

  
100
        conversationDirector.ensureBoundConversation();
101 95
        Pager<T> page = service.findByTitle(
102 96
                null,
103 97
                filter,
......
117 111
    @Override
118 112
    public int size(String filter) {
119 113

  
120
        conversationDirector.ensureBoundConversation();
121 114
        Pager<T> page = service.findByTitle(
122 115
                null,
123 116
                filter,
src/main/java/eu/etaxonomy/cdm/service/CdmStore.java
18 18
import com.vaadin.ui.UI;
19 19

  
20 20
import eu.etaxonomy.cdm.api.application.CdmRepository;
21
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
22 21
import eu.etaxonomy.cdm.api.service.DeleteResult;
23 22
import eu.etaxonomy.cdm.api.service.IService;
24 23
import eu.etaxonomy.cdm.model.common.CdmBase;
......
41 40

  
42 41
    private S service;
43 42

  
44
    TransactionStatus txNonConversational = null;
43
    TransactionStatus txStatus = null;
45 44

  
46
    ConversationHolder conversationHolder = null;
47

  
48
    /**
49
     * @return the conversationHolder
50
     */
51
    public ConversationHolder getConversationHolder() {
52
        return conversationHolder;
53
    }
45
//    ConversationHolder conversationHolder = null;
46
//
47
//    /**
48
//     * @return the conversationHolder
49
//     */
50
//    public ConversationHolder getConversationHolder() {
51
//        return conversationHolder;
52
//    }
54 53

  
55 54
    protected DefaultTransactionDefinition txDefinition = null;
56 55

  
......
68 67

  
69 68
    }
70 69

  
71
    /**
72
     * constructor which takes a ConversationHolder. The supplying class of the conversationHolder needs
73
     * to care for <code>bind()</code>, <code>unbind()</code> and <code>close()</code> since the store is
74
     * only responsible for starting and committing of transactions.
75
     *
76
     * @param repo
77
     * @param service
78
     * @param conversationHolder
79
     */
80
    public CdmStore(CdmRepository repo, S service, ConversationHolder conversationHolder) {
81

  
82
        this.repo = repo;
83
        this.service = service;
84
        this.conversationHolder = conversationHolder;
85

  
86
    }
70
//    /**
71
//     * constructor which takes a ConversationHolder. The supplying class of the conversationHolder needs
72
//     * to care for <code>bind()</code>, <code>unbind()</code> and <code>close()</code> since the store is
73
//     * only responsible for starting and committing of transactions.
74
//     *
75
//     * @param repo
76
//     * @param service
77
//     * @param conversationHolder
78
//     */
79
//    public CdmStore(CdmRepository repo, S service, ConversationHolder conversationHolder) {
80
//
81
//        this.repo = repo;
82
//        this.service = service;
83
//        this.conversationHolder = conversationHolder;
84
//
85
//    }
87 86

  
88 87
    /**
89 88
     * @return
90 89
     *
91 90
     */
92 91
    public TransactionStatus startTransaction() {
93
        if(conversationHolder != null && !conversationHolder.isTransactionActive()){
94
            //conversationHolder.setDefinition(getTransactionDefinition());
95
            return conversationHolder.startTransaction();
96
        } else {
92
//        if(conversationHolder != null && !conversationHolder.isTransactionActive()){
93
//            //conversationHolder.setDefinition(getTransactionDefinition());
94
//            return conversationHolder.startTransaction();
95
//        } else {
97 96
            checkExistingTransaction();
98
            txNonConversational = repo.startTransaction();
99
            return txNonConversational;
100
        }
97
            txStatus = repo.startTransaction();
98
            return txStatus;
99
//        }
101 100
    }
102 101

  
103 102
    /**
104 103
     *
105 104
     */
106 105
    protected void checkExistingTransaction() {
107
        if (txNonConversational != null) {
106
        if (txStatus != null) {
108 107
            // @formatter:off
109 108
            // holding the TransactionStatus as state is not good design. we
110 109
            // should change the save operation
......
159 158
    private Session getSession() {
160 159

  
161 160
        Session session;
162
        if(conversationHolder != null){
163
            session = conversationHolder.getSession();
164
        } else {
161
//        if(conversationHolder != null){
162
//            session = conversationHolder.getSession();
163
//        } else {
165 164
            session = repo.getSession();
166
        }
165
//        }
167 166
        logger.trace(this._toString() + ".getSession() - session:" + session.hashCode() + ", persistenceContext: "
168 167
                + ((SessionImplementor) session).getPersistenceContext() + " - " + session.toString());
169 168

  
......
193 192
        Session session = getSession();
194 193
        logger.trace(this._toString() + ".onEditorSaveEvent - session: " + session.hashCode());
195 194

  
196
        if(txNonConversational == null || (conversationHolder != null && !conversationHolder.isTransactionActive())){
195
        if(txStatus == null
196
//                || (conversationHolder != null && !conversationHolder.isTransactionActive())
197
                ){
197 198
            // no running transaction, start one ...
198 199
            startTransaction();
199 200
        }
......
259 260
            Notification notification = new Notification(notificationTitle, messageBody.toString(),
260 261
                    com.vaadin.ui.Notification.Type.ERROR_MESSAGE, true);
261 262
            notification.show(UI.getCurrent().getPage());
262
            txNonConversational = null;
263
            txStatus = null;
263 264
        }
264 265
        return null;
265 266
    }
......
267 268

  
268 269
    protected void commitTransction() {
269 270

  
270
        if(conversationHolder != null){
271
            conversationHolder.commit();
272
        } else {
273
            repo.commitTransaction(txNonConversational);
274
            txNonConversational = null;
275
        }
271
//        if(conversationHolder != null){
272
//            conversationHolder.commit();
273
//        } else {
274
            repo.commitTransaction(txStatus);
275
            txStatus = null;
276
//        }
276 277
    }
277 278

  
278 279
    /**
279 280
     * @param entityId
280 281
     */
281 282
    public T loadBean(int entityId) {
282
        conversationHolder.startTransaction();
283
//        conversationHolder.startTransaction();
283 284
        return service.find(entityId);
284 285
    }
285 286

  
src/main/java/eu/etaxonomy/cdm/service/CdmUserHelper.java
20 20
import org.springframework.security.core.context.SecurityContextHolder;
21 21
import org.springframework.security.core.userdetails.UserDetails;
22 22
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
23
import org.springframework.transaction.TransactionStatus;
23 24

  
24 25
import com.vaadin.spring.annotation.SpringComponent;
25 26
import com.vaadin.spring.annotation.UIScope;
......
194 195
     */
195 196
    @Override
196 197
    public CdmAuthority createAuthorityFor(String username, CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
198

  
199
        TransactionStatus txStatus = repo.startTransaction();
197 200
        UserDetails userDetails = repo.getUserService().loadUserByUsername(username);
198 201
        boolean newAuthorityAdded = false;
199 202
        CdmAuthority authority = null;
......
213 216
            SecurityContextHolder.getContext().setAuthentication(authentication);
214 217
            logger.debug("security context refreshed with user " + username);
215 218
        }
219
        repo.commitTransaction(txStatus);
216 220
        return newAuthorityAdded ? authority : null;
217 221

  
218 222
    }
......
228 232
    public CdmAuthority createAuthorityFor(String username, Class<? extends CdmBase> cdmType, Integer entitiyId, EnumSet<CRUD> crud, String property) {
229 233

  
230 234
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyId);
231
        return createAuthorityFor(username,cdmEntity, crud, property);
235
        return createAuthorityFor(username, cdmEntity, crud, property);
232 236
    }
233 237

  
234 238
    /**
src/main/java/eu/etaxonomy/cdm/service/IRegistrationWorkingSetService.java
34 34

  
35 35
    public Collection<RegistrationDTO> listDTOs(User submitter, Collection<RegistrationStatus> includedStatus);
36 36

  
37
    /**
38
     * @param  id the CDM Entity id
39
     * @return
40
     * @throws RegistrationValidationException
41
     * @deprecated Use {@link  #loadWorkingSetByReferenceID(Integer) instead
42
     */
43
    @Deprecated
44
    public RegistrationWorkingSet loadWorkingSetByCitationID(Integer id) throws RegistrationValidationException;
45

  
46 37
    /**
47 38
     * @param referenceID
48 39
     * @return
src/main/java/eu/etaxonomy/cdm/service/RegistrationWorkingSetService.java
9 9
package eu.etaxonomy.cdm.service;
10 10

  
11 11
import java.util.ArrayList;
12
import java.util.Arrays;
12 13
import java.util.Collection;
14
import java.util.HashSet;
13 15
import java.util.List;
14 16
import java.util.Optional;
17
import java.util.Set;
15 18

  
16 19
import org.apache.log4j.Logger;
17 20
import org.springframework.beans.factory.annotation.Autowired;
......
24 27
import eu.etaxonomy.cdm.model.common.User;
25 28
import eu.etaxonomy.cdm.model.name.Registration;
26 29
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
30
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
31
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
32
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
33
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
34
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
27 35
import eu.etaxonomy.cdm.model.reference.Reference;
36
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
28 37
import eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet;
29 38
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO;
30 39
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationValidationException;
......
51 60
@Transactional(readOnly=true)
52 61
public class RegistrationWorkingSetService implements IRegistrationWorkingSetService {
53 62

  
63
    public static final List<String> REGISTRATION_INIT_STRATEGY = Arrays.asList(new String []{
64
            // typeDesignation
65
            "typeDesignations.typeStatus.representations",
66
            "typeDesignations.typifiedNames",
67
            "typeDesignations.typeSpecimen",
68
            "typeDesignations.typeName",
69
            "typeDesignations.citation",
70
            "typeDesignations.citation.authorship.$",
71
            // name
72
            "name.$",
73
            "name.nomenclaturalReference.authorship",
74
            "name.nomenclaturalReference.inReference",
75
            "name.rank.representations",
76
            "name.status.type.representations",
77
            // institution
78
            "institution",
79
            }
80
    );
81

  
54 82
    /**
55 83
     *
56 84
     */
......
62 90
    @Qualifier("cdmRepository")
63 91
    private CdmRepository repo;
64 92

  
93
    @Autowired
94
    protected IBeanInitializer defaultBeanInitializer;
95

  
65 96
    public RegistrationWorkingSetService() {
66 97

  
67 98
    }
68 99

  
69 100

  
70 101
    /**
71
     * @param id the CDM Entity id
102
     * @param id the Registration entity id
72 103
     * @return
73 104
     */
74 105
    @Override
75 106
    public RegistrationDTO loadDtoById(Integer id) {
76 107
        Registration reg = repo.getRegistrationService().find(id);
108
        inititializeSpecimen(reg);
77 109
        return new RegistrationDTO(reg);
78 110
    }
79 111

  
......
81 113
    @Override
82 114
    public Collection<RegistrationDTO> listDTOs() {
83 115

  
84
        List<Registration> regs = repo.getRegistrationService().list(null, PAGE_SIZE, 0, null, null);
116
        List<Registration> regs = repo.getRegistrationService().list(null, PAGE_SIZE, 0, null, REGISTRATION_INIT_STRATEGY);
85 117

  
86 118
        List<RegistrationDTO> dtos = makeDTOs(regs);
87 119
        return dtos;
......
93 125
    @Override
94 126
    public Collection<RegistrationDTO> listDTOs(User submitter, Collection<RegistrationStatus> includedStatus) {
95 127

  
96
        Pager<Registration> pager = repo.getRegistrationService().page(submitter, includedStatus, PAGE_SIZE, 0, null, null);
97
        return makeDTOs(pager.getRecords());
128
        Pager<Registration> pager = repo.getRegistrationService().page(submitter, includedStatus, PAGE_SIZE, 0, null, REGISTRATION_INIT_STRATEGY);
129
        List<Registration> registrations = pager.getRecords();
130
        return makeDTOs(registrations);
98 131
    }
99 132

  
100 133
    /**
......
102 135
     * @throws RegistrationValidationException
103 136
     */
104 137
    @Override
105
    @Deprecated
106 138
    public RegistrationWorkingSet loadWorkingSetByReferenceID(Integer referenceID) throws RegistrationValidationException {
107 139

  
108 140
        Reference reference = repo.getReferenceService().find(referenceID);
109
        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, null);
141
        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, REGISTRATION_INIT_STRATEGY);
110 142
        return new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
111 143
    }
112 144

  
113
    @Override
114
    public RegistrationWorkingSet loadWorkingSetByCitationID(Integer id) throws RegistrationValidationException {
115

  
116
        Reference ref = repo.getReferenceService().find(id);
117
        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(ref), null, null, null, null);
118
        return new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
119
    }
120

  
121

  
122 145
    /**
123 146
     * @param regs
124 147
     * @return
125 148
     */
126 149
    private List<RegistrationDTO> makeDTOs(List<Registration> regs) {
150
        initializeSpecimens(regs);
127 151
        List<RegistrationDTO> dtos = new ArrayList<>(regs.size());
128 152
        regs.forEach(reg -> {dtos.add(new RegistrationDTO(reg));});
129 153
        return dtos;
130 154
    }
131 155

  
132 156

  
157
    /**
158
     * @param regs
159
     */
160
    private void initializeSpecimens(List<Registration> regs) {
161
        for(Registration reg : regs){
162
            inititializeSpecimen(reg);
163
        }
164

  
165
    }
166

  
167

  
168
    /**
169
     * @param reg
170
     */
171
    protected void inititializeSpecimen(Registration reg) {
172
        for(TypeDesignationBase<?> td : reg.getTypeDesignations()){
173
            if(td instanceof SpecimenTypeDesignation){
174

  
175
                DerivedUnit derivedUnit = ((SpecimenTypeDesignation) td).getTypeSpecimen();
176
                @SuppressWarnings("rawtypes")
177
                Set<SpecimenOrObservationBase> sobs = new HashSet<>();
178
                sobs.add(derivedUnit);
179

  
180
                while(sobs != null && !sobs.isEmpty()){
181
                    @SuppressWarnings("rawtypes")
182
                    Set<SpecimenOrObservationBase> nextSobs = null;
183
                    for(@SuppressWarnings("rawtypes") SpecimenOrObservationBase sob : sobs){
184
                        if(sob instanceof DerivedUnit) {
185
                            defaultBeanInitializer.initialize(sob, Arrays.asList(new String[]{
186
                                    "$",
187
                                    "derivedFrom.$",
188
                                    "derivedFrom.type"
189
                            }));
190
                            nextSobs = ((DerivedUnit)sob).getOriginals();
191
                        }
192
                        if(sob instanceof FieldUnit){
193
                            defaultBeanInitializer.initialize(sob, Arrays.asList(new String[]{
194
                                    "$",
195
                                    "gatheringEvent.$",
196
                                    "gatheringEvent.country.representations",
197
                                    "gatheringEvent.collectingAreas.representations",
198
                                    "gatheringEvent.actor"
199
                            }));
200
                            int i = 0;
201
                        }
202
                    }
203
                    sobs = nextSobs;
204
                }
205
            }
206
        }
207
    }
208

  
209

  
133 210

  
134 211

  
135 212

  
src/main/java/eu/etaxonomy/cdm/vaadin/session/ViewScopeConversationHolder.java
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.vaadin.session;
10

  
11
import java.io.Serializable;
12

  
13
import javax.sql.DataSource;
14

  
15
import org.hibernate.FlushMode;
16
import org.hibernate.SessionFactory;
17
import org.springframework.orm.hibernate5.support.OpenSessionInViewFilter;
18
import org.springframework.transaction.PlatformTransactionManager;
19
import org.springframework.transaction.TransactionDefinition;
20
import org.springframework.transaction.support.DefaultTransactionDefinition;
21

  
22
import com.vaadin.spring.annotation.SpringComponent;
23
import com.vaadin.spring.annotation.ViewScope;
24

  
25
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
26
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
27

  
28
/**
29
 * The ViewScopeConversationHolder allows to span conversations over all request threads
30
 * that are involved in the creation, interaction and ending of a View.
31
 *
32
 * <p><b>NOTE</b>: Hibernate sessions created in the conversation created by this holder
33
 * will not fluish automatically. The flush mode is initially
34
 * set to {@code FlushMode.MANUAL}. It assumes to be used
35
 * in combination with service layer transactions that care for the flushing: The
36
 * active transaction manager will temporarily change the flush mode to
37
 * {@code FlushMode.AUTO} during a read-write transaction, with the flush
38
 * mode reset to {@code FlushMode.NEVER} at the end of each transaction.
39
 * This behavior is implemented consistently in the {@link {@link AbstractEditorPresenter} methods
40
 * {@link AbstractEditorPresenter#onEditorPreSaveEvent(eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent) onEditorPreSaveEvent},
41
 * {@link AbstractEditorPresenter#onEditorSaveEvent(eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent) onEditorSaveEvent} and
42
 * {@link AbstractEditorPresenter#onEditorDeleteEvent(eu.etaxonomy.vaadin.mvp.event.EditorDeleteEvent) onEditorDeleteEvent}
43
 * In this whole strategy this class follows the ideas of the {@link OpenSessionInViewFilter}.
44
 *
45
 * @author a.kohlbecker
46
 * @since Jun 30, 2017
47
 *
48
 */
49
@SpringComponent
50
@ViewScope
51
public class ViewScopeConversationHolder extends ConversationHolder implements Serializable {
52

  
53

  
54
    private static final long serialVersionUID = 1001768184000981106L;
55

  
56
    /**
57
     *
58
     */
59
    public ViewScopeConversationHolder() {
60
        super();
61
        applyDefaultSettings();
62

  
63
    }
64

  
65
    /**
66
     * @param dataSource
67
     * @param sessionFactory
68
     * @param transactionManager
69
     */
70
    public ViewScopeConversationHolder(DataSource dataSource, SessionFactory sessionFactory,
71
            PlatformTransactionManager transactionManager) {
72
        super(dataSource, sessionFactory, transactionManager, false);
73
        applyDefaultSettings();
74
    }
75

  
76
    private void applyDefaultSettings(){
77

  
78
        setDefaultFlushMode(FlushMode.MANUAL);
79
        TransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NESTED);
80
        setDefinition(definition );
81
    }
82

  
83

  
84

  
85

  
86
}
src/main/java/eu/etaxonomy/cdm/vaadin/view/LoginPresenter.java
81 81
            }
82 82
        } catch (AuthenticationException e){
83 83
            getView().showErrorMessage("Login failed! Please check your username and password.");
84
        } finally {
85
            unbindConversation();
86 84
        }
87 85
        return false;
88 86
    }
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/SpecimenTypeDesignationWorkingsetEditorPresenter.java
8 8
*/
9 9
package eu.etaxonomy.cdm.vaadin.view.name;
10 10

  
11
import java.util.Arrays;
12 11
import java.util.EnumSet;
13 12
import java.util.HashSet;
14 13
import java.util.Iterator;
15 14
import java.util.Set;
16 15

  
17 16
import org.hibernate.Session;
17
import org.springframework.beans.factory.BeanFactory;
18
import org.springframework.beans.factory.annotation.Autowired;
18 19
import org.vaadin.viritin.fields.AbstractElementCollection;
19 20

  
20 21
import eu.etaxonomy.cdm.api.service.IRegistrationService;
......
35 36
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
36 37
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
37 38
import eu.etaxonomy.cdm.service.CdmStore;
39
import eu.etaxonomy.cdm.service.IRegistrationWorkingSetService;
40
import eu.etaxonomy.cdm.service.RegistrationWorkingSetService;
38 41
import eu.etaxonomy.cdm.vaadin.component.CdmBeanItemContainerFactory;
39 42
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityButtonUpdater;
40 43
import eu.etaxonomy.cdm.vaadin.model.TypedEntityReference;
......
47 50
import eu.etaxonomy.cdm.vaadin.util.converter.TypeDesignationSetManager.TypeDesignationWorkingSet;
48 51
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO;
49 52
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
53
import eu.etaxonomy.vaadin.ui.view.PopupEditorFactory;
50 54
/**
51 55
 * SpecimenTypeDesignationWorkingsetPopupEditorView implementation must override the showInEditor() method,
52 56
 * see {@link #prepareAsFieldGroupDataSource()} for details.
......
66 70

  
67 71
    private TaxonName typifiedName;
68 72

  
73
    /**
74
     * This object for this field will either be injected by the {@link PopupEditorFactory} or by a Spring
75
     * {@link BeanFactory}
76
     */
77
    @Autowired
78
    private IRegistrationWorkingSetService registrationWorkingSetService;
79

  
69 80
    /**
70 81
     * if not null, this CRUD set is to be used to create a CdmAuthoritiy for the base entitiy which will be
71 82
     * granted to the current use as long this grant is not assigned yet.
......
98 109
        if(identifier != null){
99 110

  
100 111
            TypeDesignationWorkingsetEditorIdSet idset = (TypeDesignationWorkingsetEditorIdSet)identifier;
101
            Registration reg = getRepo().getRegistrationService().loadByIds(Arrays.asList(idset.registrationId), null).get(0);
102 112

  
103 113
            if(idset.workingsetId != null){
104
                RegistrationDTO regDTO = new RegistrationDTO(reg);
114
                RegistrationDTO regDTO = registrationWorkingSetService.loadDtoById(idset.registrationId);
105 115
                // find the working set
106 116
                TypeDesignationWorkingSet typeDesignationWorkingSet = regDTO.getTypeDesignationWorkingSet(idset.workingsetId);
107 117
                workingSetDto = regDTO.getSpecimenTypeDesignationWorkingSetDTO(typeDesignationWorkingSet.getBaseEntityReference());
......
109 119
            } else {
110 120
                // create a new workingset, for a new fieldunit which is the base for the workingset
111 121
                FieldUnit newfieldUnit = FieldUnit.NewInstance();
122
                Registration reg = getRepo().getRegistrationService().load(idset.registrationId,
123
                        RegistrationWorkingSetService.REGISTRATION_INIT_STRATEGY);
124
                //TODO checkif passing reg as owner parameter is needed at all
112 125
                workingSetDto = new SpecimenTypeDesignationWorkingSetDTO(reg, newfieldUnit, null);
113 126
                citation = getRepo().getReferenceService().find(idset.publicationId);
114 127
                typifiedName = getRepo().getNameService().find(idset.typifiedNameId);
......
133 146

  
134 147
        getView().getTypeDesignationsCollectionField().setEditorInstantiator(new AbstractElementCollection.Instantiator<SpecimenTypeDesignationDTORow>() {
135 148

  
136
            CdmFilterablePagingProvider<Collection> collectionPagingProvider = new CdmFilterablePagingProvider<Collection>(getRepo().getCollectionService(), SpecimenTypeDesignationWorkingsetEditorPresenter.this);
149
            CdmFilterablePagingProvider<Collection> collectionPagingProvider = new CdmFilterablePagingProvider<Collection>(getRepo().getCollectionService());
137 150

  
138
            CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService(), SpecimenTypeDesignationWorkingsetEditorPresenter.this);
151
            CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService());
139 152

  
140 153
            @Override
141 154
            public SpecimenTypeDesignationDTORow create() {
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/TaxonNameEditorPresenter.java
8 8
*/
9 9
package eu.etaxonomy.cdm.vaadin.view.name;
10 10

  
11
import java.util.Arrays;
11 12
import java.util.List;
12 13
import java.util.Set;
13 14

  
......
50 51
        getView().getRankSelect().setItemCaptionPropertyId("label");
51 52

  
52 53
        getView().getNomReferenceCombobox().getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<Reference>());
53
        CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService(), TaxonNameEditorPresenter.this);
54
        CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService());
54 55
        getView().getNomReferenceCombobox().loadFrom(referencePagingProvider, referencePagingProvider, referencePagingProvider.getPageSize());
55 56
        getView().getNomReferenceCombobox().getSelect().addValueChangeListener(new ToOneRelatedEntityButtonUpdater<Reference>(getView().getNomReferenceCombobox()));
56 57

  
57 58

  
58 59
        getView().getBasionymCombobox().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
59
        CdmFilterablePagingProvider<TaxonName> namePagingProvider = new CdmFilterablePagingProvider<TaxonName>(getRepo().getNameService(), TaxonNameEditorPresenter.this);
60
        CdmFilterablePagingProvider<TaxonName> namePagingProvider = new CdmFilterablePagingProvider<TaxonName>(getRepo().getNameService());
60 61
        getView().getBasionymCombobox().setPagingProviders(namePagingProvider, namePagingProvider, namePagingProvider.getPageSize());
61 62

  
62 63
    }
......
67 68
    @Override
68 69
    protected TaxonName loadCdmEntityById(Integer identifier) {
69 70

  
71
        List<String> initStrategy = Arrays.asList(new String []{
72

  
73
                "$",
74
                "rank.representations",
75

  
76
                "nomenclaturalReference.authorship",
77
                "nomenclaturalReference.inReference",
78

  
79
                "status.type.representations",
80

  
81
                "combinationAuthorship",
82
                "exCombinationAuthorship",
83
                "basionymAuthorship",
84
                "exBasionymAuthorship",
85

  
86
                "basionyms.rank.representations",
87
                "basionyms.nomenclaturalReference.authorship",
88
                "basionyms.nomenclaturalReference.inReference",
89

  
90
                }
91
        );
92

  
70 93
        TaxonName bean;
71 94
        if(identifier != null){
72
            bean = getRepo().getNameService().find(identifier);
95
            bean = getRepo().getNameService().load(identifier, initStrategy);
73 96
        } else {
74 97
            bean = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
75 98
        }
src/main/java/eu/etaxonomy/cdm/vaadin/view/registration/ListPresenter.java
52 52
     * @return the workingSetService
53 53
     */
54 54
    public IRegistrationWorkingSetService getWorkingSetService() {
55
        ensureBoundConversation();
56 55
        return workingSetService;
57 56
    }
58 57

  
src/main/java/eu/etaxonomy/cdm/vaadin/view/registration/RegistrationWorkingsetPresenter.java
15 15
import org.springframework.beans.factory.annotation.Autowired;
16 16
import org.springframework.context.event.EventListener;
17 17
import org.springframework.security.core.Authentication;
18
import org.springframework.transaction.TransactionStatus;
18 19

  
19 20
import com.vaadin.spring.annotation.SpringComponent;
20 21
import com.vaadin.spring.annotation.ViewScope;
......
76 77
     * @return the workingSetService
77 78
     */
78 79
    public IRegistrationWorkingSetService getWorkingSetService() {
79
        ensureBoundConversation();
80 80
        return workingSetService;
81 81
    }
82 82

  
......
120 120
    protected Registration createNewRegistrationForName(Integer taxonNameId) {
121 121
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
122 122
        // move into RegistrationWorkflowStateMachine
123
        TransactionStatus txStatus = getRepo().startTransaction();
123 124
        long identifier = System.currentTimeMillis();
124 125
        Registration reg = Registration.NewInstance(
125 126
                "http://phycobank.org/" + identifier,
......
130 131
        reg.setSubmitter((User)authentication.getPrincipal());
131 132
        EntityChangeEvent event = getRegistrationStore().saveBean(reg);
132 133
        UserHelper.fromSession().createAuthorityForCurrentUser(Registration.class, event.getEntityId(), Operation.UPDATE, RegistrationStatus.PREPARATION.name());
134
        getRepo().commitTransaction(txStatus);
133 135
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134 136
        return getRepo().getRegistrationService().find(event.getEntityId());
135 137
    }
136 138

  
137 139

  
138 140
    /**
141
     * @param doReload TODO
139 142
     *
140 143
     */
141
    protected void refreshView() {
142
        getConversationHolder().getSession().clear();
143
        presentWorkingSet(workingset.getCitationId());
144
    protected void refreshView(boolean doReload) {
145
        if(doReload){
146
            loadWorkingSet(workingset.getCitationId());
147
        }
148
        getView().setWorkingset(workingset);
144 149
    }
145 150

  
146 151

  
......
152 157

  
153 158
        super.handleViewEntered();
154 159

  
155
        presentWorkingSet(getView().getCitationID());
160
        loadWorkingSet(getView().getCitationID());
161
        getView().setWorkingset(workingset);
156 162

  
157 163
        CdmFilterablePagingProvider<TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName>(
158
                getRepo().getNameService(), this);
164
                getRepo().getNameService());
159 165
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenrator = new CdmTitleCacheCaptionGenerator<TaxonName>();
160 166
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenrator);
161 167
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
162 168
    }
163 169

  
170

  
164 171
    /**
165
     * Loads the WorkingSet from the data base and passes it to the view.
166
     *
167
     * @param registrationID
172
     * @param referenceID
168 173
     */
169
    private void presentWorkingSet(Integer referenceID) {
174
    protected void loadWorkingSet(Integer referenceID) {
170 175
        try {
171 176
            workingset = getWorkingSetService().loadWorkingSetByReferenceID(referenceID);
172 177
        } catch (RegistrationValidationException error) {
......
183 188
            Reference citation = getRepo().getReferenceService().find(referenceID);
184 189
            workingset = new RegistrationWorkingSet(citation);
185 190
        }
186
        // getView().setHeaderText("Registrations for " + workingset.getCitation());
187
        getView().setWorkingset(workingset);
188 191
    }
189 192

  
190 193
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD && #event.sourceComponent == null")
......
247 250
    @EventListener
248 251
    public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
249 252
        if(event.getPopup() instanceof TaxonNamePopupEditor){
253
            TransactionStatus txStatus = getRepo().startTransaction();
250 254
            if(event.getReason().equals(Reason.SAVE)){
251 255
                if(newTaxonNameForRegistration != null){
252 256
                    int taxonNameId = newTaxonNameForRegistration.getId();
253 257
                    getRepo().getSession().refresh(newTaxonNameForRegistration);
254 258
                    Registration reg = createNewRegistrationForName(taxonNameId);
259
                    // reload workingset into current session
260
                    loadWorkingSet(workingset.getCitationId());
255 261
                    workingset.add(reg);
256 262
                }
257
                refreshView();
263
                refreshView(false);
258 264
            } else if(event.getReason().equals(Reason.CANCEL)){
259 265
                // clean up
260 266
                getTaxonNameStore().deleteBean(newTaxonNameForRegistration);
261 267
            }
268
            getRepo().commitTransaction(txStatus);
262 269
            newTaxonNameForRegistration = null;
263 270
        }
264 271
    }
......
354 361
    public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
355 362
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
356 363
            if(event.getReason().equals(Reason.SAVE)){
357
                refreshView();
364
                refreshView(true);
358 365
            } else if(event.getReason().equals(Reason.CANCEL)){
359 366
                // clean up
360 367
                if(newRegistrationDTOWithExistingName != null){
......
395 402
        }
396 403
        if(Reference.class.isAssignableFrom(event.getEntityType())){
397 404
            if(workingset.getCitationId().equals(event.getEntityId())){
398
                refreshView();
405
                refreshView(true);
399 406
            }
400 407
        } else
401 408
        if(Registration.class.isAssignableFrom(event.getEntityType())){
402 409
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getId() == event.getEntityId())){
403
                refreshView();
410
                refreshView(true);
404 411
            }
405 412
        } else
406 413
        if(TaxonName.class.isAssignableFrom(event.getEntityType())){
407 414
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
408 415
                reg.getTypifiedName() != null
409 416
                && reg.getTypifiedName().getId() == event.getEntityId())){
410
                    refreshView();
417
                    refreshView(true);
411 418
            }
412 419
        } else
413 420
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
......
417 424
                            )
418 425
                        )
419 426
                    ){
420
                refreshView();
427
                refreshView(true);
421 428
            }
422 429
        }
423 430

  
src/main/java/eu/etaxonomy/cdm/vaadin/view/registration/StartRegistrationPresenter.java
58 58
        super.onPresenterReady();
59 59

  
60 60
        CdmFilterablePagingProvider<Reference> pagingProvider = new CdmFilterablePagingProvider<Reference>(
61
                getRepo().getReferenceService(), this);
61
                getRepo().getReferenceService());
62 62
        CdmTitleCacheCaptionGenerator<Reference> titleCacheGenrator = new CdmTitleCacheCaptionGenerator<Reference>();
63 63
        getView().getReferenceCombobox().setCaptionGenerator(titleCacheGenrator);
64 64
        getView().getReferenceCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractEditorPresenter.java
12 12
import org.springframework.beans.factory.annotation.Autowired;
13 13
import org.springframework.context.ApplicationEventPublisher;
14 14
import org.springframework.context.event.EventListener;
15
import org.springframework.transaction.TransactionDefinition;
15

  
16
import com.vaadin.server.ServletPortletHelper;
17
import com.vaadin.server.VaadinRequest;
18
import com.vaadin.server.VaadinService;
19
import com.vaadin.server.VaadinSession;
20
import com.vaadin.ui.UI;
16 21

  
17 22
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction;
18
import eu.etaxonomy.cdm.vaadin.session.ViewScopeConversationHolder;
23
import eu.etaxonomy.cdm.vaadin.server.CdmSpringVaadinServletService;
24
import eu.etaxonomy.cdm.vaadin.server.RequestEndListener;
25
import eu.etaxonomy.cdm.vaadin.server.RequestStartListener;
19 26
import eu.etaxonomy.vaadin.mvp.event.EditorDeleteEvent;
20 27
import eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent;
21 28
import eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent;
......
27 34
 * @since Apr 5, 2017
28 35
 *
29 36
 */
30
public abstract class AbstractEditorPresenter<DTO extends Object, V extends ApplicationView<?>> extends AbstractPresenter<V> {
37
public abstract class AbstractEditorPresenter<DTO extends Object, V extends ApplicationView<?>> extends AbstractPresenter<V>
38
implements RequestEndListener, RequestStartListener {
31 39

  
32 40

  
33 41
    private static final long serialVersionUID = -6677074110764145236L;
......
61 69
        return bean;
62 70
    }
63 71

  
64
    @Override
65
    protected TransactionDefinition getTransactionDefinition(){
66
        super.getTransactionDefinition();
67
        if(definition.isReadOnly()){
68
            definition.setReadOnly(false);
69
        }
70
        return definition;
71
    }
72
//    @Override
73
//    protected TransactionDefinition getTransactionDefinition(){
74
//        super.getTransactionDefinition();
75
//        if(definition.isReadOnly()){
76
//            definition.setReadOnly(false);
77
//        }
78
//        return definition;
79
//    }
72 80

  
73 81
    /**
74 82
     * Regarding changing the Flush mode see see also {@link ViewScopeConversationHolder}
......
80 88
        if(!isFromOwnView(preSaveEvent)){
81 89
            return;
82 90
        }
83
        ensureBoundConversation();
84
        previousPreSaveEvenFlushMode = getConversationHolder().getSession().getFlushMode();
85
        getConversationHolder().getSession().setFlushMode(FlushMode.AUTO);
91
        getSession().setFlushMode(FlushMode.AUTO);
86 92

  
87 93
    }
88 94

  
......
98 104
        }
99 105
        DTO bean = saveEvent.getBean();
100 106
        saveBean(bean);
101
        getConversationHolder().getSession().setFlushMode(previousPreSaveEvenFlushMode);
107
        getSession().setFlushMode(previousPreSaveEvenFlushMode);
102 108
        previousPreSaveEvenFlushMode = null;
103 109
    }
104 110

  
......
112 118
       if(!isFromOwnView(deleteEvent)){
113 119
           return;
114 120
       }
115
       if(!conversationBound){
116
           bindConversation();
117
       }
118 121
       FlushMode previousFlushMode = getSession().getFlushMode();
119
       getConversationHolder().getSession().setFlushMode(FlushMode.AUTO);
122
       getSession().setFlushMode(FlushMode.AUTO);
120 123
       deleteBean(deleteEvent.getBean());
121
       getConversationHolder().getSession().setFlushMode(previousFlushMode);
124
       getSession().setFlushMode(previousFlushMode);
122 125
   }
123 126

  
124 127
    /**
......
137 140
        return action.getSourceView() != null && getView().equals(action.getSourceView());
138 141
    }
139 142

  
143
    @Override
144
    protected void init(V view) {
145
        super.init(view);
146
        registerListeners();
147
    }
148

  
149
    @Override
150
    public void onViewExit() {
151
        super.onViewExit();
152
        unregisterListeners();
153
    }
154

  
155

  
156
    // -------------------------------------------------------------------------
157

  
158
    protected void registerListeners() {
159
     // register as request start and end listener
160
        VaadinService service = UI.getCurrent().getSession().getService();
161
        if(service instanceof CdmSpringVaadinServletService){
162
            logger.trace(String.format("~~~~~ %s register as request listener", _toString()));
163
            ((CdmSpringVaadinServletService)service).addRequestEndListener(this);
164
            if(logger.isTraceEnabled()){
165
                ((CdmSpringVaadinServletService)service).addRequestStartListener(this);
166
            }
167
        } else {
168
            throw new RuntimeException("Using the CdmSpringVaadinServletService is required for proper per view conversation handling");
169
        }
170
    }
171

  
172
    /**
173
    *
174
    */
175
   protected void unregisterListeners() {
176
       VaadinService service = UI.getCurrent().getSession().getService();
177
       if(service instanceof CdmSpringVaadinServletService){
178
           logger.trace(String.format("~~~~~ %s un-register as request listener", _toString()));
179
           ((CdmSpringVaadinServletService)service).removeRequestEndListener(this);
180
           if(logger.isTraceEnabled()){
181
               ((CdmSpringVaadinServletService)service).removeRequestStartListener(this);
182
           }
183
       } else {
184
           throw new RuntimeException("Using the CdmSpringVaadinServletService is required for proper per view conversation handling");
185
       }
186
   }
187

  
188
    /**
189
     * <b>ONLY USED FOR LOGGING</b> when Level==TRACE
190
     * {@inheritDoc}
191
     */
192
    @Override
193
    public void onRequestStart(VaadinRequest request){
194

  
195
        if(requestNeedsSession(request) ){
196

  
197
            if(getView() instanceof AbstractPopupEditor){
198
                Object bean = ((AbstractPopupEditor)getView()).getBean();
199
                getSession().merge(bean);
200
            }
201

  
202
        } else {
203
            // ignore hartbeat, fileupload, push etc
204
            logger.trace("ignoring request:" + request.getPathInfo());
205
        }
206
    }
207

  
208
    /**
209
     * Returns <code>true</code> for:
210
     * <ul>
211
     *   <li>..</li>
212
     * <ul>
213
     *
214
     * Return <code>false</code> for:
215
     *
216
     * <ul>
217
     *   <li>UILD request in a existing view, like clicking on a button</li>
218
     * <ul>
219
     *
220
     * @return
221
    protected boolean isActiveView(){
222
        return UI.getCurrent() != null && getView() != null && getView() == navigationManager.getCurrentView();
223
    }
224
     */
225

  
226
    @Override
227
    public void onRequestEnd(VaadinRequest request, VaadinSession session){
228

  
229
        if(requestNeedsSession(request) ){
230
            logger.trace("onRequestEnd() " + request.getPathInfo() + " " + _toString());
231

  
232
        } else {
233
            // ignore hartbeat, fileupload, push etc
234
            logger.trace("ignoring request:" + request.getPathInfo());
235
        }
236

  
237
    }
238

  
239
    /**
240
     * @param request
241
     * @return
242
     */
243
    protected boolean requestNeedsSession(VaadinRequest request) {
244
        return !(
245
                ServletPortletHelper.isAppRequest(request) // includes published file request
246
             || ServletPortletHelper.isFileUploadRequest(request)
247
             || ServletPortletHelper.isHeartbeatRequest(request)
248
             || ServletPortletHelper.isPushRequest(request)
249
             );
250
    }
251

  
140 252
    protected abstract void saveBean(DTO bean);
141 253

  
142 254
    /**
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPresenter.java
4 4

  
5 5
import org.apache.log4j.Logger;
6 6
import org.hibernate.Session;
7
import org.hibernate.engine.internal.StatefulPersistenceContext;
7 8
import org.hibernate.engine.spi.SessionImplementor;
8 9
import org.springframework.beans.factory.annotation.Autowired;
9 10
import org.springframework.beans.factory.annotation.Qualifier;
10 11
import org.springframework.security.core.context.SecurityContext;
11 12
import org.springframework.security.core.context.SecurityContextHolder;
12
import org.springframework.transaction.IllegalTransactionStateException;
13
import org.springframework.transaction.TransactionDefinition;
14
import org.springframework.transaction.support.DefaultTransactionDefinition;
15

  
16
import com.vaadin.server.ServletPortletHelper;
17
import com.vaadin.server.VaadinRequest;
18
import com.vaadin.server.VaadinService;
19
import com.vaadin.server.VaadinSession;
20
import com.vaadin.ui.UI;
21 13

  
22 14
import eu.etaxonomy.cdm.api.application.CdmRepository;
23
import eu.etaxonomy.cdm.vaadin.server.CdmSpringVaadinServletService;
24
import eu.etaxonomy.cdm.vaadin.server.RequestStartListener;
25
import eu.etaxonomy.cdm.vaadin.session.IntraViewConversationDirector;
26
import eu.etaxonomy.cdm.vaadin.session.ViewScopeConversationHolder;
27 15
import eu.etaxonomy.vaadin.ui.navigation.NavigationManager;
28 16
import eu.etaxonomy.vaadin.ui.navigation.NavigationManagerBean;
29 17

  
......
37 25
 * @param <V>
38 26
 *            type of the view this presenter governs
39 27
 */
40
public abstract class AbstractPresenter<V extends ApplicationView> implements Serializable, IntraViewConversationDirector, RequestStartListener {
28
public abstract class AbstractPresenter<V extends ApplicationView> implements Serializable {
41 29

  
42 30

  
43 31
    private static final long serialVersionUID = 5260910510283481832L;
......
61 49
	@Autowired
62 50
	private NavigationManager navigationManager;
63 51

  
64
	private ViewScopeConversationHolder conversationHolder;
65

  
66
	protected DefaultTransactionDefinition definition = null;
67

  
68
    protected boolean conversationBound;
69

  
70
	@Autowired
71
	private void setConversationHolder(ViewScopeConversationHolder conversationHolder){
72
	    this.conversationHolder = conversationHolder;
73
	    this.conversationHolder.setDefinition(getTransactionDefinition());
74
	}
75

  
76
	protected TransactionDefinition getTransactionDefinition(){
77
	    if(definition == null){
78
    	    definition = new DefaultTransactionDefinition();
79
    	    definition.setReadOnly(true);
80
	    }
81
	    return definition;
82
	}
83 52

  
53
	//	protected DefaultTransactionDefinition definition = null;
84 54

  
55
    //	protected TransactionDefinition getTransactionDefinition(){
56
    //	    if(definition == null){
57
    //    	    definition = new DefaultTransactionDefinition();
58
    //    	    definition.setReadOnly(true);
59
    //	    }
60
    //	    return definition;
61
    //	}
85 62

  
86 63

  
87 64
	/**
88 65
	 * @return the repo
89 66
	 */
90 67
	public CdmRepository getRepo() {
91
	    if(!conversationBound){
92
	        // this is the central access point for getting access to the service layer.
93
	        // In case the presenter needs access to the repository, it most probably will use
94
	        // a service, so it is a good idea to bind the conversation at this point.
95
	        bindConversation();
96
	    }
97 68
	    return repo;
98 69
	}
99 70

  
......
110 81
     * @return
111 82
     */
112 83
    protected Session getSession() {
113
        Session session = conversationHolder.getSession();
84
        Session session = getRepo().getSession();
114 85
        logger.trace(this._toString() + ".getSession() - session:" + session.hashCode() +", persistenceContext: " + ((SessionImplementor)session).getPersistenceContext() + " - " + session.toString());
115 86
        return session;
116 87
    }
......
125 96
	 *
126 97
	 * @param view
127 98
	 */
128
	protected final void init(V view) {
99
	protected void init(V view) {
129 100
	    logger.trace(String.format("Presenter %s init()", _toString()));
130 101
		this.view = view;
131
		// bind the conversation to the thread of the first request send to the according View
132
		// all other requests are handled in onRequestStart()
133
		// logger.trace(String.format(">>>>> %s init() bind()", _toString()));
134
	    ensureBoundConversation();
135
	    // register as request start and end listener
136
	    VaadinService service = UI.getCurrent().getSession().getService();
137
	    if(service instanceof CdmSpringVaadinServletService){
138
	        logger.trace(String.format("~~~~~ %s register as request listener", _toString()));
139
	        ((CdmSpringVaadinServletService)service).addRequestEndListener(this);
140
	        if(logger.isTraceEnabled()){
141
	            ((CdmSpringVaadinServletService)service).addRequestStartListener(this);
142
	        }
143
	    } else {
144
	        throw new RuntimeException("Using the CdmSpringVaadinServletService is required for proper per view conversation handling");
145
	    }
146 102
		onPresenterReady();
147 103
	}
148 104

  
149
	/**
150
	 * Returns <code>true</code> for:
151
	 * <ul>
152
	 *   <li>..</li>
153
	 * <ul>
154
	 *
155
	 * Return <code>false</code> for:
156
	 *
157
	 * <ul>
158
     *   <li>UILD request in a existing view, like clicking on a button</li>
159
     * <ul>
160
     *
161
	 * @return
162
	protected boolean isActiveView(){
163
        return UI.getCurrent() != null && getView() != null && getView() == navigationManager.getCurrentView();
164
    }
165
	 */
166

  
167
    /**
168
     *
169
     */
170
	protected void bindConversation() {
171
        logger.trace(String.format(">>>>> %s bind()", _toString()));
172
        conversationHolder.bind();
173
        conversationBound = true;
174
    }
175

  
176
    @Override
177
    public void ensureBoundConversation() {
178
        if(!conversationBound){
179
            bindConversation();
180
        }
181
        if(!conversationHolder.isTransactionActive()){
182
            logger.trace(String.format(">>   %s starting transaction ", _toString()));
183
            conversationHolder.startTransaction();
184
        }
185
    }
186

  
187
    /**
188
     *
189
     */
190
    protected void unbindConversation() {
191
        logger.trace(String.format("<<<<< %s unbind()", _toString()));
192
        conversationHolder.unbind();
193
        // FIXME conversationHolder.isTransactionActive() always returns true
194
        // see https://dev.e-taxonomy.eu/redmine/issues/6780
195
        if(false && conversationHolder.isTransactionActive()){
196
            logger.trace(String.format("<<    %s comitting transaction ", _toString()));
197
            try{
198
                conversationHolder.commit(false);
199
            } catch (IllegalTransactionStateException | IllegalStateException e){
200
                // log this exception, but stop from propagating
201
                // FIXME remove this catch once https://dev.e-taxonomy.eu/redmine/issues/6780 is fixed
202
                logger.error(e.getMessage());
203
            }
204
        }
205
        conversationBound = false;
206
    }
207 105

  
208 106
    /**
209 107
	 * Extending classes should overwrite this method in order to perform logic
......
217 115
	}
218 116

  
219 117
    /**
220
     * <b>ONLY USED FOR LOGGING</b> when Level==TRACE
221
     * {@inheritDoc}
222
     */
223
    @Override
224
    public void onRequestStart(VaadinRequest request){
225

  
226
        if( ! requestNeedsConversation(request) ){
227
            // ignore hartbeat, fileupload, push etc
228
            logger.trace("ignoring request:" + request.getPathInfo());
229
            return;
230
        }
231
        logger.trace("onRequestStart() " + request.getPathInfo() + " " + _toString());
232
    }
233

  
234
    /**
235
     * @param request
236 118
     * @return
237 119
     */
238
    protected boolean requestNeedsConversation(VaadinRequest request) {
239
        return !(
240
                ServletPortletHelper.isAppRequest(request) // includes published file request
241
             || ServletPortletHelper.isFileUploadRequest(request)
242
             || ServletPortletHelper.isHeartbeatRequest(request)
243
             || ServletPortletHelper.isPushRequest(request)
244
             );
245
    }
246

  
247
    @Override
248
    public void onRequestEnd(VaadinRequest request, VaadinSession session){
249

  
250
        if( ! requestNeedsConversation(request) ){
251
            // ignore hartbeat, fileupload, push etc
252
            logger.trace("ignoring request:" + request.getPathInfo());
253
            return;
254
        }
255

  
256
        // always unbind at the end of a request to clean up the threadLocal variables in the
257
        // TransactionManager. This is crucial since applications containers manage threads in a pool
258
        // and the recycled threads may still have a reference to a SessionHolder from the processing
259
        // of a former request
260
        logger.trace("onRequestEnd() " + request.getPathInfo() + " " + _toString());
261
        if(conversationBound){
262
            unbindConversation();
263
        }
120
    private StatefulPersistenceContext getPersitenceContext() {
121
        return (StatefulPersistenceContext)((SessionImplementor)getSession()).getPersistenceContext();
264 122
    }
265 123

  
266 124
    public final void onViewEnter() {
......
268 126
	    handleViewEntered();
269 127
	}
270 128

  
271
	public final void onViewExit() {
129
	public void onViewExit() {
272 130
	    logger.trace(String.format("%s onViewExit()", _toString()));
273 131
	    handleViewExit();
274
	    // un-register as request start and end listener
275
	    if(conversationBound){
276
    	    logger.trace(String.format("<<<<< %s onViewExit() unbind()", _toString()));
277
            conversationHolder.unbind();
278
            conversationBound = false;
279
	    }
280
	    logger.trace(String.format("<<<<< %s onViewExit() close()", _toString()));
281
	    conversationHolder.close();
282
        VaadinService service = UI.getCurrent().getSession().getService();
283
        if(service instanceof CdmSpringVaadinServletService){
284
            logger.trace(String.format("~~~~~ %s un-register as request listener", _toString()));
285
            ((CdmSpringVaadinServletService)service).removeRequestEndListener(this);
286
            if(logger.isTraceEnabled()){
287
                ((CdmSpringVaadinServletService)service).removeRequestStartListener(this);
288
            }
289
        } else {
290
            throw new RuntimeException("Using the CdmSpringVaadinServletService is required for proper per view conversation handling");
291
        }
292 132
	}
293 133

  
294 134
	/**
......
317 157
        return navigationManager;
318 158
    }
319 159

  
320
    protected ViewScopeConversationHolder getConversationHolder(){
321
        return conversationHolder;
322
    }
323

  
324 160
    /**
325 161
     * @param repo the repo to set
326 162
     */
......
335 171
        this.navigationManager = navigationManager;
336 172
    }
337 173

  
338

  
339

  
340 174
}
src/main/java/eu/etaxonomy/vaadin/ui/view/PopupEditorFactory.java
27 27
import com.vaadin.spring.annotation.UIScope;
28 28

  
29 29
import eu.etaxonomy.cdm.api.application.CdmRepository;
30
import eu.etaxonomy.cdm.vaadin.session.ViewScopeConversationHolder;
30
import eu.etaxonomy.cdm.service.IRegistrationWorkingSetService;
31
import eu.etaxonomy.cdm.vaadin.view.name.SpecimenTypeDesignationWorkingsetEditorPresenter;
31 32
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
32 33
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
33 34
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
......
60 61
    @Autowired
61 62
    private PlatformTransactionManager transactionManager;
62 63

  
64
    @Autowired
65
    private IRegistrationWorkingSetService registrationWorkingSetService;
66

  
63 67
    @Autowired
64 68
    @Lazy
65 69
    private NavigationManager navigationManager;
66 70

  
67

  
68 71
    private Field presenterRepoField;
69 72
    private Field presenterNavigationManagerField;
70 73
    private Field presenterEventBusField;
71 74

  
72 75
    private Field viewEventBusField;
76
    private Field registrationWorkingSetServiceField;
73 77
    private Method viewInjectPresenterMethod;
74 78

  
75 79
    private Method viewInitMethod;
76 80

  
77
    private Method conversationHolderMethod;
78

  
79 81
    public PopupEditorFactory(){
80 82
        initFieldsAccess();
81 83
    }
......
96 98
            presenterEventBusField = AbstractEditorPresenter.class.getDeclaredField("eventBus");
97 99
            presenterEventBusField.setAccessible(true);
98 100

  
99
            conversationHolderMethod = AbstractPresenter.class.getDeclaredMethod("setConversationHolder", ViewScopeConversationHolder.class);
100
            conversationHolderMethod.setAccessible(true);
101

  
102 101
            viewEventBusField = AbstractView.class.getDeclaredField("eventBus");
103 102
            viewEventBusField.setAccessible(true);
104 103

  
......
108 107
            viewInitMethod = AbstractView.class.getDeclaredMethod("init");
109 108
            viewInitMethod.setAccessible(true);
110 109

  
110
            registrationWorkingSetServiceField = SpecimenTypeDesignationWorkingsetEditorPresenter.class.getDeclaredField("registrationWorkingSetService");
111
            registrationWorkingSetServiceField.setAccessible(true);
112

  
111 113
        } catch (NoSuchFieldException | SecurityException | NoSuchMethodException  e) {
112 114
            throw new RuntimeException("Severe error during initialization. Please check the classes AbstractPresenter, AbstractEditorPresenter, AbstractView for modificactions.", e);
113 115
        }
......
155 157
            Class<? extends AbstractPresenter<?>> presenterClass, P presenter) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
156 158
        presenterRepoField.set(presenter, repo);
157 159
        presenterNavigationManagerField.set(presenter, navigationManager);
158
        conversationHolderMethod.invoke(presenter, new ViewScopeConversationHolder(dataSource, sessionFactory, transactionManager));
159 160

  
160 161
        if(AbstractEditorPresenter.class.isAssignableFrom(presenterClass)){
161 162
            presenterEventBusField.set(presenter, eventBus);
162 163
        }
164
        if(SpecimenTypeDesignationWorkingsetEditorPresenter.class.equals(presenterClass)){
165
            registrationWorkingSetServiceField.set(presenter, registrationWorkingSetService);
166
        }
163 167
    }
164 168

  
165 169
    /**

Also available in: Unified diff