Java API break - java

I have the following API:
public interface MyApi {
/**
* Performs some stuff.
* #throws MyException if condition C1
*/
public void method() throws MyException;
}
I am now performing the following modification in my API implementation
public class MyApiImpl {
public void method() throws MyException {
if (C1) {
throw new MyException("c1 message");
}
...
}
}
is replaced by :
public class MyApiImpl {
public void method() throws MyException {
if (C1) {
throw new MyException("c1 message");
} else if (c2) {
throw new MyException("c2 message");
}
...
}
}
Do you consider this as an API breakage ?
Client's code will still compile but method contract defined by the API javadoc is no more respected since MyExcepiton is thrown by a "new" condition.
If only my API jar file is updated, clients application will still work but depending on the way clients catch the exception the application behavior can change a lot.
What's your point of view on that ?

Yes, you're breaking the contract of the interface by throwing an exception when C1 doesn't occur.
As a rule of thumb, the vaguer the interface contract, the easier it is not to break :) If the interface isn't defined in terms of an explicit C1, but in more general terms, that gives a lot more flexibility.

My point of view is that you should not change the contract defined by the API in the documentation. If you need new behavior you should either a.) create a new method that can be called by the client reflecting this new behavior or b.) discuss with the client the need for the change and make them aware of it.
This really can go both ways, it is between you and your clients as to what your approach will be.

It largely depends on what c2 is. Is it within the logical bounds on the pre-existing contract? If so, you're satisfying the contract by throwing a MyException. If not then perhaps you need to throw a new type of exception.
I should point out that I'm not a huge fan of checked exceptions. Ultimately, forcing someone to deal with an exception doesn't necessarily make their code any better or safer (in fact it can have the opposite effect as they can sloppily swallow spurious exceptions).

I'd say "no", no API breakage, unless MyException is a RuntimeException. Then it is.
Anyway, I'd subclass MyException for condition C2
And both conditions C1 and C2 should be "exceptional" IMHO, I would not make an habit of throwing exceptions

It's a breakage. Whether the API is enforced by language constructs or simply documented is irrelevant.
Whether this breakage causes a problem for client code is a different question. It may be that you are fixing a defect and need to cover case C2 in this way to fix it. From that respect client code developers may be happy that you've made this change (assuming they are not currently working around the defect in such a way which would break in the face of the change!)

I think the problem here is that you made part of your interface, implementation specific conditions. If the "C1" condition were only part of your implementation, then you could have simply created a new implementation that throws an exception on "C1" or "C2" without breaking the interface.

Related

"Specializing" a subtype's method to throw a checked exception?

In my Java project, I have the following class / interface hierarchy:
public interface ProductSearcher {
Set<Product> search(String request);
}
public interface OnlineProductSearcher extends ProductSearcher {
}
public interface DatabaseProductSearcher extends ProductSearcher {
}
The OnlineProductSearcher searches for products at some remote machine (e.g. an implementation uses HTTP), while the DatabaseProductSearcher searches for products within my local machine (e.g. an implementation uses JPA).
As it turns out, from time to time, the OnlineProductSearcher may have problems searching for products because the remote machine is down, is rate-limiting my requests, responses with 5xx, 4xx, and whatnot.
So I had the idea to have my OnlineProductSearcher implementations throw an RemoteMadeProblemsException whenever there is a problem related to the remote machine.
And as I want to force any OnlineProductSearcher user to handle these exception gracefully and not forget to do so, I made RemoteMadeProblemsException a checked exception, i.e. RemoteMadeProblemsException extends Exception.
So I went along and had the idea to redefine OnlineProductSearcher like this:
public interface OnlineProductSearcher extends ProductSearcher {
Set<Product> search(String request) throws RemoteMadeProblemsException;
}
But in Java, it is not possible to redeclare/constrain methods from a supertype inside a subtype (Eclipse tells me "Exception RemoteMadeProblemsException is not compatible with throws clause in
ProductSearcher.search(String)")
Now I see two solutions to this situations:
define ProductSearcher.search(String) to throw a RemoteMadeProblemsException.
or make RemoteMadeProblemsException extend RuntimeException and don't have OnlineProductSearcher.search(String) declare a throws clause.
I find both solutions inadequate:
the first solution e.g. forces any user of DatabaseProductSearcher.search to catch/throw a RemoteMadeProblemsException which doesn't make sense (it's a local database after all).
the second solution opens the door for sloppy programming. E.g. someone uses OnlineProductSearcher.search(String) and forgets to try-catch a RemoteMadeProblemsException, letting the exception fall through and ripple up.
What are better solutions to this "only some subtype may throw an exception" problem?
The problem you have is this:
ProductSearcher x = new OnlineProductSearcher();
This is entirely legal syntax and now if someone calls x.method() there is no way for Java to know about that checked exception.
This is why subclasses can only make implementations more specific. They can return subclasses and accept super classes but not the other way around. This is because the requirement is that any call made to the super method is also valid against the subclass method.
For example if:
Number process(Integer i) {
}
is a super class then a valid subclass is:
Integer process(Number i) {
}
Because every call to process in the super class is also valid in the sub class. The exact same argument applies to throws declarations. By making the sub class throw a checked exception you make it impossible to treat it as a method with the same signature as in the super class.
The solution to your dilemma is to define a more generic exception ProductSearcherException and have ProductSearcher throw that exception.
Your OnlineSearcherException then subclasses ProductSearcherException and your throw declaration becomes legal.
One thing you can do to improve things involves having three classes instead of one:
Your base ProductSearcher which declares the method as throwing the exception
Your local implementation which does not throw the exception
The remote implementation which does throw the exception (or a more specialized one).
This does weaken the ability for people to doProductSearcher x = new LocalProductSearcher and then use the more generic class (as then they would need to catch the exception) but for anyone using LocalProductSearcher throughout they would never need to do the catch.
Note though that even in the local case you may find yourself needing to throw exceptions in the future so having them is not terrible.
IMHO You should add the throws Exception to your superinterface (and probably some more refined version, not just Exception).
The reasoning is that if you do not declare throws exception, then your contract is: Under normal execution no implementation of this method should throw an exception. In your program this is clearly not the case, as the remote may experience problems.
Your reason for not adding an exception to the database version is silly: The DB is local today, but may be remote tomorrow. And local DBs can have problems too.
If you REALLY don't want to catch exceptions from the DatabaseProductSearcher version, then you need to reference it as itself, not as the superinterface, and redefine the method in DatabaseProductSearcher to not throw anything. Then when you refer to it by that interface, you are not forced to catch anything, as the compiler now knows that this version is safe.

Omitting throws declarations in derived classes

Consider the following interface:
public interface Generator {
String generate() throws IOException;
}
and the following implementation:
public class EmptyStringGenerator implements Generator {
#Override
public String generate() {
return "";
}
}
Note that I omitted the throws IOException part of the signature specified in the Generator interface. Yet there is no compiler error, no compiler warning, not even the #Override annotation complains.
I am aware that this is working as intended. I would, however, like to know the intent behind this. If my method does not actually throw an IOException, it would be fine to just not throw it, I do not have to remove it from the signature. But if I do remove it from my method signature in EmptyStringGenerator, I am forcing all current and future subclasses of this class to forego the possibility of throwing an exception that is actually specified in the interface.
This, to me, sounds like a feature that does not really bring you any benefit (apart from saving a couple of keystrokes, which is not really a benefit at all), but has the potential to be a terrible mistake, when actually used.
So my question, effectively, is this: What is the point of omitting throws exceptions in derived classes? What is the problem that this possibility solves? Why is this allowed?
UPDATE
For people asking "but where is the harm in that?", here is my example from one of my comments. It is not far-fetched, by the way, because that is exactly what I am dealing with right now:
Programmer A specifies interface I. Programmer B writes implementation class X, but forgets to add the throws. He also never notices, because there is not even a warning being thrown here. Programmer C writes implementation class Y, inheriting from class X, he even specifically also wants to put the throws there, because he is gonna throw. But even though the interface stipulates it, he is now not allowed to do so anymore, because of B's oversight. He is effectively not allowed to use that exception here anymore. That's a pretty big harm. Especially if class X is not under your control.
If you omit the throws exception in derived classes you can call the method of the derived class without having to catch the exception.
You make sure that subclasses of EmptyStringGenerator also don't throw an exception. Otherwise it would not be sure for the compiler if the method call can cause a checked exception which the code must handle. In that case the throws wouldn't make sense at all.
Based on your class decleration, campare these two conditions:
EmptyStringGenerator generator = new EmptyStringGenerator();
generator.generate();
if you create an instance of EmptyStringGenerator like above, Since you omit the throws in EmptyStringGenerator, the above code indicates you are using the class itself, which of course has nothing to do with the interface, so the code works just fine.
but if you intend to use the interface instead of the class, like this:
Generator generator = new EmptyStringGenerator();
generator.generate();
than the compiler would actually remind you that there is an unhandled exception, you must handle it with a try-catch or throw it, otherwise the code will not compile.
if you use any subclass of EmptyStringGenerator in the latter manner, the same compile error will occur. So omitting the throw does not actually rlease you from handling the exception. It's only natural not to throw exception in a class and its subclasses when there is none to throw, but When you are calling the method through the interface, the exception still has to be handle.
In Java its OK and normal that you can make your classes less restrictive when implementing or extending that is a design decision of the Java developer. I can not say why Sun decided it this way and of course I can understand your problem with it, but the current way also has some benefits.
I see an Interface as a possibility to have multiple implementations for one job. For example the List classes which have different implementations for different needs. But they can all be used via the List interface. Lets say the remove method throws a CheckedException if the element is not part of the list. Now if am not able to be less restrictive in my implementations all List classes must throw this CheckedException, even they do not need or use it.
So if I use the remove method internally in my Class I am forced to handle the CheckedException. If I use my List class directly without the Interface I am forced to catch the exception. But for both cases I am pretty sure I do not need it and it will never happen. So with the current approach I can save a lot of "try catch ignore" blocks.
An other benefit of the current solution is that a class can easily match similar Interfaces.
So for example in one lib someone added a:
public interface Generator {
String generate() throws IOException;
}
And in an other lib:
public interface GeneratorInterface {
String generate();
}
If I write a Class with a generate method without any CheckedException I can easily use this to satisfy both Interfaces and maybe work with both libs:
public class EmptyStringGenerator implements Generator,GeneratorInterface {
#Override
public String generate() {
return "";
}
}
Also as far as I know Java is the only language with such handling of Checked and Unchecked exceptions and so the design decisions which pull through Java are strange compared with other languages not having Checked exceptions.

Java: Exception in constructors: Problematic or not?

I am recently thinking about if throwing constructor from Java is good or not. Currently this is what I gathered:
Can constructors throw exceptions in Java?
Here, Mr. StackOverflow (aka Jon Skeet) does not seem to hold anything against it, but he did hint about having subclass throwing exceptions. What will happen (anything bad?) when subclass throws exceptions?
http://futuretask.blogspot.com/2006/05/java-tip-10-constructor-exceptions-are.html
This blog post "Constructor Exceptions are Evil" tells me a way to show that constructor exceptions could be dangerous. However, the example seem to be really esoteric. Is there any real danger here?
I am thinking that if static factory methods (Effective Java 2nd ed., Item 1) are used instead of public constructors, we could safely remove the exceptions from constructors to the static factory method. Is this a valid way to avoid constructor exceptions and is this useful or used in anywhere?
Any inputs are helpful & appreciated. Thanks!
There is nothing wrong with exceptions in constructors (or factory methods, either way is fine). sometimes, doing too much work in a constructor can be a poor design, and may make sense to move to a factory method.
the only thing that point 2 proves is that exceptions in constructors are not an adequate security mechanism for protecting a class from evil usage. however, there are any number of ways to subvert such a design, which is why the only way to truly run secure code in java is running with a SecurityManager. so point 2 is just a straw man argument.
My point about a subclass throwing an exception is a situation like this:
public class Parent {
private final InputStream stream;
public Parent() {
stream = new FileInputStream(...);
}
public void close() throws IOException {
stream.close();
}
}
public class Child extends Parent {
public Child() {
// Implicit call to super()
if (someCondition) {
throw new RuntimeException();
}
}
}
Now the Child class really should call close() if it's going to throw an exception. Of course, if close() is overridden by yet another layer of inheritance, that could also cause problems. Just another example of how inheritance gets messy.
I still think it's basically fine for constructors to throw exceptions. Even your second link was more about an evil way of capturing the not-successfully-constructed object rather than really about constructor exceptions being evil - it certainly doesn't give any reasons for not throwing exceptions from constructors. It doesn't even give the messy situation I mentioned.
Factory methods could potentially help, but as far as the caller is concerned the result is the same: they don't get to see the partially-constructed object. Unless you really need to do something like clean-up on an object which was constructed but then failed some element of validation, I don't think that should be a reason to use factory methods instead of constructors. (There are other reasons to do so, but that's a different matter.)
I believe throwing exceptions from constructors is fine, more so the one's which checks for the preconditions to a successful object creation, example IllegalArgumentException.
However, I do not believe that constructors are the right place to handle business logic or throw business exception/ custom exceptions.
As for the reasons cited to not throw an exception, IMHO they are quite contrived; bottom line is if a careless developer wishes to do something evil he can find numerous ways to do it and there's no stopping till the developer does a self review of the code/ follows best practices.

Custom Exceptions: Differentiate via many subclasses or single class backed with enum?

I'm looking to implement my own set of Exceptions for a projects I am currently working on. The project relies on a core framework with a base framework exception MyFrameworkException (I am also writing this framework).
For any given project I would like to throw several different types of Exceptions and I can't decide between using multiple subclasses or a single subclass with some form of an Enum as a constructor parameter.
In both cases I have:
public class MyFrameworkException extends Exception { /*...*/ }
Option 1:
public class MyProjectBaseException extends MyFrameworkException { /*...*/ }
public class SpecificExceptionType1 extends MyProjectBaseException { /*...*/ }
public class SpecificExceptionType1 extends MyProjectBaseException { /*...*/ }
public class SpecificExceptionType1 extends MyProjectBaseException { /*...*/ }
Then, throughout the project I would throw the specific exception for any problem that occurs.
Option 2:
public class MyProjectException extends MyFrameworkException {
public static enum Type {
SpecificType1, SpecificType2, SpecificType3
}
public MyProjectException( Type type ) { /*...*/ }
}
Here I would always throw MyProjectException with the specific enum type for any problem that occurs. I'd provide some mechanism so that a switch statement could be performed on any MyProjectException based on the type enum.
What's the best way to handle exceptions in projects, especially those sharing a common infrastructure? Are the two options above good solutions? Why or why not? And what are any better solutions?
The chief disadvantage to Option 2 (a common exception + enum) is that you lose some of the utility of checked exceptions. A method pretty much has to say simply "something framework-related might go wrong":
public void foo()
throws MyFrameworkException
...rather than "x or y might go wrong":
public void foo()
throws SomethingWentWrongException, SomethingElseWentWrongException
It means a function that may need to handle one framework exception has to be prepared to handle any of them, whereas if you're specific, a function need only be prepared to handle the exceptions that are thrown by the framework methods it calls.
So for me, a hierarchy such as Option 1 (it needn't be quite so flat, if a structure suggests itself) is the way to go. That said, there are people who don't like checked exceptions at all, and for them I suspect the above is not a compelling argument. :-)
Edit And picking up duffymo's point: I've assumed you were talking about exceptions you really did have to create. Absolutely throw standard exceptions wherever it makes sense (which is nearly everywhere). Don't create your own MyFrameworkIllegalArgumentException, for instance, just use IllegalArgumentException (or its various subclasses).
I would go with exceptions extending java.lang.RuntimeException with descriptive class names.
If you have so many business-specific exceptions that this becomes oppressive, it means you're probably doing it wrong.
See Joshua Bloch's advice about favoring standard exceptions.
I wouldn't inherit from a generic MyFrameworkException, as long as you dont provide any functionality in there common to all projects. Else, always extend Exception.
Normally you should throw meaningful exceptions at domain/layer boundaries. So regarding your question, you should go with option 1, having in mind the point above. Option 2 would increase code complexity, as you will always have to check for the exception type to determine what went wrong. Let the exception class speak for itself.

Java interface extends questions

I have to implement an RMI server which will be 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?
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.
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.
A few ideas for you:
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.
You could create a new exception - ObjectNotFoundException and have BookNotFoundException and StudentNotFoundException inherit from there, then declare addBookToStudent to throw an ObjectNotFoundException.
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.
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
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.
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.

Categories

Resources