使用Tomcat88中的SpringBootServletInitializer在另一个bean中注入Bean配置时出错

时间:2017-09-04 10:25:53

标签: spring-boot spring-data-jpa tomcat8 spring-4

我在注入带有@Inject@Autowired注释的bean时遇到问题:这在一个名为MultitenantConfiguration的类中发生:在部署期间,我的Tomcat 8挂起并停止它!只有当应用程序在tomcat上展开时才会发生这种情况,而不是在pom packaging = jar时(所以它作为独立的应用程序运行,因为它是Spring启动应用程序)。注意FileProperties道具仍然null我得到NullPointerException符合代码files = Paths.get(props.getTenantsFilePath()).toFile().listFiles(); .. beacuse propr是null .. 为什么?我能做什么..这些是我的代码行:

的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.cadit</groupId>
  <artifactId>xxx</artifactId>
  <version>1.0</version>
<!--   <packaging>jar</packaging> -->
   <packaging>war</packaging>

  <name>soci-af-import</name>
  <url>http://maven.apache.org</url>

   <properties>
        <start-class>com.cadit.web.WebApplicationAware</start-class>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <camel.version>2.18.1</camel.version>
   </properties>

     <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

    <dependencies>
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>




        <!-- altre dipendenze non spring -->
          <!-- CDI API -->
        <dependency>
          <groupId>javax.enterprise</groupId>
          <artifactId>cdi-api</artifactId>
          <version>1.2</version>
          <scope>provided</scope>
        </dependency>

        <!-- camel -->

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot</artifactId>
            <version>${camel.version}</version> <!-- use the same version as your Camel core version -->
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-starter</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
             <artifactId>spring-boot-starter-web</artifactId> 
         </dependency> 
         <dependency> 
             <groupId>org.apache.camel</groupId> 
            <artifactId>camel-swagger-java-starter</artifactId>
            <version>${camel.version}</version> 
         </dependency>  
        <dependency> 
            <groupId>org.apache.camel</groupId> 
            <artifactId>camel-servlet-starter</artifactId> 
             <version>${camel.version}</version>
        </dependency> 
        <dependency> 
            <groupId>org.apache.camel</groupId> 
            <artifactId>camel-jackson-starter</artifactId> 
             <version>${camel.version}</version>
        </dependency> 
        <dependency>
          <groupId>org.apache.camel</groupId>
          <artifactId>camel-csv</artifactId>
          <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-quartz2</artifactId>
            <version>${camel.version}</version>
        </dependency>

        <!-- fine camel -->



        <dependency>
              <groupId>com.microsoft.sqlserver</groupId>
              <artifactId>sqljdbc4</artifactId>
              <version>4.0</version>
              <scope>runtime</scope>
        </dependency>



        <!--  end -->


         <!-- dipendenze logback -->
      <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.7</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.7</version>
        </dependency>

        <!-- fine dip logback -->

    </dependencies>


    <build>
    <!-- commentato perchè viene usato SpringBootServletInitializer -->
      <plugins> 
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
<!--        <plugin> -->
<!--              <groupId>org.apache.maven.plugins</groupId> -->
<!--              <artifactId>maven-war-plugin</artifactId> -->
<!--              <version>3.0.0</version> -->
<!--              <configuration> -->
<!--                 <warName>AfSociImporterRest</warName> -->
<!--              </configuration> -->
<!--         </plugin> -->

    </plugins>

   <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
</project>

在网络包中:

@Configuration
@SpringBootApplication
@ComponentScan(basePackages={"com.cadit.multitenant","com.cadit.dao", "com.cadit.entities", "com.cadit.camel"})
@EnableJpaRepositories(basePackages={"com.cadit.dao"})
@EntityScan(basePackages="com.cadit.entities")
@Import(value={FileProperties.class, CamelContextConfVB.class, CamelContextConfS2.class, CamelContextConfRestServices.class})
public class WebApplicationAware extends SpringBootServletInitializer{

    private static Class<WebApplicationAware> applicationClass = WebApplicationAware.class;

     static final Logger logger = LoggerFactory.getLogger(WebApplicationAware.class);

      public static void main(String[] args) {
            String pathconf = null;
            String path_properties=null;
            if (args.length > 0){
                path_properties = args[0];
            }

            if (path_properties == null) logger.error("Manca l'argomento relativo al path assoluto al file di configurazione app.properties!");
            if (pathconf == null) pathconf = "application.properties";
            System.setProperty("properties.url", pathconf);
            System.setProperty("path.properties", path_properties);
            //logger.info("** " + System.getenv("path.properties"));
            //logger.info("** " + System.getProperty("properties.url"));
            //logger.info("** " + System.getProperty("path.properties"));
            logger.info("** Registered default application.properties");
            if (System.getProperty("path.properties")!= null) {
                logger.info("** Registered app.properties from location " + System.getProperty("path.properties"));
            }
            SpringApplication.run(applicationClass, args);
        }

        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(applicationClass);
        }

        @Bean 
       public ServletRegistrationBean camelServletRegistrationBean() { 
             ServletRegistrationBean registration = new ServletRegistrationBean(new CamelHttpTransportServlet(), "/afsiss/*"); 
             registration.setName("CamelServlet"); 
             logger.info("** CamelServlet initialized..");
             TenantContext.setCurrentTenant("tenant_1");
             return registration; 
         } 

}

在multitenant包中(道具为空!):

@Configuration
public class MultitenantConfiguration {

    @Autowired
    private DataSourceProperties properties;

    @Inject
    FileProperties props;

    /**
     * Defines the data source for the application
     * @return
     */
    @Bean
    @ConfigurationProperties(
            prefix = "spring.datasource"
    )
    public DataSource dataSource() {
        //se sono in un jar ed esternamente al jar o nel jar stesso il path tenants esiste 
        File folderTenatsConf = Paths.get("tenants").toFile();
         File[] files =null;

        if (folderTenatsConf.exists()){
          files = Paths.get("tenants").toFile().listFiles();
        }//se sono in una  application server come Tomcat  (war).. 
        else {
            files = Paths.get(props.getTenantsFilePath()).toFile().listFiles();
        }
        Map<Object,Object> resolvedDataSources = new HashMap<>();

        for(File propertyFile : files) {
            Properties tenantProperties = new Properties();
            DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(this.getClass().getClassLoader());

            try {
                tenantProperties.load(new FileInputStream(propertyFile));

                String tenantId = tenantProperties.getProperty("name");

                dataSourceBuilder.driverClassName(properties.getDriverClassName())
                        .url(tenantProperties.getProperty("datasource.url"))
                        .username(tenantProperties.getProperty("datasource.username"))
                        .password(tenantProperties.getProperty("datasource.password"));

                if(properties.getType() != null) {
                    dataSourceBuilder.type(properties.getType());
                }

                resolvedDataSources.put(tenantId, dataSourceBuilder.build());
            } catch (IOException e) {
                e.printStackTrace();

                return null;
            }
        }

        // Create the final multi-tenant source.
        // It needs a default database to connect to.
        // Make sure that the default database is actually an empty tenant database.
        // Don't use that for a regular tenant if you want things to be safe!
        MultitenantDataSource dataSource = new MultitenantDataSource();
        dataSource.setDefaultTargetDataSource(defaultDataSource());
        dataSource.setTargetDataSources(resolvedDataSources);

        // Call this to finalize the initialization of the data source.
        dataSource.afterPropertiesSet();

        return dataSource;
    }

    /**
     * Creates the default data source for the application
     * @return
     */
    private DataSource defaultDataSource() {
        DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(this.getClass().getClassLoader())
                .driverClassName(properties.getDriverClassName())
                .url(properties.getUrl())
                .username(properties.getUsername())
                .password(properties.getPassword());

        if(properties.getType() != null) {
            dataSourceBuilder.type(properties.getType());
        }

        return dataSourceBuilder.build();
    }
}

包骆驼:

@Configuration
@PropertySource("file:${path.properties}/app.properties")
@ConfigurationProperties(prefix="multitenancy")
public class FileProperties {


    private List<DirProps> dir =new ArrayList<DirProps>();

    private String tenantsFilePath; 


    /**
     * lista delle proprietà relative alle directories di ogni società
     * @return
     */
    public List<DirProps> getDir() {
        return dir;
    }



    public void setDir(List<DirProps> dir) {
        this.dir = dir;
    }



    public String getTenantsFilePath() {
        return tenantsFilePath;
    }



    public void setTenantsFilePath(String tenantsFilePath) {
        this.tenantsFilePath = tenantsFilePath;
    }



    public static class DirProps{

        private String tenant; //nome del tenant della società

        private String root; //root della societa

        private String in; //sottocartella della root dove vanno i file di input

        private String out; //sottocartella della root dove vanno i file di out, quelli elaborati

        private String refused;//sottocartella della root dove vanno i file di out che non sono stati elaborati perchè errati

        private boolean enabled = true; //di default la societa è abilitata

        public String getTenant() {
            return tenant;
        }

        public void setTenant(String tenant) {
            this.tenant = tenant;
        }

        public String getRoot() {
            return root;
        }

        public void setRoot(String root) {
            this.root = root;
        }

        public String getIn() {
            return in;
        }

        public void setIn(String in) {
            this.in = in;
        }

        public String getOut() {
            return out;
        }

        public void setOut(String out) {
            this.out = out;
        }

        public String getRefused() {
            return refused;
        }

        public void setRefused(String refused) {
            this.refused = refused;
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }



    }





}

这是我的app.properties(在C:/ Progetti / soci-af-import2 / config中):

multitenancy.tenantsFilePath= C:/Progetti/tenants/

#tenant_1.properties
#tenant di riferimento
multitenancy.dir[0].tenant = tenant_1
multitenancy.dir[0].root = C:/Progetti/
multitenancy.dir[0].in = IN
multitenancy.dir[0].out = ../OUT
#VB\REFUSED IDEM SOPRA
multitenancy.dir[0].refused = ../REFUSED
multitenancy.dir[0].enabled = true

这就是app.properties以及我的webapp如何部署的方式(Tomcat / conf / Server.xml):

<Service name="siss-af-import2Service">
     <Connector port="8090"/>
      <Engine defaultHost="localhost" name="siss-af-import2Engine">
      <Host name="localhost" appBase="C:/Progetticcc/target">
      <Context docBase="soci-af-import-1.0" path="afsiss">
       <Parameter name="path.properties" value="C:/Progetti/soci-af-import2/config"/>
      </Context>
      </Host>
      </Engine>
      </Service>

这是tomcat stackTrace:

 Sep 04, 2017 2:42:59 PM org.apache.jasper.servlet.TldScanner scanJars
 [com/cadit/multitenant/MultitenantConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NullPointerException
    04/09/2017 14:43:08.894 INFO  [localhost-startStop-1] - org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer: 
    Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
    04/09/2017 14:43:08.912 ERROR [localhost-startStop-1] - org.springframework.boot.SpringApplication: Application startup failed
    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/cadit/multitenant/MultitenantConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NullPointerException
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
        at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:151)
        at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:131)
        at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:86)
        at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5244)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/cadit/multitenant/MultitenantConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NullPointerException
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
        ... 37 common frames omitted
    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.NullPointerException
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
        ... 50 common frames omitted
    Caused by: java.lang.NullPointerException: null
        at com.cadit.multitenant.MultitenantConfiguration.dataSource(MultitenantConfiguration.java:62)
        at com.cadit.multitenant.MultitenantConfiguration$$EnhancerBySpringCGLIB$$321a1e90.CGLIB$dataSource$0(<generated>)
        at com.cadit.multitenant.MultitenantConfiguration$$EnhancerBySpringCGLIB$$321a1e90$$FastClassBySpringCGLIB$$e04a7d0b.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
        at com.cadit.multitenant.MultitenantConfiguration$$EnhancerBySpringCGLIB$$321a1e90.dataSource(<generated>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
        ... 51 common frames omitted

感谢

1 个答案:

答案 0 :(得分:0)

对于Inject可以使用以下依赖

    <dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
    </dependency>

注意:我使用了这种依赖

相关问题