org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start spring spring

org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start


I would like to write a detailed answer on the issue and the steps I have followed to solve the problem.

A. There was not enough logging info. I looked up the POM and found this,

<dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>${spring.version}</version>            <exclusions>                <!-- Exclude Commons Logging in favor of SLF4j -->                <exclusion>                    <groupId>commons-logging</groupId>                    <artifactId>commons-logging</artifactId>                </exclusion>            </exclusions>        </dependency>

I have excluded the logging in the favour of SLF4J and I just deleted the exclusion XML tag to get more logging info. So, it becomes like this,

        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>${spring.version}</version>        </dependency>

B. Now, I get the logging info. I have this error message like,

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'userService' for bean class [mobi.puut.services.UserServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [mobi.puut.services.UserService2Impl]

You get the ConflictingBeanDefinitionException for creating the bean with the same name. Though I have some experience with the Spring, I need to create with a project with the Apache Cxf and hence, clone a demo project for the very purpose. They have the one same entity User and same definition - interface and same implementation of that. Though I have refactored to all classes in the project and there seem no apparent errors, I still keep an issue - I keep the same bean name "userService in 2 implementations of the interface.

The User2 class in the entities,

public class User2 {    private Integer id;    private String name;    public User2() {    }    public User2(Integer id, String name) {        this.id = id;        this.name = name;    }    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public void setName(String name) {        this.name = name;    }    public String getName() {        return name;    }    @Override    public String toString() {        return String.format("{id=%s,name=%s}", id, name);    }}

The User class in the entities,

@Entity@Table(name = "users")public class User {    @Id    @Column    @NotNull    @GeneratedValue(strategy = GenerationType.IDENTITY)    private int id;    @NotNull    @Column(name = "name")    @Size(min = 5, max = 45, message = "Name must be between 5 and 45 characters.")    private String name;    public User() {    }    public User(int id, String name) {        super();        this.id = id;        this.name = name;    }    public User(String name) {        this.name = name;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (!(o instanceof User)) return false;        User user = (User) o;        if (getId() != user.getId()) return false;        return getName().equals(user.getName());    }    @Override    public int hashCode() {        int result = getId();        result = 31 * result + getName().hashCode();        return result;    }    @Override    public String toString() {        return "User{" +                "id=" + id +                ", name='" + name + '\'' +                '}';    }}

The interfaces in the services directories,

public interface IUserService2 {    Collection<User2> getUsers();    User2 getUser(Integer id);    Response add(User2 user);}public interface IUserService {    List<User> getCurrentStatuses();    void create(User user);    List<User> getAllUsers();}

The implementations of the interfaces inside the services derectory,

@Service("userService")public class UserService2Impl implements IUserService2 {    private static Map<Integer, User2> users = new HashMap<Integer, User2>();    static {        users.put(1, new User2(1, "foo"));        users.put(2, new User2(2, "bar"));        users.put(3, new User2(3, "baz"));    }    public UserService2Impl() {    }    @Override    public Collection<User2> getUsers() {        return users.values();    }    @Override    public User2 getUser(Integer id) {        return users.get(id);    }    @Override    public Response add(User2 user) {        user.setId(users.size()+1);        users.put(user.getId(), user);        //do more stuff to add user to the system..        return Response.status(Response.Status.OK).build();    }}@Service("userService")public class UserServiceImpl implements IUserService {    @Autowired    @Qualifier("userDao")    public IUserDao userDao;    public List<User> getCurrentStatuses() {        return userDao.getAllUsers();    }    public void create(User user) {        userDao.saveOrUpdate(user);    }    public List<User> getAllUsers() {        List<User> users = userDao.getAllUsers();        if (Objects.isNull(users)) {            return null;        }        return users;    }}

And, there was the error - I annotaed 2 classes with the same bean name of "userService". I had to change it like this to provide the bean a different name,

@Service("user2Service")public class UserService2Impl implements IUserService2 {    // some code}

And, that error goes away. In short, the error ConflictingBeanDefinitionException due to the 2 beans of the same name and I just had to provide a different name.

C. I still had things to fix. Afterwards, when I run the program, I get the

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'mobi.puut.database.IUserDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=userDao)}// some consequent error messages not necessay to solve the issueCaused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'mobi.puut.database.IUserDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=userDao)}

The error here is UnsatisfiedDependencyException and says it can't create a bean with the name of userService. OK, this is the code I had and integrated into the project. The Unsatisfied dependency expressed through the field namely userDao. userDao is the instance of the interface of IUserDao and it was @autowired like this,

    @Autowired    public IUserDao userDao;

Here is more insight of the code,

@Service("userService")public class UserServiceImpl implements IUserService {    @Autowired    public IUserDao userDao;     public List<User> getCurrentStatuses() {        return userDao.getAllUsers();    }    public void create(User user) {        userDao.saveOrUpdate(user);    }    public List<User> getAllUsers() {        List<User> users = userDao.getAllUsers();        if (Objects.isNull(users)) {            return null;        }        return users;    }}

I have an interface in the database directory and consequent implementation of the interface for the user. The interface name is IUserDao and looks

soemthing like this, public interface IUserDao {    boolean create(User user);    void saveOrUpdate(User user);    boolean create(List<User> users);    List<User> getAllUsers();    User getById(int id);}

And, the implementation,

@Repository("userDao")public class UserDaoImpl implements IUserDao {    @Autowired    private SessionFactory sessionFactory;    // the HQL queries}

The consequent part of the error message was NoSuchBeanDefinitionException and the app doesn't find a qualifying bean of the type (class) of IUserDao. I have all the HQL queries in the implementation of the IUserDao and the code works perfectly before.

I have to take a moment to think and finally, I have an intuition that may be the database layer is NOT integrated into the app. Here is the configuration I used,

public class WebAppInitializer implements WebApplicationInitializer {    @Override    public void onStartup(ServletContext servletContext) throws ServletException {        servletContext.addListener(new ContextLoaderListener(createWebAppContext()));        addApacheCxfServlet(servletContext);    }    private void addApacheCxfServlet(ServletContext servletContext) {        CXFServlet cxfServlet = new CXFServlet();        ServletRegistration.Dynamic appServlet = servletContext.addServlet("CXFServlet", cxfServlet);        appServlet.setLoadOnStartup(1);        Set<String> mappingConflicts = appServlet.addMapping(AppConfig.API_BASE);    }    private WebApplicationContext createWebAppContext() {        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();        // register all the config classes here        appContext.register(AppConfig.class);        return appContext;    }}

Obviously, the no database code is integrated in the WebInitializer. I wrote a new class provides all the info of the database connection and the hibernate integration and looks like,

@Configuration@EnableWebMvc@EnableTransactionManagement@ComponentScan(basePackages = {"mobi.puut.database"})public class DatabaseConfig {    @Bean    public LocalSessionFactoryBean sessionFactory() {        //  mobi.puut.entities        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();        sessionFactory.setDataSource(dataSource());        sessionFactory.setPackagesToScan(                new String[]{"mobi.puut.entities"});        sessionFactory.setHibernateProperties(hibernateProperties());        return sessionFactory;    }    @Bean    @Autowired    public HibernateTransactionManager transactionManager(            SessionFactory sessionFactory) {        HibernateTransactionManager txManager                = new HibernateTransactionManager();        txManager.setSessionFactory(sessionFactory);        return txManager;    }    @Bean    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {        return new PersistenceExceptionTranslationPostProcessor();    }    @Bean    public DataSource dataSource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");        // dataSource.setUrl("jdbc:mysql://localhost:3306/wallet?createDatabaseIfNotExist=true");        dataSource.setUrl("jdbc:mysql://localhost:3306/Wallet");        dataSource.setUsername("testuser");        dataSource.setPassword("testpassword");        return dataSource;    }    Properties hibernateProperties() {        Properties properties = new Properties();//        properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");        return properties;    }}

And, then finally integrate into the WebInitializer. This is the code I used to registered the config earlier in the WebInitializer,

appContext.register(AppConfig.class);

Updated the line with the,

appContext.register(AppConfig.class, DatabaseConfig.class);

Finally, everything works fine. So, the config directory looks like,

enter image description here

SUMMERY

I had to solve this problem through the 3 errors,

i. ConflictingBeanDefinitionExceptionii. UnsatisfiedDependencyExceptioniii. NoSuchBeanDefinitionException

ConflictingBeanDefinitionException -> 2 beans with the same name

UnsatisfiedDependencyException -> Have a bean (= "userDao") in the class which was not correct to use

NoSuchBeanDefinitionException -> the code was correct but needed to add the datbase layer in the congig so the Spring IoC finds the bean.

I sincerely hope this will help some people.