2013-09-24 2 views
0

Прежде чем задать этот вопрос, я пытался следовать следующие вопросы, которые похожи:@value аннотаций внутри моего класса Java не загружаются значения из файла .properties

Injecting Properties using Spring & annotation @Value

How can I inject a property value into a Spring Bean which was configured using annotations?

Loading up properties file to a class in Spring

Однако в моем случае я не использую никаких веб-приложений или Tomcat; Я просто пытаюсь загрузить файл cluster.properties в обычный Java-проект через Spring, поэтому я могу затем использовать фиктивные данные в Accumulo. Кроме того, я пытаюсь загрузить свойства из файла cluster.properties, а не из пар значений ключа, определенных в XML-файле.

Используя то, что я узнал из ссылки выше и много чтения на весну, вот что у меня есть:

Я создал следующий context.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" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 

     <!-- Define the Spring Bean to load our cluster properties --> 
     <bean id="props" class="accumuloIngest.LoadProperties"></bean> 

    </beans> 

А вот небольшой фрагмент кода чего мой файл cluster.properties выглядит следующим образом:

cluster.instance=instance 
    cluster.username=user 

    etc... 

Далее, я создал следующий основной метод Spring под класс MainApp.java:

package accumuloIngest; 

    import org.springframework.context.ApplicationContext; 
    import org.springframework.context.support.ClassPathXmlApplicationContext; 

    public class MainApp { 

     // Spring main method used to load a cluster.properties file with the Spring framework 
     public static void main(String[] args) { 
      ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml"); 
      LoadProperties myObj = LoadProperties.class.cast(ctx.getBean("props")); 

      // Now print out the cluster.properties loaded by Spring to verify they aren't null 
      StringBuffer springPropsBuffer = new StringBuffer(); 
      springPropsBuffer.append("Printing out cluster.properties read via Spring..."); 
      springPropsBuffer.append("\n\n"); 
      springPropsBuffer.append("instanceName= "); 
      springPropsBuffer.append(myObj.getInstanceName()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("userName= "); 
      springPropsBuffer.append(myObj.getUserName()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("password= "); 
      springPropsBuffer.append(myObj.getPassword()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("zooServers= "); 
      springPropsBuffer.append(myObj.getZooServers()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("tableName= "); 
      springPropsBuffer.append(myObj.getTableName()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("dataFile= "); 
      springPropsBuffer.append(myObj.getDataFile()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("dataDelim= "); 
      springPropsBuffer.append(myObj.getDataDelim()); 
      springPropsBuffer.append("\n"); 
      springPropsBuffer.append("rowCount= "); 
      springPropsBuffer.append(myObj.getRowCount()); 
      springPropsBuffer.append("\n"); 
      System.out.println(springPropsBuffer.toString()); 

      // now start data ingest 
      myObj.startIngest(); // method that calls Ingester class to start data ingest 
     } // end of main method 

    } // end of MainApp class 

Весна загружает мой файл context.xml и загружает Bean, который я называю «реквизит», но значения по-прежнему равны нулю. Кажется, что мои @value аннотаций не работают в моем классе LoadProperties:

package accumuloIngest; 
    import java.io.IOException; 

    import org.apache.accumulo.core.client.AccumuloException; 
    import org.apache.accumulo.core.client.AccumuloSecurityException; 
    import org.apache.accumulo.core.client.TableExistsException; 
    import org.apache.accumulo.core.client.TableNotFoundException; 
    import org.springframework.beans.factory.annotation.Value; 
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; 
    import org.springframework.context.annotation.Bean; 
    import org.springframework.core.io.ClassPathResource; 
    import org.springframework.core.io.Resource; 

    public class LoadProperties { 

     // this class defines the Spring Bean and loads the cluster properties 
     // using the SpringFramework 

     @Bean 
     public static PropertyPlaceholderConfigurer props(){ 
     PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); 
     Resource[] resource = new ClassPathResource[ ] 
       { new ClassPathResource("/EclipseProjectName/src/cluster.properties") }; 
     ppc.setLocations(resource); 
     ppc.setIgnoreUnresolvablePlaceholders(true); 
     return ppc; 
} 

// Now load the properties from cluster.properties using the Spring Framework 
private @Value("${cluster.instance}") String instanceName; 
private @Value("${cluster.username}") String userName; 
private @Value("${cluster.password}") String password; 
private @Value("${cluster.zooServers}") String zooServers; 
private @Value("${cluster.TableName}") String tableName; 
private @Value("${cluster.DataFile}") String dataFile; 
private @Value("${cluster.DataDelimiter}") String dataDelim; 
private @Value("${cluster.rowCount}") int rowCount; 

// Getters for the other Java classes to access properties loaded by Spring 
public String getInstanceName() { 
    return instanceName; 
} 
public String getUserName() { 
    return userName; 
} 
public String getPassword() { 
    return password; 
} 
public String getZooServers() { 
    return zooServers; 
} 
public String getTableName() { 
    return tableName; 
} 
public String getDataFile() { 
    return dataFile; 
} 
public String getDataDelim() { 
    return dataDelim; 
} 
public int getRowCount() { 
    return rowCount; 
} 

     // method to kick off the ingest of dummy data 
     void startIngest() { 
      Ingester ingestObject = new Ingester(); 
      try { 
       ingestObject.ingestData(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (TableNotFoundException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (TableExistsException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (AccumuloException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (AccumuloSecurityException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } // end of try-catch block 
     } // end of startIngest method 

    } // end of LoadProperties class 

Но когда я бегу MainApp.java в Затмении значения равны нулю, когда мой класс Ingester.java называет добытчиками.

Вот вывод на консоль при запуске MainApp.java в Eclipse:

13/09/24 14:08:24 INFO support.ClassPathXmlApplicationContext: Refreshing org[email protected]191f667c: startup date [Tue Sep 24 14:08:24 EDT 2013]; root of context hierarchy 
    13/09/24 14:08:24 INFO xml.XmlBeanDefinitionReader: Loading XML bean definitions from class path resource [context.xml] 
    13/09/24 14:08:24 INFO support.DefaultListableBeanFactory: Pre-instantiating singletons in org.s[email protected]3cdd17f5: defining beans [props]; root of factory hierarchy 
    Printing out cluster.properties read via Spring... 

    instanceName= null 
    userName= null 
    password= null 
    zooServers= null 
    tableName= null 
    dataFile= null 
    dataDelim= null 
    rowCount= 0 

    Exception in thread "main" java.lang.IllegalArgumentException: argument was null:Is null- arg1? true arg2? true 
     at org.apache.accumulo.core.util.ArgumentChecker.notNull(ArgumentChecker.java:36) 
     at org.apache.accumulo.core.client.ZooKeeperInstance.<init>(ZooKeeperInstance.java:99) 
     at org.apache.accumulo.core.client.ZooKeeperInstance.<init>(ZooKeeperInstance.java:85) 
     at accumuloIngest.Ingester.ingestData(Ingester.java:65) 
     at accumuloIngest.LoadProperties.startIngest(LoadProperties.java:69) 
     at accumuloIngest.MainApp.main(MainApp.java:44) 

мне не хватает кусок Spring Framework, который загружает свойства в файле мои cluster.properties? Я попробовал добавить @AutoWired для обоих классов JavaAvp и LoadProperties, но это, похоже, не помогло.

+0

Здесь есть несколько проблем. Во-первых, почему ваше пространство имен контекста объявляет Spring beans версии 2.0, когда вы используете '@ Bean', который был введен в 3.0? –

+0

Да, это была ошибка копирования/вставки с моей стороны. Я определил Spring Framework 3.2.4 в моем pom.xml, поэтому я изменил свой context.xml, чтобы использовать Spring beans version 3.2 – erj2code

ответ

0

Если вы собираетесь использовать @Bean, вам понадобится @Configuration. Вы не должны объявлять контекст xml для включения контекста аннотации. Вы также не должны использовать экземпляр класса @Configuration в качестве компонента. ClassPathXmlApplicationContext не подходит для обработки основанных на аннотациях конфигураций.

использовать что-то вроде следующего

@Configuration 
@ComponentScan(basePackageClasses = LoadProperties.class) 
public static class Config { 
    @Bean 
    public static PropertyPlaceholderConfigurer props() { 
     PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); 
     Resource[] resource = new ClassPathResource[] { new ClassPathResource(
       "/EclipseProjectName/src/cluster.properties") }; 
     ppc.setLocations(resource); 
     ppc.setIgnoreUnresolvablePlaceholders(true); 
     return ppc; 
    } 

    @Bean 
    public LoadProperties loadProperties() { 
     return new LoadProperties(); 
    } 
} 

public static class LoadProperties { 
    private @Value("${cluster.zooServers}") String zooServers; 
    ... // getters and setters 
} 

public static void main(String[] args) throws Exception { 
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); 
    LoadProperties load = (LoadProperties) context.getBean(LoadProperties.class); 
    System.out.println(load.getZooServers()); 
} 

Несколько вещей, чтобы отметить:

  1. В вашей ClassPathResource вам нужно указать путь к классам ресурса. У вас действительно есть ресурс /EclipseProjectName/src/cluster.properties в корне вашего пути к классам? Я очень сомневаюсь в этом.
  2. В этом случае вам не понадобится @ComponentScan, но ознакомьтесь с ним.
  3. A PropertyPlaceholderConfigurer должен быть объявлен статическим, чтобы он мог быть инициализирован перед другими объявлениями @Bean. Вы должны использовать PropertySourcesPlaceholderConfigurer как explained in the javadoc.
+0

Да, вы правы, у меня нет ресурса в корне моего пути к классам. Я прочитал API Spring, рассказывающий о ClassPathResource i.e., http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/, и понял, что должен был указать выше класс java. Но как определить, какой ClassPathResource указать? – erj2code

+0

@ user2160928 Здесь я предполагаю, что вам нужен файл '.properties', чтобы указать путь к этому. Вам нужно будет выяснить, как ваша программа скомпилирована и построена, чтобы понять, что этот путь или должен быть. –

+0

Хорошо, так что у меня есть правильно. Файл cluster.properties находится в каталоге src в моем проекте Eclipse (который я назвал EclipseProjectName выше) – erj2code