On 27.01.2008 16:15:45 Vincent Hennebert wrote:
> <snip/>
> >>>> But that mentioning of exceptions just makes me wondering of the
> >>>> following: what if an unrecoverable error occurs (say, too many cells on
> >>>> a table row)? I guess I’ll trigger an event of severity
> >>>> EventSeverity.ERROR and I absolutely expect that /every/ listener will
> >>>> throw an exception in such a case? Otherwise the processing will become
> >>>> hazardous.
> >>> You can always throw an exception right after the line where you
> >>> broadbast the event. That makes sure that the exception is thrown.
> >>> There's no need to rely on external behaviour.
> >> Hmmm, not very beautiful IMHO. You’ll have to do basically the same
> >> thing twice every time. And, suppose the listener doesn’t do anything
> >> particular, the exception that would be thrown afterwards would result
> >> into the same ugly stacktrace as we have currently, which would kill
> >> a bit the benefit of the new feedback mechanism, wouldn’t it?
> >> Is there anything wrong with expecting the error level (or fatal, or
> >> whatever) to somehow stop the process?
> >>
> >> Now that I’ve written that, re-read myself and was about to hit the
> >> “send message” button, I realise that processing feedback is
> >> a slightly different notion from exception handling.
> >> Still, my question above holds.
> >
> > Please note that there is no stacktrace information with the event, only
> 
> So? Do we care about the stacktrace ?

In the exception case, yes, very much, in the event case, no. I was
trying to show that the two are very different beasts because you wrote: 
"the exception that would be thrown afterwards would result
into the same ugly stacktrace as we have currently, which would kill
a bit the benefit of the new feedback mechanism, ..."

IMO, the two aspects have no overlap so cannot be played one against the
other.

> > with the exception. The event mechanism is for clients with advanced
> > requirements about getting, for example, the may want to create a list
> > of all the problems which they present to the client in a special GUI
> > that may even allow them to jump to the right place in the original
> > document. An exception may not have this kind of information.
> >
> >> It’s not the listener that would have to throw the exception
> >
> > but it is allowed to do so (an overflow may be a reason to stop for some).
> 
> Sure
> 
> 
> >> (IIUC the whole thing is meant to allow third-party listeners to be
> >> implemented in the future, like graphical progress bars?), but the
> >> broadcaster (like you say below actually).
> >> If for some reason this is not implemented that way, then I’d expect
> >> something like the following: I would throw a FOPException, without any
> >> explicit error message —this was already done via the feedback
> >> mechanism— and some higher-level object would catch it, send a message
> >> like “a fatal error occurred, processing stopped.” and actually stop.
> >> I’m not very familiar with the API, but I guess this would be the
> >> Renderer.startRenderer method, which would simply terminate normally.
> >
> > No, the exception should always contain the cause.
> 
> Then I’m missing the point of the new feedback mechanism. Why would you
> have to both create an event and throw an exception? All the more than
> the exception’s message wouldn’t be localized. And in the case of e.g.
> an error in the FO file we all but care about knowing at each place of
> the code exactly did the problem occur. Why couldn’t the broadcaster
> stop the process?

Because a broadcaster (as its name says) only delivers messages.
Interrupting the process flow is the job of the programming language's
exception feature. Again, the event flow is mainly for informing the
user (or the technical user). He may or may not react on it. An
exception happens on exclusively a technical level (and in the past
could bubble up to the user because there was nothing else). Of course,
you could just swallow the last event that is generated right before the
exception but then you have to make sure the exception can equally be
localized, contains the same information as the event and you have two
different sources for event information (which the user has to know).

The main point of the feedback mechanism is to have a sequence of
notifications about the events in FOP (per processed document) so an
application can react on them and the user is informed about what's
going on. An exception is after all only a one time information and may
not happen at all (even though there may be multiple events during a
processing run). At the moment these events only appear in the log in an
unstructred, non-machine-readable way and without the benefit of keeping
the events appart in a multi-threaded system.

I acknowledge that there is a certain overlap area between an exception
and the last event that indicates a fatal error. But sending the fatal
error event just before throwing the exception just makes sure we have a
uniform way of sending notifications to (potentially) multiple information
sinks. The "fatal error" will always produce an exception afterwards so
the integrator will know that he doesn't have to translate the exception
into a form that he can display it in the same spot as the events. If he
wants to filter the fatal exception, he can still do that, of course.
Again, I consider exceptions and events two completely different things
even if at first sight, it looks like redundancy.

> 
> >>> We could even add a convention that for an event with
> >>> EventSeverity.FATAL the first/second/last parameter must be an Exception
> >>> class. The Exception class would have to have a constructor that takes
> >>> an EventObject as parameter for initializing the exception. The dynamic
> >>> proxy would then throw the exception right after broadcasting the
> >>> exception. Or we could change the EventProducer convention so that every
> >>> method returns the generated EventObject that you can then use to
> >>> initialize an exception. Probably easier and more flexible.
> <snip/>
> >>> Please tell me how I should "keep Java 1.5 in mind"? I cannot use
> >> Well, nothing more than avoid designing classes to circumvent Java 1.4’s
> >> lack of genericity (or typesafe enums). The following method:
> >>     public EventProducer getEventProducerFor(Class class)
> >> isn’t safe and bad design in Java 1.4.
> >
> > How is this bad design? It's just generic. Your solution below is just
> 
> Precisely because it’s not typesafe. Ok, bad design is probably a bit
> strong, but it’s certainly dangerous.

I don't have a non-sarcastic answer to that, so I'll keep my mouth shut.

> > the typesafe wrapper around the above. Otherwise you have to duplicate
> > the code for each method which is worse.
> >
> >> To keep on the safe way you would
> >> probably have to do something like
> >>     public BasicFOValidationEventProducer 
> >> getBasicFOValidationEventProducer()
> >> and add as many methods as there are EventProducer implementations. Just
> >> forget that and go with the simple version.
> >
> > -1 to that because
> 
> Yeah, that’s precisely what I’m saying.

Beg your pardon?

> > I will import interfaces from all sorts of packages
> > in FOP, at least if these methods are added to DefaultEventBroadcaster.
> > Better would be something like:
> >
> > public class BasicFOValidationEventProducerFactory {
> >   public static BasicFOValidationEventProducer 
> > getBasicFOValidationEventProducer(EventBroadcaster broadcaster) {
> >     return 
> > (BasicFOValidationEventProducer)broadcaster.getEventProducerFor(BasicFOValidationEventProducer.class);
> <snip/>

No comments on the counterproposal?

> Vincent
> 
> 
> -- 
> Vincent Hennebert                            Anyware Technologies
> http://people.apache.org/~vhennebert         http://www.anyware-tech.com
> Apache FOP Committer                         FOP Development/Consulting




Jeremias Maerki

Reply via email to