Doubt with Spring dependency injection (injected object returning null)

Asked

Viewed 710 times

2

good afternoon to all.

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

My case is that I have one two controllers. One of them I call Destinationcontroller.java and the other Filecontroller.java. I will paste the classes below omitting some methods to reduce the size and make it 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 on the code to make it easier to visualize. In short: the method imageReplication(String destination) when called by my controller Destinationcontroller.java dashbordFacade Inside Filecontroller is returned null thus triggering a nullPointerExeption.

Can someone take away this doubt of what I might be doing wrong?

A hug to all and success.

1 answer

1


The problem is exactly what you put in the comment, you are using a wrong approach:

Dependency injection: This concept is not being employed. You should not instantiate in your class the objects it needs to work, it should receive them from Spring (Autowired). However, in the form that is implemented there is another problem, because it lacks...

Distribution of responsibilities: A controller is used to respond to requests, and that’s what it should do. A controller should not use the other as a utility for image replication, or file uploading or whatever. The maximum ratio between controllers is redirect, but a non instance or receive by injection to use it this way.

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

From where I stand, there’s something else to be improved here. Instead of injecting the object directly into the class attribute, it is more interesting to inject it via a constructor. This makes evident the dependencies of the object so that it can carry out its work, its code becomes much clearer, and when you write unit tests it will make your life much easier.

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

  • Hi Juliano, thanks for the reply. I must be honest with you and say that my understanding of dependency injection and even Spring is very little, because it is my first project in which I am using the framework. I understood some things, such as injection by constructor and the way I am instantiating my Filecontroller object. I just couldn’t understand how I can implement this componentization, because if I do the spring-controlled injection of the Filecontroller object inside my Destinationontroler, won’t it heal my need? Hug

  • 1

    Yes, but in an inappropriate way, because there is a confusion in the separation of responsibilities. My suggestion is, create an object ImageReplicator, take the method code imageReplication and move to that object and call it replicate. Now you can inject this new object and use it in your 2 controllers! =)

  • Show Juliano Ball! Killed the cock. I could understand and really is a way more "clean" programming. I’m already changing the application structure that has a low coupling, as well as changing the injection to be done with builders. I will give a read on your blog that seems to be very enlightening too. A hug and success!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.