Tuesday, 21 August 2018

Causes and Solutions for NoSuchBeanDefinitionException in Spring

         In the previous post, we discussed the causes and solutions for LazyInitializationException in Hibernate. In this post, we will discuss the causes and solutions for NoSuchBeanDefinitionException in Spring.

Spring provides several exceptions related to bean creation and dependency injection, such as NoSuchBeanDefinitionException, NoUniqueBeanDefinitionException, BeanInstantiationException, and CannotLoadBeanClassException. Among these, NoSuchBeanDefinitionException is one of the most common exceptions encountered by Spring developers.

The NoSuchBeanDefinitionException is thrown when the BeanFactory is asked to provide a bean instance, but it cannot find a corresponding bean definition. This may occur because the requested bean does not exist, multiple beans match the requested type, or a singleton instance has been registered manually without an associated bean definition.

Below are some common reasons why the BeanFactory cannot find a 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 several ways to register bean definitions in Spring. Some of the most common approaches are:

  1. Using the @Bean annotation in a @Configuration class or the <bean> element in an XML configuration file.

  2. Using the @Component annotation and its specialized stereotype annotations (@Service, @Repository, and @Controller) along with @ComponentScan, or the <context:component-scan> element in an XML configuration file.



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 in Spring, there are also multiple ways to assign names to them.

When using the @Bean annotation, you can specify the bean name using its name or value attribute. If no name is specified, the name of the annotated method is used as the bean name by default. If a name is explicitly provided, the method name is ignored.

When using XML configuration, the <bean> element provides the id and name attributes for naming a bean. The id attribute specifies the unique identifier for the bean, while the name attribute can be used to define one or more aliases for the same bean.


Thank you for visiting blog.


Related Posts:--

Monday, 13 August 2018

Causes and Solutions for LazyInitializationException in Hibernate

        In the previous post, we discussed the differences between the update() and merge() methods in Hibernate. In this post, we will discuss the causes of LazyInitializationException in Hibernate and explore the different approaches to resolve it.

       A LazyInitializationException occurs when the Hibernate Session has been closed and the entity becomes detached. If you then attempt to access a lazily loaded property or associated object of the detached entity, Hibernate throws the following exception:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

In other words, Hibernate does not support lazy initialization for detached entities. Accessing a lazily loaded association outside the context of an active Hibernate Session results in a LazyInitializationException because Hibernate can no longer retrieve the required data from the database.

The following example demonstrates this scenario:


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 for the address association (mapped by the address_id foreign key) in the Employee entity. With FetchType.EAGER, Hibernate loads the associated Address entity along with the Employee entity when session.get() is called. As a result, even after the Hibernate Session is closed, you can access the Address details without encountering a LazyInitializationException.

Thank you for visiting the 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 Examples

                As we discussed in the previous post, a Hibernate object can exist in different states: transient, persistent, and detached.

Both the update() and merge() methods are used to reattach a detached object to a Hibernate session. In other words, they transition an object from the detached state to the persistent state.

A detached object can be made persistent again by reattaching it to a session. If the previous session has already been closed, you can create a new session and reattach the object to it. Hibernate provides the update() and merge() methods for this purpose.

Although both methods are used to reattach detached objects, they differ in how they work internally. We will discuss these differences in the following sections.


merge and update in hibernate
Merge and Update methods in hibernate


  • update() method:--   

         When we call the update() method on a Hibernate Session, it first checks whether an entity with the same identifier already exists in the session cache.

If the session does not contain an entity with the same identifier, the update() method executes successfully, and the detached object is reattached to the session, transitioning from the detached state to the persistent state.

However, if the session already contains an entity with the same identifier, the update() method throws a NonUniqueObjectException and the update operation fails.


Example:--

Consider an Employee object with the properties id, name, and age. In this example, the session cache is empty, meaning it does not contain any Employee objects.

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 an object with the same identifier already exists in the session cache, the update() method throws a NonUniqueObjectException, as shown in the example 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 provides functionality similar to the update() method. However, unlike update(), it works whether the session cache is empty or already contains an instance of the same entity. It does not throw a NonUniqueObjectException if an object with the same identifier already exists in the session cache. As discussed in the previous example, the update() method throws a NonUniqueObjectException in such cases.

If an object with the same identifier already exists in the session cache, the merge() method copies the state of the detached object into the persistent object managed by the current session.

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