Project

General

Profile

Revision c78fd1ac

IDc78fd1acbf37a74fc29944db1a4cea7d227181bc
Parent 3e625af9
Child 6d2a0540

Added by Andreas Kohlbecker almost 2 years ago

improving error messaging: PopupEditorException with editor context information

View differences:

src/main/java/eu/etaxonomy/cdm/vaadin/event/EditorActionContextFormat.java
19 19
     */
20 20
    public boolean doClassName;
21 21
    /**
22
     *
22
     * add information on the target class and field if possible
23 23
     */
24 24
    public boolean doTargetInfo;
25

  
26
    /**
27
     * add on the target entity like including titlecache and uuid
28
     */
29
    public boolean doTargetEntity;
25 30
    /**
26 31
     *
27 32
     */
......
32 37
    public boolean doCreateOrNew;
33 38

  
34 39
    /**
35
     * The name of the html tag to be used
40
     * The name of the html tag to be used, may be <code>null</code> to format as plain text
36 41
     */
37 42
    public String tagName = "span";
38 43

  
src/main/java/eu/etaxonomy/cdm/vaadin/event/EditorActionContextFormatter.java
8 8
*/
9 9
package eu.etaxonomy.cdm.vaadin.event;
10 10

  
11
import java.util.Collection;
11 12
import java.util.Stack;
12 13

  
13 14
import org.apache.commons.lang3.StringUtils;
14 15

  
15
import com.vaadin.ui.Component;
16

  
17 16
import eu.etaxonomy.cdm.model.common.CdmBase;
18 17
import eu.etaxonomy.cdm.ref.TypedEntityReference;
19 18
import eu.etaxonomy.cdm.vaadin.event.EditorActionContextFormat.TargetInfoType;
......
36 35

  
37 36
        String className = null;
38 37
        String targetInfo = null;
38
        String targetEntityStr = null;
39 39
        String createOrNew = null;
40 40

  
41 41
        Object parentEntity = cntxt.getParentEntity();
......
60 60
            className += "[NULL_CLASS]";
61 61
        }
62 62

  
63
        if (format.doTargetInfo && cntxt.getParentView() != null && AbstractPopupEditor.class.isAssignableFrom(cntxt.getParentView().getClass())) {
63
        if ((format.doTargetInfo || format.doTargetEntity) && cntxt.getParentView() != null && AbstractPopupEditor.class.isAssignableFrom(cntxt.getParentView().getClass())) {
64 64
            // the top element is the cntxt istself!! we need to dig one step deeper to get the previous popup editor
65 65
            // TODO chaining the EditorActionContext would ease find the contexts of parent editors
66 66
            Stack<EditorActionContext> ctxtStack = ((AbstractPopupEditor)cntxt.getParentView()).getEditorActionContext();
......
72 72
                    if (propertyIdPath != null) {
73 73
                        targetInfo = propertyIdPath.toString();
74 74
                    }
75
                } else {
76
                    // TargetInfoType.FIELD_CAPTION
77
                    if(parentCtx.getTargetField() != null){
78
                        Component captionComponent = parentCtx.getTargetField();
79
                        while(captionComponent != null){
80
                            targetInfo = captionComponent.getCaption();
81
                            if(targetInfo != null){
82
                                break;
83
                            }
84
                            captionComponent = captionComponent.getParent();
85
                        }
86
                    }
87 75
                }
88 76
            }
89 77
        }
78
        if(format.doTargetEntity){
79
            targetEntityStr = formatTargetEntityString(cntxt.parentEntity, format);
80
        }
90 81

  
91 82
        // create output
92
        String markup = "";
83
        String outStr = "";
93 84

  
94 85
        if (format.doCreateOrNew && createOrNew != null) {
95
            markup += "<" + format.tagName + " class=\"operation " + format.classAttributes + "\">" + createOrNew + "</" + format.tagName + ">";
86
            if(format.tagName != null){
87
                outStr += "<" + format.tagName + " class=\"operation " + format.classAttributes + "\">" + createOrNew + "</" + format.tagName + ">";
88
            } else {
89
                outStr += createOrNew;
90
            }
96 91
        }
97 92

  
98 93
        if (format.doTargetInfo) {
......
100 95
                targetInfo = className;
101 96
            }
102 97
            if(targetInfo != null){
103
                if(!markup.isEmpty()){
104
                    markup += " ";
98
                if(!outStr.isEmpty()){
99
                    outStr += " ";
105 100
                    targetInfo = normalizeTargetInfo(targetInfo);
106 101
                }
107
                markup += "<" + format.tagName + " class=\"target " + format.classAttributes + "\">" + targetInfo + "</" + format.tagName + ">";
102
                if(format.tagName != null){
103
                    outStr += "<" + format.tagName + " class=\"target " + format.classAttributes + "\">" + targetInfo + "</" + format.tagName + ">";
104
                } else {
105
                    outStr += targetInfo;
106
                }
107
            }
108
        }
109
        if(format.doTargetEntity && targetEntityStr != null){
110
            if(format.tagName != null){
111
                outStr += "<" + format.tagName + " class=\"target-entity" + format.classAttributes + "\">" + targetEntityStr + "</" + format.tagName + ">";
112
            } else {
113
                outStr += " (" + targetEntityStr + ")";
114
            }
115
        }
116
        return outStr;
117
    }
118

  
119
    public String format(Collection<EditorActionContext> cntxts, EditorActionContextFormat format) {
120
        String outStr = "";
121
        for(EditorActionContext ctx : cntxts){
122
            if(!outStr.isEmpty()){
123
                outStr += " > "; // FIXME allow configuring the separator
108 124
            }
125
            outStr += format(ctx, format) ;
126
        }
127
        return outStr;
128
    }
129

  
130
    /**
131
     * @param value
132
     * @param format
133
     * @return
134
     */
135
    private String formatTargetEntityString(Object value, EditorActionContextFormat format) {
136

  
137
        if(value == null){
138
            return "NULL";
139
        }
140
        String outStr;
141
        if(value instanceof CdmBase){
142
            outStr = ((CdmBase)value).instanceToString();
143
        } else if(value instanceof CdmEntityAdapterDTO) {
144
            outStr = value.getClass().getSimpleName() + ": ";
145
            outStr += ((CdmEntityAdapterDTO)value).cdmEntity().toString();
146
        } else {
147
            outStr = value.getClass().getSimpleName() + ": " + value.toString();
109 148
        }
110
        return markup;
149
        return outStr;
111 150
    }
112 151

  
113 152
    /**
src/main/java/eu/etaxonomy/cdm/vaadin/event/error/DelegatingErrorHandler.java
15 15

  
16 16
import com.vaadin.server.ErrorEvent;
17 17
import com.vaadin.server.ErrorHandler;
18
import com.vaadin.server.ServerRpcManager.RpcInvocationException;
18 19
import com.vaadin.ui.Notification;
19 20

  
20 21
/**
......
41 42
    @SuppressWarnings("unchecked")
42 43
    public <E extends Throwable> ErrorTypeHandler<E> findHandler(Class<E> errorClass){
43 44
        for(ErrorTypeHandler<?> h : handlers){
44
            if(h.supports().equals(errorClass)){
45
            if(h.supports().isAssignableFrom(errorClass)){
45 46
                return (ErrorTypeHandler<E>) h;
46 47
            }
47 48
        }
......
57 58

  
58 59
        boolean handlerFound = true;
59 60
        Throwable throwable = event.getThrowable();
61
        if(throwable != null && RpcInvocationException.class.isAssignableFrom(throwable.getClass())){
62
            // we are only interested into the cause and will will remove RpcInvocationException > InvocationTargetException
63
            throwable = throwable.getCause().getCause();
64
            event.setThrowable(throwable);
65
        }
60 66
        while(throwable != null){
61 67
            if(delegate(event, throwable)){
62 68
                break;
src/main/java/eu/etaxonomy/cdm/vaadin/event/error/ErrorTypeErrorHandlerWrapper.java
1
/**
2
* Copyright (C) 2018 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.event.error;
10

  
11
import com.vaadin.server.ErrorEvent;
12
import com.vaadin.server.ErrorHandler;
13

  
14
/**
15
 * @author a.kohlbecker
16
 * @since Nov 8, 2018
17
 *
18
 */
19
public class ErrorTypeErrorHandlerWrapper<E extends Throwable> extends ErrorTypeHandler<E> {
20

  
21
    private static final long serialVersionUID = 856246216519945768L;
22

  
23
    private Class<E> errorType;
24

  
25
    private ErrorHandler errorHandler;
26

  
27
    public ErrorTypeErrorHandlerWrapper(Class<E> errorType, ErrorHandler errorHandler){
28
        this.errorType = errorType;
29
        this.errorHandler = errorHandler;
30
    }
31

  
32
    @Override
33
    public void error(ErrorEvent event) {
34
        errorHandler.error(event);
35
    }
36

  
37
    @Override
38
    public Class<E> supports() {
39
        return errorType;
40
    }
41

  
42
    @Override
43
    public void exception(Throwable throwable) {
44
        // nothing to do, since the errorHandler is expected to provide user feedback
45
    }
46

  
47
}
src/main/java/eu/etaxonomy/cdm/vaadin/ui/RegistrationUI.java
33 33
import com.vaadin.ui.themes.ValoTheme;
34 34

  
35 35
import eu.etaxonomy.cdm.vaadin.debug.EntityCacheDebugger;
36
import eu.etaxonomy.cdm.vaadin.event.error.DelegatingErrorHandler;
37
import eu.etaxonomy.cdm.vaadin.event.error.ErrorTypeErrorHandlerWrapper;
36 38
import eu.etaxonomy.cdm.vaadin.toolbar.Toolbar;
37 39
import eu.etaxonomy.cdm.vaadin.view.RedirectToLoginView;
38 40
import eu.etaxonomy.cdm.vaadin.view.registration.DashBoardView;
......
115 117
    @Override
116 118
    protected void init(VaadinRequest request) {
117 119

  
120
        DelegatingErrorHandler delegatingErrorHander = new DelegatingErrorHandler();
118 121
        WindowErrorHandler errorHandler = new WindowErrorHandler(this, RegistrationUIDefaults.ERROR_CONTACT_MESSAGE_LINE + "</br></br>"
119 122
                + "<i>To help analyzing the problem please describe your actions that lead to this error and provide the error details from below in your email. "
120 123
                + "You also might want to add a sreenshot of the browser page in error.</i>");
121
        setErrorHandler(errorHandler);
122
        VaadinSession.getCurrent().setErrorHandler(errorHandler);
124
        delegatingErrorHander.registerHandler(new ErrorTypeErrorHandlerWrapper<Exception>(Exception.class, errorHandler));
125
        setErrorHandler(delegatingErrorHander);
126
        VaadinSession.getCurrent().setErrorHandler(delegatingErrorHander);
123 127

  
124 128
        navigator.setViewDisplay(viewDisplay);
125 129
        configureAccessDeniedView();
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPopupEditor.java
411 411
                PermissionDeniedException permissionDeniedException = (PermissionDeniedException)e.getCause().getCause();
412 412
                Notification.show("Permission denied", permissionDeniedException.getMessage(), Type.ERROR_MESSAGE);
413 413
            } else {
414
//                Logger.getLogger(this.getClass()).error("Error saving", e);
415
//                Notification.show("Error saving", Type.ERROR_MESSAGE);
416
                throw new RuntimeException("Error saving", e);
414
                throw new PopupEditorException("Error saving popup editor", this, e);
417 415
            }
418 416
        }
419 417
    }
src/main/java/eu/etaxonomy/vaadin/mvp/PopupEditorException.java
1
/**
2
* Copyright (C) 2018 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.vaadin.mvp;
10

  
11
import eu.etaxonomy.cdm.vaadin.event.EditorActionContextFormat;
12
import eu.etaxonomy.cdm.vaadin.event.EditorActionContextFormat.TargetInfoType;
13
import eu.etaxonomy.cdm.vaadin.event.EditorActionContextFormatter;
14

  
15
/**
16
 * @author a.kohlbecker
17
 * @since Nov 8, 2018
18
 *
19
 */
20
public class PopupEditorException extends RuntimeException {
21

  
22
    private static final long serialVersionUID = -4242789621156408545L;
23

  
24
    private String contextInfo;
25

  
26
    /**
27
     * @param message
28
     */
29
    public PopupEditorException(String message, AbstractPopupEditor<?,?> editor, Throwable e) {
30
        super(message, e);
31

  
32
        EditorActionContextFormatter formatter = new EditorActionContextFormatter();
33
        EditorActionContextFormat format = new EditorActionContextFormat(true, true, true, true, TargetInfoType.PROPERTIES, null);
34
        format.tagName = null;
35
        format.doTargetEntity = true;
36
        contextInfo = formatter.format(editor.getEditorActionContext(), format);
37
    }
38

  
39
    public PopupEditorException(String message, AbstractPopupEditor<?,?> editor) {
40
        super(message);
41

  
42
        EditorActionContextFormatter formatter = new EditorActionContextFormatter();
43
        EditorActionContextFormat format = new EditorActionContextFormat(true, true, true, true, TargetInfoType.PROPERTIES, null);
44
        format.tagName = null;
45
        format.doTargetEntity = true;
46
        contextInfo = formatter.format(editor.getEditorActionContext(), format);
47
    }
48

  
49
    @Override
50
    public String getMessage() {
51
        return super.getMessage() + " - context:" + contextInfo;
52
    }
53

  
54

  
55
    @Override
56
    public String getLocalizedMessage() {
57
        return getMessage();
58
    }
59

  
60
}

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)