I am writing piece of code in Java, which job is to parse configuration file. It's convenient for the end-users, because they can see and fix all parsing errors at once. But it's not very good for testing - instead of specific exceptions test function just expects very general ParsingError exception.
It's always a room for dark magic here, like testing private methods, but I don't want to go for it. Could you suggest better design solution for the case?
Why not throw just a single InvalidConfigurationException (I wouldn't use ParsingError - aside from anything else, I wouldn't expect this to be an Error subclass) which contains information about the specific problems? That information wouldn't be in terms of exceptions, but just "normal" data classes indicating (say) the line number and type of error.
Your tests would then catch the exception, and validate the contents was as expected.
The implementation would probably start off with an empty list of errors, and accumulate them - then if the list is non-empty at the end of the parsing code, throw an exception which is provided with that list of errors.
I have been here before. Exceptions are unsuitable. Instead you should provide a report inside your parser.
parser.parse();
if (parser.hasErrors()) {
for (ParserError error : parser.getErrors()) {
// Provide a report to the user somehow
}
}
Simple and easy to read. An exception should be thrown if there is an exception condition - e.g. there is no source data to parse, not because the parser found problems.
Why not use chained exceptions? You could build specific exceptions (say ParticularParsingError), then chain this with ParsingError and throw that back.
In your unit tests, use e.getCause() where e is a ParsingError.
First things first: ParsingError seems a strange name, ParsingException looks better (Error is a java.lang class that should not be caught)
You could add a list in your ParsingException and add a try-catch block in your test in which you test that your list contains what you expect.
For example you had:
#Test(expected=ParsingException.class)
public void test_myMethod_myTestCase(){
myMethod()
}
but then you would have:
public void test_myMethod_myTestCase(){
try {
myMethod()
}
catch(ParsingException pe) {
if (! pe.list.contains(anError)
|| ! pe.list.contains(anOtherError) ) {
fail();
}
}
}
Related
I'd like some feedback on a situation where:
A method constructs an object, but some of the work done while constructing it might fail. This will lead to an object that is missing some data. I want to give the user of this method the ability to handle the object if complete but also handle the object if incomplete while also being able to handle the exception thrown.
Use Case:
I'm reading a file from disk into a POJO and some of the file attributes like date created can throw an exception while being read from the Operating System. In that case I'm throwing a custom exception but I also want the user to be able to handle that incomplete file representation (POJO).
My solution:
I used a custom exception that wraps the thrown exception and the incomplete object.
My code:
public FileDto getFromFile(File f) throws IncompleteFileDtoException {
FileDto dto = new FileDto();
dto.setName(f.getName());
dto.setPath(f.getAbsolutePath());
dto.setDirectory(f.isDirectory());
dto.setSize(f.length());
dto.setModifiedAt(f.lastModified());
try {
BasicFileAttributes attr = Files.readAttributes(f.toPath(), BasicFileAttributes.class);
dto.setCreatedAt(attr.creationTime().toMillis());
}
catch(Exception e)
{
throw new IncompleteFileDtoException("Unable to transform " +f.getAbsolutePath() + " to DTO.", e, dto );
}
return dto;
}
public static class IncompleteFileDtoException extends Exception
{
private FileDto fileDto;
public IncompleteFileDtoException(String message, Exception e, FileDto fileDto)
{
super(message,e);
this.fileDto = fileDto;
}
public FileDto getFileDto() {
return fileDto;
}
}
What negative effects could this code have ?
Your example only contained one value that might lead to a problem but as soon as you have multiple values you end up with quiet complicated code, because you have to keep the information if such an exception should be thrown.
Personally a better approach might be to just set fitting default values (if not just a null) if the processing failed but it's OK for the initialization of that particular value. And if it's OK that a value can be null you can just the whole exception-throwing. If you need to know if there was a problem during setup, add a flag in that object that gives the information if something failed that can be cheecked. That would also allow you to pass the object around without losing that information in subsequent classes, etc.
In short: Exception should only indicate exceptional situations, i.e. that an object can't be used and not to indicate expected situations
I offer you to use Builder pattern. Do create FileDtoBuilder and put it into exception. When you read file successfully, the do create FileDto instance from existed FileDtoBuilder.
Gang Of Four Design Patterns
https://en.wikipedia.org/wiki/Builder_pattern
I need to write a RestClient used by several application that return a specific object.
In case of bad request (400) I'd like to advice the caller application of the message error and status code.
I wonder if is it a good behavior to throw a managed Exception with code and message property in order to be catched properly from the caller code.
Something like this:
RestClient.java
ClientResponse response;
try {
response = client.resource(requestURI).queryParams(queryParams)
.type(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, richiesta);
boolean output = response.getStatus() == Response.Status.NO_CONTENT.getStatusCode();
if (!output && response.getStatus() == Response.Status.BAD_REQUEST)
throw new RestClientRuntimeException(response.getStatus, response.getEntity(String.class));
} catch (ClientHandlerException e) {
throw new RestClientRuntimeException(e);
} catch (UniformInterfaceException e) {
throw new RestClientRuntimeException(e);
}
Caller application
try
{
boolean output = restClient.method()
} catch (RestClientRuntimeException e) {
// read exception status and message entity
}
Is it a good practice ?
Your question has several aspects. Lets consider them separately:
Should I translate http error codes into exceptions?
Yes you should translate error codes into exceptions. Exceptions are nice (if used correctly of course). They separate the happy path from the exceptional cases. If you don't use exceptions but return codes, your callers need to check for that return code. And if you call several methods you get some nasty cascading ifs:
if (service1.method1() == NO_ERROR) {
if (service2.method2() = NO_ERROR) {
if (service3.method2() = NO_ERROR) {
...
} else {
...
}
} else {
...
}
} else {
...
}
Furthermore if you have several layers (and you almost certainly have), you need to do this at every level again. Exceptions are much better here. They let you code (and read!) the nice and clean happy path first and then
you can worry about the exceptions in the catch block. That's easier to write and easier to read.
Should I use checked exceptions?
This can get quite religious. Some people think checked exceptions are a good idea, some think, they are evil. I don't want to debate that here in detail. Just that: Do you want to force your callers to think about that particular exception? Is there always or at least in the vast majority of cases a way for the caller to handle that exception?
If you come to the conclusion that the caller cannot do anything but log the exception and fail itself, you should refrain from using checked exceptions. This makes the caller code much cleaner. There is no use in pointless try..catch blocks that are just there to make the compiler happy.
Speaking of REST: In case of a 500, there is most likely no chance to recover. If you get a 405 you most likely have a bug and there is no way to recover either. If you get a 409 Conflict with some special info on how to resolve the conflict there might be a good way to handle that (depending on your requirements). In such a case you may consider a checked exception.
Should I store the response code in the exception?
When you use generic RestClientRuntimeExceptions and have your callers query the response code, then your caller is obviously coupled to this being a REST call. You can do that if you are writing a generic REST client that can query arbitrary REST APIs. No problem in this case.
But you are already using a generic library (I guess Jersey). So what's the point in wrapping a generic API around a generic API? There may be some reasons (e.g. evaluating some internally used header params) but you should think about it whether this is justified.
Maybe you want to write an application-specific REST client, i.e. one that deserializes your application-specific representation classes (DTOs). In such a case you should not use generic exceptions but rather application-specific ones. If you use application-specific exceptions your callers are not coupled to this being a REST call. Maybe in the future a cool new technology shows up and you need to change your client. If you use the generic exceptions and have your callers evaluate the response codes, the callers need to change, too. But if you use application-specific exceptions, this interface will be more stable. The callers don't even need to know that such a thing as REST exists. This makes the caller code simpler and more maintainable as you separate concerns.
Should I put a rest client into a jar?
I know you haven't asked that question. But maybe you should do so. Providing a rest-client jar with a Jersey dependency to arbitrary clients (that's what it seems to me that you do) looks nice at first but can get you into real trouble with dependencies. If you are not convinced, I can explain that in detail but lets discuss this in a separate question.
Since your success response is JSON, I would model the error responses as JSON too.
For example consider the following JSON serialized from a POJO like ErrorMessage.java having corresponding fields.
{
"statusCode": 400,
"errorMessage": "Bad Request",
"errorDetails": "<details here>"
}
Since it is HTTP, it would be better to communicate error codes based on HTTP status codes. errorMessage and errorDetails can be blank in case of a successful status code.
Why don't you check the HTTP status code family?
Other errors besides 400 can happen. If you test the status code family, you catch them all:
switch (response.getStatusInfo().getFamily()) {
case CLIENT_ERROR:
// It's a client error
// You can throw an exception
break;
case SERVER_ERROR:
// It's a server error
// You can throw an exception
break;
default:
break;
}
IMHO it's a good practice at least for 400 status code to have custom exception because it implies malformed data was sent.
Instead of throwing unchecked exception and catching them, checked exceptions are more suitable.
I have some function works with database.
I have set a try/catch for error handling here, and display a message, It works fine.
Now the class calling this delete function need to know if there is a error or not. In my case : refresh the GUI if success, nothing to do if fail (as there already show up a message message dialog).
I come up a idea to return boolean in this function.
public static Boolean delete(int id){
String id2 = Integer.toString(id);
try {
String sql =
"DELETE FROM toDoItem " +
"WHERE id = ?;";
String[] values = {id2};
SQLiteConnection.start();
SQLiteConnection.updateWithPara(sql, values);
} catch (SQLException e) {
Main.getGui().alert("Fail when doing delete in DataBase.");
System.out.println("Exception : "+ e.getMessage());
return false;
}
return true;
}
Don't know if this is good or bad, please tell.
EDIT :
Here is more detail for How do I use :
Let's say the code above is inside Class A,
in Class B :
public boolean deleteItem(int id){
int i = index.get(id);
if(theList[i].delete()){ //<---- here is the function from Class A
theList[i] = null;
index.remove(id);
retutn true;
}
retutn false;
}
I need to pass the boolean in more than one class, I don't know if that can better through...
in Class C :
public void toDoList_deleteItem(){
MyButton btn = (MyButton)source;
int id = btn.getRefId();
List toDoList = Main.getToDoList();
if(toDoList.deleteItem(id)){ //<-------function in Class B
Main.getGui().refresh();
}
}
Edit 2 :
I have notice the question is somehow more likely asking "What should I handle a Exception at database Layer that affect to GUI Layer ?"... Something like that. Please correct me if the question title should be edit.
It looks like you are returning a boolean status to indicate that an exceptional condition had occurred. Generally, this is not a good practice, for two reasons:
It encourages an error-prone way of handling exceptions - it is very easy to miss a status check, leading to ignored errors
It limits your API's ability to report errors - a single pass/fail bit is not always sufficient, it may be desirable to pass more information about the error.
A better approach would be to define an application-specific exception, and use it in your API. This forces the users of your API to pay attention to exceptional situations that may happen, while letting you pass as much (or as little) additional information as you find necessary. At the same time, your code does not get polluted with if (!delete(id)) { /* handle error */ } code on each API call, shrinking your code base, and improving its readability.
Can you tell me more about "define an application-specific exception", or show some code example please?
Here is how I would do it:
public class DataAccessException extends Exception {
... // Define getters/setters for passing more info about the problem
}
...
public static void delete(int id) throws DataAccessException {
try {
... // Do something that may lead to SQLException
} catch (SQLException se) {
// Do additional logging etc., then
throw new DataAccessException("Error deleting "+id, se);
}
}
Note: It is common to give custom exceptions four constructors mirroring the constructors of the Exception class to allow exception chaining. The constructors are described here.
As long as you do not want the caller to know what happens, just that it fails (and that failing is part of its intended behavior) you should be fine.
That being said, I am noticing this: Main.getGui().alert("Fail when doing delete in DataBase.");.
It would seem that you are accessing the GUI layer from some other place. This might cause issues should you decide to multi-thread your application. Also, it is usually considered good practice to have your layers not intersect.
Don't return a Boolean, return a boolean. Since this is not an exception / error condition, it is fine.
Exceptions should be used when you don't expect a failure.
In your case, if it's fine for you that a SQLException is thrown and does not affect your program, it's ok to return a boolean.
If the SQLExcetion causing the delete to fail can cause problems in another part of your application it's better to throw an exception.
Edit:
Based on your edits, it seems that you are doing some maintenance and cleaning when an error happens. In such a case I would recommend to use Exceptions better than using booleans to control the execution.
This question is primarly opinion based. Personally I would prefer not to catch the exception at that point.
Depending on what the caller of delete() should do, you might need other resulutions. So you should better add a throw statement and let the calling method decide if the error is critical - or if it can proceed.
Just true and false is not necessary enough to let the caller decide correctly. He won't know if deletion fails due to database errors, due to foreignkey constraints, or something else.
letting the exception bubble up the call stack will provide the caller with the exact error going on, increasing the chance to handle the error in a proper way, or just displaying a custom error message helping the user to take proper actions.
So I have this one question. Lets say we have classes: Main, Info, Cats, Food
Now, lets say that in main we create new object Info. In Info object we are saving list of Cats that have been created. Cats are being created and stored in Info class and Food is being created and stored in Cats class. Now lets say, that in Main class, I want to get specific Food object, which is stored in Cats class. So, in order to do so we do the following:
Info.getFood(name). Then in Info's getFood method we say Cats.getFood(name). Finally, in Cats class we have method getFood, in which we try to find Food object by its field "name". If we are unable to find such an element, we throw NoSuchElement exception rather than return an object. Here is my question:
If we throw exception in Cats class getFood method, should we catch that exception in Main class (where our interface is), in Info class (which is our system class) or in both of them?
Generally speaking, inside a method, if you can do something with the Exception being thrown (log an error, show an error message, make a different decision in your code, etc), then you should catch it. Otherwise, just throw it to the calling method.
As with many other coding practices, it all boils down to what you and your team agree on.
A concrete example which isn't related to your code, but which will show you how the decision process can be made. Assume the following code:
public MyConfiguration loadConfiguration () throws ConfigurationException {
MyConfiguration config = null;
try {
readConfigurationFromFile ();
// Parse configuration string
} catch (IOException ioex) {
throw new ConfigurationException (ioex);
}
return config;
}
private String readConfigurationFromFile () throws IOException {
String configuration = "";
// Read a file on disk, append data to the string.
return configuration;
}
In readConfigurationFromFile (), if an exception occurs while reading the file, you'll get an IOException. At this point in the code, there's no real action you can take, since this method only reads the configuration file, appends the data to a String, then returns it.
In loadConfiguration (), you can surround the call to readConfigurationFromFile () with a try/catch, and throw a more generic exception (ConfigurationException). Again, at this point, there's nothing you can do with the exception, except wrap it in a new exception which adds more context information to the original exception that was thrown.
Now assume that there's two flavors of your software: a GUI version, and a command-line version. If you are running the GUI flavor, then the method calling loadConfiguration could decide to show an error message to the user whenever a ConfigurationException is being thrown, so that the user knows that something happened. If you are running the command-line version, then maybe it would be more logical to add an entry to some error log with the exception that was caught.
The following site says "Most of the developers are embarrassed when they have to choose between the two options. This type of decision should not be taken at development time. If you are a development team, it should be discussed between all the developers in order to have a common exception handling policy."
http://en.wikibooks.org/wiki/Java_Programming/Throwing_and_Catching_Exceptions
It depends a lot on what you want to do after throwing that exception.
Say for instance that if all you want is to return any food object from any cat (and as you said 'Info' stores lots of cats) then you might have a catch in Info where you catch the NoSuchElement exception and then create some logic that moves onto the next Cat in Info to get its food! Finally if you exhaust all the 'Cats' in Info with no food found, you can throw another exception inside Info that you catch in Main that lets main know, "There's no food".
Again that's just an example. As people have said, it's not a "Always do this..." kind of answer. It depends greatly on what you need to do when handling that exception
I'm pondering on exception handling and unit tests best practices because we're trying to get some code best practices in place.
A previous article regarding best practices, found on our company wiki, stated "Do not use try/catch, but use Junit4 #Test(expect=MyException.class)", without further information. I'm not convinced.
Many of our custom exception have an Enum in order to identify the failure cause.
As a result, I would rather see a test like :
#Test
public void testDoSomethingFailsBecauseZzz() {
try{
doSomething();
} catch(OurCustomException e){
assertEquals("Omg it failed, but not like we planned", FailureEnum.ZZZ, e.getFailure());
}
}
than :
#Test(expected = OurCustomException.class)
public void testDoSomethingFailsBecauseZzz() {
doSomething();
}
when doSomethig() looks like :
public void doSomething throws OurCustomException {
if(Aaa) {
throw OurCustomException(FailureEnum.AAA);
}
if(Zzz) {
throw OurCustomException(FailureEnum.ZZZ);
}
// ...
}
On a side note, I am more than convinced that on some cases #Test(expected=blabla.class) IS the best choice (for example when the exception is precise and there can be no doubt about what's causing it).
Am I missing something here or should I push the use of try/catch when necessary ?
It sounds like your enum is being used as an alternative to an exception hierarchy? Perhaps if you had an exception hierarchy the #Test(expected=XYZ.class) would become more useful?
If you simply want to check that an exception of a certain type was thrown, use the annotation's expected property.
If you want to check properties of the thrown exception (e.g. the message, or a custom member value), catch it in the test and make assertions.
In your case, it seems like you want the latter (to assert that the exception has a certain FailureEnum value); there's nothing wrong with using the try/catch.
The generalization that you should "not use try/catch" (interpreted as "never") is bunk.
Jeff is right though; the organization of your exception hierarchy is suspect. However, you seem to recognize this. :)
If you want to check the raw exception type, then the expected method is appropriate. Otherwise, if you need to test something about the exception (and regardless of the enum weirdness testing the message content is common) you can do the try catch, but that is a bit old-school. The new JUnit way to do it is with a MethodRule. The one that comes in the API (ExpectedException) is about testing the message specifically, but you can easily look at the code and adapt that implementation to check for failure enums.
In your special case, you want to test (1) if the expected exception type is thrown and (2) if the error number is correct, because the method can thrown the same exception with different types.
This requires an inspection of the exception object. But, you can stick to the recommendation and verify that the right exception has been thrown:
#Test(expected = OurCustomException.class)
public void testDoSomethingFailsBecauseZzz() {
try {
doSomething();
} catch (OurCustomException e) {
if (e.getFailureEnum.equals(FailureEnum.ZZZ)) // use *your* method here
throw e;
fail("Catched OurCostomException with unexpected failure number: "
+ e.getFailureEnum().getValue()); // again: your enum method here
}
}
This pattern will eat the unexpected exception and make the test fail.
Edit
Changed it because I missed the obvious: we can make a test case fail and capture a message. So now: the test passes, if the expected exception with the expected error code is thrown. If the test fails because we got an unexpected error, then we can read the error code.
I came across this when searching how to handle exceptions.
As #Yishai mentioned, the preferred way to expect exceptions is using JUnit rules and ExpectedException.
When using #Test(expected=SomeException.class) a test method will pass if the exception is thrown anywhere in the method.
When you use ExpectedException:
#Test
public void testException()
{
// If SomeException is thrown here, the test will fail.
expectedException.expect(SomeException.class);
// If SomeException is thrown here, the test will pass.
}
You can also test:
an expected message: ExpectedException.expectMessage();
an expected cause: expectedException.expectCause().
As a side note: I don't think using enums for exception messages/causes is good practice. (Please correct me if I'm wrong.)
I made catch-exception because I was facing the same problem as you did, Stph.
With catch-exception your code could look like this:
#Test
public void testDoSomethingFailsBecauseZzz() {
verifyException(myObj, OurCustomException.class).doSomething();
assertEquals("Omg it failed, but not like we planned", FailureEnum.ZZZ,
((OurCustomException)caughtException()).getFailure() ;
}