Java exception handling in parsers - java

Let's say we have such a simple parser:
public class ResourceManager {
private final static Logger LOG = Logger.getLogger(ResourceManager.class);
public Museum parseJSONFile(String filePath) /*throws IOException ???? */ {
Museum museum = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
museum = objectMapper.readValue(new File(filePath), Museum.class);
} catch(IOException e) {
LOG.error(e);
}
return museum;
}
}
Should the exception be caught in method or in the calling code? Which variant is better?

Parser can't do anything with exception, so that's an exceptional situation for a parser and it can't produce any expectable result. Someone from the outside should handle it.
In particular, it should not return null as it will result in bunch of null-checks in calling code (which you can easily forget to put, or due to the lack of documentation on your implementation I just don't know whether I have to check for null without seeing the code). This is one of the problems that exceptions in Java were intended to solve. By declaring checked-exception in method signature, you're enforcing users of your parser to deal with fact that value might not come.

Related

Proper way to get error message and code from exception

I have a simple try catch method that returns an exception as String
public class Program {
try {
someFunction()
} catch (Exception e){
// i need to get the code and message as strings
}
}
these are some examples of the exceptions I can get:
You have got the error. [ErrorCode: 400 XYZ]
You have got the error. [ErrorCode: 404 XYZ]
You got error which has no errorCode
and these are the error codes I want for each of these exceptions:
INVALID_TEMPLATE
REQUEST_REJECTED
NO_ERROR_CODE
I tried a few things and this is what I came up with
public class Program {
try {
someFunction(x);
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String message = sw.toString();
Matcher m = Pattern.compile(".*:\\s+(.*)\\s+\\[ErrorCode: (\\d+)").matcher(message);
if (m.find()) {
String errorMessage = m.group(1); // You have got the error.
String errorCode = m.group(2); // 400
// Here I want to fetch the error Category based on the errorCode
String errorCategory = XYZ.errorCategory(errorCode);
`//Based on`
the errorCode, errorCategory of INVALID_TEMPLATE which is an enum must be returned
SomeOtherFunc(errorCategory, errorMessage);
}
}
public class XYZ {
private static final Map < String, String > errorMap = new HashMap < > ();
public void populateErrorMap() {
errorMap.put("400", INVALID_TEMPLATE(400, 400));
errorMap.put("404", REQUEST_REJECTED(404, 404));
}
}
public static String errorCategory(String errorCode) {
return errorMap.get(errorCode);
}
Is this optimal or is there a better solution?
Also this is still unable to handle the exception in case there is no error code (should return NO_ERROR_CODE).
How can I archive that?
In real life there are two audiences:
the log handler with a configurable log level (ERROR) and logging (in English) with much info;
the end user with an localized translated message, also with parameters.
The first property is that you probably want a message as format String with Object... parameters. Probably should use MessageFormat.
Sensible would be to support typed parameters.
/** Type-checkable Message Definition. */
public record MessageDef(String format, Class<?>... parameterTypes) {
public void checkFormat() {
... check actual parameters with parameterTypes.length
}
public void checkUsage(Object[] args) {
... check parameter types
}
}
One could make an enum for the error categories. However enums are more suitable for closed domains with a fixed set of values. Extending values in future means that you have created a needless common bottleneck for source version control and so on.
An error is more like an open domain. However if you number them with error codes, an enum gives a nice overview.
The only advantage of error codes is the internationalisation. An Hungarian error message can be easily retrieved.
Then, if you rethrow check exceptions as RuntimeException, like IllegalArgumentException or you own custom ones, you might not want parallel classes: run-time exceptions and categories.
All-in-all I would advise an enum:
public enum MessageType {
INVALID_TEMPLATE(400, Level.ERROR,
new MessageDef("You have got the error in {0}.", String.class)),
...
REQUEST_REJECTED(200, Level.INFO,
new MessageDef("Done."));
public final int code;
public final Level level;
public final MessageDef def;
MessageType(int code, Level level, MessageDef def) {
this.code = code;
this.level = level;
this.def = def;
}
}
One small remark: such little discussion points in the beginning of a project sometimes might be better postponed to a fast refactoring after having written sufficient code. Here an enum might not fit, you might have much re-throwing of exceptions. A premature decision is not needed. And might hamper fast productivity.
Especially as you probably need not mark the code places, you most likely call the same show-error dialog.
I am not sure if I understood your issue properly
If you want to transform your exception code to a custom category this looks shorter:
public class Program {
Map<Integer, String> errorMap = new HashMap<Integer, String>();
errorMap.put(400, "INVALID_TEMPLATE");
errorMap.put(404, "REQUEST_REJECTED");
try {
someFunction (x) ;
} catch (Exception e ) {
SomeOtherFunction(errorMap.get(e.getStatusCode()),errorMessage);
}
}
Otherwise, you could add multiple catches for each exception type if you want to call different functions.
try {
someFunction (x) ;
} catch (IllegalArgumentException e ) {
// do this if exception 1
callThisFunction1()
} catch (IndexOutOfBoundsException e ) {
// do this if exception 2
callThisFunction2()
} catch(ExceptionType3 | Exceptiontype4 ex) {
// do this if exception 3 or 4
callThisFunction3()
}
Also please try to write down your questions better, like give it a proper order.
1)your input
2)your desired output
3)your code
4)the issue
Thank you...

Throwing exception passed by parameter to a function - java

im currently working in a complete generic scenario in which i map a json as string to a dto class. That works fine with my function mapJsonToDto but im trying to make it more generic so that the developer who uses this function can also specify what exception to be thrown. So they can catch as they like. With this i avoid catching an IOException. Letting the function handle everything.
public class MapperUtils {
public <T extends Throwable> Object mapJsonToDto(Class<?> dtoClass, String jsonDto, T exceptionToThrow) throws IOException {
Object dto = null;
try {
dto = new ObjectMapper().readValue(jsonDto, dtoClass);
} catch (IOException e) {
throw new exceptionToThrow();
}
return dto;
}
}
I cannot understand how to pass an exception class instance to a function and throwing that specific as well.
Instead of passing the exception to throw (which would then have a completely wrong stack trace), I think you'd want a function that converts an exception from one type to another:
public <T extends Throwable, D> D mapJsonToDto(Class<D> dtoClass, String json, Function<IOException, T> exceptionMapper) throws T {
try {
return new ObjectMapper().readValue(json, dtoClass);
// if readValue doesn't do the casting right, try:
return dtoClass.cast(new ObjectMapper().readValue(json, dtoClass);
} catch (IOException e) {
throw exceptionMapper.apply(e);
}
}
And an example:
Person p = mapJsonToDto(Person.class, "{name: \"Joe\"}",
e -> new IllegalArgumentException("malformed JSON", e));
As a general rule, though, this seems like boneheaded design. If you find the IOException overly general, then you can't handwave the problem away by allowing the caller to provide a no doubt similarly overly general mapper. The only way out for a caller is to do a deep dive on the exception and write, I dunno, an if/elseif block with a ton of levels to it to try to ascertain the real problem e.g. via analysing the message, which is all sorts of ugly.
Either you don't care about that level of detail and you should therefore just stick with IOException (what point is there adding code and pointless layers of indirection?), or you do care and this isn't good enough; you'd want to design a better error system. Except, that's not your job, that'd be ObjectMapper.readValue's job. Which is why the IOException it throws should probably just be sent on unmolested.
Your example is nearly done.
I changed only the throws Type to T and throw the given exception.
public <T extends Throwable> Object mapJsonToDto(Class<?> dtoClass, String jsonDto, T exceptionToThrow) throws T {
Object dto = null;
try {
dto = new ObjectMapper().readValue(jsonDto, dtoClass);
} catch (IOException e) {
throw exceptionToThrow;
}
return dto;
}
Call: mapJsonToDto(String.class, "helo", new IllegalStateException());

Writing Junit test to cover exception and catch block

I have written Junit test case for following function. When checked JACOCO test coverage. It is showing only try block is covered by test case. I am newbie to writing test cases. How the exceptions and catch block can be covered in test cases
Here is a method
public static List<Student> readCsvFile(String fileName)
{
BufferedReader fileReader = null;
//logic to read file
}
catch (Exception e)
{
System.out.println("Error in CsvFileReader !!!");
e.printStackTrace();
} finally
{
try
{
fileReader.close();
} catch (IOException e)
{
System.out.println("Error while closing fileReader !!!");
e.printStackTrace();
}
}
return students;
}
And TestMethod
#Test
public void ReadCsvFileTest()
{
String fileName = "test.csv";
List<Student> result = new ArrayList<Student>();
result = CsvFileReader.readCsvFile(fileName);
Student student1 = null;
Iterator<Student> it = result.iterator();
while (it.hasNext())
{
Student s = it.next();
if ("471908US".equals(s.getId()))
{
student1 = s;
break;
}
}
assertTrue(student1 != null);
}
In such situations you may often consider the introduction of additional dependencies to your class. Here is what I mean with a rough example. Create a factory for readers:
interface BufferedReaderFactory
{
public BufferedReader createBufferedReader(String fileName) throws IOException;
}
Then you will have a trivial implementation that hardly needs any testing, e.g. something similar:
class BufferedReaderFactoryImpl implements BufferedReaderFactory
{
#Override
public BufferedReader createBufferedReader(String fileName) throws IOException
{
return new BufferedReader(new FileReader(fileName));
}
}
Then you have to find a way to inject this dependency into your class. I usually use Guice in my daily work but you may try something as simple as using constructor injection and making your method non static. Here is an example:
class CsvFileReader
{
private final BufferedReaderFactory factory;
public CsvFileReader(BufferedReaderFactory factory)
{
this.factory = factory;
}
public List<Student> readCsvFile(String fileName)
{
BufferedReader fileReader = null;
try
{
fileReader = factory.createBufferedReader(fileName);
...
}
catch(IOException e)
{
...
}
finally
{
...
}
return new LinkedList<>();
}
}
With a mocking framework like Mockito the behavior of this class in case of IOException-s is easier to test now (note that you may also return mocks that throw exceptions from the factory). Here is a sample:
#RunWith(MockitoJUnitRunner.class)
public class MyTest
{
#Mock
private BufferedReaderFactory mockFactroy;
#Test
public void testIOException() throws IOException
{
String ivalidFileName = "invalid.txt";
//throw exception in case that invalid file name is passed to the factory
Mockito.when(mockFactroy.createBufferedReader(ivalidFileName)).thenThrow(new IOException("Hello!"));
CsvFileReader csvFileReader = new CsvFileReader(mockFactroy);
//invoke with a factory that throws exceptions
csvFileReader.readCsvFile(ivalidFileName);
//...
//and make a sensible test here, e.g. check that empty list is returned, or proper message is logged, etc.
}
}
You may do that without Mockito, of course - by implementing a test factory. But this is more cumbersome especially in more complicated use cases. Once the IOException is thrown you will get appropriate coverage report by JaCoCo.
Also mind a limitation of JaCoCo mentioned here, in section Source code lines with exceptions show no coverage. Why?
Given the current signature of your method under test, getting to full coverage isn't easy: your catch block is only executed when an exception is thrown within your try block.
One way to solve this: do not pass in the file name, but the reader object itself. Like:
public static List<Student> readCsvFile(String fileName) {
return readCsvFile(new BufferedReader(fileName));
}
static List<Student> readCsvFile(BufferedReader reader) {
try {
...
} catch( ...
Now you can write several specific unit tests for that second method. You keep your tests that simply do "correct" reading; but you add one where you pass in a mocked reader object ... that simply throws an Exception at some point. Please note that I made that new method just package protected - you probably don't want to use that "public"; and making it private would prevent it from being unit tested.
That should help you achieving full coverage. Of course you will also need at least one test to "cover" the string-taking method, too.
Some notes:
Be careful about re-inventing the wheel. There are many existing CSV parsers already. And be assured: writing a correct CSV parser that is able to deal with all "correct" input CSV is much harder than it sounds. If this is not for "learning purposes" I strongly advise to not write your own CSV parser.
Be careful about making such things static. As said, a real CSV parser is a complicated thing, and worth its complete own class. So no static helper methods - a normal class which you instantiate to then call methods on it (that would also for using dependency injection which would help with the problem you are asking about ... getting exceptions thrown within try blocks)
You are catching Exception in your code example. Don't do that - try to catch exactly those exceptions that your code can actually produce (probably IOException in your case).

final static SecureRandom.getInstanceStrong() [duplicate]

I am facing a use case where I would like to declare a static finalfield with an initializer statement that is declared to throw a checked exception. Typically, it'd look like this:
public static final ObjectName OBJECT_NAME = new ObjectName("foo:type=bar");
The issue I have here is that the ObjectName constructor may throw various checked exceptions, which I don't care about (because I'd know my name is valid, and it's allright if it miserably crashes in case it's not). The java compiler won't let me just ignore this (as it's a checked exception), and I would prefer not to resort to:
public static final ObjectName OBJECT_NAME;
static {
try {
OBJECT_NAME = new ObjectName("foo:type=bar");
} catch (final Exception ex) {
throw new RuntimeException("Failed to create ObjectName instance in static block.", ex);
}
}
Because static blocks are really, really difficult to read. Does anyone have a suggestion on how to handle this case in a nice, clean way?
If you don't like static blocks (some people don't) then an alternative is to use a static method. IIRC, Josh Bloch recommended this (apparently not in Effective Java on quick inspection).
public static final ObjectName OBJECT_NAME = createObjectName("foo:type=bar");
private static ObjectName createObjectName(final String name) {
try {
return new ObjectName(name);
} catch (final SomeException exc) {
throw new Error(exc);
}
}
Or:
public static final ObjectName OBJECT_NAME = createObjectName();
private static ObjectName createObjectName() {
try {
return new ObjectName("foo:type=bar");
} catch (final SomeException exc) {
throw new Error(exc);
}
}
(Edited: Corrected second example to return from method instead of assign the static.)
Your code is perfectly valid. I don't find it difficult to read. Other ways would only make it more worse. They're only difficult to read for starters, because most of them are not familiar with that. Just follow the standard conventions with regard to ordering of the elements in the code. E.g. do not put static initializers halfway or at the whole bottom of the code and also do not have multiple of them spreading over the class. Just put one at top, after static declarations.
static blocks aren't difficult to read. So I'd recommend that solution.
However, you can wrap your object in another object, for example
ObjectNameWrapper which shares an interface with your ObjectName, and whose constructor calls your ObjectName constructor, hiding all checked exceptions that occur. But again, I'd go for the static option.
You can use a method annotated with Lombok's #SneakyThrows
public static final ObjectName OBJECT_NAME = createObjectName();
#SneakyThrows(SomeException.class)
private static ObjectName createObjectName() {
return new ObjectName("foo:type=bar");
}
This annotation makes a checked exception behaves like an unchecked one.

Is there an utility to parse an URL without checked exception in java?

I'd like to create an URL constant, like so
public static final URL REMOTE_URL = new URL("http://example.com/");
But I can't since the constructor throw a checked exception. Right now I use
public static final URL REMOTE_URL = createUrl("http://example.com/");
private static URL createUrl(String url) {
try {
return new URL(url);
} catch (MalformedURLException error) {
throw new IllegalArgumentException(error.getMessage(), error);
}
}
But it feel like reinventing the wheel. I can't possibly be the only one who want to use a URL constant no? So I was wondering if there is third-party toolbox library (like guava or apache-commons, or something else, anything) or even better, something in standard Java that include this facilities? That would help me when we start a new project by reducing the size of our util package :) .
This complaint must have been a common one, because Java has (since 1.7) introduced the URI class. You can construct it using either of the following ways:
new URI(), which throws a checked exception
URI.create(), which throws an unchecked exception
For URIs/URLs like yours that are known to come from a safe source, you can use the URI.create() variant and not have to worry about catching the exception as you know it won't be thrown.
Unfortunately, sometimes you can't use a URI and you still need a URL. There's no standard method (that I have found so far) of converting a URI into a URL that doesn't throw a checked exception.
Since everyone else is just commenting, I will provide the answer which is that no there is no standard way to do what you want :)
Also, since you mention apache commons and google guava, I would point out that standard is not exactly the correct word to use either....maybe you want open-source, free, or just third-party.
Just throwing this one in the mix - there's a lot of stylistic variation for accomplishing the same thing, this one initializes in a static init block, but it can't be final.
public static URL g_url;
static {
try {
g_url = new URL("http://www.example.org");
} catch (Exception e) {
e.printStackTrace();
}
}
You cant extend URL because it is final, but you can create a new class, perhaps named MyURL, and have it proxy the URL methods to a private (or protected) URL member.
Here is the beginnings of such a class:
package blammo.url;
import java.net.MalformedURLException;
import java.net.URL;
public class MyURL
{
private URL containedURL;
public MyURL(final String spec)
{
try
{
containedURL = new URL(spec);
}
catch (MalformedURLException exception)
{
throw new RuntimeException(exception);
}
}
public String getAuthority()
{
return containedURL.getAuthority();
}
// required for stuff that needs a URL class.
public URL getContainedURL()
{
return containedURL;
}
}

Categories