有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java组织。阿帕奇。卡塔琳娜。果心标准语境。startInternal一个或多个侦听器无法启动

我在一个Java/Spring/ Apache Cxf网络应用程序上工作,突然,当我做出一些明显幼稚的改变时,我发现了错误

25-Aug-2017 11:48:43.036 INFO [RMI TCP Connection(2)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
25-Aug-2017 11:48:43.540 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file
25-Aug-2017 11:48:43.554 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal Context [] startup failed due to previous errors
[2017-08-25 11:48:43,586] Artifact jaxrs-tutorials:war exploded: Error during artifact deployment. See server log for details.
25-Aug-2017 11:48:49.258 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/Applications/Tomcat-8.5.16/webapps/manager]
25-Aug-2017 11:48:49.310 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Applications/Tomcat-8.5.16/webapps/manager] has finished in [51] ms

我猜这是错误的主要原因

25-Aug-2017 11:48:43.540 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file
25-Aug-2017 11:48:43.554 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal Context [] startup failed due to previous errors

提供了项目结构

enter image description here

config目录用于Java annotation based config,下面提供了代码

AppConfig文件

@Configuration
@ComponentScan(AppConfig.SERVICE_PACKAGE)
public class AppConfig {

    public static final String BASE_PACKAGE = "mobi.puut";
    public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".services";
    private static final String RESOURCES_PACKAGE = BASE_PACKAGE + ".rest";
    private static final String PROVIDER_PACKAGE = BASE_PACKAGE + ".rest.provider";

    public static final String API_BASE = "/api/*";

    @ApplicationPath("/")
    public class JaxRsApiApplication extends Application {
    }

    @Bean(destroyMethod = "shutdown")
    public SpringBus cxf() {
        return new SpringBus();
    }

    @Bean
    @DependsOn("cxf")
    public Server jaxRsServer(ApplicationContext appContext) {
        JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);
        factory.setServiceBeans(restServiceList(appContext));
        factory.setAddress("/" + factory.getAddress());
        factory.setProviders(restProviderList(appContext, jsonProvider()));
        return factory.create();
    }

    @Bean
    public JaxRsApiApplication jaxRsApiApplication() {
        return new JaxRsApiApplication();
    }

    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }

    private List<Object> restServiceList(ApplicationContext appContext) {
        return RestServiceBeanScanner.scan(appContext, AppConfig.RESOURCES_PACKAGE);
    }

    private List<Object> restProviderList(final ApplicationContext appContext,
                                          final JacksonJsonProvider jsonProvider) {
        final List<Object> providers = RestProviderBeanScanner.scan(appContext, PROVIDER_PACKAGE);
        providers.add(jsonProvider);
        return providers;
    }

}

提供了WebInitializer

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();
        appContext.register(AppConfig.class);
        return appContext;
    }

}

我在平台上看到过类似的问题,但这些问题对我没有帮助,我几乎没有什么信息可以解决这个问题

我如何使用logger获取更多信息,以及应该在哪里使用它们?此外,任何关于解决问题的见解都会有所帮助。我已经用mvn clean installmvn idea:idea命令更新了JAR文件

UPDATE

Tomcat Localhost Log

enter image description here

Tomcat Catalina Log

enter image description here


共 (1) 个答案

  1. # 1 楼答案

    我想写一个关于这个问题的详细答案,以及我为解决这个问题所采取的步骤

    答:没有足够的日志信息。我查了一下POM发现了这个

    <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>
    

    我为了SLF4J而排除了日志记录,我刚刚删除了排除XML标记以获取更多日志记录信息。所以变成这样

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

    B.现在,我得到了日志信息。我有这样的错误信息

    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]
    

    您可以通过ConflictingBeanDefinitionException创建同名bean。虽然我对Spring有一些经验,但我需要用Apache Cxf创建一个项目,因此,为了这个目的,我需要克隆一个演示项目。它们有一个相同的实体User和相同的definition - interface和相同的implementation。虽然我对项目中的所有类都有refactored,而且似乎没有明显的错误,但我仍然有一个问题——我在接口的两个实现中保持了相同的bean名称"userService

    实体中的User2

    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);
        }
    }
    

    实体中的User

    @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 + '\'' +
                    '}';
        }
    }
    

    services目录中的接口

    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();
    }
    

    services目录中接口的实现

    @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;
        }
    }
    

    还有error,我用相同的bean名"userService"注释了两个类。我不得不这样改变它,给豆子起一个不同的名字

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

    然后,这个错误就消失了。简而言之,错误ConflictingBeanDefinitionException是由于两个bean的名称相同,我只需要提供一个不同的名称

    C.我还有事情要解决。之后,当我运行程序时,我得到

    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 issue
    
    Caused 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)}
    

    这里的错误是UnsatisfiedDependencyException,并表示无法创建名为userService的bean。好的,这是我的代码,并集成到项目中。未满足的依赖关系通过字段表示,即userDaouserDaoIUserDao接口的实例,它是@autowired这样的

        @Autowired
        public IUserDao userDao;
    

    下面是对代码的更多了解

    @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;
        }
    }
    

    我在database目录中有一个接口,并为用户实现了该接口。接口名为IUserDao,看起来

    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);
    }
    

    还有,实施

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

    错误消息的后续部分是NoSuchBeanDefinitionException,应用程序找不到IUserDao类型(类)的合格bean。在IUserDao的实现中,我有所有的HQL查询,代码以前工作得很好

    我必须花点时间思考,最后,我有一个直觉,可能是databaseNOT集成到了应用程序中。这是我用的configuration

    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;
        }
    
    }
    

    显然,no数据库代码集成在WebInitializer中。我写了一个新类,提供了database connectionhibernate integration的所有信息,看起来

    @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;
        }
    }
    

    然后,最后集成到WebInitializer。这是我之前在{}中用于{}配置的代码

    appContext.register(AppConfig.class);
    

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

    最后,一切正常。所以config目录看起来像

    enter image description here

    SUMMERY

    我必须通过三个错误来解决这个问题

    i. ConflictingBeanDefinitionException
    ii. UnsatisfiedDependencyException
    iii. NoSuchBeanDefinitionException
    

    ConflictingBeanDefinitionException->;两个同名的豆子

    UnsatisfiedDependencyException->;在类中有一个不正确使用的bean (= "userDao")

    NoSuchBeanDefinitionException->;代码是正确的,但需要在congig中添加datbase层,以便Spring IoC找到bean

    我真诚地希望这将帮助一些人