1

I had already tried solutions mentioned in Why is my Spring @Autowired field null? yet the problem persists. I have tried annotating the class DevicePojo(code below) with @Configurable @Service.

Here are my beans DistributionConfig.java

@Component
@Configuration
public class DistributionConfig {

    @Qualifier("exponentialDistribution")
    @Bean
    @Scope("prototype")
    public DistributionService exponentialDistribution() {
        return new ExponentiallyDistribute();
    }

    @Qualifier("normalDistribution")
    @Bean
    @Scope("prototype")
    public DistributionService normalDistribution() {
        return new NormallyDistribute();
    }

    @Qualifier("uniformDistribution")
    @Bean
    @Scope("prototype")
    public DistributionService uniformDistribution() {
        return new UniformlyDistribute();
    }
}

JsonFileConfig.java

@Configuration
public class JsonFileConfig {

    private static ObjectMapper mapper=new ObjectMapper();

    @Qualifier("devicesPojo")
    @Bean
    public DevicesPojo[] devicesPojo() throws Exception {
        DevicesPojo[] devicePojo=mapper.readValue(new File(getClass().getClassLoader().getResource("Topo/esnet-devices.json").getFile()),DevicesPojo[].class);
        return devicePojo;
    }


    @Qualifier("linksPojo")
    @Bean
    public LinksPojo[] linksPojo() throws Exception {
        LinksPojo[] linksPojo=mapper.readValue(new File(getClass().getClassLoader().getResource("Topo/esnet-adjcies.json").getFile()),LinksPojo[].class);
        return linksPojo;
    }
}

Here is my DevicePojo where i get the null pointer exception.

@JsonDeserialize(using = DeviceDeserializer.class)
@Component
public class DevicesPojo {

    private String device;
    private List<String> ports;
    private List<Integer> bandwidth;

    @Autowired
    @Qualifier("uniformDistribution")
    private DistributionService uniformDistribution; // Here uniformDistribution is null

    public DevicesPojo(String device, List<String> port, List<Integer> bandwidth) {
        this.device = device;
        this.ports= port;
        this.bandwidth=bandwidth;
        this.uniformDistribution.createUniformDistribution(1000,0,ports.size());
    }

    public String getDevice(){
        return device;
    }

    public String getRandomPortForDevice()
    {
       return ports.get((int)uniformDistribution.getSample());
    }

    public List<String> getAllPorts(){
       return ports;
    }

    public int getBandwidthForPort(String port){    
       return bandwidth.get(ports.indexOf(port));
    }
}

However, if i replace private DistributionService uniformDistribution;with private DistributionService uniformDistribution=new UniformDistribution() the code is working fine.

Struse
  • 75
  • 3
  • 13
  • Why do you think the "mapper" should "honor" spring annotations? When you use `mapper.readValue`, there is a `new DevicesPojo` that is made. One solution would be to let the mapper do his thing then "set" the DistributionService on the result (DistributionService you get with some @Autowired) –  Jul 08 '17 at 08:05
  • It worked fine as long as i added @Autowired inside DevicePojo. Why what's wrong? – Struse Jul 08 '17 at 08:08
  • Can you elaborate a bit? Some sort of pseudo code would help. – Struse Jul 08 '17 at 08:13

1 Answers1

1

There is a mix of problems here.
1. You create your DevicesPojo objects using JSON deserializer. Spring has no chance to interfere and inject the DistributionService.
2. Even if it could interfere, it would fail, since you are trying to use the 'distributionService' object in the constructor. Field injection would work only after an object is constructed.

Now regarding fixing the problems.
Long answer short - don't expect auto-injection in your POJOs.
Normally, dependencies like 'distributionService' in objects that are created on the fly, like your DevicesPojo are avoided altogether.
If you insist on having them, inject them manually at construction time:

class DevicesPojoFactory {
    @Autowired @Qualifier("uniformDistribution") 
    private DistributionService uniformDistribution;
    ObjectMapper mapper = new ObjectMapper();

    DevicesPojo[] readFromFile(String path) {
         DevicesPojo[] devicePojoArr = mapper.readValue(...);
         for (DevicesPojo dp: devicePojoArr) {
              dp.setDistribution(uniformDistribution);
         }
    }
}
Alexander
  • 2,761
  • 1
  • 28
  • 33
  • Can I autowire distributionservice in the devicedeserialiser and create the instance of devicespojo from there? – Struse Jul 08 '17 at 08:58
  • 'Field injection happens after object is constructed' makes sense. That's what I thought might be wrong as well. But in some hope I tried it. Now it becomes clear.thanks – Struse Jul 08 '17 at 09:03
  • Not sure about DeviceDeserializer as its instances are going to be created by JSON that knows nothing about Spring. It's much easier just to wrap JSON. – Alexander Jul 08 '17 at 09:07
  • Deserializer did not do as well. But I worked around the problem somehow. – Struse Jul 08 '17 at 22:35