I am trying to implement some validation on Enum types in wink for jaxb/jackson.
I have an enum which takes some values. I want to allow a null, i.e. not set it in xml/json, but I also want to check for invalid values and give an error.
I found that by default jaxb/wink just returns a null if I supply a value not in the enum, so I tried using a setter to allow validation of the input. Using Level.valueOf(newLevel) to try and convert the supplied string to a value throws an exception and gives me a stack trace and http error.
This is ok, but what I really want is a custom exception so that I can have some control over the marshalling of the error response. I tried throwing one but it gets swallowed by (I think) wink.
enum Level {BASIC, ADVANCED};
#XmlAttribute
public void setLevel(String newLevel) throws MyException {
if (newNodeLevel != null) {
try {
this.level = Level.valueOf(newLevel);
} catch (IllegalArgumentException e) {
throw new MyException("level invalid");
}
}
}
Other than using a Throwable rather than an Exception, is there any way I can achieve this?
Related
Let's say I have a class like the following one:
public class Parameter {
private double[] parameterValues;
public Parameter(double[] parameterValues) throws BadElementInitializationException {
checkParameterValues(parameterValues);
this.parameterValues = parameterValues;
}
public double[] getParameterValues() {
return parameterValues;
}
public void setParameterValues(double[] parameterValues) throws BadElementInitializationException {
checkParameterValues(parameterValues);
this.parameterValues = parameterValues;
}
private void checkParameterValues(double[] parameterValues) throws BadElementInitializationException {
if(parameterValues == null)
throw new BadElementInitializationException("Parameter values cannot be null");
if(parameterValues.length == 0)
throw new BadElementInitializationException("Parameter values cannot be empty");
}
public int noOfValues(){
return parameterValues.length;
}
}
And the array is later used to perform some calculations.
My question is, where should I check that parameterValues is not null, nor empty? Should I do that in the Parameter class, like I did, or should I do that in the class which performs calculations?
Moreover, should I throw an exception here, or in the Calculation class? And what would be the reason to throw checked and what to throw unchecked exception? My goal is to make a stable application that won't crash easily.
You should do it in all places where getting an null or empty array is not valid. If you do it just in your Parameter class and rely on this having done the check in your Calculator class, then what if you start to use your Calculator class somewhere else? Who are you going to rely on to do the checks there? If you do it in the Calculator class and then refactor the Parameters class to use something else in the future, then your check will go away.
If its also invalid to have a null or empty array in your Calculator class then you need to check there as well.
Alternatively pass an object to both which cannot be empty and then you only need to make the null check.
Should I do that in the Parameter class, like I did, or should I do
that in the class which performs calculations?
In my opinion, better to check in Parameter class then any other classes. You could see how it do in google guava , for example, in most class they use:
public static boolean isPowerOfTwo(BigInteger x) {
checkNotNull(x);
return x.signum() > 0 && x.getLowestSetBit() == x.bitLength() - 1;
}
or
public static int log2(BigInteger x, RoundingMode mode) {
checkPositive("x", checkNotNull(x));
...
Moreover, should I throw an exception here, or in the Calculation
class?
If you check your parameters in Parameter class, better throw in Parameter class also. In addition to, you may use some standart function to check and throw exception, for example from google guava:
com.google.common.base.Preconditions.checkNotNull
com.google.common.base.Preconditions.checkArgument
com.google.common.math.MathPreconditions.checkPositive
And what would be the reason to throw checked and what to throw
unchecked exception?
A checked exception is good if you think that you must catch and working this exception later. In most case, for wrong parameters quite enough unchecked exception, like standart IllegalArgumentException in Java. Also, a checked exception need to say other programmers (who use this API) that this exception could be happened, and they need to working with it. Working with an unchecked exception is quite easy for programmer (and often reduce your source code), however a checked exception become your code is more reliable.
A more info about checked and uncheked exceptions, you could find in this post
I'm a beginner in java writing an frontend for a webservice.I have to validate the input to get useful error messages for the user.Currently it works this way:
public Object zipVal(String zip)
{
try
{
if (zip.length() == 5)
{
val.setZip(Integer.parseInt(zip));
return val.getZip();
} else
{
return lengthError;
}
} catch (NumberFormatException e)
{
return formatError;
}
}
for zip Codes.Using Objects to declare the return type is not what I want tho(and is afaik discouraged),but I'm not sure how I should handle wrong inputs other than that.Should I just return null for every Exception and invalid input and handle such things in another method?
Edit:Added something to actually throw an Exception...
Yeah, exception handling might be one of the trickier things to consider (if one comes from a C programming background for example, where we used to be happy with < 0 return code for indicating erroneous program flow).
Normally you are pretty safe off by catching other API:s you integrate with and encapsulate them in your own exception (sort of masking them away), but by doing so don't forget to chain the original exception into your own with this constructor (and/or derivatives of such):
public MyException(final String message, final Throwable cause) {
super(message, cause);
}
One surely see alot of:
catch (Exception) {
return null;
}
and such in code as well, I wouldn't say that this is "good" object orientation, but it is still common and could be used in special occasions.
And also, its usually very important what you do (how to handle) when you catch the exception, someone told me that programing is 90% about error control and 10% about functionality :)
Here are some tutorials/resources:
http://docs.oracle.com/javase/tutorial/essential/exceptions/
http://howtodoinjava.com/2013/04/04/java-exception-handling-best-practices/
If you are returning a value, then there is no need to handle the exception. It is better you declare that the method may throw the exception.
NumberFormatException is a RunTimeException. So if you wish to handle it, then better return an invalid zip (say -1) to let the caller know that something went wrong.
Otherwise, declare that you will throw a Custom Exception if NFE occurs.
This snippet may be useful.
public int setZipVal(String zip) // throws CustomException
{
try
{
if (zip.length() == 5)
{
val.setZip(Integer.parseInt(zip));
return val.getZip();
}
} catch (NumberFormatException e)
{
// Log the error and return invalid zip
return -1;
// OR throw custom exception
throw new CustomException("Length Error"));
}
}
I have a method:
public void SomeDataMethod() throws BadDataException {
try {
// do something
} catch(IOException e) {
throw new BadDataException("Bad data",e);
} finally {
// do something regardless of above
}
}
And now for example some code will invoke this method, and I want to see all failures which happened in this method,
so how can I do it by using initCause()? Or maybe is there any other way to do this? And if I use initCause():
1) will I get all exceptions which were catch or the last one?
2) and What form do I get them / it?**
When you call an Excepion Constructor with the throwable attached, like you have the e as part of the new BadDataException("Bad data",e); then the result is effectively the same as:
BadDataException bde = new BadDataException("Bad data");
bde.initCause(e);
This is to keep compatibility with earlier Java versions which did not have the initCause concept.
Not all exceptions support adding the cause as part of the constructor, and for those exceptions you can initCause it.
note that you can only initCause an exception once, and initializing it with 'null' cannot later be changed:
BadDataException bde = new BadDataException("Bad data", null);
// this will fail.....
bde.initCause(e);
To get the cause of an exception, you call... getCause(). In this case, this method will return the IOException that you wrapped inside your BadDataException. It can't return more that one exception, since you can only wrap one exception.
Below is the class somebody else wrote.
The problem that I am facing is that when it get's into the parse method with null as the rawString, it is throwing NumberFormatException.
So what I was thinking to do is, I should catch that NumberFormatException and set the value itself as null. So the way I did is right?
public class ByteAttr {
#JExType(sequence = 1)
private Byte value;
public static ByteAttr parse(String rawString) {
ByteAttr attr = new ByteAttr();
try {
attr.setValue(Byte.valueOf(rawString));
} catch (NumberFormatException nfEx) {
attr.setValue(null);
}
return attr;
}
public Byte getValue() {
return this.value;
}
public void setValue(Byte value) {
this.value = value;
}
}
The correct approach depends on what you want to accomplish in the program.
If it makes sense for ByteAttr.getValue() to return null later in your program, then your approach could work.
However, you need to consider whether you should be throwing an exception if parse is called with an indecipherable argument (including null). An alternative is to catch the NumberFormatException and throw a different exception that has semantic meaning in your program.
public static ByteAttr parse(String rawString) throws BadAttributeException {
ByteAttr attr = new ByteAttr();
try {
attr.setValue(Byte.valueOf(rawString));
} catch (NumberFormatException nfEx) {
throw new BadAttributeException(nfEx); // wrap original exception
}
return attr;
}
Another technique is to pass a default value to parse for those cases when rawString is indecipherable:
public static ByteAttr parse(String rawString, Byte defaultValue) {
ByteAttr attr = new ByteAttr();
try {
attr.setValue(Byte.valueOf(rawString));
} catch (NumberFormatException nfEx) {
attr.setValue(default);
}
return attr;
}
You need to do four things:
Decide what an unparsable number string means in the context in which you will be using the method. Does it mean an internal problem in the program? A corrupt file? A user typo? Nothing wrong but that string needs to be handled differently?
Decide the best way to handle it, taking that into account. Almost always, if the error is triggered by external input you need to report it back. Substituting null may be a good way of handling it.
Document what you decide to do. If a method is going to return null with some specific meaning, that needs to be written down as comments, preferably Javadoc commments.
Implement your decision.
I get the impression, perhaps unfairly, that you have jumped straight to step 4, without thinking through the possible causes and proper reporting of the problem.
You can add an early exit with a condition like:
if (rawString != null) {
return attr; // or other value you prefer
}
You can also make sure the caller of the parse method test for null value and avoid calling parse when it is.
It depends on the tolerance to null values in your application. If you expect the users to not pass null string to the parse() method, then you should do a defensive null check and throw an exception.
if (null == rawString) {
throw new CustomException("rawString cannot be null");
}
The same would apply to the catch block for NumberFormatException, where instead of silently setting the value of Byte attribute to null, you should throw an exception with appropriate message.
But if null is perfectly acceptable, then you should perform a defensive null check and set the Byte attribute to null. The NumberFormatException should certainly be NOT suppressed, IMHO.
I am debugging my application, I have added exception.getMessage() in logger, but exception.getMessage() prints Null, but , when I debug I could see my Exception String in exception object's detailed message, how can I get the exception message that is coming as detailed message? Note - getMessage returns Null.
P.S - I am not using PrintStackTrace or stacktraceElement, my logger should return the string from exception.getmessage(), that is the requirement.
From comment:
DBException dbExe = new DBException(sqlExe);
DBException objDbEx = (DBException) ExceptionUtil.populateSuperException(dbExe, strTraceMesg, ConstantsIF.SEVERE_LEVEL, false, null, null, null);
throw objDbEx;
public static SuperException populateSuperException (SuperException exSuperException, String strTraceMsg, char chTraceLevel, ) {
if (strTraceMsg != null) {
switch (chTraceLevel) {
case Con.IN:
case Con.S:
//log
}
}
return exSuperException;
}
You can print out the full stack trace:
exception.printStackTrace();
Try:
switch (chTraceLevel) {
case Con.IN:
case Con.S:
String msg = exSuperException.getCause().getMessage();
// LOG msg
}
That is pretty strange. The message that you see with debugging is usually created through Throwable#toString and that calls getLocalizedMessage() internally.
So if the exception does have a message, then it should be returned through getMessage() and be part of the toString() result.
An exception/throwable does not need to have a detailed message. Please double check, if you've created your exceptions with a message.
After making your code readable: your DBException is created without a message, so dbExe.getMessage() will return null. Either look the the cause or add a message while creating:
DBException dbExe = new DBException(sqlExe.toString(), sqlExe);// just an example
You are creating your exception object without any message (you're only specifying the chained exception):
DBException dbExe = new DBException(sqlExe);
hence calling dbExe.getMessage() may (correctly) return null (with the details depending on what your constructor does in this situation). The reason you can see a message in the stacktrace, incidentally, is because the generation of the stacktrace recurses to the underlying exception, and sqlExe.getMessage() will be what you're seeing.
The solution is simply to provide a message as well as the underlying exception when constructing your exception. The general wisdom is that this should reflect the level at which the exception is thrown, so perhaps something like the following:
DBException dbExe = new DBException("Unable to persist widgets", sqlExe);
If your unspecified "requirement about the existing code flow" means that you need the actual database exception to be the message in dbExe, you could construct this like the following:
DBException dbExe = new DBException(sqlExe.getMessage(), sqlExe);
though on the whole that duplication of the message isn't very nice, and the former option is the more "correct" one.
From the discussion in the comments, it is my conclusion that the root cause of your problem is in the implementation of the DBException constructor or its hierarchy. For a valid reason or not, I think it's not calling the exception class hierarchy (e.g. super(reason);) and therefore, you are not getting the expected behaviour from the call to dbException.getMessage(). Note that a call to new Exception(anotherException) will always populate the field backing the getMessage() call in the base Throwable class through this call chain: (only relevant bits shown)
public Throwable(Throwable cause) {
...
detailMessage = (cause==null ? null : cause.toString());
...
}
public String toString() {
...
String message = getLocalizedMessage();
...
}
public String getLocalizedMessage() {
return getMessage();
}
Check the implementation of DBException as the root cause of the problem discussed.