I am learning features in java including exceptions. I am writing a custom exceptions. Here is what i am doing :custom exception class:
public class ServiceException extends Exception {
private String customMessage;
public ServiceException(String customMessage) {
super(customMessage);
this.customMessage = customMessage;
}
}
Main class:
public class Main {
public static void main(String[] args) {
try {
new Main().test();
} catch (Exception e) {
System.out.println("the exception message is " + e.getMessage());
}
}
public void test() throws ServiceException {
try {
int i = 1 / 0;
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
}
This much i know:
if super class constructor is not invoked in the custom exception class, the message set in the custom exception is not passed to the Exception class. But if i have a method public String getMessage in my custom exception class, even if the super is not invoked, that message is printed . Sorry if this is a naive question. But i am failing to understand he concept. Could come one help clear the concept ?
In main where you are catching the error, you are basically assigning a ServiceException object to a Exception reference, i.e. assigning derived class object to base class reference, so if the derived class has overridden the method, it will get called.
the e.message() being called is from ServiceException not Exception, you are right, no data is being passed when you are not calling super, data is inside ServiceException class only and the function invoked is also from ServiceException class.
That is because you are supplying it. You are passing e.getMessage() to your constructor as the only argument, customMessage. You then pass customMessage to its parent's constructor that takes a String, Exception(String). In doing so, you are giving it the message to use for serviceExceptionInstance.getMessage(). Instead, do not pass the customMessage to its parent (use super();, which is implied if no call to a parent constructor is given and a no-arg, parent constructor exists). Then the message will be null as it is not supplied.
In other words:
new ServiceException(e.getMessage());
Creates a new ServiceException with the message from e. You pass that message to Exception, ServiceException's parent.
super(customMessage);
In doing so, you use the single argument, String-based constructor of Exception. Passing a value to that constructor implies that you want it used when callers invoke getMessage. To avoid doing this, call a different parent constructor, or none at all (calling none is technically not possible, and it will implicitly do super(); for you):
public ServiceException(String customMessage)
{
this.customMessage = customMessage;
}
This will call super(); for you, which means that the parent class has no message to send, and by not overriding getMessage() yourself, then it will return its default value (null). To be clear, Exception itself extends from Throwable, which is really the class providing this functionality, but it all stems from how you work with Exception as it serves as a pass-thru to Throwable.
Related
I'm trying to get into exception handling via custom exceptions.
I'm creating the class CustomExceptions and extending Exception as follows:
public class CustomExceptions extends Exception{
public CustomExceptions (String s) {
super(s);
}
However, rather than having to create multiple files for every custom exception I want, or bloating my main class file, I'd like to put all of my custom exceptions in this class and invoke them via a method
So let's say that I want to handle 2 situations: When the user tries to input a seat reservation, but the seat is already taken, and when the user tries to provide a ticket for someone outside of the age range.
Can I create 2 methods inside of the CustomExceptions class which invoke the constructor passing a custom message to it?
public void seatTaken(String s) {
String s = "The seat is taken, please choose a new one";
CustomExceptions(s);
}
public void notOldEnough(String s) {
String s = "User is not old enough for this movie.";
CustomExceptions(s)
}
}
Would this work? Or am I forced to create multiple custom exception files?
Generally custom exceptions should be defined in the top level. Because, almost universally, these exceptions are part of the interface of the package or module.
If the user cannot see them, then how are they going to catch them separately? And if you don't want to catch them separately, then why would you need separate classes?
However, if you must, you can include them into a class for which they are required:
public class SeatReservationSystem {
public static class ReservationFailedException {
... constructors taking a message ...
}
public static class SeatTakenException extends ReservationFailedException {
... constructors taking a message ...
}
public static class OutsideAgeException extends ReservationFailedException {
... constructors taking a message ...
}
....
}
After that you can create any method that returns them as required. Don't create methods that throw them as the compiler won't see those as exit points of the block you're in, and you'll get strange situations.
Here is some code to show what I mean:
// wrong
public static void throwRuntimeException() throws RuntimeException {
throw new RuntimeException();
}
// correct, but dangerous
public static RuntimeException createRuntimeException() {
return new RuntimeException();
}
public static void main(String[] args) {
String initializeMeOrThrowException;
if (new Random().nextBoolean()) {
// compiler doesn't recognize that the method always throws an exception
throwRuntimeException();
// this the compiler can understand, there is an explicit throw here:
// throw createRuntimeException();
// but this is the pitfall, it doesn't do anything:
// createRuntimeException();
} else {
initializeMeOrThrowException = "Initialized!";
}
// Compiler error for throwRuntimeException and createRuntimeException without throws:
// "The local variable initializeMeOrThrowException may not have been initialized"
System.out.println(initializeMeOrThrowException);
}
However, experience learns me that I forget the throws statement for the throw createException(...); method, and the stupid compiler doesn't warn me about that (even though the statement is utterly useless without it). So I try and not use either.
Note that I'm not certain if you should use exceptions for this. If your system is a reservation system, then refusing tickets is not that exceptional. Returning a ReservationResult makes more sense.
If module was not injected, in methodA which type of exception can i throw?
public class Customer{
private String module;
public void methodA(){
if (StringUtils.isBlank(module))
throw new ???
}
}
You can either create your own custom exception, or throw IllegalStateException along with an appropriate message. From the docs:
Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation. (emphasis mine)
Since you don't expect module to be blank, you're in an invalid state and hence this exception would be appropriate to throw in this case IMO.
No Specfic predefined Exception is already there which you can make use of. So you can make a new one like ModuleException:-
public class ModuleException extends Exception {
public ModuleException() { super(); }
public ModuleException(String message) { super(message); }
public ModuleException(String message, Throwable cause) { super(message, cause); }
public ModuleException(Throwable cause) { super(cause); }
}
After creating ModuleException you can throw it in your class like:-
public void methodA(){
if (StringUtils.isBlank(module))
throw new ModuleException("Module is blank but is MANDATORY");
}
I would've said to use NullPointerException but the isBlank method also returns true when it's an empty String. The best option would probably be to make your own Exception (info can be found here). That way you also get complete customization.
Assume we have two classes:
Class A:
import java.io.IOException;
public class A {
public void test() throws IOException{
System.out.println("test in A");
}
}
Class B:
import java.io.IOException;
public class B extends A {
#Override
public void test() throws Exception{
System.out.println("test in B");
}
}
This gives a compiler error, and I would like to know the reason for it. I can get the answer by myself, but this is not fully scientific, but partly logically.
I wrote a blog post in Azerbaijani. When I wrote the blog I was stuck in the loading process.
Please be careful in quotes:
I think that when the compiler reads the B class, it loads the method headers of A and method headers of B. And when you call test of A, the JVM calls the test of A, but as body calls test of B, and at that time we will have this method:
public void test() throws IOException{ // <-- Header of A
System.out.println("test in B"); // <-- Body of B
// Here I can throw wide Exception from IOException
// because here is the body of the test in B. The test
// method in B can throw Exception so the compiler
// doesn't approve of this version of the code.
}
Is the process really going on as what I wrote above?
Loading headers issue I was stuck exactly here.
How does the linking process work? I can't figure out background of
A a = new B(); // When the compiler converts this line into bytecode
// does it loads of method headers of A and method
// body's of B
a.test()
calls the test of the B class. I know logically, but I can't figure out at the compiler level, linking process.
Imaigine you have the following code:
A a = new B();
try {
a.test();
} catch (IOExceoption e) {
//do some specific handle for IOExceoption
}
Now imaigine what happens if b.test() throw an Exception which is NOT IOException? nobody will handle it, and that breaks java's checked exceptions mechanism.
The other way around however, is perfectly fine:
public class A {
public void test() throws Exception {
System.out.println("test in A");
}
}
public class B extends A {
#Override
public void test() throws IOException{
System.out.println("test in B");
}
}
A a = new B();
try {
a.test();
} catch (Exception e) {
//handle
}
Now, note that the catch handles a general Exception, including the specific IOException, and the code will compile perfectly.
The overidden method can throw anything which is an IOException your case. Or more generally, it can throw any exception that is a ParentException. So, you can throw FileNotFoundException since it is also an IOException.
Why?
Not adhereing to this rule breaks the primary contract between parent-child in inheritance.
Somewhere else in your code you can safely assume that the exception thrown from the call to test() will always be IOException irrespective of Which implementation of A threw it. If you were allowed to throw InterruptedException in your case, what exception should the caller catch?
The compiler doesn't load anything. It just marks the method as invoke virtual which means this method is overriden and supposed to be called at run-time based on the object type
From a bit different angle, you are basically not overriding existing method in super type.
Exceptions which are thrown are part of the method's signature.
When you declare your test method in class B with override annotation, you are in fact trying to override (or implement) method which does not exist in its parent A.
Here is a piece of code I have: (what I am trying to do with it is: define a method "renamingrule" in my main class, instantiate a instance of my other class "renamescript" and call its rename method passing as a parameter the "renamingrule" method i've defined in the main class. Everything is well in the RenamScript class, no errors, but i dont know how to call the rename method of the script class from my main class/method. thanks)
public class RenameScript2 {
...
public void rename(Method methodToCall) throws IOException, IllegalAccessException, InvocationTargetException {
try
{
...
String command = "cmd /c rename "+_path+"\\"+"\""+next_file+"\" "
+"\""+methodToCall.invoke(next_file, next_index)+"\"";
p = Runtime.getRuntime().exec(command);
}catch(IOException e1) {} catch(IllegalAccessException IA1) {} catch(InvocationTargetException IT1) {} ;
}//end of rename
} //end of class
//=======================================
public class RenameScriptMain2 {
public static String RenamingRule(String input, int file_row)
{
String output = "renamed file "+(file_row+1)+".mp3";
return output;
}
public static void main(String[] args) throws IOException
{
RenameScript2 renamer = new RenameScript2();
renamer.setPath("c:\\users\\roise\\documents\\netbeansprojects\\temp\\files");
try{
renamer.rename(RenamingRule);
}catch(IOException e2) {};
System.out.println("Done from main()\n\n");
}
} //end of class
You get hold of the Method object through Class.getMethod method. Something like this:
RenameScript2.class.getMethod("rename", parameters);
However, I suggest you consider writing an interface for a class that can perform the renaming, instead of passing a Method.
Such interface could look like
interface RenameAction {
void performRename();
}
To wrap the script in a RenameAction object you would do something like
RenameAction action = new RenameAction() {
void performRename() {
// ...
String command = "cmd /c rename "+_path+"\\"+"\""+next_file+"\" "...
p = Runtime.getRuntime().exec(command);
// ...
}
};
You would then simply do like this:
public void rename(RenameAction action) {
action.performRename();
}
Firstly, aioobe is definitely correct, passing a Method object is a little ugly. I'll assume that you're stuck with it!
To get a method, you'll need to use reflection. The below code grabs the method called toString on the class Integer. It then invokes the toString method.
Method method = Integer.class.getMethod("toString");
Object o = method.invoke(new Integer(7));
System.out.println(o);
Static methods don't need to pass the first parameter to method.invoke
Method method = File.class.getMethod("listRoots");
System.out.println(method.invoke(null));
This shows the reason why you shouldn't use it. That string "toString" and "listRoots" are not refactorable. If someone renames a method, then instead of a compile-time error, you'll get a runtime exception thrown (hence the exceptions you'll need to catch, NoSuchMethodException and IllegalAccessException). It's also much slower to use reflection than to use normal code.
Here is how you should do:
Make class RenameScript2 abstract by adding an abstract method public static String RenamingRule(String input, int file_row)
Then have your main class RenameScriptMain2 extend above class RenameScript2 and provide implementation of the method RenamingRule().
Now inside main method create instance of the class RenameScriptMain2 and call method RenamingRule()
I've the following class. It has the code to connect to SAP in its constructor. There is an abstract method(the subclasses define the implementation) which I want to mock.
public abstract class BapiExecutor {
...
public BapiExecutor(final SapConnectionInfo connectionInfo)
throws java.lang.Exception {
if (!validConnectorData()) {
throw new IllegalArgumentException(
"Does not have valid data to connect to SAP");
}
initializeState(connectionInfo);
}
public abstract Object execute() throws Exception ;
....
}
The unit I want to test is :
I want to mock the call to execute() method.
private String invokeBapiToAddAssociation(Map associationMap,
SapConnectionInfo connectionInfo) {
EidCcBapiExecutor executor = null;
String bapiExecutionResult = null;
try {
executor = new EidCcBapiExecutor(connectionInfo, associationMap);
bapiExecutionResult = (String) executor.execute();
} catch (Exception e) {
e.printStackTrace();
throw new CcGenericException(
"Exception occurred while invoking the EID-CC Association BAPI executor!",
e);
}
return bapiExecutionResult;
}
Any frameworks in Java that supports the mocking of parametrized constructors?
i just want to avoid connecting to SAP in the constructor.
JMock with the ClassImposteriser can do that, as can most good mocking frameworks.
The ClassImposteriser creates mock
instances without calling the
constructor of the mocked class. So
classes with constructors that have
arguments or call overideable methods
of the object can be safely mocked.
You can simply create the mock class, subclassing the abstract BapiExecutor class, and implementing the behavior you want in execute() (or any other method). You don't need to revert to a framework here.
Could you please elaborate about what the blocking point is ?
I expect that the EidCcBapiExecutor extends from BapiExecutor.
public class EidCcBapiExecutor extends BapiExecutor {
...
}
Than you could create the Mockup class for testing a specific method like:
public class EidCcBapiExecutorMockup extends EidCcBapiExecutor{
public EidCcBapiExecutorMockup (final SapConnectionInfo connectionInfo){
super(connectionInfo);
}
public Object execute() throws Exception {
// You mockup code
}
}
If you want to test the constructor you can create the class like:
public class EidCcBapiExecutorMockup extends EidCcBapiExecutor{
public EidCcBapiExecutorMockup (){
super(new SapConnectionInfo());
}
}
The object you place in the Constructor could be created in the setUp method of you JUnit test!