Revision 262c713c
Added by Andreas Kohlbecker over 6 years ago
src/main/java/eu/etaxonomy/cdm/service/CdmStore.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.service; |
|
10 |
|
|
11 |
import org.apache.log4j.Logger; |
|
12 |
import org.hibernate.Session; |
|
13 |
import org.hibernate.engine.spi.SessionImplementor; |
|
14 |
import org.springframework.transaction.TransactionStatus; |
|
15 |
|
|
16 |
import com.vaadin.ui.Notification; |
|
17 |
import com.vaadin.ui.UI; |
|
18 |
|
|
19 |
import eu.etaxonomy.cdm.api.application.CdmRepository; |
|
20 |
import eu.etaxonomy.cdm.api.service.DeleteResult; |
|
21 |
import eu.etaxonomy.cdm.api.service.IService; |
|
22 |
import eu.etaxonomy.cdm.model.common.CdmBase; |
|
23 |
import eu.etaxonomy.cdm.model.common.IdentifiableEntity; |
|
24 |
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent; |
|
25 |
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent.Type; |
|
26 |
|
|
27 |
/** |
|
28 |
* @author a.kohlbecker |
|
29 |
* @since Jun 26, 2017 |
|
30 |
* |
|
31 |
* TODO better naming of this class, ServiceWrapper, ServiceOperator, ...? |
|
32 |
* |
|
33 |
*/ |
|
34 |
public class CdmStore<T extends CdmBase, S extends IService<T>> { |
|
35 |
|
|
36 |
private static final Logger logger = Logger.getLogger(CdmStore.class); |
|
37 |
|
|
38 |
private CdmRepository repo; |
|
39 |
|
|
40 |
private S service; |
|
41 |
|
|
42 |
TransactionStatus tx = null; |
|
43 |
|
|
44 |
Session session = null; |
|
45 |
|
|
46 |
/** |
|
47 |
* |
|
48 |
* @param repo |
|
49 |
* @param service |
|
50 |
* may be <code>null</code>, but delete operations will fail with |
|
51 |
* a NullPointerException in this case. |
|
52 |
*/ |
|
53 |
public CdmStore(CdmRepository repo, S service) { |
|
54 |
|
|
55 |
this.repo = repo; |
|
56 |
this.service = service; |
|
57 |
} |
|
58 |
|
|
59 |
/** |
|
60 |
* @return |
|
61 |
* |
|
62 |
*/ |
|
63 |
public TransactionStatus startTransaction() { |
|
64 |
if (tx != null) { |
|
65 |
// @formatter:off |
|
66 |
// holding the TransactionStatus as state is not good design. we |
|
67 |
// should change the save operation |
|
68 |
// in the EditorView so that the presenter can process the save in |
|
69 |
// one method call. |
|
70 |
// Problems: |
|
71 |
// 1. the fieldGroup needs a open session and read transaction |
|
72 |
// during the validation, otherwise |
|
73 |
// LazyInitialisationExceptions occur. |
|
74 |
// 2. passing the TransactionState to the view also doesn't seem |
|
75 |
// like a good idea. |
|
76 |
// @formatter:on |
|
77 |
throw new RuntimeException("Can't process a second save operation while another one is in progress."); |
|
78 |
} |
|
79 |
return repo.startTransaction(true); |
|
80 |
} |
|
81 |
|
|
82 |
/** |
|
83 |
* If the bean is contained in the session it is being updated by doing an |
|
84 |
* evict and merge. The fieldGroup is updated with the merged bean. |
|
85 |
* |
|
86 |
* |
|
87 |
* @param bean |
|
88 |
* @return The bean merged to the session or original bean in case a merge |
|
89 |
* was not necessary. |
|
90 |
*/ |
|
91 |
public T mergedBean(T bean) { |
|
92 |
Session session = getSession(); |
|
93 |
|
|
94 |
// session.clear(); |
|
95 |
if (session.contains(bean)) { |
|
96 |
// evict bean before merge to avoid duplicate beans in same session |
|
97 |
logger.trace(this._toString() + ".mergedBean() - evict " + bean.toString()); |
|
98 |
session.evict(bean); |
|
99 |
} |
|
100 |
|
|
101 |
logger.trace(this._toString() + ".mergedBean() - doing merge of" + bean.toString()); |
|
102 |
// to avoid merge problems as described in |
|
103 |
// https://dev.e-taxonomy.eu/redmine/issues/6687 |
|
104 |
// we are set the hibernate property |
|
105 |
// hibernate.event.merge.entity_copy_observer=allow |
|
106 |
@SuppressWarnings("unchecked") |
|
107 |
T mergedBean = (T) session.merge(bean); |
|
108 |
logger.trace(this._toString() + ".mergedBean() - bean after merge " + bean.toString()); |
|
109 |
return mergedBean; |
|
110 |
|
|
111 |
} |
|
112 |
|
|
113 |
/** |
|
114 |
* @return |
|
115 |
*/ |
|
116 |
protected Session getSession() { |
|
117 |
Session session = repo.getSession(); |
|
118 |
logger.trace(this._toString() + ".getSession() - session:" + session.hashCode() + ", persistenceContext: " |
|
119 |
+ ((SessionImplementor) session).getPersistenceContext() + " - " + session.toString()); |
|
120 |
return session; |
|
121 |
} |
|
122 |
|
|
123 |
protected String _toString() { |
|
124 |
return this.getClass().getSimpleName() + "@" + this.hashCode(); |
|
125 |
} |
|
126 |
|
|
127 |
/** |
|
128 |
* |
|
129 |
* @param bean |
|
130 |
* @return the merged bean, this bean is <b>not reloaded</b> from the |
|
131 |
* persistent storage. |
|
132 |
*/ |
|
133 |
public EntityChangeEvent saveBean(T bean) { |
|
134 |
|
|
135 |
Type changeEventType; |
|
136 |
if(bean.getId() > 1){ |
|
137 |
changeEventType = Type.MODIFIED; |
|
138 |
} else { |
|
139 |
changeEventType = Type.CREATED; |
|
140 |
} |
|
141 |
|
|
142 |
// Session session = getSession(); |
|
143 |
logger.trace(this._toString() + ".onEditorSaveEvent - session: " + session); |
|
144 |
logger.trace(this._toString() + ".onEditorSaveEvent - merging bean into session"); |
|
145 |
// merge the changes into the session, ... |
|
146 |
T mergedBean = mergedBean(bean); |
|
147 |
repo.getCommonService().saveOrUpdate(mergedBean); |
|
148 |
session.flush(); |
|
149 |
logger.trace(this._toString() + ".onEditorSaveEvent - session flushed"); |
|
150 |
repo.commitTransaction(tx); |
|
151 |
tx = null; |
|
152 |
if (session.isOpen()) { |
|
153 |
session.close(); |
|
154 |
} |
|
155 |
logger.trace(this._toString() + ".onEditorSaveEvent - transaction comitted"); |
|
156 |
return new EntityChangeEvent(mergedBean.getClass(), mergedBean.getId(), changeEventType); |
|
157 |
} |
|
158 |
|
|
159 |
/** |
|
160 |
* |
|
161 |
* @param bean |
|
162 |
* @return a EntityChangeEvent in case the deletion was successful otherwise <code>null</code>. |
|
163 |
*/ |
|
164 |
public final EntityChangeEvent deleteBean(T bean) { |
|
165 |
logger.trace(this._toString() + ".onEditorPreSaveEvent - starting transaction"); |
|
166 |
tx = startTransaction(); |
|
167 |
logger.trace(this._toString() + ".deleteBean - deleting" + bean.toString()); |
|
168 |
DeleteResult result = service.delete(bean); |
|
169 |
if (result.isOk()) { |
|
170 |
Session session = getSession(); |
|
171 |
session.flush(); |
|
172 |
logger.trace(this._toString() + ".deleteBean - session flushed"); |
|
173 |
repo.commitTransaction(tx); |
|
174 |
tx = null; |
|
175 |
session.close(); |
|
176 |
logger.trace(this._toString() + ".deleteBean - transaction comitted"); |
|
177 |
return new EntityChangeEvent(bean.getClass(), bean.getId(), Type.REMOVED); |
|
178 |
} else { |
|
179 |
String notificationTitle; |
|
180 |
StringBuffer messageBody = new StringBuffer(); |
|
181 |
if (result.isAbort()) { |
|
182 |
notificationTitle = "The delete operation as abborded by the system."; |
|
183 |
} else { |
|
184 |
notificationTitle = "An error occured during the delete operation."; |
|
185 |
} |
|
186 |
if (!result.getExceptions().isEmpty()) { |
|
187 |
messageBody.append("<h3>").append("Exceptions:").append("</h3>").append("<ul>"); |
|
188 |
result.getExceptions().forEach(e -> messageBody.append("<li>").append(e.getMessage()).append("</li>")); |
|
189 |
messageBody.append("</ul>"); |
|
190 |
} |
|
191 |
if (!result.getRelatedObjects().isEmpty()) { |
|
192 |
messageBody.append("<h3>").append("Related objects exist:").append("</h3>").append("<ul>"); |
|
193 |
result.getRelatedObjects().forEach(e -> { |
|
194 |
messageBody.append("<li>"); |
|
195 |
if (IdentifiableEntity.class.isAssignableFrom(e.getClass())) { |
|
196 |
messageBody.append(((IdentifiableEntity) e).getTitleCache()); |
|
197 |
} else { |
|
198 |
messageBody.append(e.toString()); |
|
199 |
} |
|
200 |
messageBody.append("</li>"); |
|
201 |
}); |
|
202 |
|
|
203 |
messageBody.append("</ul>"); |
|
204 |
} |
|
205 |
Notification notification = new Notification(notificationTitle, messageBody.toString(), |
|
206 |
com.vaadin.ui.Notification.Type.ERROR_MESSAGE, true); |
|
207 |
notification.show(UI.getCurrent().getPage()); |
|
208 |
tx = null; |
|
209 |
} |
|
210 |
return null; |
|
211 |
} |
|
212 |
|
|
213 |
} |
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/SpecimenTypeDesignationWorkingsetEditorPresenter.java | ||
---|---|---|
175 | 175 |
*/ |
176 | 176 |
@Override |
177 | 177 |
protected void saveBean(SpecimenTypeDesignationWorkingSetDTO bean) { |
178 |
// TODO Auto-generated method stub |
|
178 |
Session session = getSession(); |
|
179 |
getRepo().startTransaction(); |
|
179 | 180 |
|
180 | 181 |
} |
181 | 182 |
|
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/SpecimenTypeDesignationWorkingsetPopupEditor.java | ||
---|---|---|
56 | 56 |
|
57 | 57 |
private ElementCollectionField<SpecimenTypeDesignationDTO> typeDesignationsCollectionField; |
58 | 58 |
|
59 |
private static int windowPixelWidth = 900; |
|
60 |
|
|
61 | 59 |
/** |
62 | 60 |
* @return the countrySelectField |
63 | 61 |
*/ |
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/TaxonNameEditorPresenter.java | ||
---|---|---|
14 | 14 |
|
15 | 15 |
import org.apache.log4j.Logger; |
16 | 16 |
|
17 |
import eu.etaxonomy.cdm.api.service.DeleteResult; |
|
18 |
import eu.etaxonomy.cdm.api.service.config.NameDeletionConfigurator; |
|
17 |
import eu.etaxonomy.cdm.api.service.INameService; |
|
19 | 18 |
import eu.etaxonomy.cdm.model.name.TaxonName; |
20 | 19 |
import eu.etaxonomy.cdm.model.reference.Reference; |
21 | 20 |
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider; |
... | ... | |
63 | 62 |
} |
64 | 63 |
|
65 | 64 |
|
66 |
/** |
|
67 |
* {@inheritDoc} |
|
68 |
*/ |
|
69 |
@Override |
|
70 |
protected DeleteResult executeServiceDeleteOperation(TaxonName bean) { |
|
71 |
NameDeletionConfigurator config = new NameDeletionConfigurator(); |
|
72 |
return getRepo().getNameService().delete(bean.getUuid(), config); |
|
73 |
} |
|
74 |
|
|
75 | 65 |
@Override |
76 | 66 |
protected TaxonName handleTransientProperties(TaxonName bean) { |
77 | 67 |
logger.trace(this._toString() + ".onEditorSaveEvent - handling transient properties"); |
... | ... | |
92 | 82 |
} |
93 | 83 |
} |
94 | 84 |
return bean; |
85 |
} |
|
95 | 86 |
|
87 |
/** |
|
88 |
* {@inheritDoc} |
|
89 |
*/ |
|
90 |
@Override |
|
91 |
protected INameService getService() { |
|
92 |
return getRepo().getNameService(); |
|
96 | 93 |
} |
97 | 94 |
|
98 | 95 |
|
96 |
|
|
99 | 97 |
} |
src/main/java/eu/etaxonomy/cdm/vaadin/view/reference/ReferenceEditorPresenter.java | ||
---|---|---|
18 | 18 |
import org.vaadin.viritin.fields.LazyComboBox.FilterableCountProvider; |
19 | 19 |
import org.vaadin.viritin.fields.LazyComboBox.FilterablePagingProvider; |
20 | 20 |
|
21 |
import eu.etaxonomy.cdm.api.service.DeleteResult;
|
|
21 |
import eu.etaxonomy.cdm.api.service.IService;
|
|
22 | 22 |
import eu.etaxonomy.cdm.api.service.pager.Pager; |
23 | 23 |
import eu.etaxonomy.cdm.model.reference.Reference; |
24 | 24 |
import eu.etaxonomy.cdm.model.reference.ReferenceFactory; |
... | ... | |
143 | 143 |
* {@inheritDoc} |
144 | 144 |
*/ |
145 | 145 |
@Override |
146 |
protected DeleteResult executeServiceDeleteOperation(Reference bean) {
|
|
147 |
return getRepo().getReferenceService().delete(bean);
|
|
146 |
protected IService<Reference> getService() {
|
|
147 |
return getRepo().getReferenceService(); |
|
148 | 148 |
} |
149 | 149 |
|
150 |
|
|
151 |
|
|
150 | 152 |
} |
src/main/java/eu/etaxonomy/cdm/vaadin/view/registration/RegistrationEditorPresenter.java | ||
---|---|---|
8 | 8 |
*/ |
9 | 9 |
package eu.etaxonomy.cdm.vaadin.view.registration; |
10 | 10 |
|
11 |
import eu.etaxonomy.cdm.api.service.DeleteResult;
|
|
11 |
import eu.etaxonomy.cdm.api.service.IRegistrationService;
|
|
12 | 12 |
import eu.etaxonomy.cdm.model.name.Registration; |
13 | 13 |
import eu.etaxonomy.vaadin.mvp.AbstractCdmEditorPresenter; |
14 | 14 |
|
... | ... | |
25 | 25 |
* {@inheritDoc} |
26 | 26 |
*/ |
27 | 27 |
@Override |
28 |
protected DeleteResult executeServiceDeleteOperation(Registration bean) {
|
|
29 |
return getRepo().getRegistrationService().delete(bean);
|
|
28 |
protected IRegistrationService getService() {
|
|
29 |
return getRepo().getRegistrationService(); |
|
30 | 30 |
} |
31 | 31 |
|
32 | 32 |
|
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractCdmEditorPresenter.java | ||
---|---|---|
13 | 13 |
import org.springframework.context.event.EventListener; |
14 | 14 |
import org.springframework.transaction.TransactionStatus; |
15 | 15 |
|
16 |
import com.vaadin.ui.Notification; |
|
17 |
import com.vaadin.ui.UI; |
|
18 |
|
|
19 |
import eu.etaxonomy.cdm.api.service.DeleteResult; |
|
16 |
import eu.etaxonomy.cdm.api.service.IService; |
|
20 | 17 |
import eu.etaxonomy.cdm.model.common.CdmBase; |
21 |
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
|
|
18 |
import eu.etaxonomy.cdm.service.CdmStore;
|
|
22 | 19 |
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent; |
23 |
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent.Type; |
|
24 | 20 |
import eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent; |
25 | 21 |
import eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent; |
26 | 22 |
|
... | ... | |
39 | 35 |
|
40 | 36 |
TransactionStatus tx = null; |
41 | 37 |
|
38 |
Session session = null; |
|
39 |
|
|
40 |
CdmStore<DTO, IService<DTO>> store ; |
|
41 |
|
|
42 | 42 |
public AbstractCdmEditorPresenter() { |
43 | 43 |
super(); |
44 | 44 |
logger.trace(this._toString() + " constructor"); |
45 | 45 |
} |
46 | 46 |
|
47 |
protected CdmStore<DTO, IService<DTO>> getStore() { |
|
48 |
if(store == null){ |
|
49 |
store = new CdmStore<>(getRepo(), getService()); |
|
50 |
} |
|
51 |
return store; |
|
52 |
} |
|
53 |
|
|
54 |
|
|
47 | 55 |
/** |
48 | 56 |
* @return |
49 |
* |
|
50 | 57 |
*/ |
51 |
protected TransactionStatus startTransaction() { |
|
52 |
if(tx != null){ |
|
53 |
// @formatter:off |
|
54 |
// holding the TransactionStatus as state is not good design. we should change the save operation |
|
55 |
// in the EditorView so that the presenter can process the save in one method call. |
|
56 |
// Problems: |
|
57 |
// 1. the fieldGroup needs a open session and read transaction during the validation, otherwise |
|
58 |
// LazyInitialisationExceptions occur. |
|
59 |
// 2. passing the TransactionState to the view also doesn't seem like a good idea. |
|
60 |
// @formatter:on |
|
61 |
throw new RuntimeException("Can't process a second save operation while another one is in progress."); |
|
62 |
} |
|
63 |
return getRepo().startTransaction(true); |
|
64 |
} |
|
58 |
protected abstract IService<DTO> getService(); |
|
65 | 59 |
|
66 | 60 |
@SuppressWarnings("unchecked") |
67 | 61 |
@Override |
... | ... | |
71 | 65 |
return; |
72 | 66 |
} |
73 | 67 |
|
68 |
session = getSession(); |
|
69 |
logger.trace(this._toString() + ".onEditorPreSaveEvent - session: " + session); |
|
74 | 70 |
logger.trace(this._toString() + ".onEditorPreSaveEvent - starting transaction"); |
75 |
tx = startTransaction(); |
|
71 |
tx = getStore().startTransaction();
|
|
76 | 72 |
// merge the bean and update the fieldGroup with the merged bean, so that updating |
77 | 73 |
// of field values in turn of the commit are can not cause LazyInitializationExeptions |
78 | 74 |
// the bean still has the original values at this point |
... | ... | |
88 | 84 |
return; |
89 | 85 |
} |
90 | 86 |
// the bean is now updated with the changes made by the user |
91 |
Session session = getSession(); |
|
92 |
logger.trace(this._toString() + ".onEditorSaveEvent - merging bean into session"); |
|
93 | 87 |
DTO bean = (DTO) saveEvent.getBean(); |
94 |
Type changeEventType; |
|
95 |
if(bean.getId() > 1){ |
|
96 |
changeEventType = Type.MODIFIED; |
|
97 |
} else { |
|
98 |
changeEventType = Type.CREATED; |
|
99 |
} |
|
100 | 88 |
bean = handleTransientProperties(bean); |
101 |
// merge the changes into the session, ... |
|
102 |
DTO mergedBean = mergedBean(bean); |
|
103 |
getRepo().getCommonService().saveOrUpdate(mergedBean); |
|
104 |
session.flush(); |
|
105 |
logger.trace(this._toString() + ".onEditorSaveEvent - session flushed"); |
|
106 |
getRepo().commitTransaction(tx); |
|
107 |
tx = null; |
|
108 |
if(session.isOpen()){ |
|
109 |
session.close(); |
|
89 |
EntityChangeEvent changeEvent = getStore().saveBean(bean); |
|
90 |
if(changeEvent != null){ |
|
91 |
eventBus.publishEvent(changeEvent); |
|
110 | 92 |
} |
111 |
logger.trace(this._toString() + ".onEditorSaveEvent - transaction comitted"); |
|
112 |
eventBus.publishEvent(new EntityChangeEvent(mergedBean.getClass(), mergedBean.getId(), changeEventType)); |
|
113 | 93 |
} |
114 | 94 |
|
115 | 95 |
/** |
... | ... | |
119 | 99 |
* This is necessary because Vaadin MethodProperties are readonly when no setter is |
120 | 100 |
* available. This can be the case with transient properties. Automatic updating |
121 | 101 |
* of the property during the fieldGroup commit does not work in this case. |
102 |
* |
|
103 |
* @deprecated editors should operate on DTOs instead, remove this method if unused. |
|
122 | 104 |
*/ |
105 |
@Deprecated |
|
123 | 106 |
protected DTO handleTransientProperties(DTO bean) { |
124 | 107 |
// no need to handle transient properties in the generic case |
125 | 108 |
return bean; |
126 | 109 |
} |
127 | 110 |
|
128 | 111 |
/** |
129 |
* Obtains the bean from the fieldGroup. If the bean is contained in the session is being updated by
|
|
112 |
* If the bean is contained in the session it is being updated by
|
|
130 | 113 |
* doing an evict and merge. The fieldGroup is updated with the merged bean. |
131 | 114 |
* |
115 |
* @param bean |
|
132 | 116 |
* |
133 |
* @param CommitEvent |
|
134 | 117 |
* @return The bean merged to the session or original bean in case a merge was not necessary. |
135 | 118 |
*/ |
136 | 119 |
private DTO mergedBean(DTO bean) { |
137 |
Session session = getSession(); |
|
138 |
|
|
139 |
// session.clear(); |
|
140 |
if(session.contains(bean)){ |
|
141 |
// evict bean before merge to avoid duplicate beans in same session |
|
142 |
logger.trace(this._toString() + ".mergedBean() - evict " + bean.toString()); |
|
143 |
session.evict(bean); |
|
144 |
} |
|
145 |
|
|
146 |
logger.trace(this._toString() + ".mergedBean() - doing merge of" + bean.toString()); |
|
147 |
// to avoid merge problems as described in https://dev.e-taxonomy.eu/redmine/issues/6687 |
|
148 |
// we are set the hibernate property hibernate.event.merge.entity_copy_observer=allow |
|
149 |
@SuppressWarnings("unchecked") |
|
150 |
DTO mergedBean = (DTO) session.merge(bean); |
|
151 |
logger.trace(this._toString() + ".mergedBean() - bean after merge " + bean.toString()); |
|
120 |
DTO mergedBean = getStore().mergedBean(bean); |
|
152 | 121 |
((AbstractPopupEditor<DTO, AbstractCdmEditorPresenter<DTO, V>>)getView()).updateItemDataSource(mergedBean); |
153 | 122 |
return mergedBean; |
154 | 123 |
|
155 | 124 |
} |
156 | 125 |
|
157 |
|
|
158 | 126 |
@Override |
159 | 127 |
protected final void saveBean(DTO bean){ |
160 | 128 |
// blank implementation, since this is not needed in this or any sub class |
129 |
// see onEditorSaveEvent() instead |
|
161 | 130 |
} |
162 | 131 |
|
163 | 132 |
@Override |
164 | 133 |
protected final void deleteBean(DTO bean){ |
165 |
logger.trace(this._toString() + ".onEditorPreSaveEvent - starting transaction"); |
|
166 |
tx = startTransaction(); |
|
167 |
logger.trace(this._toString() + ".deleteBean - deleting" + bean.toString()); |
|
168 |
DeleteResult result = executeServiceDeleteOperation(bean); |
|
169 |
if(result.isOk()){ |
|
170 |
Session session = getSession(); |
|
171 |
session.flush(); |
|
172 |
logger.trace(this._toString() + ".deleteBean - session flushed"); |
|
173 |
getRepo().commitTransaction(tx); |
|
174 |
tx = null; |
|
175 |
session.close(); |
|
176 |
logger.trace(this._toString() + ".deleteBean - transaction comitted"); |
|
177 |
eventBus.publishEvent(new EntityChangeEvent(bean.getClass(), bean.getId(), Type.REMOVED)); |
|
178 |
} else { |
|
179 |
String notificationTitle; |
|
180 |
StringBuffer messageBody = new StringBuffer(); |
|
181 |
if(result.isAbort()){ |
|
182 |
notificationTitle = "The delete operation as abborded by the system."; |
|
183 |
} else { |
|
184 |
notificationTitle = "An error occured during the delete operation."; |
|
185 |
} |
|
186 |
if(!result.getExceptions().isEmpty()){ |
|
187 |
messageBody.append("<h3>").append("Exceptions:").append("</h3>").append("<ul>"); |
|
188 |
result.getExceptions().forEach(e -> messageBody.append("<li>").append(e.getMessage()).append("</li>")); |
|
189 |
messageBody.append("</ul>"); |
|
190 |
} |
|
191 |
if(!result.getRelatedObjects().isEmpty()){ |
|
192 |
messageBody.append("<h3>").append("Related objects exist:").append("</h3>").append("<ul>"); |
|
193 |
result.getRelatedObjects().forEach(e -> { |
|
194 |
messageBody.append("<li>"); |
|
195 |
if(IdentifiableEntity.class.isAssignableFrom(e.getClass())){ |
|
196 |
messageBody.append(((IdentifiableEntity)e).getTitleCache()); |
|
197 |
} else { |
|
198 |
messageBody.append(e.toString()); |
|
199 |
} |
|
200 |
messageBody.append("</li>"); |
|
201 |
} |
|
202 |
); |
|
203 |
|
|
204 |
messageBody.append("</ul>"); |
|
205 |
} |
|
206 |
Notification notification = new Notification( |
|
207 |
notificationTitle, |
|
208 |
messageBody.toString(), |
|
209 |
com.vaadin.ui.Notification.Type.ERROR_MESSAGE, |
|
210 |
true); |
|
211 |
notification.show(UI.getCurrent().getPage()); |
|
212 |
tx = null; |
|
134 |
EntityChangeEvent changeEvent = getStore().deleteBean(bean); |
|
135 |
if(changeEvent != null){ |
|
136 |
eventBus.publishEvent(changeEvent); |
|
213 | 137 |
} |
214 |
} |
|
215 | 138 |
|
216 |
/** |
|
217 |
* Implementations will execute the {@link |
|
218 |
* |
|
219 |
* @return |
|
220 |
*/ |
|
221 |
protected abstract DeleteResult executeServiceDeleteOperation(DTO bean); |
|
139 |
} |
|
222 | 140 |
|
223 | 141 |
} |
Also available in: Unified diff
ref #6687 moving all update and delete operations into a dedicated class: CdmStore