In my previous articles Why Should We Follow Method Overloading Rules, I discussed about method overloading and rules we need to follow to overload a method. I have also discussed why we need to follow these rules and why some method overloading rules are necessary and others are optional.

In a similar manner in this article, we will see what rules we need to follow to override a method and why we should follow these rules.

Method Overriding and its Rules

As discussed in Everything About Method Overloading Vs Method Overriding, every child class inherits all the inheritable behaviour from its parent class but the child class can also define its own new behaviours or override some of the inherited behaviour.

Overriding means redefining a behaviour (method) again in the child class which was already defined by its parent class but to do so overriding method in the child class must follow certain rules and guidelines.

With respect to the method it overrides, the overriding method must follow following rules.
Why We Should Follow Method Overriding Rules

To understand these reasons properly let's consider below example where we have a class Mammal which defines readAndGet method which is reading some file and returning an instance of class Mammal.

Class Human extends class Mammal and overrides readAndGet method to return instance of Human instead of instance of Mammal.

class Mammal {
    public Mammal readAndGet() throws IOException {//read file and return Mammal`s object}
}

class Human extends Mammal {
    @Override
    public Human readAndGet() throws FileNotFoundException {//read file and return Human object}
}

And we know in case of method overriding we can make polymorphic calls. Which means if we assign a child instance to a parent reference and call an overridden method on that reference eventually the method from child class will get called.

Let's do that

Mammal mammal = new Human();
try {
    Mammal obj = mammal.readAndGet();
} catch (IOException ex) {..}

As discussed in  How Does JVM Handle Method Overloading and Overriding Internally till compilation phase compiler thinks the method is getting called from the parent class. While bytecode generation phase compiler generates a constant pool where it maps every method string literal and class reference to a memory reference

During runtime, JVM creates a vtable or virtual table to identify which method is getting called exactly. JVM creates a vtable for every class and it is common for all the objects of that class. Mammal row in a vtable contains method name and memory reference of that method.

First JVM creates a vtable for the parent class and then copy that parent's vtable to child class's vtable and update just the memory reference for the overloaded method while keeping the same method name.

You can read it more clearly on  How Does JVM Handle Method Overloading and Overriding Internally if it seems hard.
So as of now we are clear that
  • For compiler mammal.readAndGet() means method is getting called from instance of class Mammal
  • For JVM mammal.readAndGet() is getting called from a memory address which vtable is holding for Mammal.readAndGet() which is pointing to a method call from class Human.

Why overriding method must have same name and same argument list

Well conceptually mammal is pointing to an object of class Human and we are calling readAndGet method on mammal, so to get this call resolved at runtime Human should also have a method readAndGet. And if Human have inherited that method from Mammal then there is no problem but if Human is overriding readAndGet, it should provide the same method signature as provided by Mammal because method has been already got called according to that method signature.

But you may be asking how it is handled physically from vtables so I must tell you that, JVM creates a vtable for every class and when it encounters an overriding method it keeps the same method name (Mammal.readAndGet()) while just update the memory address for that method. So both overridden and overriding method must have same method and argument list.

Why overriding method must have same or covariant return type

So we know, for compiler the method is getting called from class Mammal and for JVM call is from the instance of class Human but in both cases, readAndGet method call must return an object which can be assigned to obj. And since obj is of the type Mammal it can either hold an instance of Mammal class or an instance of a child class of Mammal (child of Mammal are covariant to Mammal).

Now suppose if readAndGet method in Human class is returning something else so during compile time mammal.readAndGet() will not create any problem but at runtime, this will cause a ClassCastException because at runtime mammal.readAndGet() will get resolved to new Human().readAndGet() and this call will not return an object of type Mammal.

And this why having a different return type is not allowed by the compiler in the first place.

Why overriding method must not have a more restrictive access modifier

The same logic is applicable here as well, call to readAndGet method will be resolved at runtime and as we can see readAndGet is public in class Mammal, now suppose
  • If we define readAndGet as default or protected in Human but Human is defined in another package
  • If we define readAndGet as private in Human
In both cases code will compile successfully because for compiler readAndGet is getting called from class Mammal but in both cases, JVM will not be able to access readAndGet from Human because it will be restricted.

So to avoid this uncertainty, assigning restrictive access to the overriding method in the child class is not allowed at all.

Why overriding method may have less restrictive access modifier

If readAndGet method is accessible from Mammal and we are able to execute mammal.readAndGet() which means this method is accessible. And we make readAndGet less restrictive Human which means it will be more open to get called.

So making the overriding method less restrictive cannot create any problem in the future and that's it is allowed.

Why overriding method must not throw new or broader checked exceptions

Because IOException is a checked exception compiler will force us to catch it whenever we call readAndGet on mammal

Now suppose readAndGet in Human is throwing any other checked exception e.g. Exception and we know readAndGet will get called from the instance of Human because mammal is holding new Human().

Because for compiler the method is getting called from Mammal, so the compiler will force us to handle only IOException but at runtime we know method will be throwing Exception which is not getting handled and our code will break if the method throws an exception.

That's why it is prevented at the compiler level itself and we are not allowed to throw any new or broader checked exception because it will not be handled by JVM at the end.

Why overriding method may throw narrower checked exceptions or any unchecked exception

But if readAndGet in Human throws any sub-exception of IOException e.g., FileNotFoundException, it will be handled because catch (IOException ex) can handle all child of IOException.

And we know unchecked exception (subclasses of RuntimeException) are called unchecked because we don't need to handle them necessarily.

And that's why overriding methods are allowed to throw narrower checked and other unchecked exceptions.

To force our code to adhere method overriding rules we should always use @Override annotation on our overriding methods, @Override annotation force compiler to check if the method is a valid override or not.

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
In my previous articles, Everything About Method Overloading Vs Method Overriding and How Does JVM Handle Method Overloading and Overriding Internally, I have discussed what is method overloading and overriding, how both are different than each other, How JVM handles them internally and what rules we should follow in order to implement these concepts.

In order to overload or override a method we need to follow certain rules, some of them are mandatory while others are optional and to become a good programmer we should always try to understand the reason behind these rules.

I am going to write two articles where I will try to look into the method overloading and overriding rules and try to figure out why we need to follow them.

In this article, we will see what rules we should follow to overload a method and we will also try to know why we should follow these rules.

Method Overloading

In general, method overloading means reusing same method name to define more than one method but all methods must have a different argument list.

We can take the example of the print method present in PrintStream class which gets called when we call System.out.print() to print something. By calling this method on several data types it seems like there is just one print method which is accepting all types and printing their values.

But actually, there are 9 different print methods as shown in below image

method-overloading

Well, the PrintStream class creator could have created methods like printBoolean or printInt or printFloat, but the idea behind naming all the 9 methods same is to let the user think that there is only one method which is printing whatever we pass to it.

Which sounds like polymorphism but as discussed in the article How Does JVM Handle Method Overloading and Overriding Internally that how method overloading get resolved at compile time, some people also term method overloading as compile-time polymorphism.

Method Overloading Rules

While defining a method we need to provide it with a proper method signature which includes access specifier, return type, method name, argument list, exceptions method might throw. Based on these five things method overloading has some mandatory rules and some optional rules, which we are going to see below.

Mandatory Rules

  • Overloaded methods must have same method name: Having the same name let us reuse the same method name for different purposes and let the user believe that there is only one method which is accepting different kinds of input and doing the work according to the input.
  • Overloaded methods must have different argument lists: Since all overloaded methods must have the same name, having a different argument list becomes necessary because it is the only way to differentiate the methods from each other. Java compiler differentiates a method from other based on its method name and argument list, So different argument list helps the compiler to differentiate and recognize methods from each other so the compiler will know which method is getting called at compile time only.

Optional Rules

The compiler knows that at the time of method calling JVM needs to know the method name and JVM will pass some arguments to that method so it must also know the argument list. While other method signature elements e.g. return type, access modifier, the exception method throwing also matter but at the time of method call they become optional.

So the different argument list is sufficient for the compiler to differentiate between the methods even if they have the same name so the rules mentioned below are optional and we are free to follow or not follow them. Going with below rules totally depends on your requirements and they are there to just provide us with additional functionality.
  • Overloaded methods can have different return types: Return type matters when the method call is finished and JVM assigning back the value returned by that method call to some variable. But it is not required while calling the method and JVM cannot use it to differentiate between methods based on just return type. So we can either return the same as the overloaded method did or return something different or return nothing.
  • Overloaded methods can have different access modifiers: If a method is getting called by the JVM it means it has passed the compilation phase because executing the bytecode which is already compiled. So access specifier of a method is useful for the compiler but it is useless for JVM and JVM cannot differentiate between methods based on access modifier. So an overloading method can have any access modifier and we can use it according to our need.
  • Overloaded methods can throw different checked or unchecked exceptions: Again what exceptions a method might throw cannot differentiate a method from another method. And also overloaded methods are different from each other but usually, they perform the same operation on different data set and in order to do so overloaded methods may do some different operation as well which may throw a different exception.
You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
In a previous article Everything About ClassNotFoundException Vs NoClassDefFoundError, I have explained ClassNotFoundException and NoClassDefFoundError in details and also discussed their differences and how to avoid them. If you have not read it, please go ahead and give it a look.

Similar to that here in this article, we will look into one more core concept of Java which is method overloading and overriding. As soon as we start learning Java we get introduced to them and their contracts which are pretty simple to understand but sometimes programmers get confused between them or they do not know either it is a correct overload/override because of the different rules.

Here we will discuss What is method overloading and overriding, What contract one must follow to correctly overload or override a method, What are the different rules of method overloading and overriding and what are the differences between them.

Method Overloading

Method overloading means providing two separate methods in a class with the same name but different arguments while method return type may or may not be different which allows us to reuse the same method name.

And this becomes very handy for the consumer of our class, he can pass different types of parameters to the same method (in his eyes but actually they are different) and get the response according to his input e.g. System.out.println() method accepts all types of objects primitive types and print them but in reality there several println present in the PrintStream class.

public class PrintStream {

    // other methods

    public void println() { /*code*/ }
    public void println(boolean x) { /*code*/ }
    public void println(char x) { /*code*/ }
    public void println(int x) { /*code*/ }
    public void println(long x) { /*code*/ }
    public void println(float x) { /*code*/ }
    public void println(double x) { /*code*/ }
    public void println(char x[]) { /*code*/ }
    public void println(String x) { /*code*/ }
    public void println(Object x) { /*code*/ }
    
    // other methods
}

While overloading has nothing to deal with polymorphism but Java programmers also refer method overloading as Compile Time Polymorphism because which method is going to get called will be decided at compile time only.

In the case of method overloading compiler decides which method is going to get called based on the reference on which it is getting called and the method name, return type, and argument list.

class Human {
    public String speak() { return "Hello"; }

    // Valid overload of speak
    public String speak(String language) {
        if (language.equals("Hindi")) return "Namaste";
        else return "Hello";
    }

    public long calculate(int a, long b) { return a + b; }

    // However nobody should do it but Valid overload of calculate
    // by just changing sequence of arguments
    public long calculate(long b, int a) { return a + b; }
}

Method Overloading Rules

There are some rules which we need to follow to overload a method and some of them are mandatory while some are optional.

Two methods will be treated as Overloaded if both follow below mandatory rule.
  • Both must have same method name
  • Both must have different argument lists
And if both methods follow above mandatory rules then they may or may not
  • Have different return types
  • Have different access modifiers
  • Throw different checked or unchecked exceptions
Usually, method overloading happens inside a single class but a method can also be treated as overloaded in the subclass of that class because subclass inherits one version of the method from the parent class and then can have another overloaded version in its class definition.

Method Overriding

Method Overriding means defining a method in the child class which is already defined in the parent class with same method signature i.e same name, arguments and return type (after Java 5 you can also use a covariant type as return type).

Whenever we extend a superclass in a child class, child class automatically gets all the methods defined in the super and we call them derived methods. But in some cases we do not want some derived methods to work in a manner which they are doing in the parent then we can override those methods in child class e.g. we always override equals, hashCode and toString from Object class, you can read more on Why can't we override clone() method from Object class.

In case of abstract methods either from a parent abstract class or interface we do not have any option we need to implement or in other words override all the abstract methods.

Method overriding is also known as Runtime Polymorphism and Dynamic Method Dispatch because which method is going to get called is decided at runtime by JVM.

abstract class Mammal {
    // Well might speak something
    public String speak() { return "ohlllalalalalalaoaoaoa"; }
}

class Cat extends Mammal {
    @Override
    public String speak() { return "Meow"; }
}

class Human extends Mammal {
    @Override
    public String speak() { return "Hello"; }
}

Using @Override annotation on the overridden methods is not necessary but using it will tell you if you are not obeying overriding rules. 

Mammal mammal = new Cat();
System.out.println(mammal.speak()); // Will print Meow

At the line mammal.speak() compiler says the speak() method of reference type Mammal is getting called, so for compiler this call is Mammal.speak().

But at the execution time JVM knows clearly that mammal reference is holding the reference of object of Cat, so for JVM this call is Cat.speak(). You can read more on How Does JVM Handle Method Overloading and Overriding Internally.

Method Overriding Rules

Similar to method overloading we also have some mandatory and some optional rules which we need to follow to override a method.

With respect to the method it overrides, the overriding method must follow below mandatory rule.
  • It must have same method name
  • Must have same arguments.
  • Must have the same return type, from Java 5 the return type can also be a subclass (Subclass is a covariant type to its parent).
  • Must not have a more restrictive access modifier (if parent --> protected then child --> private is not allowed).
  • Must not throw new or broader checked exceptions.
And if both overriding methods follow above mandatory rules then it
  • May have a less restrictive access modifier (if parent --> protected then child --> public is allowed).
  • May throw fewer or narrower checked exceptions or any unchecked exception.
Apart from above rules, there are also some facts
  • Only inherited methods can be overridden, Means methods can be overridden in child class only.
  • Constructors and private methods are not inherited so cannot be overridden.
  • Abstract methods must be overridden by the first concrete (non-abstract) subclass.
  • final methods cannot be overridden.
  • A subclass can use super.overridden_method() to call the superclass version of an overridden method.

Difference Between Method Overloading and Method Overriding


difference-between-method-overloading-and-method-overriding

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
In my previous article Everything About Method Overloading Vs Method Overriding, I have discussed method overloading and overriding, their rules and differences.

In this article, we will see How Does JVM Handle Method Overloading And Overriding Internally, how JVM identifies which method should get called.

Let’s take the example of a parent class Mammal and a child Human classes from our previous blog to understand it more clearly.

public class OverridingInternalExample {

    private static class Mammal {
        public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
    }

    private static class Human extends Mammal {

        @Override
        public void speak() { System.out.println("Hello"); }

        // Valid overload of speak
        public void speak(String language) {
            if (language.equals("Hindi")) System.out.println("Namaste");
            else System.out.println("Hello");
        }

        @Override
        public String toString() { return "Human Class"; }

    }

    //  Code below contains the output and and bytecode of the method calls
    public static void main(String[] args) {
        Mammal anyMammal = new Mammal();
        anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
        // 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

        Mammal humanMammal = new Human();
        humanMammal.speak(); // Output - Hello
        // 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

        Human human = new Human();
        human.speak(); // Output - Hello
        // 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

        human.speak("Hindi"); // Output - Namaste
        // 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
    }
}

We can answer this answer in two ways, Logical way and Physical way, let's take a look at the logical way.

Logical Way

Logically we can say, during compilation phase calling method is considered from the reference type. But at execution time method will be called from the object which the reference is holding.

For Example on humanMammal.speak(); line compiler will say Mammal.speak() is getting called because humanMammal is of type Mammal . But during execution, JVM knows that humanMammal is holding a Human's object so Human.speak() will get called.

Well, it is pretty simple until we keep it at the conceptual level only. Once we get the doubt that how JVM is handling all this internally? or how JVM is calculating which method it should call.

Also, we know that overloaded methods are not called polymorphic and get resolved at compile time and this is why sometimes method overloading is also known as compile time polymorphism or early/static binding.

But overridden methods get resolved at runtime time because the compiler does not know that, the object which we are assigning to our reference have overridden the method or not.

Physical Way

In this section, we will try to find out physical proof of all aforementioned statements and to find them we will read the bytecode of our program which we can do by executing javap -verbose OverridingInternalExample. By using -verbose option we will get the descriptive bytecode same as our Java program.

Above command shows the bytecode in two sections

1. Constant Pool: holds almost everything which is necessary for our program’s execution e.g. method references (#Methodref), Class objects ( #Class ), string literals ( #String ), please click one image to zoom.

java-method-area-or-constant-pool-or-method-table


2. Program’s Bytecode: executable bytecode instructions, please click one image to zoom.

method-overloading-overriding-internals-byte-code

Why Method overloading is called static binding

In the above mention code humanMammal.speak() compiler will say speak() is getting called from Mammal but at execution time it will be called from the object which humanMammal is holding, which is the object of the Human class.

And by looking at the above code and images we can see that the bytecodes of humanMammal.speak() , human.speak() and human.speak("Hindi") are totally different because the compiler is able to differentiate between them based on the class reference.

So in the case of method overloading compiler is able to identify the bytecode instructions and method’s address at compile time and that is why it is also known as static binding or compile time polymorphism.

Why Method overriding is called dynamic binding

Bytecode for anyMammal.speak() and humanMammal.speak() are same ( invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V ) because according to compiler both methods are called on Mammal reference.

So now the question comes if both method calls have same bytecode then how does JVM know which method to call?

Well, the answer is hidden in the bytecode itself and it is invokevirtual instruction, according to JVM specification

invokevirtual invokes an instance method of an object, dispatching on the (virtual) type of the object. This is the normal method dispatch in the Java programming language.

JVM uses the invokevirtual instruction to invoke Java equivalent of the C++ virtual methods. In C++ if we want to override one method in another class we need to declare it as virtual, But in Java, all methods are virtual by default (except final and static methods) because we can override every method in the child class.

Operation invokevirtual accepts a pointer to method reference call ( #4 an index into the constant pool)

invokevirtual #4   // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

And that method reference #4 again refers to a method name and Class reference

#4 = Methodref   #2.#27   // org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
#2 = Class   #25   // org/programming/mitra/exercises/OverridingInternalExample$Mammal
#25 = Utf8   org/programming/mitra/exercises/OverridingInternalExample$Mammal
#27 = NameAndType   #35:#17   // speak:()V
#35 = Utf8   speak
#17 = Utf8   ()V

All these references combinedly used to get a reference to a method and class in which the method is to be found. This is also mentioned in JVM Specification

The Java virtual machine does not mandate any particular internal structure for objects 4.

And the bookmark 4 states

In some of Oracle’s implementations of the Java virtual machine, a reference to a class instance is a pointer to a handle that is itself a pair of pointers: one to a table containing the methods of the object and a pointer to the Class object that represents the type of the object, and the other to the memory allocated from the heap for the object data.

It means every reference variable holds two hidden pointers
  1. A pointer to a table which again holds methods of the object and a pointer to the Class object. e.g. [speak(), speak(String) Class object]
  2. A pointer to the memory allocated on the heap for that object’s data e.g. values of instance variables.
But again the question comes, how invokevirtual internally do this? Well, no one can answer this because it depends on JVM implementation and it varies from JVM to JVM.

And from the above statements, we can conclude that an object reference indirectly holds a reference/pointer to a table which holds all the method references of that object. Java has borrowed this concept from C++ and this table is known by various names which such as virtual method table ( VMT ), virtual function table (vftable), virtual table (vtable), dispatch table.

We can not sure of how vtable is implemented in Java because it is JVM dependent. But we can expect that it will be following the same strategy as C++ where vtable is an array like structure which holds method names and their references on array indices. And whenever JVM tries to execute a virtual method it always asks the vtable for it address.

There is only one vtable per class, which means it is unique and same for all objects of a class similar to Class object. I have discussed more on Class object in my articles Why an outer Java class can’t be static and Why Java is Purely Object-Oriented Language Or Why Not.

So there is only one vtable for Object class which contains all 11 methods (if we don't count registerNatives) and references to their respective method bodies.

vtable-of-object

When JVM loads the Mammal class into memory it creates a Class object for it and creates a vtable which contains all the methods from the vtable of Object class with the same references (Because Mammal is not overriding any method from Object) and adds a new entry for speak method.

vtable-human


Now here comes the turn of Human class and now JVM will copy all entries from the vtable of Mammal class to the vtable of Human and adds a new entry for the overloaded version of speak(String).

JVM knows that Human class has overridden two methods one is toString() from Object and second is speck() from Mammal . Now instead of creating new entries for these methods with updated references. JVM will modify the references to the already present methods on the same index where they were present earlier and will keep the same method names.




The invokevirtual causes the JVM to treat the value at method reference #4 , not as an address but as the name of a method to look up in the vtable for the current object.

I hope now it would have become a little bit clear that how the JVM mixes constant pool entries and vtable to conclude which method it is going to call.

You can find the complete code on this Github Repository and please feel free to provide your valuable feedback.
We know Java is an Object Oriented Programming Language and almost everything is an object in Java and in order to create an object we need a class.

While executing our program whenever JVM find a class, First JVM will try to load that class into memory if it has not done it already.

For Example, If JVM is executing below the line of code, before creating the object of Employee class JVM will load this class into memory using a ClassLoader.

Employee emp = new Employee();

In above example, JVM will load the Employee class because it is present in the execution path and JVM want to create an object of this class.

But we can also ask JVM to just load a class through its string name using Class.forName() or ClassLoader.findSystemClass() or ClassLoader.loadClass() methods. For Example below the line of code will only load the Employee class into memory and do nothing else.

Class.forName("Employee");

Both ClassNotFoundException and NoClassDefFoundError occur when a particular class is not found at run time but under different scenarios. And here in this article, we going to study these different scenarios.

ClassNotFoundException

Is a checked exception that occurs when we tell JVM to load a class by its string name using Class.forName() or ClassLoader.findSystemClass() or ClassLoader.loadClass() methods and mentioned class is not found in the classpath.

Most of the time, this exception occurs when you try to run an application without updating the classpath with required JAR files. For Example, You may have seen this exception when doing the JDBC code to connect to your database i.e.MySQL but your classpath does not have JAR for it.

If we compile below example, the compiler will produce two class files Test.class and Person.class. And Now if we execute the program it will successfully print Hello. But if we delete Person.class file and again try to execute the program we will receive ClassNotFoundException.

public class Test {
    public static void main(String[] args) throws Exception {

        // ClassNotFoundException Example
        // Provide any class name to Class.forName() which does not exist
        // Or compile Test.java and then manually delete Person.class file so Person class will become unavailable
        // Run the program using java Test

        Class clazz = Class.forName("Person");
        Person person = (Person) clazz.newInstance();
        person.saySomething();
    }
}

class Person {
    void saySomething() {
        System.out.println("Hello");
    }
}

NoClassDefFoundError

Is a subtype of java.lang.Error and Error class indicates an abnormal behavior which really should not happen with an application but and application developers should not try to catch it, it is there for JVM use only.

NoClassDefFoundError occurs when JVM tries to load a particular class that is the part of your code execution (as part of a normal method call or as part of creating an instance using the new keyword) and that class is not present in your classpath but was present at compile time because in order to execute your program you need to compile it and if you are trying use a class which is not present compiler will raise compilation error.

Similar to above example if we try to compile below program, we will get two class files Test.class and Employee.class. A and on execution it will print Hello.

public class Test {
    public static void main(String[] args) throws Exception {

        // NoClassDefFoundError Example
        // Do javac on Test.java, 
        // Program will compile successfully because Empoyee class exits
        // Manually delete Employee.class file
        // Run the program using java Test
        Employee emp = new Employee();
        emp.saySomething();

    }
}

class Employee {
    void saySomething() {
        System.out.println("Hello");
    }
}

But if we delete Employee.class and try to execute the program we will get NoClassDefFoundError.

Exception in thread "main" java.lang.NoClassDefFoundError: Employee
 at Test.main(Test.java:9)
Caused by: java.lang.ClassNotFoundException: Employee
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
 ... 1 more

As you can see in above stack trace NoClassDefFoundError is caused by ClassNotFoundException, because JVM is not able to find the Employee class in the class path.

Conclusion

Difference-Between-ClassNotFoundException-and-NoClassDefFoundError

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
In my previous article JPA Auditing: Persisting Audit Logs Automatically using EntityListeners, I have discussed how we can use Spring Data JPA automate Auditing and automatically create audit logs or history records and update CreatedBy, CreatedDate, LastModifiedBy, LastModifiedDate properties.

So in order to save history records for our File entity, we were trying to auto-wire EntityManager inside our FileEntityListener class and we have come to know that we can not do this.

We can not inject any Spring-managed bean in the EntityListener because EntityListeners are instantiated by JPA before Spring inject anything into it. EntityListeners are not managed Spring so Spring cannot inject any Spring-managed bean e.g. EntityManager in the EntityListeners.

And this case is not just with EntityListeners, you can not auto wire any Spring-managed bean into another class (i.e. utility classes) which is not managed by Spring.

Because it is a very common problem and can also arise with other classes so I tried to come out with a common solution which will not just solve this problem but will also help us getting Spring managed beans in other places.

AutoWiring-Spring-Beans-Into-Classes-Not-Managed-By-Spring-Like-JPA-Entity-Listeners

So I have created one utility class to fetch any bean according to our requirement.

@Service
public class BeanUtil implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

}

Now to get any a bean in class we will just need call the BeanUtil.getBean(YourClass.class) and pass the class type to it and we will get the bean.

For Example in our case, we were trying to get the EntityManager bean inside FileEntityListener, we can simply do it by writing BeanUtil.getBean(EntityManager.class).

public class FileEntityListener {

    private void perform(File target, Action action) {
        EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
        entityManager.persist(new FileHistory(target, action));
    }

}

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
Next Post Newer Posts Previous Post Older Posts Home