Difference between revisions of "BioUML exceptions"
Tagir Valeev (Talk | contribs) (+getDataElement) |
Tagir Valeev (Talk | contribs) (→Usage guidelines) |
||
Line 83: | Line 83: | ||
Try not to 'swallow' the exception if you cannot handle it properly. Printing the exception to log and returning null is bad practice as calling code won't know what's going on. Also printing to the log might be useless for [[BioUML web edition]] as messages from your log object may not be passed to the client at all. Consider wrapping the exception to higher-level BioUML exception and throw it outside. If you think that user might be interested in exception, but you can continue ignoring it, use {{Method|ru.biosoft.access.exception.ExceptionRegistry.log(Throwable)}}, which will translate an exception to BioUML exception, log it and return the user-friendly message. | Try not to 'swallow' the exception if you cannot handle it properly. Printing the exception to log and returning null is bad practice as calling code won't know what's going on. Also printing to the log might be useless for [[BioUML web edition]] as messages from your log object may not be passed to the client at all. Consider wrapping the exception to higher-level BioUML exception and throw it outside. If you think that user might be interested in exception, but you can continue ignoring it, use {{Method|ru.biosoft.access.exception.ExceptionRegistry.log(Throwable)}}, which will translate an exception to BioUML exception, log it and return the user-friendly message. | ||
− | Currently the prefered way to get the data element is {{Method|ru.biosoft.access.DataElementPath.getDataElement(Class | + | Currently the prefered way to get the data element is {{Method|ru.biosoft.access.DataElementPath.getDataElement(Class<T>)}}. The parameter is the wanted element class. This method never returns null. Instead it throws BioUMLRepositoryException if element cannot be fetched or has invalid class. |
[[Category:Development]] | [[Category:Development]] |
Revision as of 17:58, 22 July 2013
This page or section is under construction right now. |
This article describes new BioUML exception handling concept introduced in version 0.9.6.
Contents |
Overview
BioUML exceptions (short: BUEX) are descendants of class BioUMLException
. All other exceptions are called raw exceptions. Now it's undesired to throw raw exception in BioUML code except some cases when particular part of code can become BioUML-independent.
Class BioUMLException
extends RuntimeException
, thus it's not necessary (but desired!) to declare it in throws
clause.
Exception levels
Exceptions are divided to several categories called exception levels. Low-level BioUML exceptions include:
- System
- Low level errors: out of memory, NPE, programmatic errors, etc.
- SQL
- Low level SQL database access problem
- IO
- Low level input/output access problem
- Network
- Low level network problem
High-level BioUML exceptions include:
- Repository
- Repository problem (unable to get, put, delete element, etc.)
- Security
- Access violation, quota, etc.
- Computational
- Computational problem during some data analysis
- Parameter
- User input problem
List of levels may change in future. Every level has its base exception class. For example, exceptions of level 'System' are related to BioUMLSystemException
and its subclasses.
Exception properties
Each BioUML exception has the following properties:
- ID
- Autoincrementing number starting from 1 identifying the exception.
- Level
- Exception level (described above)
- Code
- Text string which together with level refers to particular error situation. For example, code 'NPE' of level 'System' refers to null pointer exception. Usually level and code are written together as 'System.NPE'
- Logging level
- How this exception should be displayed in log:
- None - Do not log this Exception even if requested
- Summary - Log summary
- Parameters - Log summary+properties
- Trace - Log summary+properties+trace
Also BioUML exception has custom properties defined in DynamicPropertySet
. They can be logged and used in generating user-friendly messages.
Chaining
BioUML exceptions can be chained. Usually (but not always) high-level exception has low-level exception cause, which may have raw exception as the cause. Every raw exception can be converted to BioUML exception using ExceptionRegistry.translateException(Throwable)
method (if BioUML exception was passed to this method it will just return it). However in many cases it's desired to create BioUML exception manually as you may specify additional details. BioUML exception should not be the cause of raw exception. Low-level exception should has raw exception or nothing as the cause (not another BioUML exception).
Reporting
There are two ways to report the BioUML exception: to display it to user and to log it. All BioUML exceptions are logged into special logger error.log
. In BioUML workbench it's displayed as a separate sub tab of Application log viewpart. On BioUML server this might be appended to separate file depending on your server.lcf configuration. Ideally all low-level technical information including all the stacktraces must go there. Messages displayed to the user (including ones displayed in normal Application log) should be more user-friendly.
For example, this is how the exception is reported in Application log:
ERROR : Cannot create collection data/Collaboration/Lan_test/Data/MACS/profile Error reason: Internal error occured (Java class ru.biosoft.bsa.analysis.chipseqprofile.PeakProfileTransformer not found). Please check error log for BUEX#136.
And this is how the same exception is reported in Error log:
ERROR : BUEX#137/Repository.CannotCreate: Cannot create collection data/Collaboration/Lan_test/Data/MACS/profile Caused by: BUEX#136/System.NoClass: Internal error occured (Java class ru.biosoft.bsa.analysis.chipseqprofile.PeakProfileTransformer not found). Caused by: java.lang.ClassNotFoundException: Can't load class ru.biosoft.bsa.analysis.chipseqprofile.PeakProfileTransformer at ru.biosoft.access.CollectionFactory.loadClass(CollectionFactory.java:269) at ru.biosoft.access.TransformedDataCollection.<init>(TransformedDataCollection.java:45) at sun.reflect.GeneratedConstructorAccessor12.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at ru.biosoft.access.CollectionFactory.createCollection(CollectionFactory.java:195) at ru.biosoft.access.CollectionFactory.createCollection(CollectionFactory.java:148) at ru.biosoft.access.LocalRepository.createCollection(LocalRepository.java:224) at ru.biosoft.access.LocalRepository.init(LocalRepository.java:131) (many more stacktrace lines)
To log the exception, use BioUMLException.log()
method. Each exception can be logged only once in order not to pollute the error log with dublicates.
To get the user-friendly message use BioUMLException.getMessage()
method. This method provides one-line description of the problem followed by the description of the cause. If cause is absent or it's raw exception, it's not returned. By default for low-level exceptions additional message added like Please check error log for BUEX#...
for BioUML workbench or Please contact application vendor supplying ID BUEX#...
for BioUML server.
Message templates are registered currently in the static section of ExceptionRegistry
class. In future this might be changed to some kind of extension point. Templates can use all custom properties defined by exception referring to them like $path$
. Bean properties of these properties can also be used like $cause/class/simpleName$
(the same syntax is used by OptionEx.makeAutoProperty
).
Usage guidelines
Try not to 'swallow' the exception if you cannot handle it properly. Printing the exception to log and returning null is bad practice as calling code won't know what's going on. Also printing to the log might be useless for BioUML web edition as messages from your log object may not be passed to the client at all. Consider wrapping the exception to higher-level BioUML exception and throw it outside. If you think that user might be interested in exception, but you can continue ignoring it, use ExceptionRegistry.log(Throwable)
, which will translate an exception to BioUML exception, log it and return the user-friendly message.
Currently the prefered way to get the data element is DataElementPath.getDataElement(Class<T>)
. The parameter is the wanted element class. This method never returns null. Instead it throws BioUMLRepositoryException if element cannot be fetched or has invalid class.