36

I'd like to extend Exception to create a custom exception class that takes several arguments in addition to the standard string message.

I've found examples showing basic inheritance (An Introduction to Exception Handling) and adding custom constructors (Extended Class Example).

public virtual class MyException extends Exception {
    public Double d;

    // Exception class constructor     
    MyException(string message, Double d) {
        // How can I pass 'message' to the base constructor?
        this.d = d;
    }
}

When using a custom exception similar to the example above calls to getMessage() return 'Script-thrown exception', which makes sense as message hasn't been utilized yet.

How can I extend Exception and include a custom constructor such that Exception.getMessage() returns a string specified in the constructor?

Or more generally, how do I pass arguments from my custom constructor to the base constructor in Apex?

6
  • 1
    I'm not too familiar yet with Apex, but in other languages you can invoke the base constructor. Is that not possible in Apex? Your links don't say either way.
    – Mike Chale
    Oct 1, 2012 at 0:37
  • @MikeChale When I'm not writing Apex I'm writing .NET. So I was looking for the equivalent of the base keyword for specifying which base-class constructor should be called when creating instances of the derived class. I haven't found how to do this yet. Oct 1, 2012 at 1:11
  • Looks like I want super Oct 1, 2012 at 1:13
  • I'm a .Net guy, too. Oh well.
    – Mike Chale
    Oct 1, 2012 at 1:30
  • @MikeChale Sometimes I feel a bit out of place because I like .NET and Visual Studio as well as Salesforce. :) Oh well. Do you think there would be any value in a question about how a primarily .NET developer can work with apex? Might be a bit too general. Oct 1, 2012 at 1:58

4 Answers 4

37

You can use this(message) in your constructor to call the base class constructor:

public virtual class MyException extends Exception
{
    public Decimal d;

    public MyException(String message, Decimal d)
    {
        this(message);
        this.d = d;
    }

    @isTest
    static void test()
    {
        try
        {
            throw new MyException('this is my message',3.1415);
        }
        catch(Exception e)
        {
            system.assertEquals('this is my message', e.getMessage());
            MyException me = (MyException) e;
            system.assertEquals('this is my message', me.getMessage());
            system.assertEquals(3.1415, me.d);
        }
    }
}

However, I would have expected the System Exception class to behave like a virtual Apex class (and therefore be able to use super(message) in this situation).

5
  • 1
    When I tried super(message) I wasn't able to save/compile the class. The error message was "Save error: Object has no superclass for super invocation". Oct 1, 2012 at 20:42
  • 2
    Yes, same here. I think that perhaps Exception is a special case. For a long time Exception was the only class that could be extended in Apex, so there may be a historical reason. Oct 2, 2012 at 7:20
  • 1
    it really make no sense that you'd need to call this instead of super... Just another inconsistency in the apex language
    – NSjonas
    Dec 4, 2017 at 3:40
  • Apex Exceptions are special, and behind the scenes, Apex defines the "default" Constructors for you. If you try to define an Exception: public with sharing class SampleException extends Exception { public SampleException() { super(); } } you get a compile error: System exception constructor already defined: void <init>() (Line: ___, Column: __) classes/InboundEmail.cls: Method is not visible: void System.ApexBaseException.<init>() (Line: ___, Column: _). Mar 8, 2018 at 15:07
  • 1
    I wish we could add our own "default" constructors. For instance, when a SObjectField is null, throw an Exception which uses a Custom Label for the Message so the messange and Field Label are translated automatically. public virtual class NullSObjectFieldException extends Exception { public NullSObjectFieldException(SObjectField field) { this.setMessage(String.format(System.Label.Field_Cannot_Be_Null, new String[] { field == null ? 'null' : Schema.EmailMessage.RelatedToId.getDescribe().getLabel() } )); } } Mar 8, 2018 at 15:11
7

I found one possible solution in the post Custom Exception message by Corey_B.

In the custom constructor explicitly call setMessage. E.g.

public virtual class MyException extends Exception {
    public Double d;

    // Exception class constructor     
    MyException(string message, Double d) {
        // Pass 'message' to the base class
        this.setMessage(message);

        this.d = d;
    }
}

This does solve my explicit issue, but doesn't really address how to handle base constructors with inheritance.


Update for "how do I pass arguments from my custom constructor to the base constructor in Apex?"

I tried using super(message); as the first line of the constructor but it resulted in the error:

Save error: Object has no superclass for super invocation

So I'm assuming that Exception isn't virtual.

"Only classes that are extending from virtual or abstract classes can use super." [Super keyword]

2
  • 1
    Did you try using this.super keyword?
    – doga
    Oct 1, 2012 at 8:10
  • @doga Yes I did, as per my answer I received a save error. Does it work for you? Oct 1, 2012 at 19:32
1

This.setMessage() seems like the only plausible alternative. If you're just bothered about the message you could try this. http://th3silverlining.com/2009/06/11/throwing-custom-apex-exceptions/

1
  • That is how I've previously been handling custom exceptions. It does bother me that I can extend Exception and still use the Exception constructors but not invoke them via Super. Oct 1, 2012 at 9:26
-2

I think following can help you. It has complete example of SFDC APEX standard and custom exceptions

http://share-salesforce.blogspot.in/2013/05/salesforce-apex-exception-handling-and_29.html

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .