For code quality reasons, I would like to replace a try catch block inside my code with an if condition in order to avoid using a FrontendException.
Here is my code :
Schema mySchema = new Schema();
mySchema.add(new Schema.FieldSchema("myInteger", DataType.INTEGER));
mySchema.add(new Schema.FieldSchema("myBoolean", DataType.BOOLEAN));
Schema tupleSchema = new Schema();
try {
tupleSchema.add(new Schema.FieldSchema("ARRAY_ELEM", mySchema, DataType.BAG));
} catch (FrontendException e) {
tupleSchema = new Schema(new Schema.FieldSchema(getSchemaName("myClass", input), DataType.DOUBLE));
}
return tupleSchema;
Is it possible to replace this code using an if else condition? This way I won't have to use this type of Exception and that would be better for SonarQube.
Any ideas?
The exception thrown by the Schema.FieldSchema constructor is deterministic. Here is the code of the constructor;
public FieldSchema(String a, Schema s, byte t) throws FrontendException {
alias = a;
schema = s;
log.debug("t: " + t + " Bag: " + DataType.BAG + " tuple: " + DataType.TUPLE);
if ((null != s) && !(DataType.isSchemaType(t))) {
int errCode = 1020;
throw new FrontendException("Only a BAG, TUPLE or MAP can have schemas. Got "
+ DataType.findTypeName(t), errCode, PigException.INPUT);
}
type = t;
canonicalName = CanonicalNamer.getNewName();
}
So the exception is thrown if;
the Schema given is null
the DataType given is not a schema type
You know in advance whether the exception will be thrown. In your case it is not so you can safely ignore the exception as it can never be thrown. You can remove the code in the catch block. You may as well replace it with;
throw new IllegalStateException("Summon Cthulhu");
Its a similar case to getting the UTF-8 charset;
String test = "abc";
byte[] bytes;
try {
bytes = test.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
//Can never happen although the compiler forces us to catch it
}
although the method getBytes can throw an exception if the charset is not supported, the UTF-8 charset is always guaranteed to be supported.
Related
Faced this with a situation - in the main method, a child method is called, which checks the object, and an exception is thrown in this child method (one of the objects in the list NULL). But the code of the main method still continues to be executed!
Example code:
#Transactional
public boolean addCompany(List<Company> companies, List<Address> addresses) throws Exception{
checkAddress(addresses);
try{
for(int i = 0; i < companies.size(); i++){
if(findCompany(companies.get(i).getId()) == null && !isExistsCompany(companies.get(i))){
companies.get(i).setAddress(addresses.get(i));
this.em.persist(companies.get(i));
}
}
}catch(Exception e){
return false;
}
return true;
}
public void checkAddress(List<Address> addresses) throws Exception{
try{
if(addresses == null)
throw new Exception(Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName() + ": Invalid parameter: list is null");
for(Address a : addresses)
if(a == null)
throw new Exception(Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName() + ": Invalid list item: object is null");
}catch(Exception e){
e.printStackTrace();
}
}
In this regard, several questions arose:
- why the code does not stop?
- Is it now necessary, as an option, to get out of the situation by changing the type of the checkAddress method from void to boolean, and in the main method to process true/false?
- How is correctly handled on the frontend such error - do the text send exceptions to the frontend or just process the code 500 and if so, then why generate an exception on the backend - to help in the development process? How to deal with it competently?
Advise please.
Thanks in advance.
You are catching the Exception(s), when you do not rethrow a Exception the Java runtime considers it handled. If you expected program execution to stop then you need the Exception(s) to propagate to the caller. For example, in checkAddress change
} catch(Exception e) {
e.printStackTrace();
}
to something like
} catch(Exception e) {
e.printStackTrace();
throw e; // <-- re-throw the Exception
}
or simply remove the try and catch altogether, then the Exception is automatically thrown to the caller. Also, in Java 8+, you could use a Stream. Like,
public void checkAddress(List<Address> addresses) throws Exception {
if (addresses == null) {
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
throw new Exception(ste[2].getClassName() + "."
+ ste[2].getMethodName() + "." + ste[1].getMethodName()
+ ": Invalid parameter: list is null");
}
if (addresses.stream().anyMatch(a -> a == null)) {
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
throw new Exception(ste[2].getClassName() + "."
+ ste[2].getMethodName() + "." + ste[1].getMethodName()
+ ": Invalid list item: object is null");
}
}
You need to remove try.. catch block from inside checkAddress() method. That way, any exception thrown from inside checkAddress() are propagate to its caller.
In addCompany() method, put call to checkAddress() method inside try .. catch and handle the exception there.
When checkAddress() throws exception, code execution will jump to catch block.
e.printStackTrace();
This line suppresses the exception, causing your code to continue rather than fail. It prints the stack trace, which might make it look like the exception is being thrown, but it's not getting any further than that line.
You almost never want to use printStackTrace(), you should instead properly handle the exceptions you intend to, or just let the exception propagate to the callers of your method.
Try this:
public void checkAddress(List<Address> addresses) throws Exception{
if(addresses == null)
throw new Exception(Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName() + ": Invalid parameter: list is null");
for(Address a : addresses)
if(a == null)
throw new Exception(Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName() + ": Invalid list item: object is null");
}
}
What is all that stuff about threads? Crazy code.
Don't allow anyone to add a null instance to the List in the first place.
I might write it this way:
public void checkAddresses(List<Address> addresses) {
if (addresses == null) throw new IllegalArgumentException("Address List cannot be null");
for (Address a : addresses) {
if (a == null) throw new IllegalArgumentException("Address cannot be null");
}
}
When throw exception, I found that always included java.lang.exception or javax.ssl.xxxx and so on, I just want to get only messages but not including exception type, how can I do it?
As exception has many types, I can not just filter string start with, is it available to do so?
Find below a small snippet as demonstration for my comment
try {
int i = 1 / 0;
} catch (Exception e) {
System.out.println("exception = " + e);
System.out.println("getMessage = " + e.getMessage());
}
output
exception = java.lang.ArithmeticException: / by zero
getMessage = / by zero
Im kinda new to handling exceptions in Java with Junit, a little guidence would be much appreciated.
What I am trying to do:
I surround the creation of the new CustomObject with a try as the user can pass in a String that will not match an enum when we call valueof(). I want to be able to catch an exception here, which I am, though I am told: "A catch statement that catches an exception only to rethrow it should be avoided.". There must be a better way to handle this?
If the new object has the correct enum then I call isValidObject, which returns a boolean. If the Integer is not valid then I throw an exception.
My test has a #Test(expected = AssertionError.class) and is passing.
Is there a better/cleaner way to use the exceptions?
I have the code below:
private CustomObject getObjectFromString(String objectDataString) {
if (objectDataString != null) {
String[] customObjectComponents = objectDataString.split(":");
try {
CustomObject singleObject = new CustomObject(EnumObjectType.valueOf(customObjectComponents [0]),
Integer.parseInt(customObjectComponents [1]));
if (isValidCustomObject(singleObject)) {
return singleObject;
} else {
throw new IllegalArgumentException("Unknown custom object type/value: " + EnumObjectType.valueOf(customObjectComponents [0]) + ":"
+ Integer.parseInt(customObjectComponents [1]));
}
} catch (IllegalArgumentException e) {
throw e;
}
}
Oh, and if anyone can recommend anything good to read about exception handling, that would be great.
A catch statement that catches an exception only to rethrow it should be avoided.". There must be a better way to handle this?
Yes, simply remove the try catch. Your code is equivalent to:
private CustomObject getObjectFromString(String objectDataString) {
if (objectDataString != null) {
String[] customObjectComponents = objectDataString.split(":");
CustomObject singleObject = new CustomObject(EnumObjectType.valueOf(customObjectComponents[0]),
Integer.parseInt(customObjectComponents[1]));
if (isValidCustomObject(singleObject)) {
return singleObject;
} else {
throw new IllegalArgumentException("Unknown custom object type/value: " + EnumObjectType.valueOf(customObjectComponents[0]) + ":"
+ Integer.parseInt(customObjectComponents[1]));
}
}
}
That code will throw an IllegalArgumentException if the value passed to your enum.valueOf() is not valid or if your isValidCustomObject method returns false.
Note that it might also throw an IndexOutOfBoundException if the string does not contain a : which you probably want to test before calling customObjectComponents[1]. And it might throw NumberFormatException too.
And you seem to accept a null String as a valid entry, which is probably not a good idea (depends on your use case obviously).
I would probably have written it that way:
private CustomObject getObjectFromString(String objectDataString) {
Objects.requireNonNull(objectDataString, "objectDataString should not be null");
String[] customObjectComponents = objectDataString.split(":");
if (customObjectComponents.length != 2) {
throw new IllegalArgumentException("Malformed string: " + objectDataString);
}
EnumObjectType type = EnumObjectType.valueOf(customObjectComponents[0]);
try {
int value = Integer.parseInt(customObjectComponents[1]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(customObjectComponents[1] + " is not an integer);
}
CustomObject singleObject = new CustomObject(type, value);
if (isValidCustomObject(singleObject)) {
return singleObject;
} else {
throw new IllegalArgumentException("Unknown custom object type/value: " + type + ":" + value);
}
}
And finally, it would probably make sense for the CustomObject's constructor to check whether its arguments are ok or not by itself, instead of having to call a separate isValid method. The last block would then simply be:
return new CustomObject(type, value);
which would throw an IllegalArgumentException from the constructor if required.
I have the following java code:
if (ps.executeUpdate() != 1)
{
// Error - did not insert one row
String err = "insert unable to insert LocalUsage data: " + usg.toString();
Logger.log(err, _MODULE_CLASS, Logger.DEBUG);
throw new DaoException(err);
}
The problem if the query had a foreign key exception, then it will be thrown but it will never get to inside the if. what should I do so that it will get inside the if and output the log I have?
The problem is that this if condition is inside a try catch block, and it is going to the catch and never enters to the if condition.
executeUpdate() might throw an SQLException, as is described in its API documentation. You might want to catch that exception.
int count;
try {
count = ps.executeUpdate();
} catch (SQLException e) {
throw new DaoException("Exception while executing update: " + e.getMessage());
}
if (count != 1) {
// ...
}
As the docs states executeUpdate() may throw an exception so your code flow will fail and you will not be able to do any processing afterwards incase your exception handling is not proper.
Which I think is happening in your code right now.
While doing database call I would suggest you do it like this:
int operationStatus;
try {
operationStatus = ps.executeUpdate();
} catch(SQLException exp) {
final String message = "SQL Exception while calling executeUpdate()";
logger.error(message, exp);
throw new DAOException(message, logger);
} catch(Exception exp) {
final String message = "Exception while calling executeUpdate()";
logger.error(message, exp);
throw new DAOException(message, logger);
} finally {
//you may wish to clean up resources if they are not going to be used after this point.
}
if(operationStatus < 0) {
//Next steps
}
Let's say I can a set of statements:
try {
String a = getProperty("a");
String b = getProperty("b");
String c = getProperty("c");
} catch(Exception e) {
}
Now, lets say property b was not found and the function throws an exception. In this case, how would I just continue or perhaps set b to null without having to write a try-catch block for each property? I mean, a,b,c exist but sometime they might not be found at all during which an exception is thrown.
Assuming you can't change the function so that it returns null when the property isn't found, you are kind of stuck wrapping everything in its own try catch block -- especially if you want for every value that can be retrieved to be retrieved (as opposed to letting the first value that fails cancel the whole operation.)
If you have a lot of these properties to retrieve, perhaps it would be cleaner to write a helper method to use:
String getPropertySafely(String key) {
try {
return getProperty(key);
} catch (Exception e) {
return null;
}
}
You have to put a try-catch around each statement. There is no continue (like there is in ON ERROR ... RESUME blocks in VB). Instead of:
String a = null;
try {
a = getProperty("a");
} catch(Exception e) {
...
}
String b = null;
try {
b = getProperty("b");
} catch(Exception e) {
...
}
String c = null;
try {
c = getProperty("c");
} catch(Exception e) {
...
}
you could write:
public String getPropertyNoException(String name) {
try {
return getProperty(name);
} catch (Exception e) {
return null;
}
}
Personally I think a getProperty() is a poor candidate for throwing exceptions just for all this extra boilerplate required
Since you are using the same function each time you might be able to put this in a loop:
String[] abc = new String[3];
String[] param = {"a", "b", "c"};
for (int i = 0; i < 3; i++) {
try {
abc[i] = getProperty(param[i]);
} catch(Exception e) {
}
}
but this is rather contrived and would only be useful for a large number of properties. I suspect you will have to simple write 3 try-catch.
You should reconsider how getProperty is handled if you plan to use many of them because there isn't a plain way to do it.
You can exploit finally statement but you still need a try-catch for every call.