I have a HelloWorld Java project that uses Camel to obtain a Map, and print
out its contents in JSON format.  The Map currently has hardcoded values,
but I really want to change my code so that it uses Spring to load a
sensor.properties file of nested key,value pairs into this Map.

I have another Java project I wrote that only uses Spring, and can load the
sensor.properties file just fine into an Arraylist object.

However, when I try to use code from that project to load the
sensor.properties in my HelloWorld project I get the following Camel error
with a NPE:

    Returning Map
    3310 [hello.world.request.timer] ERROR
org.apache.camel.processor.DefaultErrorHandler      - Failed delivery for
exchangeId: 4e984884-df7f-4b82-a977-f5cf4c311814. Exhausted after    
delivery attempt: 1 caught: java.lang.NullPointerException
    java.lang.NullPointerException
        at sample.SensorGenerator.getSensors(SensorGenerator.java:17)
        at sample.HelloWorld.returnMap(HelloWorld.java:22)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at
org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:231)
        at
org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:146)
        at
org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:138)
   
org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:67)
        at
org.apache.camel.processor.DelegateProcessor.processNext(DelegateProcessor.java:53)
        at
org.apache.camel.processor.DelegateProcessor.proceed(DelegateProcessor.java:82)
        at
org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:97)
        at
org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:67)
        at
org.apache.camel.processor.RedeliveryErrorHandler.processExchange(RedeliveryErrorHandler.java:185)
     at
org.apache.camel.processor.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:151)
        at    
org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:89)
        at    
org.apache.camel.processor.DefaultErrorHandler.process(DefaultErrorHandler.java:49)
        at
org.apache.camel.processor.DefaultChannel.process(DefaultChannel.java:228)
        at org.apache.camel.processor.Pipeline.process(Pipeline.java:75)
        at    
org.apache.camel.processor.UnitOfWorkProcessor.processNext(UnitOfWorkProcessor.java:70)
        at
org.apache.camel.processor.DelegateProcessor.process(DelegateProcessor.java:48)
        at org.   
apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:67)
        at    
org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:102)
        at
org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:49)
        at java.util.TimerThread.mainLoop(Timer.java:555)
        at java.util.TimerThread.run(Timer.java:505)
    
Is there something I need to add to my applicationContext.xml to tell Camel
that Spring will load my sensor.properties?  Do I need to use the Spring
integration component specified at
http://camel.apache.org/springintegration.html ?

Here is my current 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:camel="http://camel.apache.org/schema/spring";
            xmlns:context="http://www.springframework.org/schema/context";
            xmlns:util="http://www.springframework.org/schema/util";
            xsi:schemaLocation="
            http://www.springframework.org/schema/beans    
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/util    
http://www.springframework.org/schema/util/spring-util-3.0.xsd
            http://camel.apache.org/schema/spring    
http://camel.apache.org/schema/spring/camel-spring.xsd
            http://www.springframework.org/schema/context    
http://www.springframework.org/schema/context/spring-context.xsd";>

        <bean
        
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"
/>
        <context:component-scan base-package="sample" />
        <context:annotation-config />

        <camel:camelContext id="HelloWorldContext">
        
            
            <camel:dataFormats>
          <camel:json id="jack" library="Jackson"/>
        </camel:dataFormats>
        
                <camel:route>
                        
                        <camel:from
                                
uri="timer://hello.world.request.timer?fixedRate=true&amp;period=10000"
/>
                        <camel:to 
uri="log:hello.world.request?level=INFO?showAll=true" />
                        <camel:bean ref="helloWorld" />
                        
                        
                        <camel:marshal ref ="jack"/>
                        <camel:convertBodyTo type="java.lang.String" />
                        <camel:log message="${body}"/> 
            
            
                        <camel:to 
uri="log:hello.world.response?level=INFO?showAll=true" />
                        
                </camel:route>

        </camel:camelContext>
        
        <bean id="jms"
class="org.apache.activemq.camel.component.ActiveMQComponent">
                <property name="configuration" ref="jmsConfig" />
        </bean>

        <bean id="jmsConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
                <property name="connectionFactory" ref="jmsConnectionFactory" />
                <property name="transacted" value="false" />
                <property name="concurrentConsumers" value="1" />
        </bean>

        <bean id="jmsConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
                <property name="brokerURL" value="vm://localhost" />
                <property name="redeliveryPolicy" ref="redeliveryPolicy" />
                <property name="prefetchPolicy" ref="prefetchPolicy" />
        </bean>

        <bean id="prefetchPolicy"
class="org.apache.activemq.ActiveMQPrefetchPolicy">
                <property name="queuePrefetch" value="5" />
        </bean>

        <bean id="redeliveryPolicy" 
class="org.apache.activemq.RedeliveryPolicy">
                <property name="maximumRedeliveries" value="1" />
                <property name="backOffMultiplier" value="2" />
                <property name="initialRedeliveryDelay" value="2000" />
                <property name="useExponentialBackOff" value="true" />
        </bean>
    
    
    <util:properties id="sensorProperties"
location="classpath:/sensor.properties"/>
        <bean class="sample.SensorGenerator">
            <property name="sourceProperties" ref="sensorProperties" />
        </bean>
    
    </beans>

Here is are the four Java Classes I have (HelloWorldMain.java,
HelloWorld.java, Sensor.java, and SensorGenerator.Java):

HelloWorldMain.java:

    package sample;

    import org.springframework.context.support.AbstractApplicationContext;
    import
org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    public class HelloWorldMain {
        
            // define context to load properties with Spring

            public static void main(String[] args) throws Exception {

                    AbstractApplicationContext context = new
ClassPathXmlApplicationContext(
                                "applicationContext.xml");
                    Thread.currentThread().join();
            }

    }      

HelloWorld.java:

    package sample;
    
    import java.util.*;
    
    import org.apache.camel.Handler;
    import org.springframework.stereotype.Service;
    
    
    /**
     * POJO that returns Hello World string
     *
     */
    @Service
    public class HelloWorld {
        
        @Handler
        public Map<?, ?> returnMap(){
                SensorGenerator sensorGenerator = new SensorGenerator();
                System.out.println();
                System.out.println("Returning Map");
                // get the map of Sensors
                Map<String,String> mySensorMap = sensorGenerator.getSensors();
                // print out the Sensors in the map on the console
                Set keys = mySensorMap.keySet();
            
            for (Iterator i = keys.iterator(); i.hasNext();) {
                        String key = (String) i.next();
                        String value = (String) mySensorMap.get(key);
                        System.out.println("key= " + key + ", value= " + value);
                }
                return mySensorMap;
        }

    }
    
Sensor.java (which defines the fields I'm reading from sensor.properties):

    package sample;
    
    public class Sensor {
    
        private String make;
        private String makeDataType;
        private String model;
        private String modelDataType;
        private String serialNumber;
        private String serialNumberDataType;
        private String sensorType;
        private String sensorTypeDataType;
        
        // getters and setters
        public String getMake() {
                return make;
        }
        public void setMake(String make) {
                this.make = make;
        }
        public String getMakeDataType() {
                return makeDataType;
        }
        public void setMakeDataType(String makeDataType) {
                this.makeDataType = makeDataType;
        }
        public String getModel() {
                return model;
        }
        public void setModel(String model) {
                this.model = model;
        }
        public String getModelDataType() {
                return modelDataType;
        }
        public void setModelDataType(String modelDataType) {
                this.modelDataType = modelDataType;
        }
        public String getSerialNumber() {
                return serialNumber;
        }
        public void setSerialNumber(String serialNumber) {
                this.serialNumber = serialNumber;
        }
        public String getSerialNumberDataType() {
                return serialNumberDataType;
        }
        public void setSerialNumberDataType(String serialNumberDataType) {
                this.serialNumberDataType = serialNumberDataType;
        }
        public String getSensorType() {
                return sensorType;
        }
        public void setSensorType(String sensorType) {
                this.sensorType = sensorType;
        }
        public String getSensorTypeDataType() {
                return sensorTypeDataType;
        }
        public void setSensorTypeDataType(String sensorTypeDataType) {
                this.sensorTypeDataType = sensorTypeDataType;
        }
    }

SensorGenerator.java (the class where I current hard-code the properties but
want to have Spring load them from sensor.properties.  If I comment out the
For loop and any lines referencing sourceProperties I can get the map
returned with the hard coded values just fine.  That's why I suspect its
some sort of Spring/Camel integration issue):

  package sample;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    public class SensorGenerator {
    
        private Properties sourceProperties;
    
        // variable to increment key number for each sensor
        int sensorNumber = 1;
    
        // method to inject sensor.properties into a Map using Spring
        Map<String, String> getSensors() {
                Map<String, String> sensorMap = new HashMap<String, String>();
                for (Object key : sourceProperties.keySet()) {
    
                        // Separate out each of the key,value pairs as an entry 
in the
                        // values array
                        String[] values = sourceProperties.getProperty((String) 
key).split(
                                        ",");
                        System.out.println("values array size= " + 
values.length);
    
                        // define string buffer that appends sensor number for 
each sensor's
                        // keys.  Ex: sensor1 would have s1make, 
s1makeDataType, etc.
                        StringBuffer sensorNumberStringBuffer = new 
StringBuffer();
                        sensorNumberStringBuffer.append("s");
                        sensorNumberStringBuffer.append(sensorNumber);
    
                        // make and its data type (with sensor number prefix)
                        StringBuffer makeStringBuffer = new StringBuffer();
                        makeStringBuffer.append(sensorNumberStringBuffer);
                        makeStringBuffer.append("make");
                        StringBuffer makeDataTypeStringBuffer = new 
StringBuffer();
                        
makeDataTypeStringBuffer.append(sensorNumberStringBuffer);
                        makeDataTypeStringBuffer.append("makeDataType");
    
                        // model and its data type (with sensor number prefix)
                        StringBuffer modelStringBuffer = new StringBuffer();
                        modelStringBuffer.append(sensorNumberStringBuffer);
                        modelStringBuffer.append("model");
                        StringBuffer modelDataTypeStringBuffer = new 
StringBuffer();
                        
modelDataTypeStringBuffer.append(sensorNumberStringBuffer);
                        modelDataTypeStringBuffer.append("modelDataType");
    
                        // serialNumber and its data type (with sensor number 
prefix)
                        StringBuffer serialNumberStringBuffer = new 
StringBuffer();
                        
serialNumberStringBuffer.append(sensorNumberStringBuffer);
                        serialNumberStringBuffer.append("serialNumber");
                        StringBuffer serialNumberDataTypeStringBuffer = new 
StringBuffer();
                        
serialNumberDataTypeStringBuffer.append(sensorNumberStringBuffer);
                        
serialNumberDataTypeStringBuffer.append("serialNumberDataType");
    
                        // sensorType and its data type (with sensor number 
prefix)
                        StringBuffer sensorTypeStringBuffer = new 
StringBuffer();
                        sensorTypeStringBuffer.append(sensorNumberStringBuffer);
                        sensorTypeStringBuffer.append("sensorType");
                        StringBuffer sensorTypeDataTypeStringBuffer = new 
StringBuffer();
                        
sensorTypeDataTypeStringBuffer.append(sensorNumberStringBuffer);
                        
sensorTypeDataTypeStringBuffer.append("sensorTypeDataType");
    
                        /*
                          put all the key,value pairs for this sensor in the 
sensorMap
                */
                        
                        //TODO: Change all the hard coded values below to be 
elements
                        // from the values array once Spring can load 
spring.properties
                        
                        // make and and its data type
                        sensorMap.put(makeStringBuffer.toString(), "DummyMake");
                        sensorMap.put(makeDataTypeStringBuffer.toString(), 
"String");
    
                        // model and and its data type
                        sensorMap.put(modelStringBuffer.toString(), 
"DummyModel");
                        sensorMap.put(modelDataTypeStringBuffer.toString(), 
"String");
    
                        // serialNumber and and its data type
                        sensorMap.put(serialNumberStringBuffer.toString(), 
"1234567890");
                        
sensorMap.put(serialNumberDataTypeStringBuffer.toString(), "long");
    
                        // sensorType and its data type
                        sensorMap.put(sensorTypeStringBuffer.toString(), 
"DummyType");
                        
sensorMap.put(sensorTypeDataTypeStringBuffer.toString(), "String");
    
                        // increment for next sensor
                        sensorNumber++;
                }
                return sensorMap;
        }
    
        public void setSourceProperties(Properties properties) {
                this.sourceProperties = properties;
        }
    
    }

Btw: Line 17 of SensorGenerator.java as mentioned in the stack trace above
is:

                for (Object key : sourceProperties.keySet()) {
     
Here is an example sensor.properties file:

   
sensor1=DummySensor1:String,SensorModel1:String,1234567890:long,SensorType1:String
   
sensor2=DummySensor2:String,SensorModel2:String,8675309123:long,SensorType2:String



--
View this message in context: 
http://camel.465427.n5.nabble.com/How-do-I-load-properties-with-Spring-when-also-using-Camel-tp5741563.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Reply via email to