Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read application.properties from non-component class like pojo or singleton

I'm using spring boot & for properties I've placed application.properties inside src/main/resources

From @Controllers & @Services, I'm able to read properties, but from my model pojo & a singleton class, I'm not able to read the values.

My @SpringBootApplication is in com.vehicle & I've not overriden @ComponentScan, so I belive it should read all the underlying packages.

Below is code:

application.properties

vehicle.lift.maxWeight=10
vehicle.lift.error.overWeight=Overweight

vehicle.battery.default=5.0
vehicle.battery.critical.limit=15
vehicle.walk.distance.error=Not able to move

WalkServiceImpl.java (able to read from here)

package com.vehicle.prototype.service.impl;

@Service
public class WalkServiceImpl implements CapabilityService {

    @Value("${vehicle.walk.distance.error}")
    private String mDistanceError;

    @Override
    public void performTask(VehicleData vehicleData) {
        double distance = vehicleData.getWalkingDistance();
        double remainingBattery = vehicleData.getRemainingBattery();

        if (remainingBattery < distance) {
            vehicleData.setErrorMessage(mDistanceError);
            System.out.println(mDistanceError);
        } else {
            vehicleData.setRemainingBattery(remainingBattery - distance);
        }

        VehicleUtil.checkBatteryStatus(vehicleData);

    }

}

VehicleData.java (Pojo - not able read from here)

package com.vehicle.prototype.model;

public class VehicleData {

    private double walkingDistance;
    private double liftWeight;

    @Value("${vehicle.battery.default}")
    private double remainingBattery;

    // setters & getters ....

}

VehicleUtil.java (Singleton - not able to read from here)

package com.vehicle.prototype.utils;

public class VehicleUtil {

    private static VehicleUtil mInstance = null;
    private static Object mLock = new Object();

    @Value("${vehicle.battery.critical.limit}")
    private static double mCriticalLimit;

    @Value("${vehicle.battery.default}")
    private static double mTotalPower;

    @Value("${vehicle.battery.critical.warning}")
    private static String powerWarning;


    private VehicleUtil() {
        // empty private constructor.
    }

    public static VehicleUtil getInstance() {
        if (mInstance == null) {
            synchronized (mLock) {
                if (mInstance == null)
                    mInstance = new VehicleUtil();
            }
        }
        return mInstance;
    }

    public static void checkBatteryStatus(VehicleData vehicleData) {
        double criticalMark = (mCriticalLimit * 100.0f) / mTotalPower;
        if (vehicleData.getRemainingBattery() < criticalMark) {
            vehicleData.setBatteryCritical(Boolean.TRUE);
            System.out.println(powerWarning);
        } else {
            vehicleData.setBatteryCritical(Boolean.FALSE);
        }
    }

}

Please let me know how to fix this.

Thank You

like image 974
rahul s Avatar asked Sep 04 '16 11:09

rahul s


1 Answers

You need to inject the properties into a spring-managed bean. What you can do, is to bundle the properties in a bean like this (see documentation)

@ConfigurationProperties(prefix="vehicle")
public class VehicleProperties {
    @Value("${battery.critical.limit}")
    private double mCriticalLimit;

    @Value("${battery.default}")
    private double mTotalPower;

    @Value("${battery.critical.warning}")
    private String powerWarning;
}

Then, inject the Vehicle Properties into your service and passe them to VehicleUtil:

public class WalkServiceImpl {
    @Autowired
    private VehicleProperties vehicleProperties;

    @Override
    public void performTask(VehicleData vehicleData) {
        ...
        VehicleUtil.checkBatteryStatus(vehicleProperties, vehicleData);
    }
}

Better yet, I would convert VehicleUtil into a managed-bean

@Component
public class VehicleUtil {
    @Autowired
    private VehicleProperties vehicleProperties;
}

VehicleData

I'm assuming VehicleData is some business object, passed from the client or that you create yourself, for which they are many instances (not just one singleton). In this case, it wouldn't make sense to convert VehicleData into a managed-bean, and its external dependencies could just be provided to it through its setters:

public class VehicleData {
    private double walkingDistance;
    private double liftWeight;
    private double remainingBattery;
    // setters & getters ....
}
like image 62
alexbt Avatar answered Sep 22 '22 02:09

alexbt