Doubts with dependency injection with Spring (object injected returning null)

2

Good afternoon everyone.

Personally, I have a problem that I should probably be missing or forgetting the order of something.

My case is that I have a two controllers. One is DestinationController.java and the other is FileController.java. I will paste the classes below omitting some methods to reduce size and become easier to understand:

DestinationController.java

@Controller
@Transactional(propagation = Propagation.REQUIRED)
public class DestinationController{

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

        //Injeta objetos da minha classe de serviço.
    @Autowired
    public DashboardFacade dashboardFacade;

    //Retorna o body do destino para inclusão
    @RequestMapping("destination")
    public String getMenudestination(Model model){

                //Funciona normalmente. Ou seja, ele retorna a lista para mim sem disparar exeções
        List<Destination> destinationList = dashboardFacade.getDestinationList();
        model.addAttribute("destination", destinationList);
        return "destination/destinationList";    
    }
     @ModelAttribute("destination")
     public Destination getDestinationObject() {
      return new Destination();
     }


    //Adicona um novo destino
    @RequestMapping(value="/addDestination", method = RequestMethod.POST)
    public ModelAndView addDestination(@ModelAttribute("destination") @Valid Destination destination, BindingResult result, RedirectAttributes redirectAttributes, Model model){

        List<String> error = new ArrayList<>();

        if(result.hasErrors()){
            List<ObjectError> allErrors = result.getAllErrors();


            for (ObjectError objectError : allErrors) {
                String objectName = objectError.getDefaultMessage();
                error.add(objectName);
            }

            model.addAttribute("errors", error);
            model.addAttribute("validator", true);
            setnewDestination(model);

            return new ModelAndView("destination/newDestination");

        }else{
            if(destination.getCategories().getIdCategory() == -1){            
                error.add("Você precisa selecionar uma categoria.");
                model.addAttribute("errors", error);
                return new ModelAndView("destination/newDestination");

            }else{
                                //Aqui eu instancio um objeto do FileController passando um parametro (creio que aqui eu esteja usando uma abordagem errada)
                FileController fileController = new FileController();
                fileController.imageReplication(destination.getDtName());

                Category category = dashboardFacade.getCategoryId(destination.getCategories().getIdCategory());
                destination.setCategories(category);

                dashboardFacade.addDestination(destination);

                redirectAttributes.addFlashAttribute("message", "O destino " + destination.getDtName() + " foi adicionado(a) com sucesso!");

                logger.info("Destino " + destination.getDtName() + " adicionado com sucesso para a agência: " + dashboardFacade.getAgency());
                return new ModelAndView(new RedirectView("destination"));
            }
        }
    }
}

FileController.java

@Controller
@Transactional(propagation = Propagation.REQUIRED)
@RequestMapping("/file")
public class FileController {

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


    @Autowired
    public DashboardFacade dashboardFacade;

        //Quando eu passo um objeto do tipo FileMeta e chamo o dashboardFacade.addImagePathTmp(pathJson); o funcionamento é normal. o dashboardFacade não me retorna nulo
    public void generateJson(FileMeta fileMeta) {
        Gson gson = new Gson();
        String generated = gson.toJson(fileMeta);
        pathJson = new ImageJson();
        pathJson.setJson(generated);
        dashboardFacade.addImagePathTmp(pathJson);
        logger.info("Imagem adicionada.");
    }


    public Set<Image> imageReplication(String destination) {
        Set<Image> img = new HashSet<>();
        try {
                        // Aqui que mora o problema. Quando o metodo é invocado pelo outro controller (DestinationController.java) Meu dashboradFacade é nulo.
            List<ImageJson> imagePathTmpList = dashboardFacade.getImagePathTmpList();

            Gson gson = null;

            String subdomain = dashboardFacade.getAgency().getSubdomain();
            File base = new File("/home/manolo/joocebox-img/" + subdomain + "/"
                    + destination);

            for (ImageJson imageJsonList : imagePathTmpList) {
                gson = new Gson();
                FileMeta imgTmp = gson.fromJson(imageJsonList.getJson(), FileMeta.class);
                String path = base + "/" + imgTmp.getFileName();
                System.out.println(path);

            }

        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        return img;
    }
}

Well, I made some comments in the code to make it easier to see. In short, the imageReplication(String destination) method when called by my controller DestinationController.java dashbordFacade Within the FileController is returned null by firing a nullPointerExeption.

Can Algume take away my doubt of what I might be doing wrong?

A hug to everyone and success.

    
asked by anonymous 22.08.2014 / 20:11

1 answer

1

The problem is exactly what you put in the comment, you're using the wrong approach:

Dependency Injection: This concept is not being used. You should not instantiate in your class the objects that it needs to work, it must receive them from Spring (Autowired). However, in the way that is implemented there is another problem, since it is missing ...

Distribution of responsibilities: A controller is used to respond to requests, and this is what it should do. A controller should not use the other as a utility for image replication, or file upload or whatever. The maximum of the relationship between controllers is redirection, but a non-instance or receives by injection to use it that way.

Component: The ideal would be to extract the code from the imageReplication method to another object, responsible only for working with images. So this new object can be injected into all objects that need this functionality.

From my point of view there is something else to improve here. Instead of injecting the object directly into the class attribute, it is more interesting to inject it via the counter. This makes obvious the dependencies of the object so that it can carry out its work, its code becomes much clearer, and when you write unit tests this will make your life much easier.

Some time ago I wrote a post about Spring MVC and another about how integrate it with Hibernate . Take a look, I believe that the part how the dependencies are injected can serve as an example.

    
22.08.2014 / 20:48