Changes between Initial Version and Version 1 of MapGuideRfc183


Ignore:
Timestamp:
Oct 29, 2020, 1:40:43 AM (19 months ago)
Author:
jng
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • MapGuideRfc183

    v1 v1  
     1
     2= !MapGuide RFC 183 - Flatten exception hierarchy =
     3
     4This page contains a change request (RFC) for the !MapGuide Open Source project.
     5More !MapGuide RFCs can be found on the [wiki:MapGuideRfcs RFCs] page.
     6
     7== Status ==
     8
     9||RFC Template Version||(1.0)||
     10||Submission Date||29 Oct 2020||
     11||Last Modified||29 Oct 2020||
     12||Author||Jackie Ng||
     13||RFC Status||draft||
     14||Implementation Status||||
     15||Proposed Milestone||4.0||
     16||Assigned PSC guide(s)||(when determined)||
     17||'''Voting History'''||(vote date)||
     18||+1||||
     19||+0||||
     20||-0||||
     21||-1||||
     22||no vote|| ||
     23
     24== Overview ==
     25
     26This RFC proposes to flatten the MapGuide exception hierarchy to just the `MgException` class
     27
     28== Motivation ==
     29
     30Currently, the full MapGuide exception class hierarchy is replicated out to the respective Java/PHP/.net wrapper APIs.
     31
     32The upcoming work to generate an updated set of wrapper APIs (in particular, for PHP7) with vanilla SWIG has hit some several roadblocks in wrapping the MapGuide classes. One of the roadblocks concerns trying to replicate the current MapGuide exception hierarchy in PHP7.
     33
     34Also in our various developer samples and documentation, we never really tell developers to catch anything *other* than {{{MgException}}}
     35
     36To simplify our wrapping process and developer experience, we can flatten the MapGuide exception hierarchy to just {{{MgException}}}
     37
     38== Proposed Solution ==
     39
     40Update the `MgException` class to no longer be abstract and include the following internal APIs (full class omitted, only new additions shown):
     41
     42{{{
     43///////////////////////////////////////////////////////////////////////////////
     44/// \brief
     45/// Base class for exceptions.
     46///
     47class MG_FOUNDATION_API MgException : public MgSerializable
     48{
     49PUBLISHED_API:
     50
     51    ///////////////////////////////////////////////////////////////////////////
     52    /// \brief
     53    /// Retrieve the exception code for this exception
     54    ///
     55    /// <!-- Syntax in .Net, Java, and PHP -->
     56    /// \htmlinclude DotNetSyntaxTop.html
     57    /// string GetExceptionCode();
     58    /// \htmlinclude SyntaxBottom.html
     59    /// \htmlinclude JavaSyntaxTop.html
     60    /// String GetExceptionCode();
     61    /// \htmlinclude SyntaxBottom.html
     62    /// \htmlinclude PHPSyntaxTop.html
     63    /// string GetExceptionCode();
     64    /// \htmlinclude SyntaxBottom.html
     65    ///
     66    /// \return
     67    /// The exception code
     68    ///
     69    /// \since 4.0
     70    ///
     71    STRING GetExceptionCode();
     72
     73    ///////////////////////////////////////////////////////////////////////////
     74    /// \brief
     75    /// Retrieve the native error code that may be set by errors from thirdparty
     76    /// libraries
     77    ///
     78    /// <!-- Syntax in .Net, Java, and PHP -->
     79    /// \htmlinclude DotNetSyntaxTop.html
     80    /// string GetNativeErrorCode();
     81    /// \htmlinclude SyntaxBottom.html
     82    /// \htmlinclude JavaSyntaxTop.html
     83    /// String GetNativeErrorCode();
     84    /// \htmlinclude SyntaxBottom.html
     85    /// \htmlinclude PHPSyntaxTop.html
     86    /// string GetNativeErrorCode();
     87    /// \htmlinclude SyntaxBottom.html
     88    ///
     89    /// \return
     90    /// The native error code
     91    ///
     92    /// \since 4.0
     93    ///
     94
     95INTERNAL_API:
     96
     97    ///////////////////////////////////////////////////////////////////////////
     98    /// \brief
     99    /// Create a MgException from mapping a standard CPP exception to a MgException.
     100    ///
     101    static MgException* Create(std::exception& stdLibException, CREFSTRING methodName, INT32 lineNumber, CREFSTRING fileName) throw();
     102
     103    ///////////////////////////////////////////////////////////////////////////
     104    /// \brief
     105    /// Sets the native error code
     106    ///
     107    /// \param nativeErrorCode
     108    /// The native error code
     109    ///
     110    void SetNativeErrorCode(INT64 nativeErrorCode);
     111
     112protected:
     113
     114    /// The exception code
     115    STRING m_code;
     116
     117    /// The native error code
     118    INT64 m_nativeErrorCode;
     119
     120INTERNAL_API:
     121
     122    ///////////////////////////////////////////////////////////////////////////
     123    /// \brief
     124    /// Construct the object.
     125    ///
     126    /// \param exceptionCode
     127    /// The exception code
     128    /// \param methodName
     129    /// Name of the method where the exception occurred.
     130    /// \param lineNumber
     131    /// Line number where the exception occurred.
     132    /// \param fileName
     133    /// File name where the exception occurred.
     134    /// \param whatArguments
     135    /// Collection of arguments used to format the message that describes what the exception is.
     136    /// \param whyMessageId
     137    /// ID of the message that describes why the exception occurs.
     138    /// \param whyArguments
     139    /// Collection of arguments used to format the message that describes why the exception occurs.
     140    ///
     141    MgException(CREFSTRING exceptionCode, CREFSTRING methodName, INT32 lineNumber,
     142        CREFSTRING fileName, MgStringCollection* whatArguments,
     143        CREFSTRING whyMessageId, MgStringCollection* whyArguments) throw();
     144
     145};
     146}}}
     147
     148The key points with these changes are that:
     149
     150 * `MgException` is no longer abstract
     151 * Instead of throwing a specific subclass of `MgException`, code will simply throw a `MgException` with the appropriate exception code (accessible by the new `GetExceptionCode()` API). A new `MgExceptionCodes` string constant class contains all the valid exception codes that can be specified.
     152 * For code that needs to re-map an existing `std::exception` type, they will now throw a `MgException` created from the `MgException::Create()` static method
     153 * For code that needs to surface an error code from an external library (eg. FDO, berkeley db, dbxml), they can use the new `SetNativeErrorCode()` method to set the error code, which MapGuide applications can get throw the new `GetNativeErrorCode()` API.
     154
     155All subclasses of {{{MgException}}} will be removed.
     156
     157All references to these headers from our SWIG generation files.
     158
     159Replace all usages where {{{MgException}}} subclasess are thrown to throw {{{MgException}}} instead and pass the original exception name as the error code. For applicable error cases (eg. Errors from FDO, berkeley db, dbxml), the native error code is also set on the exception before throwing.
     160
     161== Implications ==
     162
     163If developers have been catching exception types other than {{{MgException}}}, they will have to refactor their code so that it catches {{{MgException}}} and check the result of {{{GetExceptionCode()}}} to determine the appropriate course of action to take.
     164
     165For example, a catch block like this in .net
     166
     167{{{
     168
     169try {
     170
     171} catch (MgUnauthorizedAccessException ex) {
     172    // Handle unauthorized acceess
     173} catch (MgSessionExpiredException ex) {
     174    // Handle session expired
     175} catch (MgException ex) {
     176    // Handle general errors
     177}
     178
     179}}}
     180
     181Will need to be refactored to this
     182
     183{{{
     184
     185try {
     186
     187} catch (MgException ex) {
     188    if (ex.GetExceptionCode() == MgExceptionCodes.MgUnauthorizedAccessException) {
     189        // Handle unauthorized acceess
     190    } else if (ex.GetExceptionCode() == MgExceptionCodes.MgSessionExpiredException) {
     191        // Handle session expired
     192    } else {
     193        // Handle general errors
     194    }
     195}
     196
     197}}}
     198
     199== Test Plan ==
     200
     201Test APIs that throw exceptions now catch as `MgException` with the right exception code
     202
     203== Funding / Resources ==
     204
     205Community