tags:

views:

885

answers:

6

For my assignment I have to implement an RMI server which will a front end for two other RMI services. So I decided a logical thing to do would be to have the interface for this implement the interfaces for the other two services.

public interface FrontEndServer extends Remote, BookServer, StudentServer
{
    // Block empty so far
}

However there is a method on the StudentServer

/**
 * Allows a student to borrow a book
 * 
 * @param studentID of the student who wishes to borrow a book
 * @param bookID of the book the student wishes to borrow
 * @throws RemoteException
 * @throws StudentNotFoundException when a student is not found in the system
 */
void addBookToStudent(int studentID, int bookID) throws RemoteException, StudentNotFoundException;

I would like the FrontEndServer to also throw a BookNotFoundException as this service will also validate if the book actually exists before attempting to add the details in.

Is this possible or is my design idea completely off and this is actually a bad design idea as if the other interfaces change and all? And will I be better of writing the method signatures for all the methods inside the FrontEndServer?

Any advice would be greatly appreciated.

+5  A: 

If you extend an interface (the same applies if you implement an interface), you can't override a method and have it throw more checked exceptions than the original. You can it throw the same or less but not more.

Think about it:

interface A {
  void foo();
}

interface B extends A {
  void foo() throws IOException;
}

A a = new B() { ... }
a.foo();

would potentially throw an IOException but you'd have no way of knowing. That's why you can't do it.

This of course is perfectly acceptable:

interface A {
  void foo() throws IOException;
}

interface B extends A {
  void foo();
}

A a = new B() { ... }
try {
    a.foo();
} catch (IOException e) {
    // must catch even though B.foo() won't throw one
}

Your BookNotFoundException could however extend RuntimeException or RemoteException. Not sure that's a good approach however.

cletus
Thank you - Looks like I will just implement the methods in the FrontEndServer - I guess it makes sense to be fair though.
Malachi
though if you want to define your "book not found" exception as a type of RuntimeException then you can throw it without declaring it. But that is evil.
Guss
A: 

It is theoretically possible if BookNotFoundException extends RemoteExcepiton.

However, I assume that you do not have control over the StudentServer interface. It appears that the intent of that interface is to not throw a BookNotFoundException. While I can understand why you want to, the interface doesn't seem to encourage that.

Rob Di Marco
+1  A: 

A few ideas for you:

  1. Declare the addBookToStudent method in the interface to throw a BookNotFoundException. Even though the StudentServer might never actually throw the exception, that doesn't mean you can't put it in the interface anyways.

  2. You could create a new exception - ObjectNotFoundException and have BookNotFoundException and StudentNotFoundException inherit from there, then declare addBookToStudent to throw an ObjectNotFoundException.

  3. What I would probably do in "real life" - have the StudentServer talk to the BookServer to validate the book id and throw the exception itself, rather than doing that check in the FrontEndServer. Especially if the StudentServer would actually be used directly by anything other than the FrontEndServer.

Eric Petroelje
A: 

I would suggest you attempt to separate your exposed API from the API's used to implement your functionality. My guess is that the purpose of front ending of the RMI services is to provide seperation and stability from the calling application.

With that I would suggest that you:

  • Write the API you want to expose
  • Write implementations that bridge between your API and back-end services

-Kam

Kam
A: 

Exceptions are thrown by methods not interfaces or classes. So if there is a method in the BookServer interface it could throw you exception when you add it to the interface.

If you are thinking of adding the exception to the addBookToStudent method in the FrontEndServer interface, the answer is no it is not possible. Overridden methods in classes and interfaces may only narrow the exception or remove it completely but not add new exceptions.

If you think about it, you see that this is logical. Your FrontEndServer could be used as a BookServer by some code. The code during compilation expects the exceptions defined in the BookServer. Then during runtime suddenly an exception is throw by the BookServer that is not defined in the BookServer interface. If that piece of code only knows the BookException is unexpected, there are no catches or throws statements to deal with it.

DefLog
+1  A: 

What good does a single type that extends both of these interfaces? Do you lose anything when a client depends on two distinct objects?

Overuse of inheritance is a common beginner mistake, because "inheritance" is one of the notable traits of object-oriented programming. However, in most cases, composition is a better choice. In this case, why not have two separate services? Then, adding CafeteriaService and DormitoryService later doesn't impact any existing interfaces.

With regard to the design, the addBookToStudent method would benefit from being able to throw BookNotFoundException. Interfaces are brittle, in the sense that changing them in any way breaks a lot of code. You have to be very careful in their initial design. For example, BookNotFoundException is probably to specific; couldn't there exist a variety of exceptions that would prevent "adding" a book to a student? (I'm guessing that students are checking books out of a lending library.) For example: CheckOutLimitExceededException, UnpaidFinePendingException, AdultLiteraturePermissionException, etc.

Think carefully about the types of checked-exceptions that might be appropriate for the level of abstraction when designing interfaces, because they are hard to change later.

erickson