Search code examples
javaspringmavenaopapplicationcontext

class cast exception while initializing bean using ApplicationContext


I need your help in solving an issue concerning spring bean initialization. below is the details of the issue:

dao interface

  package com.dao;

  import com.entity.Employee;

  public interface IEmployeeDao {

       Employee create(final Employee aEmployee);
       Employee fetchEmployeeById(final Integer aEmployeeId);
  }

The dao impl class

  package com.dao.impl;

  import javax.persistence.EntityManager;

  import com.dao.IEmployeeDao;
  import com.entity.Employee;

  public class EmployeeDao implements IEmployeeDao {

      private EntityManager em;

      @Override
      public Employee create(Employee aEmployee) {
           return this.em.merge(aEmployee);
      }

      @Override
      public Employee fetchEmployeeById(Integer aEmployeeId) {
         return this.em.find(Employee.class, aEmployeeId);
      }
  }

the main class :

  package com.client;

  import java.sql.SQLException;

  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;

  import com.dao.impl.EmployeeDao;

  public class Client {
       private static final Logger LOGGER = LogManager.getLogger(Client.class);

       public static void main(String[] args) throws ClassNotFoundException, 
          SQLException {
       ApplicationContext applicationContext = new 
       ClassPathXmlApplicationContext(new String[] {"applicationcontext.xml"});
       LOGGER.info("client invoked");
       EmployeeDao employeeDao =  
         (EmployeeDao)applicationContext.getBean("employeeDao");    
       //....some code below
     }
   }

the last line in the code where I am trying to get employeeDao bean is throwing the below exception :

  Exception in thread "main" java.lang.ClassCastException: 
  com.sun.proxy.$Proxy17 cannot be cast to 
  com.dao.impl.EmployeeDao
  at com.client.Client.main(Client.java:26)

as suggested in some of the answers I browsed, I changed the above line to cast to an interface instead of its implementation class

    IEmployeeDao employeeDao =  
         (IEmployeeDao)applicationContext.getBean("employeeDao");

the bean is getting injected without any exception, but now the actual implementation methods are not being invoked i.e now when I call the create method of EmployeedDao like below

  employeeDao.create(new Employee());

the create methods implementation is not getting called i.e the below method:

  @Override
  public Employee create(Employee aEmployee) {
       System.out.println("com.dao.impl.EmployeeDao.create(Employee) callled")
       return this.em.merge(aEmployee);
  }

I confirmed it by placing a sysout message.

Please suggest me what I am doing wrong or what can be done to get away with this issue. I have also posted the bean configuration files and maven depedencies below.

applicationcontext.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">
    <import resource="aspects.xml"/>
    <bean id="employeeDao" class="com.dao.impl.EmployeeDao" />

    </beans>

aspects.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

         <bean id="logAspect" 
               class="com.logging.LoggingAspect" />

         <aop:config>

            <aop:aspect id="aspectLoggging" ref="logAspect">
            <aop:pointcut id="pointCutAround"
                 expression="execution(* 
         com.dao.IEmployeeDao.*(..))" />

         aop:around method="logAround" pointcut-ref="pointCutAround" />

     </aop:aspect>
     </aop:config>
     </beans>

maven dependencies :

  <dependencies>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>2.5.5</version>
     </dependency>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>2.5.5</version>
     </dependency>
     <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.7.3</version>
     </dependency>
     <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.7.3</version>
     </dependency>      
     <dependency>
        <groupId>org.apache.derby</groupId>
        <artifactId>derby</artifactId>
        <version>10.13.1.1</version>
     </dependency>  
     <dependency>
       <groupId>org.hibernate</groupId>
       <artifactId>hibernate-entitymanager</artifactId>
       <version>3.6.0.Final</version>
     </dependency>
     <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.8.2</version>
     </dependency>
   </dependencies>

EDIT :

LoggingAspect class:

  package com.logging;

  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.aspectj.lang.JoinPoint;

  public class LoggingAspect {
       private static final Logger LOGGER = 
          LogManager.getLogger(LoggingAspect.class);
       public void logAround(JoinPoint aJoinPoint) {
               LOGGER.info("aspects logging enabled");
       }
 }

Solution

  • Yes there is a problem with your Aspect. It is not actually invoking the instrumented code. Try this:

    public void logAround(ProceedingJoinPoint aJoinPoint) { // <<-- don't forget to change the type to ProceedingJoinPoint
      LOGGER.info("aspects logging enabled");
      aJoinPoint.proceed(); // this will continue to the instrumented code
    }