Tuesday, 21 August 2018

Causes and Solution of NoSuchBeanDefinitionException in Spring.

        In previous post, we discussed the cause and solution of LazyInitializationException  in Hibernate. In the current post, we will see the cause and solution of NoSuchBeanDefinitionException in Spring.

        In Spring there are so many exceptions NoSuchBeanDefinitionException,  NoUniqueBeanDefinitionException, BeanInstantiationException, CannotLoadBeanClassException and so on. But the most important and faced exception is NoSuchBeanDefinitionException.

        This  exception thrown when a BeanFactory is asked for a bean instance for which it cannot find a definition. This may point to a non-existing bean, a non-unique bean, or a manually registered singleton instance without an associated bean definition.

Below are some reasons BeanFactory doesn't find the bean definition.

1) Bean doesn't exist or it was not registered


         In the below example, the Student class is not annotated with @Bean or @Component, so it can not find the bean of Student.

@Configuration
public class Example {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
        ctx.getBean(Student.class);
    }
}

class Student {
  //
}

The Student bean is not registered with annotation or XML configuration, so can not find the Student bean, it will through the error,

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
    No qualifying bean of type [com.adnblog.Student] is defined

There are so many ways to register the bean definitions,

1)  @Bean method in a @Configuration class or <bean> in XML configuration
2)  @Component and its meta-annotations through @ComponentScan or <context:component-scan> tag in  XML file.
and so on.


2) Multiple matching beans


     In some cases we need multiple beans of same type. In XML configuration we are defining two beans of same type e.g Student in the below configuration.

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean
class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
        
  <bean id="school" class="com.test.School" >

  <bean id="student1" class="com.test.Student" >
       <property name="name" value="Mahesh" />
  </bean>

  <bean id="student2" class="com.test.Student" >
       <property name="name" value="Rajesh" />
  </bean>

</beans>

The below code to call the Student bean in the School class as follow,

package com.test;

import org.springframework.beans.factory.annotation.Autowired;

public class School{

     @Autowired
     private Student student;
 
     // other property and setter and getters
}

If you run the above code, will get the exception as,

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
 No unique bean of type [com.test.Student] is defined:
  expected single matching bean but found 2: [student1, student2]

Because Spring doesn't know which bean should autowire.

To avoid this confusion or exception, should use @Qualifier annotation.

package com.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class School{

        @Autowired
        @Qualifier("student1")
        private Student student;
 
        // other property and setter and getters
}

Reference : Spring @Qualifier Annotation with example


3) Using wrong bean name


 Just as there are multiple ways to register beans, there are also multiple ways to name them.

      The name of this bean, or if plural, aliases for this bean. If left unspecified the name of the bean is the name of the annotated method. If specified, the method name is ignored.

    <bean> has the id attribute to represent the unique identifier for a bean and name can be used to create one or more aliases illegal in an (XML) id.


Thank you for visiting blog.


Related Posts:--

Monday, 13 August 2018

Cause and solution of LazyInitializationException in Hibernate

        In previous post, we discussed the difference between the update and merge methods in Hibernate.  In the current post we will discuss Cause and Solution of  LazyInitializationException in Hibernate.

       This exception occurs when the Hibernate Session is closed and object becomes detached.  And if you try to access properties or associated object of Detached object then it results in org.hibernate.LazyInitializationException: could not initialize proxy - no session Exception.

       In other words, we can say Hibernate does not support lazy initialization for detached objects. Access to a lazy association outside of the context of an open Hibernate session will result in an LazyInitializationException.

Here is the example:--

Employee.java,

@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.ALL, FetchType.LAZY) 
     @JoinColumn(name="address_id")
     private Set<Address> address;
       
        // setters and getters
}

         In the above example, Employee and Address entity have the One to Many relationship. The default fetch type of One to Many relationship is LAZY.

Address.java,

@Entity
@Table (name="address")
public class Address {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="address")
     private String address;
       
        // setters and getters
}

The Hibernate class to get the details from entity as follows,

HibernateMain.java,

package com.adnblog;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.adnblog.Employee;

public class HibernateMain {

      public static void main(String[] args) {

            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
            Session session = sessionFactory.openSession();
            Employee emp = session.get(Employee.class, 1); 
            session.close();
            emp.getId();                     // will throw LazyInitializationException                     
            sessionFactory.close();
      }
}

The above code throw the error:--
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session


Solution:--

Use FetchType.EAGER of field address_id in  Employee entity, So that whenever you call the session.get() method, will load all the details from database. Even if you close the session you will get employee details.


Thank you for visiting blog.


Related Post:--
1) Hibernate - JPA Annotations with explanation
2) What are different states of an entity bean in Hibernate?
3) Difference between Update and Merge methods in Hibernate with example
4) What is a Hibernate Caching ? Explain first level and second level cache in Hibernate
5) What is the difference between get() and load() methods in Hibernate?
6) Hibernate JPA Cascade Types
7) Difference between save() and persist() method in Hibernate
8) What is lazy loading in Hibernate? Explain with example

Tuesday, 7 August 2018

Difference between Update and Merge methods in Hibernate with example

               As we discussed in the previous post, hibernate object has different states those are transient, persistent and detached.

             Both the update() and merge() methods are used to change the state of an object. That means we can call either update() or merge() to transfer an object from detached state to persistent state.
           
             We can  make the detached object to persist by reattching to a session.  If the previous session is already been closed, it is also possible to create a new session and attach to that session. To reattach  to a session, we can use update() or merge() methods. Both are doing the same functionality, but there are few differences internally.

merge and update in hibernate
Merge and Update methods in hibernate

  • update() method:--   

         When we call update() method on session, if that session doesn’t contains same object (provided in update())  in cache then update() method successfully executed and the object been converted from detached state to persistent state.

         When we call update() method on any object, it internally checks, if that object is already existed in session cache or not — if currently updating object is already there in session cache then it throws an exception called NonUniqueObjectException and can not update the object.

Example:--

Take an example of Employee object, has property id, name and age. This example is the empty cache i.e no data exists in a session cache.

UpdateMethodExample.java,

package com.adnblog;
import com.adnblog.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class UpdateMethodExample {
    
     public static void main(String[] args) {
        
           Configuration configuration = new Configuration();
           configuration.configure("hibernate.cfg.xml");
           SessionFactory factory = configuration.buildSessionFactory();
           Session session = factory.openSession();
           Employee employee = (Employee) session.get(Employee.class, 121);
           session.close();

             // Employeee object is in detached state
           employee.setName("Kiran");
        
             // reattaching to session
           Session session2 = factory.openSession();
           Transaction tx = session2.beginTransaction();
           session2.update(employee);
           tx.commit();
     }
}

Output:--

Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_, 
employee0_.age as age3_0_0_ from Employee employee0_ where employee0_.id=?

Hibernate: update employee set name=?, age=?, Where id=?

Example of already existed object in Session cache :--


       If already existed the same object in the Session cache, then update() method will throw NoUniqueObjectException, example shown in the below.

        Session session = factory.openSession();
        Employee employee = (Employee) session.get(Employee.class, 121);
        session.close();

        // Employeee object is in detached state
        employee.setName("Kiran");
        // reattaching to session
        Session session2 = factory.openSession();
        Transaction tx = session2.beginTransaction();
        session2.update(employee);
        tx.commit();

Output:--

Exception in thread "main" org.hibernate.NonUniqueObjectException: A different object 
with the same identifier value was already associated with the session : 
[com.adnblog.Employee#121]


  • merge() method :--


        The merge() method functionality is same as update() method. It can work both empty cache and existed cache, it doesn't throw any exception if same object is existed in the cache. The update() method will throw NonUniqueObjectException if same object exists in the session cache, already  discussed in the above example.

      The merge() method copies the current changes into the cache if object is already exists in the session cache.

Example:--

MergeMethodExample.java,

package com.adnblog;
import com.adnblog.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class MergeMethodExample {
    
     public static void main(String[] args) {
        
           Configuration configuration = new Configuration();
           configuration.configure("hibernate.cfg.xml");
           SessionFactory factory = configuration.buildSessionFactory();
           Session session = factory.openSession();
           Employee employee = (Employee) session.get(Employee.class, 121);
           session.close();
        
           // Employee object is in detached state
           employee.setName("Kiran");
           
           // reattaching to session 
           Session session2 = factory.openSession();
           Employee employee2 = session2.get(Employee.class, 121);
           Transaction tx = session2.beginTransaction();
           session2.merge(employee);
           tx.commit();
     }
}

Output:--
                It will update the employee details without exception.


Thank you for visiting blog.


Related Post:--
1) What are different states of an entity bean in Hibernate?
2) What is a Hibernate Caching ? Explain first level and second level cache in Hibernate
3) What is lazy loading in Hibernate? Explain with example
4) Hibernate JPA Cascade Types
5) Difference between save() and persist() method in Hibernate
6) What is the difference between get() and load() methods in Hibernate?
7) Hibernate Query Language(HQL) Examples
8) Hibernate Criteria Queries and Examples
9) Hibernate One to One Mapping Example - Annotation based