Documentation for Ice 3.5. The latest release is Ice 3.7. Refer to the space directory for other releases.

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 37 Next »

Inserting a User Exception in C++

As in the case of Ice objects, a Dynamic Ice application may represent user exceptions in a native format that is not directly compatible with the Ice API. If the application needs to raise such a user exception to the Ice run time (so that it will be marshaled and sent back to the client), the exception must be wrapped in a subclass of Ice::UserException. The Dynamic Ice API provides a class to simplify this process:

C++
namespace Ice {
    class UserExceptionWriter : public UserException {
    public:
        UserExceptionWriter(const CommunicatorPtr&);

        virtual void write(const OutputStreamPtr&) const = 0;

        virtual std::string ice_name() const = 0;
        virtual Ice::Exception* ice_clone() const = 0;
        virtual void ice_throw() const = 0;

        // ...
    };
    typedef ... UserExceptionWriterPtr;
}

A subclass of UserExceptionWriter is responsible for supplying a communicator to the constructor, and for implementing the following methods:

  • void write(const OutputStreamPtr&) const
    This method is invoked when the Ice run time is ready to marshal the exception. The subclass must marshal the exception using the encoding rules for exceptions.
  • std::string ice_name() const
    Return the Slice name of the exception.
  • Ice::Exception* ice_clone() const
    Return a copy of the exception.
  • void ice_throw() const
    Raise the exception by calling throw *this.

Extracting a User Exception in C++

An application extracts a user exception by calling one of two versions of the throwException method defined in the InputStream class:

C++
namespace Ice {
    class InputStream : ... {
    public:
        virtual void throwException() = 0;
        virtual void throwException(const UserExceptionReaderFactoryPtr&) = 0;

        // ...
    };
}

The version without any arguments attempts to locate and throw a C++ implementation of the encoded exception, relying on statically-generated type information emitted by the Slice-to-C++ compiler.

If your goal is to create an exception in another type system, such as a native PHP exception object, you must call the second version of throwException and pass an implementation of UserExceptionReaderFactory:

C++
namespace Ice {
    class UserExceptionReaderFactory : public IceUtil::Shared {   
    public:
        virtual void createAndThrow(const std::string& typeId) const = 0;
    };
    typedef ... UserExceptionReaderFactoryPtr;
}

As the stream iterates over slices of an exception from most-derived to least-derived, it invokes createAndThrow passing the type ID of each slice, giving the application an opportunity to raise an instance of UserExceptionReader:

C++
namespace Ice {
    class UserExceptionReader : public UserException {
    public:
        UserExceptionReader(const CommunicatorPtr&);
        ~UserExceptionReader() throw();

        virtual void read(const InputStreamPtr&) const = 0;

        virtual std::string ice_name() const = 0;
        virtual UserException* ice_clone() const = 0;
        virtual void ice_throw() const = 0;
    protected:
        const CommunicatorPtr _communicator;
    };
}

Subclasses of UserExceptionReader must implement the pure virtual functions. In particular, the implementation of read must call InputStream::startException, unmarshal the remaining slices, and then call InputStream::endException.

See Also

  • No labels