0

I have an Entity-Repo-Service Spring Boot framework to simply visualize data in JFreeChart. Admitting that this is a common problem, but I've spent too much time reading and trying solutions from the big thread Why is my Spring @Autowired field null? that it may be more efficient to ask for help. I'm still learning Spring Boot, so I must have not understood the solutions thoroughly or overlooked some key points.

Repo:

package com.tool.logsview.repository;
import ...
@Repository
@ComponentScan(basePackages = {"com.tool.logsview"})
public interface LogRepository extends JpaRepository<Log, Long> {
    @Override
    List<Log> findAll();
    List<Log> findByDept(String dept);
}

Service:

package com.tool.logsview.service;
import ...
@Service
public class LogServiceImp implements LogService{

    @Autowired
    private LogRepository logRepository;
    
    @Override
    public List<Log> findByDept(String dept) {
        return logRepository.findByDept(dept);
    }
}

Controller where I integrate with JFreeChart

package com.tool.logsview.controller;
import ...

@Component
@Configurable
@ComponentScan(basePackages = {"com.tool.logsview"})
public class GanttChartWithData extends JFrame {

    @Autowired
    LogServiceImp logServiceImp; // <- null
    
    public GanttChartWithData(final String title) {
        super(title);
        // ...
    }
    private @NotNull IntervalCategoryDataset createDataset() {
        List<Log> demoDept = logServiceImp.findByDept("Demo"); // <- npe, the only use of logServiceImp in this class
        // ...
    }

    public static void main(final String[] args) {
    // ... JFreeChart
    }
}

I tried:

  • Use annotation and no new
  • Add annotations @Component/@Service/@Controller for class GanttChartWithData
  • Solution Changing to @Service, then using construction injections.
package com.tool.logsview.controller;

import ...

@Service
public class GanttChartWithData extends JFrame {

    private static
    LogRepository logRepository;

    @Autowired
    public GanttChartWithData(final String title, LogRepository logRepository) {
        super(title);
        // ...
        this.logRepository = logRepository;
    }

    // Creates a sample dataset for a Gantt chart.
    private @NotNull IntervalCategoryDataset createDataset() {
        // ...
        List<Log> demoDept = logRepository.findByDeptAndUsernameOrderByUsernameAsc("Demo", "personA");
    }

    public static void main(final String[] args) {
        final GanttChartWithData demo = new GanttChartWithData("Gantt Chart Demo", logRepository);
    }

}

Note that this works completely fine, but I don't want to bring a junk of code to Application

@SpringBootApplication
public class LogsviewApplication {
@Autowired
    private LogRepository logRepository; // <- not null
...}

At this point, I'm completely confused. Even to a point that I don't know why we should go Repo -> Service -> Controller while I used Repo directly and it works fine (In the Application, I used Repo instead of ServiceImplementation).

Any enlightenment is much appreciated!

UPDATE:

  • My use of Application Context following this guide:
package com.tool.logsview.misc;
import ...

@Controller
public class Dummy {
    @RequestMapping("/dummy")
    @ResponseBody
    public List<Log> dummy() {
        LogServiceImp logServiceImp = ApplicationContextHolder.getContext().getBean(LogServiceImp.class);
        return logServiceImp.fetchLogList();
    }
}

This proves that Application Context works, but I don't need a web Controller. I want to call logServiceImp for business service. Thus, attempting to change it to

package com.tool.logsview.misc;
import ...

@Service
public class Dummy {
    public Dummy() { }
    @Autowired
    static LogServiceImp logServiceImp1; // null - the same problem

    public static void main(String[] args) {
        LogServiceImp logServiceImp = ApplicationContextHolder.getContext().getBean(LogServiceImp.class); // application context but still null
        System.out.println(logServiceImp.fetchLogList());
        System.out.println(logServiceImp1.fetchLogList());
    }
}

Very likely misunderstand the whole IOC concept?

Context if it helps: At first, it was intended to visualize data on a browser, hence the Controller structure, but I switch to JFreeChart java lib to run with Swing, so I don't need @Controller and @RequestMapping. As @Georgy Gobozov points out, I may not need a Controller. But I do need @Service to do visualizing services.

Elly
  • 145
  • 7
  • Are you trying to run Swing + Spring Boot app? Repo -> Service -> Controller it's a formal model of 3 layered app ( data -> business logic -> web) it's common for most of the apps but doesn't have to be this way all the time. – Georgy Gobozov Oct 20 '22 at 21:53
  • Yes, I'm trying to run Swing + Spring Boot. At first, the project was intended to run on a browser but then changed to Swing. Does that mean if we don't need a project to run on the web, I can simply do Repo -> Service (and any Swing, JFreeChart codes are in Service)? – Elly Oct 21 '22 at 13:54
  • 1
    You can ignore web, look example here https://stackoverflow.com/questions/22864008/how-to-configure-spring-boot-with-swing-application – Georgy Gobozov Oct 22 '22 at 05:10

1 Answers1

0

Hello your logService Interface should be annotated with @service then you can verify is it's not longer null , or included in your application context . you can explore all the beans loaded in your application context.

Neos
  • 127
  • 6
  • Adding @Service to logService interface didn't resolve the npe. I tried application context (post updated) on a Dummy class, still hasn't worked for my case though (see updated post) – Elly Oct 21 '22 at 16:17