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/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
}

Also available in: Unified diff